Rust: reuse shared rust trap library

This commit is contained in:
Paolo Tranquilli 2024-08-30 16:08:37 +02:00
Родитель 4f0fe1ce3a
Коммит 7e1290aa74
19 изменённых файлов: 677 добавлений и 216 удалений

Просмотреть файл

@ -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",
],
)

418
rust/extractor/Cargo.lock сгенерированный
Просмотреть файл

@ -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 {