mirror of
https://github.com/github/codeql.git
synced 2026-04-27 01:35:13 +02:00
Rust: archiving + skeleton def translator
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from . import dbschemegen, qlgen, trapgen, cppgen
|
||||
from . import dbschemegen, qlgen, trapgen, cppgen, rustgen
|
||||
|
||||
|
||||
def generate(target, opts, renderer):
|
||||
|
||||
102
misc/codegen/generators/rustgen.py
Normal file
102
misc/codegen/generators/rustgen.py
Normal 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
141
misc/codegen/lib/rust.py
Normal 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
|
||||
54
misc/codegen/templates/rust_classes.mustache
Normal file
54
misc/codegen/templates/rust_classes.mustache
Normal 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}}
|
||||
7
misc/codegen/templates/rust_module.mustache
Normal file
7
misc/codegen/templates/rust_module.mustache
Normal file
@@ -0,0 +1,7 @@
|
||||
// generated by {{generator}}
|
||||
|
||||
{{#modules}}
|
||||
mod {{.}};
|
||||
pub use {{.}}::*;
|
||||
|
||||
{{/modules}}
|
||||
4
rust/BUILD.bazel
Normal file
4
rust/BUILD.bazel
Normal file
@@ -0,0 +1,4 @@
|
||||
exports_files([
|
||||
"codegen.conf",
|
||||
"schema.py",
|
||||
])
|
||||
428
rust/Cargo.lock
generated
428
rust/Cargo.lock
generated
@@ -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"
|
||||
|
||||
@@ -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
28
rust/src/archive.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
4
rust/src/generated/mod.rs
Normal file
4
rust/src/generated/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
// generated by codegen
|
||||
|
||||
mod top;
|
||||
pub use top::*;
|
||||
@@ -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
8
rust/src/path.rs
Normal 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
36
rust/src/translate.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
103
rust/src/trap.rs
103
rust/src/trap.rs
@@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user