зеркало из https://github.com/github/codeql.git
Rust: reuse shared rust trap library
This commit is contained in:
Родитель
4f0fe1ce3a
Коммит
7e1290aa74
|
@ -45,7 +45,7 @@ repos:
|
|||
|
||||
- id: sync-files
|
||||
name: Fix files required to be identical
|
||||
files: \.(qll?|qhelp|swift)$|^config/identical-files\.json$
|
||||
files: \.(qll?|qhelp|swift|toml)$|^config/identical-files\.json$
|
||||
language: system
|
||||
entry: python3 config/sync-files.py --latest
|
||||
pass_filenames: false
|
||||
|
|
|
@ -358,6 +358,7 @@
|
|||
],
|
||||
"shared tree-sitter extractor cargo.toml": [
|
||||
"shared/tree-sitter-extractor/Cargo.toml",
|
||||
"ruby/extractor/codeql-extractor-fake-crate/Cargo.toml"
|
||||
"ruby/extractor/codeql-extractor-fake-crate/Cargo.toml",
|
||||
"rust/extractor/codeql-extractor-fake-crate/Cargo.toml"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -13,14 +13,16 @@ from misc.codegen.loaders import schemaloader
|
|||
|
||||
def _get_type(t: str) -> str:
|
||||
match t:
|
||||
case None | "boolean": # None means a predicate
|
||||
case None: # None means a predicate
|
||||
return "bool"
|
||||
case "string":
|
||||
return "String"
|
||||
case "int":
|
||||
return "i32"
|
||||
return "usize"
|
||||
case _ if t[0].isupper():
|
||||
return "TrapLabel"
|
||||
return "trap::Label"
|
||||
case "boolean":
|
||||
assert False, "boolean unsupported"
|
||||
case _:
|
||||
return t
|
||||
|
||||
|
|
|
@ -58,10 +58,6 @@ keywords = {
|
|||
}
|
||||
|
||||
_field_overrides = [
|
||||
(
|
||||
re.compile(r"(start|end)_(line|column)|(.*_)?index|width|num_.*"),
|
||||
{"base_type": "u32"},
|
||||
),
|
||||
(re.compile(r"(.*)_"), lambda m: {"field_name": m[1]}),
|
||||
]
|
||||
|
||||
|
@ -98,20 +94,13 @@ class Field:
|
|||
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"
|
||||
return self.base_type == "trap::Label"
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// generated by {{generator}}
|
||||
|
||||
use crate::trap::{TrapLabel, TrapId, TrapEntry, quoted};
|
||||
use std::io::Write;
|
||||
use crate::trap::{TrapId, TrapEntry};
|
||||
use codeql_extractor::trap;
|
||||
{{#classes}}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -17,37 +17,36 @@ impl TrapEntry for {{name}} {
|
|||
std::mem::replace(&mut self.id, TrapId::Star)
|
||||
}
|
||||
|
||||
fn emit<W: Write>(self, id: TrapLabel, out: &mut W) -> std::io::Result<()> {
|
||||
fn emit(self, id: trap::Label, out: &mut trap::Writer) {
|
||||
{{#single_field_entries}}
|
||||
write!(out, "{{table_name}}({id}{{#fields}}, {}{{/fields}})\n"{{#fields}}, {{#emitter}}self.{{field_name}}{{/emitter}}{{/fields}})?;
|
||||
out.add_tuple("{{table_name}}", vec![trap::Arg::Label(id){{#fields}}, self.{{field_name}}.into(){{/fields}}]);
|
||||
{{/single_field_entries}}
|
||||
{{#fields}}
|
||||
{{#is_predicate}}
|
||||
if self.{{field_name}} {
|
||||
write!(out, "{{table_name}}({id})\n")?;
|
||||
out.add_tuple("{{table_name}}", vec![trap::Arg::Label(id)]);
|
||||
}
|
||||
{{/is_predicate}}
|
||||
{{#is_optional}}
|
||||
{{^is_repeated}}
|
||||
if let Some(ref v) = &self.{{field_name}} {
|
||||
write!(out, "{{table_name}}({id}, {})\n", {{#emitter}}v{{/emitter}})?;
|
||||
if let Some(v) = self.{{field_name}} {
|
||||
out.add_tuple("{{table_name}}", vec![trap::Arg::Label(id), v.into()]);
|
||||
}
|
||||
{{/is_repeated}}
|
||||
{{/is_optional}}
|
||||
{{#is_repeated}}
|
||||
for (i, &ref v) in self.{{field_name}}.iter().enumerate() {
|
||||
for (i, &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}})?;
|
||||
out.add_tuple("{{table_name}}", vec![trap::Arg::Label(id){{^is_unordered}}, i.into(){{/is_unordered}}, v.into()]);
|
||||
{{/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}})?;
|
||||
if let Some(vv) = v {
|
||||
out.add_tuple("{{table_name}}", vec![trap::Arg::Label(id){{^is_unordered}}, i.into(){{/is_unordered}}, v.into()]);
|
||||
}
|
||||
{{/is_optional}}
|
||||
}
|
||||
{{/is_repeated}}
|
||||
{{/fields}}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
{{/classes}}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
paths = ["../../shared/tree-sitter-extractor"]
|
|
@ -11,5 +11,7 @@ codeql_rust_binary(
|
|||
visibility = ["//rust:__subpackages__"],
|
||||
deps = all_crate_deps(
|
||||
normal = True,
|
||||
),
|
||||
) + [
|
||||
"//shared/tree-sitter-extractor:codeql-extractor",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -2,6 +2,21 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "always-assert"
|
||||
version = "0.2.0"
|
||||
|
@ -120,6 +135,16 @@ version = "2.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.16.0"
|
||||
|
@ -132,6 +157,12 @@ version = "1.17.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "camino"
|
||||
version = "1.1.9"
|
||||
|
@ -285,12 +316,35 @@ version = "0.7.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
|
||||
|
||||
[[package]]
|
||||
name = "codeql-extractor"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"encoding",
|
||||
"flate2",
|
||||
"globset",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
"rand",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"tree-sitter",
|
||||
"tree-sitter-json",
|
||||
"tree-sitter-ql",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codeql-rust"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"codeql-extractor",
|
||||
"figment",
|
||||
"log",
|
||||
"num-traits",
|
||||
|
@ -332,6 +386,15 @@ version = "2.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0570650661aa447e7335f1d5e4f499d8e58796e617bedc9267d971e51c8b49d4"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.13"
|
||||
|
@ -445,6 +508,70 @@ dependencies = [
|
|||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding"
|
||||
version = "0.2.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
|
||||
dependencies = [
|
||||
"encoding-index-japanese",
|
||||
"encoding-index-korean",
|
||||
"encoding-index-simpchinese",
|
||||
"encoding-index-singlebyte",
|
||||
"encoding-index-tradchinese",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-japanese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
|
||||
dependencies = [
|
||||
"encoding_index_tests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-korean"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
|
||||
dependencies = [
|
||||
"encoding_index_tests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-simpchinese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
|
||||
dependencies = [
|
||||
"encoding_index_tests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-singlebyte"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
|
||||
dependencies = [
|
||||
"encoding_index_tests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-tradchinese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
|
||||
dependencies = [
|
||||
"encoding_index_tests",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_index_tests"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
|
@ -482,6 +609,16 @@ version = "0.4.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -503,6 +640,30 @@ version = "0.4.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"bstr",
|
||||
"log",
|
||||
"regex-automata 0.4.7",
|
||||
"regex-syntax 0.8.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
|
@ -527,6 +688,12 @@ version = "0.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.4.0"
|
||||
|
@ -631,7 +798,7 @@ version = "0.4.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"hermit-abi 0.4.0",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
@ -698,6 +865,12 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3752f229dcc5a481d60f385fa479ff46818033d881d2d801aa27dffcfb5e8306"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.158"
|
||||
|
@ -747,6 +920,15 @@ version = "0.11.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||
dependencies = [
|
||||
"regex-automata 0.1.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
|
@ -762,6 +944,15 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.11"
|
||||
|
@ -808,6 +999,16 @@ dependencies = [
|
|||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||
dependencies = [
|
||||
"overload",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
|
@ -823,6 +1024,16 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.9",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
|
@ -835,6 +1046,12 @@ version = "11.1.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.3"
|
||||
|
@ -922,6 +1139,15 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
|
@ -1515,6 +1741,36 @@ dependencies = [
|
|||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
|
@ -1544,6 +1800,50 @@ dependencies = [
|
|||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata 0.4.7",
|
||||
"regex-syntax 0.8.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||
dependencies = [
|
||||
"regex-syntax 0.6.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax 0.8.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
|
||||
[[package]]
|
||||
name = "rowan"
|
||||
version = "0.15.15"
|
||||
|
@ -1670,6 +1970,15 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
|
@ -1849,6 +2158,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
|
||||
dependencies = [
|
||||
"matchers",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df7cc499ceadd4dcdf7ec6d4cbc34ece92c3fa07821e287aedecd4416c516dca"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-json"
|
||||
version = "0.21.0"
|
||||
source = "git+https://github.com/tree-sitter/tree-sitter-json#bdd69eb8c8a58a9f54df03de0488d9990179be46"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-ql"
|
||||
version = "0.22.5"
|
||||
source = "git+https://github.com/tree-sitter/tree-sitter-ql#42becd6f8f7bae82c818fa3abb1b6ff34b552310"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1900,6 +2267,12 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
|
@ -1977,6 +2350,22 @@ version = "0.2.93"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.9"
|
||||
|
@ -1986,6 +2375,12 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
|
@ -2148,3 +2543,24 @@ name = "yansi"
|
|||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
[workspace]
|
||||
|
||||
[package]
|
||||
name = "codeql-rust"
|
||||
version = "0.1.0"
|
||||
|
@ -21,6 +23,10 @@ serde = "1.0.209"
|
|||
serde_with = "3.9.0"
|
||||
stderrlog = "0.6.0"
|
||||
triomphe = "0.1.13"
|
||||
# Ideally, we'd like to pull this in via a relative path.
|
||||
# However, our bazel/rust tooling chokes on this, c.f. https://github.com/bazelbuild/rules_rust/issues/1525
|
||||
# Therefore, we have a pretty bad hack in place instead, see README.md in the codeql-extractor-fake-crate directory.
|
||||
codeql-extractor = { path = "codeql-extractor-fake-crate" }
|
||||
|
||||
[patch.crates-io]
|
||||
# patch for build script bug preventing bazel build
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
[package]
|
||||
name = "codeql-extractor"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
authors = ["GitHub"]
|
||||
|
||||
[dependencies]
|
||||
flate2 = "1.0"
|
||||
globset = "0.4"
|
||||
tree-sitter = ">= 0.22.6"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3.3", features = ["env-filter"] }
|
||||
rayon = "1.5.0"
|
||||
regex = "1.7.1"
|
||||
encoding = "0.2"
|
||||
lazy_static = "1.4.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
num_cpus = "1.14.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tree-sitter-ql = { git = "https://github.com/tree-sitter/tree-sitter-ql" }
|
||||
tree-sitter-json = {git = "https://github.com/tree-sitter/tree-sitter-json" }
|
||||
rand = "0.8.5"
|
||||
|
||||
[patch.crates-io]
|
||||
tree-sitter = {git = "https://github.com/redsun82/tree-sitter.git", rev = "1f5c1112ceaa8fc6aff61d1852690407670d2a96"}
|
|
@ -0,0 +1,7 @@
|
|||
We're presenting a fake crate in this workspace that ensures that the correct crate dependencies from the shared tree sitter
|
||||
extractor can be parsed by Bazel (which doesn't resolve path dependencies outside of the cargo workspace unfortunately).
|
||||
|
||||
The sync-identical-files script keeps this up-to-date.
|
||||
For local development and IDEs, we override the path to `codeql-extractor` using the `.cargo/config.toml` mechanism.
|
||||
Bazel doesn't actually do anything with path dependencies except to pull in their dependency tree, so we manually
|
||||
specify the dependency from the ruby extractor to the shared extractor in `BUILD.bazel`.
|
|
@ -1,9 +1,28 @@
|
|||
use std::path::PathBuf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Serialize, Serializer, Deserializer};
|
||||
use serde_with;
|
||||
use figment::{Figment, providers::{Env, Serialized}};
|
||||
use clap::{Parser, ArgAction};
|
||||
use clap::{Parser, ArgAction, ValueEnum};
|
||||
use clap::builder::PossibleValue;
|
||||
use codeql_extractor::trap;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Default, Serialize, Deserialize, Clone, Copy, ValueEnum)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[clap(rename_all = "lowercase")]
|
||||
pub enum Compression {
|
||||
#[default] // TODO make gzip default
|
||||
None,
|
||||
Gzip,
|
||||
}
|
||||
|
||||
impl Into<trap::Compression> for Compression {
|
||||
fn into(self) -> trap::Compression {
|
||||
match self {
|
||||
Compression::None => trap::Compression::None,
|
||||
Compression::Gzip => trap::Compression::Gzip,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_with::apply(_ => #[serde(default)])]
|
||||
#[derive(Debug, Deserialize, Default)]
|
||||
|
@ -12,6 +31,7 @@ pub struct Config {
|
|||
pub trap_dir: PathBuf,
|
||||
pub source_archive_dir: PathBuf,
|
||||
pub verbose: u8,
|
||||
pub compression: Compression,
|
||||
pub inputs: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
|
@ -25,6 +45,8 @@ struct CliArgs {
|
|||
trap_dir: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
source_archive_dir: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
compression: Option<Compression>,
|
||||
#[arg(short, long, action = ArgAction::Count)]
|
||||
pub verbose: u8,
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// generated by codegen
|
||||
|
||||
use crate::trap::{TrapLabel, TrapId, TrapEntry, quoted};
|
||||
use std::io::Write;
|
||||
use crate::trap::{TrapId, TrapEntry};
|
||||
use codeql_extractor::trap;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DbFile {
|
||||
|
@ -14,21 +14,20 @@ impl TrapEntry for DbFile {
|
|||
std::mem::replace(&mut self.id, TrapId::Star)
|
||||
}
|
||||
|
||||
fn emit<W: Write>(self, id: TrapLabel, out: &mut W) -> std::io::Result<()> {
|
||||
write!(out, "db_files({id})\n")?;
|
||||
write!(out, "files({id}, {})\n", quoted(&self.name))?;
|
||||
Ok(())
|
||||
fn emit(self, id: trap::Label, out: &mut trap::Writer) {
|
||||
out.add_tuple("db_files", vec![trap::Arg::Label(id)]);
|
||||
out.add_tuple("files", vec![trap::Arg::Label(id), self.name.into()]);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DbLocation {
|
||||
pub id: TrapId,
|
||||
pub file: TrapLabel,
|
||||
pub start_line: u32,
|
||||
pub start_column: u32,
|
||||
pub end_line: u32,
|
||||
pub end_column: u32,
|
||||
pub file: trap::Label,
|
||||
pub start_line: usize,
|
||||
pub start_column: usize,
|
||||
pub end_line: usize,
|
||||
pub end_column: usize,
|
||||
}
|
||||
|
||||
impl TrapEntry for DbLocation {
|
||||
|
@ -36,17 +35,16 @@ impl TrapEntry for DbLocation {
|
|||
std::mem::replace(&mut self.id, TrapId::Star)
|
||||
}
|
||||
|
||||
fn emit<W: Write>(self, id: TrapLabel, out: &mut W) -> std::io::Result<()> {
|
||||
write!(out, "db_locations({id})\n")?;
|
||||
write!(out, "locations({id}, {}, {}, {}, {}, {})\n", self.file, self.start_line, self.start_column, self.end_line, self.end_column)?;
|
||||
Ok(())
|
||||
fn emit(self, id: trap::Label, out: &mut trap::Writer) {
|
||||
out.add_tuple("db_locations", vec![trap::Arg::Label(id)]);
|
||||
out.add_tuple("locations", vec![trap::Arg::Label(id), self.file.into(), self.start_line.into(), self.start_column.into(), self.end_line.into(), self.end_column.into()]);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Function {
|
||||
pub id: TrapId,
|
||||
pub location: Option<TrapLabel>,
|
||||
pub location: Option<trap::Label>,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
|
@ -55,20 +53,19 @@ impl TrapEntry for Function {
|
|||
std::mem::replace(&mut self.id, TrapId::Star)
|
||||
}
|
||||
|
||||
fn emit<W: Write>(self, id: TrapLabel, out: &mut W) -> std::io::Result<()> {
|
||||
write!(out, "functions({id}, {})\n", quoted(&self.name))?;
|
||||
if let Some(ref v) = &self.location {
|
||||
write!(out, "locatable_locations({id}, {})\n", v)?;
|
||||
fn emit(self, id: trap::Label, out: &mut trap::Writer) {
|
||||
out.add_tuple("functions", vec![trap::Arg::Label(id), self.name.into()]);
|
||||
if let Some(v) = self.location {
|
||||
out.add_tuple("locatable_locations", vec![trap::Arg::Label(id), v.into()]);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Module {
|
||||
pub id: TrapId,
|
||||
pub location: Option<TrapLabel>,
|
||||
pub declarations: Vec<TrapLabel>,
|
||||
pub location: Option<trap::Label>,
|
||||
pub declarations: Vec<trap::Label>,
|
||||
}
|
||||
|
||||
impl TrapEntry for Module {
|
||||
|
@ -76,14 +73,13 @@ impl TrapEntry for Module {
|
|||
std::mem::replace(&mut self.id, TrapId::Star)
|
||||
}
|
||||
|
||||
fn emit<W: Write>(self, id: TrapLabel, out: &mut W) -> std::io::Result<()> {
|
||||
write!(out, "modules({id})\n")?;
|
||||
if let Some(ref v) = &self.location {
|
||||
write!(out, "locatable_locations({id}, {})\n", v)?;
|
||||
fn emit(self, id: trap::Label, out: &mut trap::Writer) {
|
||||
out.add_tuple("modules", vec![trap::Arg::Label(id)]);
|
||||
if let Some(v) = self.location {
|
||||
out.add_tuple("locatable_locations", vec![trap::Arg::Label(id), v.into()]);
|
||||
}
|
||||
for (i, &ref v) in self.declarations.iter().enumerate() {
|
||||
write!(out, "module_declarations({id}, {}, {})\n", i, v)?;
|
||||
for (i, &v) in self.declarations.iter().enumerate() {
|
||||
out.add_tuple("module_declarations", vec![trap::Arg::Label(id), i.into(), v.into()]);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,21 +35,14 @@ fn main() -> anyhow::Result<()> {
|
|||
prefill_caches: false,
|
||||
};
|
||||
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 { id: name.clone().into(), name })?;
|
||||
archiver.archive(&path);
|
||||
}
|
||||
load_workspace_at(&path, &config, &load_config, &no_progress)?;
|
||||
let (db, vfs, _macro_server) = load_workspace_at(&path, &config, &load_config, &no_progress)?;
|
||||
load_workspace_at(&input, &config, &load_config, &no_progress)?;
|
||||
let (db, vfs, _macro_server) = load_workspace_at(&input, &config, &load_config, &no_progress)?;
|
||||
let crates = <dyn DefDatabase>::crate_graph(&db);
|
||||
for crate_id in crates.iter().take(1) {
|
||||
let krate = Crate::from(crate_id);
|
||||
let name = krate.display_name(&db);
|
||||
let crate_name = name.as_ref().map(|n| n.canonical_name().as_str()).unwrap_or("");
|
||||
let trap = traps.create("crates", &PathBuf::from(format!("/{}_{}", crate_name, crate_id.into_raw().into_u32())))?;
|
||||
let trap = traps.create("crates", &PathBuf::from(format!("/{}_{}", crate_name, crate_id.into_raw().into_u32())));
|
||||
translate::CrateTranslator::new(
|
||||
&db,
|
||||
trap,
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::{PathBuf};
|
||||
use crate::trap::{TrapFile, TrapId, TrapLabel};
|
||||
use crate::trap::{TrapFile, TrapId, AsTrapKeyPart};
|
||||
use crate::{generated, trap_key};
|
||||
use ra_ap_hir::{Crate, Module, ModuleDef};
|
||||
use anyhow;
|
||||
use ra_ap_base_db::{CrateId};
|
||||
use ra_ap_hir::{HasSource};
|
||||
use ra_ap_vfs::{AbsPath, FileId, Vfs};
|
||||
use ra_ap_syntax::ast::HasName;
|
||||
|
@ -15,10 +14,11 @@ use triomphe::Arc;
|
|||
use ra_ap_ide_db::{LineIndexDatabase, RootDatabase};
|
||||
use ra_ap_ide_db::line_index::LineIndex;
|
||||
use ra_ap_syntax::AstNode;
|
||||
use codeql_extractor::trap;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct FileData {
|
||||
label: TrapLabel,
|
||||
label: trap::Label,
|
||||
line_index: Arc<LineIndex>,
|
||||
}
|
||||
pub struct CrateTranslator<'a> {
|
||||
|
@ -49,55 +49,47 @@ impl CrateTranslator<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn emit_file(&mut self, file_id: FileId) -> Result<Option<FileData>> {
|
||||
if let Some(abs_path) = self.vfs.file_path(file_id).as_path() {
|
||||
fn emit_file(&mut self, file_id: FileId) -> Option<FileData> {
|
||||
self.vfs.file_path(file_id).as_path().and_then(|abs_path| {
|
||||
let mut canonical = PathBuf::from(abs_path.as_str());
|
||||
if !self.file_labels.contains_key(&canonical) {
|
||||
self.archiver.archive(&canonical);
|
||||
canonical = fs::canonicalize(&canonical).unwrap_or(canonical);
|
||||
let name = canonical.to_string_lossy();
|
||||
let label = self.trap.emit(generated::DbFile { id: trap_key!["DbFile@", name.as_ref()], name: String::from(name) })?;
|
||||
let label = self.trap.emit(generated::DbFile { id: trap_key!["file;", name.as_ref()], name: String::from(name) });
|
||||
let line_index = <dyn LineIndexDatabase>::line_index(self.db, file_id);
|
||||
self.file_labels.insert(canonical.clone(), FileData { label, line_index });
|
||||
}
|
||||
Ok(self.file_labels.get(&canonical).cloned())
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
self.file_labels.get(&canonical).cloned()
|
||||
})
|
||||
}
|
||||
|
||||
fn emit_location<T: HasSource>(&mut self, entity: T) -> Result<Option<TrapLabel>> where T::Ast: AstNode {
|
||||
if let Some(source) = entity.source(self.db) {
|
||||
if let Some(file_id) = source.file_id.file_id().map(|f| f.file_id()) {
|
||||
if let Some(data) = self.emit_file(file_id)? {
|
||||
let range = source.value.syntax().text_range();
|
||||
let start = data.line_index.line_col(range.start());
|
||||
let end = data.line_index.line_col(range.end());
|
||||
return Ok(Some(self.trap.emit(generated::DbLocation {
|
||||
id: trap_key![data.label, ":", start.line, ":", start.col, ":", end.line, ":", end.col],
|
||||
file: data.label,
|
||||
start_line: start.line,
|
||||
start_column: start.col,
|
||||
end_line: end.line,
|
||||
end_column: end.col,
|
||||
})?));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
fn emit_location<T: HasSource>(&mut self, entity: T) -> Option<trap::Label>
|
||||
where
|
||||
T::Ast: AstNode,
|
||||
{
|
||||
entity.source(self.db)
|
||||
.and_then(|source| source.file_id.file_id().map(|f| (f.file_id(), source)))
|
||||
.and_then(|(file_id, source)| self.emit_file(file_id).map(|data| (data, source)))
|
||||
.and_then(|(data, source)| {
|
||||
let range = source.value.syntax().text_range();
|
||||
let start = data.line_index.line_col(range.start());
|
||||
let end = data.line_index.line_col(range.end());
|
||||
Some(self.trap.emit_location(data.label, start, end))
|
||||
})
|
||||
}
|
||||
|
||||
fn emit_definition(&mut self, module_label: TrapLabel, id: ModuleDef, labels: &mut Vec<TrapLabel>) -> Result<()> {
|
||||
fn emit_definition(&mut self, module_label: trap::Label, id: ModuleDef, labels: &mut Vec<trap::Label>) {
|
||||
match id {
|
||||
ModuleDef::Module(_) => {}
|
||||
ModuleDef::Function(function) => {
|
||||
let name = function.name(self.db);
|
||||
let location = self.emit_location(function)?;
|
||||
let location = self.emit_location(function);
|
||||
labels.push(self.trap.emit(generated::Function {
|
||||
id: trap_key![module_label, name.as_str()],
|
||||
location,
|
||||
name: name.as_str().into(),
|
||||
})?);
|
||||
}));
|
||||
}
|
||||
ModuleDef::Adt(_) => {}
|
||||
ModuleDef::Variant(_) => {}
|
||||
|
@ -109,25 +101,23 @@ impl CrateTranslator<'_> {
|
|||
ModuleDef::BuiltinType(_) => {}
|
||||
ModuleDef::Macro(_) => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_module(&mut self, label: TrapLabel, module: Module) -> Result<()> {
|
||||
fn emit_module(&mut self, label: trap::Label, module: Module) {
|
||||
let mut children = Vec::new();
|
||||
for id in module.declarations(self.db) {
|
||||
self.emit_definition(label, id, &mut children)?;
|
||||
self.emit_definition(label, id, &mut children);
|
||||
}
|
||||
self.trap.emit(generated::Module {
|
||||
id: label.into(),
|
||||
location: None,
|
||||
declarations: children,
|
||||
})?;
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
pub fn emit_crate(&mut self) -> Result<()> {
|
||||
self.emit_file(self.krate.root_file(self.db))?;
|
||||
let mut map = HashMap::<Module, TrapLabel>::new();
|
||||
pub fn emit_crate(&mut self) -> std::io::Result<()> {
|
||||
self.emit_file(self.krate.root_file(self.db));
|
||||
let mut map = HashMap::<Module, trap::Label>::new();
|
||||
for module in self.krate.modules(self.db) {
|
||||
let mut key = String::new();
|
||||
if let Some(parent) = module.parent(self.db) {
|
||||
|
@ -137,17 +127,17 @@ impl CrateTranslator<'_> {
|
|||
}
|
||||
let def = module.definition_source(self.db);
|
||||
if let Some(file) = def.file_id.file_id() {
|
||||
if let Some(data) = self.emit_file(file.file_id())? {
|
||||
if let Some(data) = self.emit_file(file.file_id()) {
|
||||
key.push_str(&data.label.as_key_part());
|
||||
}
|
||||
}
|
||||
if let Some(name) = module.name(self.db) {
|
||||
key.push_str(name.as_str());
|
||||
}
|
||||
let label = self.trap.label(TrapId::Key(key))?;
|
||||
let label = self.trap.label(TrapId::Key(key));
|
||||
map.insert(module, label);
|
||||
self.emit_module(label, module)?;
|
||||
self.emit_module(label, module);
|
||||
}
|
||||
Ok(())
|
||||
self.trap.commit()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,35 +5,39 @@ use std::io::Write;
|
|||
use std::path::{Path, PathBuf};
|
||||
use log::{debug, trace};
|
||||
use crate::{config, path};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct TrapLabel(u64);
|
||||
|
||||
impl Debug for TrapLabel {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "TrapLabel({:x})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for TrapLabel {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "#{:x}", self.0)
|
||||
}
|
||||
}
|
||||
use codeql_extractor::trap;
|
||||
use ra_ap_ide_db::line_index::LineCol;
|
||||
use crate::config::Compression;
|
||||
use crate::generated;
|
||||
|
||||
//TODO: typed labels
|
||||
pub trait AsTrapKeyPart {
|
||||
fn as_key_part(&self) -> String;
|
||||
}
|
||||
|
||||
impl TrapLabel {
|
||||
pub fn as_key_part(&self) -> String {
|
||||
impl AsTrapKeyPart for trap::Label {
|
||||
fn as_key_part(&self) -> String {
|
||||
format!("{{{}}}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsTrapKeyPart for String {
|
||||
fn as_key_part(&self) -> String {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsTrapKeyPart for &str {
|
||||
fn as_key_part(&self) -> String {
|
||||
String::from(*self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TrapId {
|
||||
Star,
|
||||
Key(String),
|
||||
Label(TrapLabel),
|
||||
Label(trap::Label),
|
||||
}
|
||||
|
||||
impl From<String> for TrapId {
|
||||
|
@ -48,8 +52,8 @@ impl From<&str> for TrapId {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<TrapLabel> for TrapId {
|
||||
fn from(value: TrapLabel) -> Self {
|
||||
impl From<trap::Label> for TrapId {
|
||||
fn from(value: trap::Label) -> Self {
|
||||
TrapId::Label(value)
|
||||
}
|
||||
}
|
||||
|
@ -57,12 +61,6 @@ impl From<TrapLabel> for TrapId {
|
|||
#[macro_export]
|
||||
macro_rules! trap_key {
|
||||
($($x:expr),+ $(,)?) => {{
|
||||
trait BlanketKeyPart: std::fmt::Display {
|
||||
fn as_key_part(&self) -> String {
|
||||
format!("{}", self)
|
||||
}
|
||||
}
|
||||
impl<T: std::fmt::Display> BlanketKeyPart for T {}
|
||||
let mut key = String::new();
|
||||
$(
|
||||
key.push_str(&$x.as_key_part());
|
||||
|
@ -71,80 +69,63 @@ macro_rules! trap_key {
|
|||
}};
|
||||
}
|
||||
|
||||
impl Display for TrapId {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
TrapId::Star => write!(f, "*"),
|
||||
TrapId::Key(k) => write!(f, "@{}", quoted(k)),
|
||||
TrapId::Label(l) => Display::fmt(&l, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn escaped(s: &str) -> String {
|
||||
s.replace("\"", "\"\"")
|
||||
}
|
||||
|
||||
pub fn quoted(s: &str) -> String {
|
||||
format!("\"{}\"", escaped(s))
|
||||
}
|
||||
|
||||
|
||||
pub trait TrapEntry: std::fmt::Debug {
|
||||
fn extract_id(&mut self) -> TrapId;
|
||||
fn emit<W: Write>(self, id: TrapLabel, out: &mut W) -> std::io::Result<()>;
|
||||
fn emit(self, id: trap::Label, out: &mut trap::Writer);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TrapFile {
|
||||
label_index: u64,
|
||||
file: File,
|
||||
trap_name: String,
|
||||
path: PathBuf,
|
||||
writer: trap::Writer,
|
||||
compression: Compression,
|
||||
}
|
||||
|
||||
impl TrapFile {
|
||||
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 label(&mut self, mut id: TrapId) -> std::io::Result<TrapLabel> {
|
||||
match id {
|
||||
TrapId::Star => {}
|
||||
TrapId::Key(ref s) => {
|
||||
if s.is_empty() {
|
||||
id = TrapId::Star;
|
||||
}
|
||||
}
|
||||
TrapId::Label(l) => {
|
||||
return Ok(l);
|
||||
}
|
||||
}
|
||||
let ret = self.create_label();
|
||||
trace!("emit -> {}: {ret:?} = {id:?}", self.trap_name);
|
||||
write!(self.file, "{ret}={id}\n")?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn emit<T: TrapEntry>(&mut self, mut entry: T) -> std::io::Result<TrapLabel> {
|
||||
trace!("emit -> {}: {entry:?}", self.trap_name);
|
||||
let id = self.label(entry.extract_id())?;
|
||||
entry.emit(id, &mut self.file)?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
fn create_label(&mut self) -> TrapLabel {
|
||||
let ret = TrapLabel(self.label_index);
|
||||
self.label_index += 1;
|
||||
pub fn emit_location(&mut self, file_label: trap::Label, start: LineCol, end: LineCol) -> trap::Label {
|
||||
let start_line = start.line as usize;
|
||||
let start_column = start.col as usize;
|
||||
let end_line = end.line as usize;
|
||||
let end_column = end.col as usize;
|
||||
let (ret, _) = self.writer.location_label(trap::Location {
|
||||
start_line,
|
||||
start_column,
|
||||
end_line,
|
||||
end_column,
|
||||
});
|
||||
self.emit(generated::DbLocation {
|
||||
id: ret.into(),
|
||||
file: file_label,
|
||||
start_line,
|
||||
start_column,
|
||||
end_line,
|
||||
end_column,
|
||||
});
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn label(&mut self, id: TrapId) -> trap::Label {
|
||||
match id {
|
||||
TrapId::Star => self.writer.fresh_id(),
|
||||
TrapId::Key(s) => self.writer.global_id(&s).0,
|
||||
TrapId::Label(l) => l,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit<T: TrapEntry>(&mut self, mut e: T) -> trap::Label {
|
||||
let label = self.label(e.extract_id());
|
||||
e.emit(label, &mut self.writer);
|
||||
label
|
||||
}
|
||||
|
||||
pub fn commit(&self) -> std::io::Result<()> {
|
||||
std::fs::create_dir_all(self.path.parent().unwrap())?;
|
||||
self.writer.write_to_file(&self.path, self.compression.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TrapFileProvider {
|
||||
trap_dir: PathBuf,
|
||||
compression: Compression,
|
||||
}
|
||||
|
||||
impl TrapFileProvider {
|
||||
|
@ -152,27 +133,25 @@ impl TrapFileProvider {
|
|||
let trap_dir = cfg.trap_dir.clone();
|
||||
std::fs::create_dir_all(&trap_dir)?;
|
||||
Ok(TrapFileProvider {
|
||||
trap_dir
|
||||
trap_dir,
|
||||
compression: cfg.compression,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create(&self, category: &str, key: &Path) -> std::io::Result<TrapFile> {
|
||||
pub fn create(&self, category: &str, key: &Path) -> TrapFile {
|
||||
let mut path = PathBuf::from(category);
|
||||
path.push(path::key(key));
|
||||
path.set_extension(path.extension().map(|e| {
|
||||
let mut o : OsString = e.to_owned();
|
||||
let mut o: OsString = e.to_owned();
|
||||
o.push(".trap");
|
||||
o
|
||||
}).unwrap_or("trap".into()));
|
||||
let trap_name = String::from(path.to_string_lossy());
|
||||
debug!("creating trap file {}", trap_name);
|
||||
debug!("creating trap file {}", path.display());
|
||||
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,
|
||||
})
|
||||
TrapFile {
|
||||
path,
|
||||
writer: trap::Writer::new(),
|
||||
compression: self.compression,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,10 +136,16 @@ impl fmt::Display for Entry {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Copy, Clone)]
|
||||
// Identifiers of the form #0, #1...
|
||||
pub struct Label(u32);
|
||||
|
||||
impl fmt::Debug for Label {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Label({:#x})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Label {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "#{:x}", self.0)
|
||||
|
@ -170,6 +176,30 @@ impl fmt::Display for Arg {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<String> for Arg {
|
||||
fn from(value: String) -> Self {
|
||||
Arg::String(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Arg {
|
||||
fn from(value: &str) -> Self {
|
||||
Arg::String(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Label> for Arg {
|
||||
fn from(value: Label) -> Self {
|
||||
Arg::Label(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Arg {
|
||||
fn from(value: usize) -> Self {
|
||||
Arg::Int(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Program(Vec<Entry>);
|
||||
|
||||
impl fmt::Display for Program {
|
||||
|
|
Загрузка…
Ссылка в новой задаче