Rust: archiving + skeleton def translator

This commit is contained in:
Paolo Tranquilli
2024-08-28 17:15:49 +02:00
parent 2a2b79e6df
commit f40901f391
16 changed files with 914 additions and 75 deletions

View File

@@ -30,8 +30,8 @@ def _parse_args() -> argparse.Namespace:
p = argparse.ArgumentParser(description="Code generation suite")
p.add_argument("--generate", type=lambda x: x.split(","),
help="specify what targets to generate as a comma separated list, choosing among dbscheme, ql, trap "
"and cpp")
help="specify what targets to generate as a comma separated list, choosing among dbscheme, ql, "
"trap, cpp and rust")
p.add_argument("--verbose", "-v", action="store_true", help="print more information")
p.add_argument("--quiet", "-q", action="store_true", help="only print errors")
p.add_argument("--configuration-file", "-c", type=_abspath, default=conf,
@@ -57,6 +57,9 @@ def _parse_args() -> argparse.Namespace:
p.add_argument("--cpp-output",
help="output directory for generated C++ files, required if trap or cpp is provided to "
"--generate"),
p.add_argument("--rust-output",
help="output directory for generated Rust files, required if rust is provided to "
"--generate"),
p.add_argument("--generated-registry",
help="registry file containing information about checked-in generated code. A .gitattributes"
"file is generated besides it to mark those files with linguist-generated=true. Must"

View File

@@ -1,4 +1,4 @@
from . import dbschemegen, qlgen, trapgen, cppgen
from . import dbschemegen, qlgen, trapgen, cppgen, rustgen
def generate(target, opts, renderer):

View File

@@ -0,0 +1,102 @@
"""
Rust trap class generation
"""
import functools
import typing
import inflection
from misc.codegen.lib import rust, schema
from misc.codegen.loaders import schemaloader
def _get_type(t: str) -> str:
match t:
case None | "boolean": # None means a predicate
return "bool"
case "string":
return "String"
case "int":
return "i32"
case _ if t[0].isupper():
return "TrapLabel"
case _:
return t
def _get_field(cls: schema.Class, p: schema.Property) -> rust.Field:
table_name = None
if not p.is_single:
table_name = f"{cls.name}_{p.name}"
if p.is_predicate:
table_name = inflection.underscore(table_name)
else:
table_name = inflection.tableize(table_name)
args = dict(
field_name=p.name + ("_" if p.name in rust.keywords else ""),
base_type=_get_type(p.type),
is_optional=p.is_optional,
is_repeated=p.is_repeated,
is_predicate=p.is_predicate,
is_unordered=p.is_unordered,
table_name=table_name,
)
args.update(rust.get_field_override(p.name))
return rust.Field(**args)
def _get_properties(
cls: schema.Class, lookup: dict[str, schema.Class]
) -> typing.Iterable[schema.Property]:
for b in cls.bases:
yield from _get_properties(lookup[b], lookup)
yield from cls.properties
class Processor:
def __init__(self, data: schema.Schema):
self._classmap = data.classes
def _get_class(self, name: str) -> rust.Class:
cls = self._classmap[name]
return rust.Class(
name=name,
fields=[
_get_field(cls, p)
for p in _get_properties(cls, self._classmap)
if "rust_skip" not in p.pragmas and not p.synth
],
table_name=inflection.tableize(cls.name),
)
def get_classes(self):
ret = {"": []}
for k, cls in self._classmap.items():
if not cls.synth and not cls.derived:
ret.setdefault(cls.group, []).append(self._get_class(cls.name))
return ret
def generate(opts, renderer):
assert opts.rust_output
processor = Processor(schemaloader.load_file(opts.schema))
out = opts.rust_output
groups = set()
for group, classes in processor.get_classes().items():
group = group or "top"
groups.add(group)
renderer.render(
rust.ClassList(
classes,
opts.schema,
),
out / f"{group}.rs",
)
renderer.render(
rust.ModuleList(
groups,
opts.schema,
),
out / f"mod.rs",
)

141
misc/codegen/lib/rust.py Normal file
View File

@@ -0,0 +1,141 @@
import dataclasses
import re
import typing
# taken from https://doc.rust-lang.org/reference/keywords.html
keywords = {
"as",
"break",
"const",
"continue",
"crate",
"else",
"enum",
"extern",
"false",
"fn",
"for",
"if",
"impl",
"in",
"let",
"loop",
"match",
"mod",
"move",
"mut",
"pub",
"ref",
"return",
"self",
"Self",
"static",
"struct",
"super",
"trait",
"true",
"type",
"unsafe",
"use",
"where",
"while",
"async",
"await",
"dyn",
"abstract",
"become",
"box",
"do",
"final",
"macro",
"override",
"priv",
"typeof",
"unsized",
"virtual",
"yield",
"try",
}
_field_overrides = [
(
re.compile(r"(start|end)_(line|column)|(.*_)?index|width|num_.*"),
{"base_type": "usize"},
),
(re.compile(r"(.*)_"), lambda m: {"field_name": m[1]}),
]
def get_field_override(field: str):
for r, o in _field_overrides:
m = r.fullmatch(field)
if m:
return o(m) if callable(o) else o
return {}
@dataclasses.dataclass
class Field:
field_name: str
base_type: str
table_name: str = None
is_optional: bool = False
is_repeated: bool = False
is_unordered: bool = False
is_predicate: bool = False
first: bool = False
def __post_init__(self):
if self.field_name in keywords:
self.field_name += "_"
@property
def type(self) -> str:
type = self.base_type
if self.is_optional:
type = f"Option<{type}>"
if self.is_repeated:
type = f"Vec<{type}>"
return type
# using @property breaks pystache internals here
def emitter(self):
if self.type == "String":
return lambda x: f"quoted(&{x})"
else:
return lambda x: x
@property
def is_single(self):
return not (self.is_optional or self.is_repeated or self.is_predicate)
@property
def is_label(self):
return self.base_type == "TrapLabel"
@dataclasses.dataclass
class Class:
name: str
table_name: str
fields: list[Field] = dataclasses.field(default_factory=list)
@property
def single_fields(self):
return [f for f in self.fields if f.is_single]
@dataclasses.dataclass
class ClassList:
template: typing.ClassVar[str] = "rust_classes"
classes: list[Class]
source: str
@dataclasses.dataclass
class ModuleList:
template: typing.ClassVar[str] = "rust_module"
modules: list[str]
source: str

View File

@@ -0,0 +1,54 @@
// generated by {{generator}}
use crate::trap::{TrapLabel, TrapEntry, quoted};
use std::io::Write;
{{#classes}}
#[derive(Debug)]
pub struct {{name}} {
pub key: Option<String>,
{{#fields}}
pub {{field_name}}: {{type}},
{{/fields}}
}
impl TrapEntry for {{name}} {
type Label = TrapLabel;
fn prefix() -> &'static str { "{{name}}_" }
fn key(&self) -> Option<&str> { self.key.as_ref().map(String::as_str) }
fn emit<W: Write>(&self, id: &Self::Label, out: &mut W) -> std::io::Result<()> {
write!(out, "{{table_name}}({id}{{#single_fields}}, {}{{/single_fields}})\n"{{#single_fields}}, {{#emitter}}self.{{field_name}}{{/emitter}}{{/single_fields}})?;
{{#fields}}
{{#is_predicate}}
if self.{{field_name}} {
write!(out, "{{table_name}}({id})\n")?;
}
{{/is_predicate}}
{{#is_optional}}
{{^is_repeated}}
if let Some(ref v) = &self.{{field_name}} {
write!(out, "{{table_name}}({id}, {})\n", {{#emitter}}v{{/emitter}})?;
}
{{/is_repeated}}
{{/is_optional}}
{{#is_repeated}}
for (i, &ref v) in self.{{field_name}}.iter().enumerate() {
{{^is_optional}}
write!(out, "{{table_name}}({id}, {{^is_unordered}}{}, {{/is_unordered}}{})\n", {{^is_unordered}}i, {{/is_unordered}}{{#emitter}}v{{/emitter}})?;
{{/is_optional}}
{{#is_optional}}
if let Some(ref vv) = &v {
write!(out, "{{table_name}}({id}, {{^is_unordered}}{}, {{/is_unordered}}{})\n", {{^is_unordered}}i, {{/is_unordered}}{{#emitter}}vv{{/emitter}})?;
}
{{/is_optional}}
}
{{/is_repeated}}
{{/fields}}
Ok(())
}
}
{{/classes}}

View File

@@ -0,0 +1,7 @@
// generated by {{generator}}
{{#modules}}
mod {{.}};
pub use {{.}}::*;
{{/modules}}

4
rust/BUILD.bazel Normal file
View File

@@ -0,0 +1,4 @@
exports_files([
"codegen.conf",
"schema.py",
])

428
rust/Cargo.lock generated
View File

@@ -295,8 +295,9 @@ dependencies = [
"log",
"num-traits",
"ra_ap_base_db 0.0.231",
"ra_ap_hir",
"ra_ap_hir 0.0.229",
"ra_ap_hir_def 0.0.231",
"ra_ap_ide_db 0.0.232",
"ra_ap_load-cargo",
"ra_ap_project_model",
"serde",
@@ -1069,6 +1070,19 @@ dependencies = [
"tracing",
]
[[package]]
name = "ra-ap-rustc_pattern_analysis"
version = "0.63.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1709080fdeb5db630e1c2644026c2962aaa32416cd92f0190c04b0c21e114b91"
dependencies = [
"ra-ap-rustc_index 0.63.0",
"rustc-hash",
"rustc_apfloat",
"smallvec",
"tracing",
]
[[package]]
name = "ra_ap_base_db"
version = "0.0.229"
@@ -1111,6 +1125,27 @@ dependencies = [
"triomphe",
]
[[package]]
name = "ra_ap_base_db"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcb25fbab872d3f85798739db011212a98444e55163d71edb1dfdb509e616b3"
dependencies = [
"la-arena",
"lz4_flex",
"ra_ap_cfg 0.0.232",
"ra_ap_intern 0.0.232",
"ra_ap_salsa 0.0.232",
"ra_ap_span 0.0.232",
"ra_ap_stdx 0.0.232",
"ra_ap_syntax 0.0.232",
"ra_ap_vfs 0.0.232",
"rustc-hash",
"semver",
"tracing",
"triomphe",
]
[[package]]
name = "ra_ap_cfg"
version = "0.0.229"
@@ -1133,6 +1168,17 @@ dependencies = [
"rustc-hash",
]
[[package]]
name = "ra_ap_cfg"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbec14556d01bf34fb795d70941f929ed4c024dee11be9c99c712ea92225a20b"
dependencies = [
"ra_ap_intern 0.0.232",
"ra_ap_tt 0.0.232",
"rustc-hash",
]
[[package]]
name = "ra_ap_hir"
version = "0.0.229"
@@ -1147,7 +1193,7 @@ dependencies = [
"ra_ap_cfg 0.0.229",
"ra_ap_hir_def 0.0.229",
"ra_ap_hir_expand 0.0.229",
"ra_ap_hir_ty",
"ra_ap_hir_ty 0.0.229",
"ra_ap_intern 0.0.229",
"ra_ap_span 0.0.229",
"ra_ap_stdx 0.0.229",
@@ -1159,6 +1205,31 @@ dependencies = [
"triomphe",
]
[[package]]
name = "ra_ap_hir"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7c38520eb4770af561c34b908431f4e548c3282093cf3daf3c6e566d99a2937"
dependencies = [
"arrayvec",
"either",
"itertools",
"ra_ap_base_db 0.0.232",
"ra_ap_cfg 0.0.232",
"ra_ap_hir_def 0.0.232",
"ra_ap_hir_expand 0.0.232",
"ra_ap_hir_ty 0.0.232",
"ra_ap_intern 0.0.232",
"ra_ap_span 0.0.232",
"ra_ap_stdx 0.0.232",
"ra_ap_syntax 0.0.232",
"ra_ap_tt 0.0.232",
"rustc-hash",
"smallvec",
"tracing",
"triomphe",
]
[[package]]
name = "ra_ap_hir_def"
version = "0.0.229"
@@ -1232,6 +1303,42 @@ dependencies = [
"triomphe",
]
[[package]]
name = "ra_ap_hir_def"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f00b546cacca816b94a12d51df076d50965d6bae411fd68f9024420bfa026e7b"
dependencies = [
"arrayvec",
"bitflags 2.6.0",
"cov-mark",
"dashmap",
"drop_bomb",
"either",
"fst",
"hashbrown 0.14.5",
"indexmap 2.4.0",
"itertools",
"la-arena",
"ra-ap-rustc_abi 0.63.0",
"ra-ap-rustc_parse_format 0.63.0",
"ra_ap_base_db 0.0.232",
"ra_ap_cfg 0.0.232",
"ra_ap_hir_expand 0.0.232",
"ra_ap_intern 0.0.232",
"ra_ap_limit 0.0.232",
"ra_ap_mbe 0.0.232",
"ra_ap_span 0.0.232",
"ra_ap_stdx 0.0.232",
"ra_ap_syntax 0.0.232",
"ra_ap_tt 0.0.232",
"rustc-hash",
"rustc_apfloat",
"smallvec",
"tracing",
"triomphe",
]
[[package]]
name = "ra_ap_hir_expand"
version = "0.0.229"
@@ -1288,6 +1395,34 @@ dependencies = [
"triomphe",
]
[[package]]
name = "ra_ap_hir_expand"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c9675e1331dadf43cbc807ae39d2c289b8ba2af33a8e197c0927d926a6610d"
dependencies = [
"cov-mark",
"either",
"hashbrown 0.14.5",
"itertools",
"la-arena",
"ra_ap_base_db 0.0.232",
"ra_ap_cfg 0.0.232",
"ra_ap_intern 0.0.232",
"ra_ap_limit 0.0.232",
"ra_ap_mbe 0.0.232",
"ra_ap_parser 0.0.232",
"ra_ap_span 0.0.232",
"ra_ap_stdx 0.0.232",
"ra_ap_syntax 0.0.232",
"ra_ap_syntax-bridge 0.0.232",
"ra_ap_tt 0.0.232",
"rustc-hash",
"smallvec",
"tracing",
"triomphe",
]
[[package]]
name = "ra_ap_hir_ty"
version = "0.0.229"
@@ -1311,7 +1446,7 @@ dependencies = [
"oorandom",
"ra-ap-rustc_abi 0.53.0",
"ra-ap-rustc_index 0.53.0",
"ra-ap-rustc_pattern_analysis",
"ra-ap-rustc_pattern_analysis 0.53.0",
"ra_ap_base_db 0.0.229",
"ra_ap_hir_def 0.0.229",
"ra_ap_hir_expand 0.0.229",
@@ -1329,6 +1464,46 @@ dependencies = [
"typed-arena",
]
[[package]]
name = "ra_ap_hir_ty"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e308aa1b956137c82547a8b46eb60c6ee295628322e00aa5266a1ea5ea8e522e"
dependencies = [
"arrayvec",
"bitflags 2.6.0",
"chalk-derive",
"chalk-ir",
"chalk-recursive",
"chalk-solve",
"cov-mark",
"either",
"ena",
"indexmap 2.4.0",
"itertools",
"la-arena",
"nohash-hasher",
"oorandom",
"ra-ap-rustc_abi 0.63.0",
"ra-ap-rustc_index 0.63.0",
"ra-ap-rustc_pattern_analysis 0.63.0",
"ra_ap_base_db 0.0.232",
"ra_ap_hir_def 0.0.232",
"ra_ap_hir_expand 0.0.232",
"ra_ap_intern 0.0.232",
"ra_ap_limit 0.0.232",
"ra_ap_span 0.0.232",
"ra_ap_stdx 0.0.232",
"ra_ap_syntax 0.0.232",
"rustc-hash",
"rustc_apfloat",
"scoped-tls",
"smallvec",
"tracing",
"triomphe",
"typed-arena",
]
[[package]]
name = "ra_ap_ide_db"
version = "0.0.229"
@@ -1348,10 +1523,10 @@ dependencies = [
"nohash-hasher",
"once_cell",
"ra_ap_base_db 0.0.229",
"ra_ap_hir",
"ra_ap_hir 0.0.229",
"ra_ap_limit 0.0.229",
"ra_ap_parser 0.0.229",
"ra_ap_profile",
"ra_ap_profile 0.0.229",
"ra_ap_span 0.0.229",
"ra_ap_stdx 0.0.229",
"ra_ap_syntax 0.0.229",
@@ -1362,6 +1537,38 @@ dependencies = [
"triomphe",
]
[[package]]
name = "ra_ap_ide_db"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ea9c17702025001c1672ab23bf9be3cf40785376c0f368a10fe812db1327eb"
dependencies = [
"arrayvec",
"bitflags 2.6.0",
"cov-mark",
"crossbeam-channel",
"either",
"fst",
"indexmap 2.4.0",
"itertools",
"line-index",
"memchr",
"nohash-hasher",
"ra_ap_base_db 0.0.232",
"ra_ap_hir 0.0.232",
"ra_ap_limit 0.0.232",
"ra_ap_parser 0.0.232",
"ra_ap_profile 0.0.232",
"ra_ap_span 0.0.232",
"ra_ap_stdx 0.0.232",
"ra_ap_syntax 0.0.232",
"ra_ap_text_edit 0.0.232",
"rayon",
"rustc-hash",
"tracing",
"triomphe",
]
[[package]]
name = "ra_ap_intern"
version = "0.0.229"
@@ -1388,6 +1595,19 @@ dependencies = [
"triomphe",
]
[[package]]
name = "ra_ap_intern"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78e0928f2c403ebea95f97a38a720900216ea896212347e893a37ae7c1419030"
dependencies = [
"dashmap",
"hashbrown 0.14.5",
"rustc-hash",
"sptr",
"triomphe",
]
[[package]]
name = "ra_ap_limit"
version = "0.0.229"
@@ -1400,6 +1620,12 @@ version = "0.0.231"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d20a0946a1510ddad977d54f2deab510e27d4e9a7406942152560312a9d14211"
[[package]]
name = "ra_ap_limit"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60972e02e4dfe05b2755e09a6b11b27db8a47cea01cd2697e77a34c4cf60b31c"
[[package]]
name = "ra_ap_load-cargo"
version = "0.0.229"
@@ -1410,7 +1636,7 @@ dependencies = [
"crossbeam-channel",
"itertools",
"ra_ap_hir_expand 0.0.229",
"ra_ap_ide_db",
"ra_ap_ide_db 0.0.229",
"ra_ap_intern 0.0.229",
"ra_ap_paths 0.0.229",
"ra_ap_proc_macro_api",
@@ -1462,6 +1688,26 @@ dependencies = [
"tracing",
]
[[package]]
name = "ra_ap_mbe"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "714a0997373ff65e7748e7768186598c6831e95f71639f66c3f79ef591c9d496"
dependencies = [
"arrayvec",
"cov-mark",
"ra_ap_intern 0.0.232",
"ra_ap_parser 0.0.232",
"ra_ap_span 0.0.232",
"ra_ap_stdx 0.0.232",
"ra_ap_syntax 0.0.232",
"ra_ap_syntax-bridge 0.0.232",
"ra_ap_tt 0.0.232",
"rustc-hash",
"smallvec",
"tracing",
]
[[package]]
name = "ra_ap_parser"
version = "0.0.229"
@@ -1486,6 +1732,18 @@ dependencies = [
"tracing",
]
[[package]]
name = "ra_ap_parser"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8da0314db93eabbd2b92e13907690782688cfc8aaaf42b8e6726e7f5b338c2e3"
dependencies = [
"drop_bomb",
"ra-ap-rustc_lexer 0.63.0",
"ra_ap_limit 0.0.232",
"tracing",
]
[[package]]
name = "ra_ap_paths"
version = "0.0.229"
@@ -1505,6 +1763,15 @@ dependencies = [
"camino",
]
[[package]]
name = "ra_ap_paths"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc084003225204a9e5e50957a565f1cc23ebef18cd779f31563a8d2180f8940"
dependencies = [
"camino",
]
[[package]]
name = "ra_ap_proc_macro_api"
version = "0.0.229"
@@ -1536,6 +1803,18 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "ra_ap_profile"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "572193d698a8bc4245463688d10f20932ab04940d5b6c32be457bc45dc1e6ab0"
dependencies = [
"cfg-if",
"libc",
"perf-event",
"windows-sys 0.52.0",
]
[[package]]
name = "ra_ap_project_model"
version = "0.0.229"
@@ -1597,6 +1876,24 @@ dependencies = [
"triomphe",
]
[[package]]
name = "ra_ap_salsa"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "370b302873eeafd07ccc6a714fc9395cae11e385955ccb78081093ee3b86f94e"
dependencies = [
"indexmap 2.4.0",
"itertools",
"lock_api",
"oorandom",
"parking_lot",
"ra_ap_salsa-macros 0.0.232",
"rustc-hash",
"smallvec",
"tracing",
"triomphe",
]
[[package]]
name = "ra_ap_salsa-macros"
version = "0.0.229"
@@ -1621,6 +1918,18 @@ dependencies = [
"syn",
]
[[package]]
name = "ra_ap_salsa-macros"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "414ff383af5abdb731917ca46c1a0f6b291278430736fe1ff2430a8548206a62"
dependencies = [
"heck 0.4.1",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "ra_ap_span"
version = "0.0.229"
@@ -1653,6 +1962,22 @@ dependencies = [
"text-size",
]
[[package]]
name = "ra_ap_span"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1b982f799c7a8051219902ff5c1974ee353ac6ca2aa5b17ab0e3db9b8d8a7bf"
dependencies = [
"hashbrown 0.14.5",
"la-arena",
"ra_ap_salsa 0.0.232",
"ra_ap_stdx 0.0.232",
"ra_ap_syntax 0.0.232",
"ra_ap_vfs 0.0.232",
"rustc-hash",
"text-size",
]
[[package]]
name = "ra_ap_stdx"
version = "0.0.229"
@@ -1683,6 +2008,21 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "ra_ap_stdx"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb63ff9d6b11b4553fc0835f16705975258905e3b1230fcf1ddbf24c46aff69d"
dependencies = [
"always-assert",
"crossbeam-channel",
"itertools",
"jod-thread",
"libc",
"miow",
"windows-sys 0.52.0",
]
[[package]]
name = "ra_ap_syntax"
version = "0.0.229"
@@ -1726,6 +2066,27 @@ dependencies = [
"triomphe",
]
[[package]]
name = "ra_ap_syntax"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1ac12decfd5cadd880177316fc16afc1f2c67f241f6290b51fd6f222e2bd4d5"
dependencies = [
"cov-mark",
"either",
"indexmap 2.4.0",
"itertools",
"ra-ap-rustc_lexer 0.63.0",
"ra_ap_parser 0.0.232",
"ra_ap_stdx 0.0.232",
"ra_ap_text_edit 0.0.232",
"rowan",
"rustc-hash",
"smol_str",
"tracing",
"triomphe",
]
[[package]]
name = "ra_ap_syntax-bridge"
version = "0.0.229"
@@ -1758,6 +2119,22 @@ dependencies = [
"tracing",
]
[[package]]
name = "ra_ap_syntax-bridge"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d57ec874cf6d45d25ce5d63dbfdf60912d5a33138855c4ab7e4314cfd01f6fa"
dependencies = [
"ra_ap_intern 0.0.232",
"ra_ap_parser 0.0.232",
"ra_ap_span 0.0.232",
"ra_ap_stdx 0.0.232",
"ra_ap_syntax 0.0.232",
"ra_ap_tt 0.0.232",
"rustc-hash",
"tracing",
]
[[package]]
name = "ra_ap_text_edit"
version = "0.0.229"
@@ -1778,6 +2155,16 @@ dependencies = [
"text-size",
]
[[package]]
name = "ra_ap_text_edit"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cb72ee1901baec556f4f2ef77e287d749ac0e973f063990672d6207b076aeac"
dependencies = [
"itertools",
"text-size",
]
[[package]]
name = "ra_ap_toolchain"
version = "0.0.229"
@@ -1814,6 +2201,19 @@ dependencies = [
"text-size",
]
[[package]]
name = "ra_ap_tt"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9730313c495e88a89ee33f6e34205a92652d9c9a5061ebaed59436058a33000"
dependencies = [
"arrayvec",
"ra-ap-rustc_lexer 0.63.0",
"ra_ap_intern 0.0.232",
"ra_ap_stdx 0.0.232",
"text-size",
]
[[package]]
name = "ra_ap_vfs"
version = "0.0.229"
@@ -1845,6 +2245,22 @@ dependencies = [
"tracing",
]
[[package]]
name = "ra_ap_vfs"
version = "0.0.232"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d833eaa5422de9bb51ab1841fe505ed00fb51e64cce397e21de6c324bbcbffa0"
dependencies = [
"crossbeam-channel",
"fst",
"indexmap 2.4.0",
"nohash-hasher",
"ra_ap_paths 0.0.232",
"ra_ap_stdx 0.0.232",
"rustc-hash",
"tracing",
]
[[package]]
name = "ra_ap_vfs-notify"
version = "0.0.229"

View File

@@ -12,6 +12,7 @@ num-traits = "0.2.19"
ra_ap_base_db = "0.0.231"
ra_ap_hir = "0.0.229"
ra_ap_hir_def = "0.0.231"
ra_ap_ide_db = "0.0.232"
ra_ap_load-cargo = "0.0.229"
ra_ap_project_model = "0.0.229"
serde = "1.0.209"

28
rust/src/archive.rs Normal file
View File

@@ -0,0 +1,28 @@
use std::path::{Path, PathBuf};
use std::fs;
use crate::path;
use anyhow;
use log::{debug, warn};
pub struct Archiver {
pub root: PathBuf
}
impl Archiver {
pub fn archive(&self, source: &Path) {
if let Err(e) = self.try_archive(source) {
warn!("unable to archive {}: {e}", source.display());
}
}
fn try_archive(&self, source: &Path) -> std::io::Result<()> {
let mut dest = self.root.clone();
dest.push(path::key(source));
let parent = dest.parent().unwrap();
fs::create_dir_all(parent)?;
fs::copy(source, dest)?;
debug!("archived {}", source.display());
Ok(())
}
}

View File

@@ -0,0 +1,4 @@
// generated by codegen
mod top;
pub use top::*;

View File

@@ -1,14 +1,22 @@
#![feature(path_add_extension)]
use std::fs;
use ra_ap_project_model::CargoConfig;
use anyhow::Context;
use log;
use ra_ap_hir::db::DefDatabase;
use ra_ap_hir::{ModuleDefId};
use ra_ap_hir::AdtId::{EnumId, UnionId, StructId};
use ra_ap_hir::sym::ge;
use ra_ap_load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice};
mod config;
mod trap;
pub mod trap;
mod generated;
mod translate;
mod archive;
pub mod path;
fn main() -> anyhow::Result<()> {
let cfg = config::Config::extract().context("failed to load configuration")?;
@@ -17,6 +25,8 @@ fn main() -> anyhow::Result<()> {
.verbosity(2 + cfg.verbose as usize)
.init()?;
log::info!("{cfg:?}");
let traps = trap::TrapFileProvider::new(&cfg).context("failed to set up trap files")?;
let archiver = archive::Archiver{root: cfg.source_archive_dir};
let config = CargoConfig { ..Default::default() };
let no_progress = |_| ();
@@ -25,50 +35,16 @@ fn main() -> anyhow::Result<()> {
with_proc_macro_server: ProcMacroServerChoice::Sysroot,
prefill_caches: false,
};
for manifest in cfg.inputs {
let (db, vfs, _macro_server) = load_workspace_at(&manifest, &config, &load_config, &no_progress)?;
let def_db: &dyn DefDatabase = &db;
let crates = def_db.crate_graph();
for crate_id in crates.iter().take(1) {
let krate = &crates[crate_id];
let file = vfs.file_path(krate.root_file_id);
println!("Crate: idx={:x} {}", crate_id.into_raw().into_u32(), file);
let def_map = def_db.crate_def_map(crate_id);
for (module_id, &ref module) in def_map.modules.iter() {
println!(" Module: idx={:x} {:?}", module_id.into_raw().into_u32(), module.origin);
for ref decl_id in module.scope.declarations() {
match decl_id {
ModuleDefId::ModuleId(id) => {
println!(" Module: idx={:x}", id.local_id.into_raw().into_u32());
}
ModuleDefId::FunctionId(id) => {
let function = def_db.function_data(*id);
println!(" Function: {:?}", function);
}
ModuleDefId::AdtId(StructId(id)) => {
let s = def_db.struct_data(*id);
println!(" Struct: {:?}", s);
}
ModuleDefId::AdtId(EnumId(id)) => {
let e = def_db.enum_data(*id);
println!(" Enum: {:?}", e);
}
ModuleDefId::AdtId(UnionId(id)) => {
let u = def_db.union_data(*id);
println!(" Union: {:?}", u);
}
ModuleDefId::EnumVariantId(_) => {}
ModuleDefId::ConstId(_) => {}
ModuleDefId::StaticId(_) => {}
ModuleDefId::TraitId(_) => {}
ModuleDefId::TraitAliasId(_) => {}
ModuleDefId::TypeAliasId(_) => {}
ModuleDefId::BuiltinType(_) => {}
ModuleDefId::MacroId(_) => {}
}
}
}
for input in cfg.inputs {
let path = fs::canonicalize(input)?;
{
let mut trap = traps.create("input", &path)?;
let name= String::from(path.to_string_lossy());
trap.emit(generated::DbFile{key: Some(name.clone()), name })?;
archiver.archive(&path);
}
load_workspace_at(&path, &config, &load_config, &no_progress)?;
todo!()
}
Ok(())
}

8
rust/src/path.rs Normal file
View File

@@ -0,0 +1,8 @@
use std::path::{absolute, Path, PathBuf};
use std::fs::canonicalize;
pub fn key(p: &Path) -> PathBuf {
let normalized = canonicalize(p).or_else(|_| absolute(p)).unwrap_or_else(|_| p.into());
let root = normalized.ancestors().last().unwrap(); // ancestors always yields at least one
normalized.strip_prefix(root).unwrap().into() // stripping an ancestor always works
}

36
rust/src/translate.rs Normal file
View File

@@ -0,0 +1,36 @@
use crate::trap::TrapFile;
use ra_ap_hir::{ModuleDefId, db::{DefDatabase, ExpandDatabase}, AdtId::{EnumId, UnionId, StructId}};
use ra_ap_ide_db::RootDatabase;
use anyhow;
use ra_ap_ide_db::base_db::Upcast;
struct Translator<'a> {
pub db: &'a dyn DefDatabase,
pub trap: TrapFile,
}
impl Translator<'_> {
pub fn emit_definition(&mut self, id: &ModuleDefId) -> anyhow::Result<()> {
match id {
ModuleDefId::FunctionId(id) => {
let function = self.db.function_data(*id);
let name = format!("{}", function.name.display(self.db.upcast()));
println!("function {name}");
}
// ModuleDefId::AdtId(StructId(id)) => {
// let s = self.db.struct_data(*id);
// println!(" Struct: {:?}", s);
// }
// ModuleDefId::AdtId(EnumId(id)) => {
// let e = self.db.enum_data(*id);
// println!(" Enum: {:?}", e);
// }
// ModuleDefId::AdtId(UnionId(id)) => {
// let u = self.db.union_data(*id);
// println!(" Union: {:?}", u);
// }
_ => {}
}
Ok(())
}
}

View File

@@ -1,53 +1,112 @@
use std::fmt::Formatter;
use std::fmt::{Debug, Display, Formatter};
use std::fs::File;
use std::io::Write;
use std::path::{PathBuf};
use std::path::{Path, PathBuf};
use log::{debug, trace};
use crate::{config, path};
#[derive(Debug)]
struct TrapLabel(u64);
#[derive(Debug, Clone, Copy)]
pub struct TrapLabel(u64);
impl std::fmt::Display for TrapLabel {
//TODO: typed labels
impl From<u64> for TrapLabel {
fn from(value: u64) -> Self {
TrapLabel(value)
}
}
pub fn escaped(s: &str) -> String {
s.replace("\"", "\"\"")
}
pub fn quoted(s: &str) -> String {
format!("\"{}\"", escaped(s))
}
impl Display for TrapLabel {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "#{:x}", self.0)
}
}
trait TrapEntry: std::fmt::Display {}
pub trait TrapEntry: std::fmt::Debug {
type Label: Display + From<u64>;
fn prefix() -> &'static str { "" }
fn key(&self) -> Option<&str>;
fn emit<W: Write>(&self, id: &Self::Label, out: &mut W) -> std::io::Result<()>;
}
#[derive(Debug)]
struct TrapFile {
pub struct TrapFile {
label_index: u64,
file: File,
trap_name: String,
}
impl TrapFile {
pub fn new(path: &PathBuf) -> std::io::Result<TrapFile> {
let file = File::create(path)?;
Ok(TrapFile {
label_index: 0,
file: file,
})
pub fn comment(&mut self, message: &str) -> std::io::Result<()> {
for part in message.split("\n") {
trace!("emit -> {}: // {part}", self.trap_name);
write!(self.file, "// {part}\n")?;
}
Ok(())
}
pub fn insert_comment(&mut self, comment: &str) -> std::io::Result<()> {
write!(self.file, "/* {comment} */\n")
pub fn emit<T: TrapEntry>(&mut self, entry: T) -> std::io::Result<T::Label> {
let ret = match entry.key() {
None => self.create_star_label::<T>()?,
Some(key) => self.create_key_label::<T>(key)?,
};
trace!("emit -> {}: {entry:?}", self.trap_name);
entry.emit(&ret, &mut self.file)?;
Ok(ret)
}
pub fn allocate_label(&mut self) -> std::io::Result<TrapLabel> {
let ret = TrapLabel(self.label_index);
fn create_star_label<T: TrapEntry>(&mut self) -> std::io::Result<T::Label> {
let ret = T::Label::from(self.label_index);
write!(self.file, "{ret}=*\n")?;
self.label_index += 1;
Ok(ret)
}
pub fn allocate_label_for(&mut self, key: &str) -> std::io::Result<TrapLabel> {
let ret = TrapLabel(self.label_index);
write!(self.file, "{ret}=\"{}\"\n", key.replace("\"", "\"\""))?;
fn create_key_label<T: TrapEntry>(&mut self, key: &str) -> std::io::Result<T::Label> {
let ret = T::Label::from(self.label_index);
write!(self.file, "{ret}=@\"{}{}\"\n", T::prefix(), escaped(key))?;
self.label_index += 1;
Ok(ret)
}
}
pub fn emit<T: TrapEntry>(&mut self, entry: T) -> std::io::Result<()> {
write!(self.file, "{entry}\n")
pub struct TrapFileProvider {
trap_dir: PathBuf,
}
impl TrapFileProvider {
pub fn new(cfg: &config::Config) -> std::io::Result<TrapFileProvider> {
let trap_dir = cfg.trap_dir.clone();
std::fs::create_dir_all(&trap_dir)?;
Ok(TrapFileProvider {
trap_dir
})
}
pub fn create(&self, category: &str, key: &Path) -> std::io::Result<TrapFile> {
let mut path = PathBuf::from(category);
path.push(path::key(key));
path.add_extension("trap");
let trap_name = String::from(path.to_string_lossy());
debug!("creating trap file {}", trap_name);
path = self.trap_dir.join(path);
std::fs::create_dir_all(path.parent().unwrap())?;
let file = File::create(path)?;
Ok(TrapFile {
label_index: 0,
file,
trap_name,
})
}
}