Rust: some basic extraction of function names (with locations!)

This commit is contained in:
Paolo Tranquilli
2024-08-29 17:03:19 +02:00
parent f40901f391
commit 590a146b49
54 changed files with 1867 additions and 1007 deletions

View File

@@ -5,9 +5,9 @@ repos:
rev: v3.2.0
hooks:
- id: trailing-whitespace
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)|.*\.patch
exclude: /test/.*$(?<!\.qlref)|.*\.patch$|.*\.qll?$
- id: end-of-file-fixer
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)|.*\.patch
exclude: /test/.*$(?<!\.qlref)|.*\.patch$|.*\.qll?$
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v17.0.6

View File

@@ -60,7 +60,7 @@ keywords = {
_field_overrides = [
(
re.compile(r"(start|end)_(line|column)|(.*_)?index|width|num_.*"),
{"base_type": "usize"},
{"base_type": "u32"},
),
(re.compile(r"(.*)_"), lambda m: {"field_name": m[1]}),
]

View File

@@ -1,25 +1,23 @@
// generated by {{generator}}
use crate::trap::{TrapLabel, TrapEntry, quoted};
use crate::trap::{TrapLabel, TrapId, TrapEntry, quoted};
use std::io::Write;
{{#classes}}
#[derive(Debug)]
pub struct {{name}} {
pub key: Option<String>,
pub id: TrapId,
{{#fields}}
pub {{field_name}}: {{type}},
{{/fields}}
}
impl TrapEntry for {{name}} {
type Label = TrapLabel;
fn extract_id(&mut self) -> TrapId {
std::mem::replace(&mut self.id, TrapId::Star)
}
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<()> {
fn emit<W: Write>(self, id: TrapLabel, 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}}
@@ -50,5 +48,4 @@ impl TrapEntry for {{name}} {
Ok(())
}
}
{{/classes}}

View File

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

35
rust/.generated.list generated Normal file
View File

@@ -0,0 +1,35 @@
ql/lib/codeql/rust/elements/DbFile.qll 056d363e1ba5ec08cacb2e90b8a7a3b47f52ded5dc2289edd4e85921fc50f37e 18e6926f77265a3a6319ca2f3bf3d529d17d46cebdd2ef6753357fdc53c22c70
ql/lib/codeql/rust/elements/DbFileConstructor.qll ea93dc49b23b1c6d800ab9d0b9cacfa9dc661bfdb04b9e6efcad2bdb050fb0ab f7a891b1786604eee57a784733555b677e2580770d51d18073b59e7ca65df1d4
ql/lib/codeql/rust/elements/DbLocation.qll 1f694594e8e4ab65a8781cd443ad4f864447ca88e2cb65504aee5a779393c84d 003ec72275406eb8f5ddd6ccc2b258fb7c906d4bb2c0ef1ba235f291624321ca
ql/lib/codeql/rust/elements/DbLocationConstructor.qll 8848abace985818a5d3a6eddfc4cb200795970146d282b037b4f22ae6230b894 44dba880e17bb1072fa12451ccaae4830fd04dcc61f7403d35510309fde6906e
ql/lib/codeql/rust/elements/Declaration.qll d4ec5c83728f1837243caf2f27d06fd05ecdd2ca440112accff99bfd37b45e5f c1cd9b297be8b69207e75d24b29949b9f71c78406ee0ffd38d0b0810288d6140
ql/lib/codeql/rust/elements/Element.qll 2bffdeb8863a9853d019e56afa268b3d39fb3687785ad636b159656c199997ca 18020582c7d1b89f4073b6deaf793c3072fdc52503a6cc53172c96282f141de4
ql/lib/codeql/rust/elements/File.qll 75144234638417347107b75db80c561379e6372859ebc463276aef716e0ed42b 55bb468873acf24e6828faf7be3ff8963c9a4eb344bfedd95328a51b6f00a226
ql/lib/codeql/rust/elements/Function.qll 220eb1d0e6b49e83b7674a9f505d3f529cf7f4d022ddca44fa6367e0d75daa0f d156cff59ecdcffc0d62041b801025b1aaedbc92d44efd107f93f6fd06c34a6d
ql/lib/codeql/rust/elements/FunctionConstructor.qll a9269b37182c0bf432f9b2b015691da5dbd64819b9bd25445af229d873014a91 69107a7503af14a51e091e6918094a4e9fc316a72de2e1514f001872ce0f2c0c
ql/lib/codeql/rust/elements/Locatable.qll dfc0235cf5aff0ec91d85375ac03998b0e6a69f3722b099330ab0a2161af988a bb1055f59ef7e95e89748765c79f1b5832aa18226f227e689a6801adfc6247ad
ql/lib/codeql/rust/elements/Location.qll 17a222ffe30ecfa252bfd2a5d6ef668f9579824b78d241d576c8c0112a9f93f0 9ae822cd9ce3c70824cccae500651f0cba70ad9c9195b611e7542cb928093b0b
ql/lib/codeql/rust/elements/Module.qll d8995b361cc672f86a314bd53bd3e4d1ddb26b6afde62eb7c380923810785af0 3c10180c812d89a8116ac6e32cbd4d7ac2f549c8a76d327ed75c764b09251d52
ql/lib/codeql/rust/elements/ModuleConstructor.qll 109ed8c1b5c61cc1d3e8613aa8bb8c168dc1943c93b5b622fa79665751b78318 601526c7f56578883d261d14653fdad08329f80fea71de14a5ac5ce671a8d436
ql/lib/codeql/rust/elements/UnknownFile.qll 638ac1c5baef4ab8eb98ef4a37202334290001ca183dab769f729b61f9fc0aa9 fae24f8b29c3e5a124e6c71c9bcb0e2bf4bb033eaf3348fd2db3644ce2803b43
ql/lib/codeql/rust/elements/UnknownLocation.qll eaadf1702e2f5df0c0917dd9e452a3ceb81e5c2d182675c32e988d826ac3fc71 9bf63fbd74c6114678189a62f63795156c0e5b9ad467c020f16842038e84a226
ql/lib/codeql/rust/elements.qll 658d3d26ac2685a077714d41d83ac47f87b0df1c4f0cc7d099c96e06bd1f9d0e 658d3d26ac2685a077714d41d83ac47f87b0df1c4f0cc7d099c96e06bd1f9d0e
ql/lib/codeql/rust/generated/DbFile.qll 4dbf1931124291e0d6a958ae882f8aeef006642f72adc7ff86cffd3a4e9a970a 4dbf1931124291e0d6a958ae882f8aeef006642f72adc7ff86cffd3a4e9a970a
ql/lib/codeql/rust/generated/DbLocation.qll 735d9351b5eb46a3231b528600dddec3a4122c18c210d4d632a8d4ceaf7f02e9 735d9351b5eb46a3231b528600dddec3a4122c18c210d4d632a8d4ceaf7f02e9
ql/lib/codeql/rust/generated/Declaration.qll 4487ac3f5ffa5b92e8628bc04b51e818d4ea1c9a333375cf1b729428d36a4ee7 6481d5e2d99a548f857213a283da75d45db8b3adac949e90fd5d17ceb5e22b54
ql/lib/codeql/rust/generated/Element.qll 21567fa7348dccdf69dd34e73cb6de7cc9c7e0f3f7bb419a1abd787f7dc851a1 21567fa7348dccdf69dd34e73cb6de7cc9c7e0f3f7bb419a1abd787f7dc851a1
ql/lib/codeql/rust/generated/File.qll 2eff5c882d044d2e360fe6382fb55e5a45f6ccb9df323cfa1fae41eae9d2a47f 87e7a906b3a1b4de056952e288ddd7f69fa7cb1bd9dc7dd3972868a9002ac1e4
ql/lib/codeql/rust/generated/Function.qll 6429619a284cadaf64d74ab408f57a399c7e5df2ad182bd38f77b580879d9e33 8c4cfa4f23b5ed461f0f8aa40c5833a953fc9ba3f99584f0f05cf7d7d6a9b617
ql/lib/codeql/rust/generated/Locatable.qll 9e9685bba50ad2220701f3465e63af9331f7f9dc548ad906ff954fc2ce0a4400 78c89b2cc78a357d682ab65310dd474603071f07c1eaaab07711714ce17549f2
ql/lib/codeql/rust/generated/Location.qll bce4c72988ec6fedd1439c60a37c45aa6147c962904709ef9f12206937174be4 d57000571771a2d997c50d9a43ef1c2f075960f847effa0e80ea91fd4c6b4d6c
ql/lib/codeql/rust/generated/Module.qll 2a931a4f2cdb2fee00ed83af045ea63d36b7dbd708e58c30445b5610feaae333 cd62add5c31a509f965aa294f44a1607ec7c62e3a9e3fe9ee063b3c814f4eb62
ql/lib/codeql/rust/generated/ParentChild.qll b44f149bff05a96ee16c88883f06d5d2c159a89423ec32b00765da6964af029e 1d13e54fbc27d9cc29405a21c2f4a63043cbb7aade317184f440a17d3f5645c4
ql/lib/codeql/rust/generated/PureSynthConstructors.qll 5eb1fc4f6a04172c34ae31e4931e4bf1f8b72fbe414c5f644731a45372d13573 5eb1fc4f6a04172c34ae31e4931e4bf1f8b72fbe414c5f644731a45372d13573
ql/lib/codeql/rust/generated/Raw.qll 921cb1afb5c1c3177acb557151755d4f97e7c65f656c5069d6f095b0e078074f a25fdad01e70bbab2d2663b152a4a5844677edcf0a0af2ec93c42dc3248ac9b2
ql/lib/codeql/rust/generated/Synth.qll d278de9c2d06cb7549cd8f2e10ed186827a2ceab6ff46725ca76e78e7fecac72 acacd9afc5ca4a288e037a43375d933c3ba3cd8d08ef122b31695e74be260eb2
ql/lib/codeql/rust/generated/SynthConstructors.qll 35b36df0c4fff05bcbd4ed10b1e6fa2e58fe8d8c818e7805111044825788fc01 35b36df0c4fff05bcbd4ed10b1e6fa2e58fe8d8c818e7805111044825788fc01
ql/lib/codeql/rust/generated/UnknownFile.qll ec9d1a3f15ecbf1743d4e39cb3b2f217aa9b54951c93302c2c4c238c3f0ce595 ec9d1a3f15ecbf1743d4e39cb3b2f217aa9b54951c93302c2c4c238c3f0ce595
ql/lib/codeql/rust/generated/UnknownLocation.qll a19e2838c52d702d268ae530f3dbd6fcd8bb28a237a52636a960f225454103cf a19e2838c52d702d268ae530f3dbd6fcd8bb28a237a52636a960f225454103cf
ql/test/extractor-tests/generated/File/MISSING_SOURCE.txt cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e
ql/test/extractor-tests/generated/Function/MISSING_SOURCE.txt cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e
ql/test/extractor-tests/generated/Module/MISSING_SOURCE.txt cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e

37
rust/.gitattributes generated vendored Normal file
View File

@@ -0,0 +1,37 @@
/.generated.list linguist-generated
/.gitattributes linguist-generated
/ql/lib/codeql/rust/elements/DbFile.qll linguist-generated
/ql/lib/codeql/rust/elements/DbFileConstructor.qll linguist-generated
/ql/lib/codeql/rust/elements/DbLocation.qll linguist-generated
/ql/lib/codeql/rust/elements/DbLocationConstructor.qll linguist-generated
/ql/lib/codeql/rust/elements/Declaration.qll linguist-generated
/ql/lib/codeql/rust/elements/Element.qll linguist-generated
/ql/lib/codeql/rust/elements/File.qll linguist-generated
/ql/lib/codeql/rust/elements/Function.qll linguist-generated
/ql/lib/codeql/rust/elements/FunctionConstructor.qll linguist-generated
/ql/lib/codeql/rust/elements/Locatable.qll linguist-generated
/ql/lib/codeql/rust/elements/Location.qll linguist-generated
/ql/lib/codeql/rust/elements/Module.qll linguist-generated
/ql/lib/codeql/rust/elements/ModuleConstructor.qll linguist-generated
/ql/lib/codeql/rust/elements/UnknownFile.qll linguist-generated
/ql/lib/codeql/rust/elements/UnknownLocation.qll linguist-generated
/ql/lib/codeql/rust/elements.qll linguist-generated
/ql/lib/codeql/rust/generated/DbFile.qll linguist-generated
/ql/lib/codeql/rust/generated/DbLocation.qll linguist-generated
/ql/lib/codeql/rust/generated/Declaration.qll linguist-generated
/ql/lib/codeql/rust/generated/Element.qll linguist-generated
/ql/lib/codeql/rust/generated/File.qll linguist-generated
/ql/lib/codeql/rust/generated/Function.qll linguist-generated
/ql/lib/codeql/rust/generated/Locatable.qll linguist-generated
/ql/lib/codeql/rust/generated/Location.qll linguist-generated
/ql/lib/codeql/rust/generated/Module.qll linguist-generated
/ql/lib/codeql/rust/generated/ParentChild.qll linguist-generated
/ql/lib/codeql/rust/generated/PureSynthConstructors.qll linguist-generated
/ql/lib/codeql/rust/generated/Raw.qll linguist-generated
/ql/lib/codeql/rust/generated/Synth.qll linguist-generated
/ql/lib/codeql/rust/generated/SynthConstructors.qll linguist-generated
/ql/lib/codeql/rust/generated/UnknownFile.qll linguist-generated
/ql/lib/codeql/rust/generated/UnknownLocation.qll linguist-generated
/ql/test/extractor-tests/generated/File/MISSING_SOURCE.txt linguist-generated
/ql/test/extractor-tests/generated/Function/MISSING_SOURCE.txt linguist-generated
/ql/test/extractor-tests/generated/Module/MISSING_SOURCE.txt linguist-generated

1075
rust/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,12 +9,15 @@ clap = { version = "4.5.16", features = ["derive"] }
figment = { version = "0.10.19", features = ["env"]}
log = "0.4.22"
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_base_db = "0.0.232"
ra_ap_hir = "0.0.232"
ra_ap_hir_def = "0.0.232"
ra_ap_ide_db = "0.0.232"
ra_ap_load-cargo = "0.0.229"
ra_ap_project_model = "0.0.229"
ra_ap_load-cargo = "0.0.232"
ra_ap_project_model = "0.0.232"
ra_ap_syntax = "0.0.232"
ra_ap_vfs = "0.0.232"
serde = "1.0.209"
serde_with = "3.9.0"
stderrlog = "0.6.0"
triomphe = "0.1.13"

9
rust/codegen.conf Normal file
View File

@@ -0,0 +1,9 @@
# configuration file for Swift code generation default options
--generate=dbscheme,ql,rust
--dbscheme=ql/lib/rust.dbscheme
--ql-output=ql/lib/codeql/rust/generated
--ql-stub-output=ql/lib/codeql/rust/elements
--ql-test-output=ql/test/extractor-tests/generated
--rust-output=src/generated
--generated-registry=.generated.list
--script-name=codegen

15
rust/codegen/BUILD.bazel Normal file
View File

@@ -0,0 +1,15 @@
load("@bazel_skylib//rules:native_binary.bzl", "native_binary")
native_binary(
name = "codegen",
src = "//misc/codegen",
out = "codegen",
args = [
"--configuration-file=$(location //rust:codegen.conf)",
],
data = [
"//rust:codegen.conf",
"//rust:schema.py",
],
visibility = ["//rust:__subpackages__"],
)

6
rust/codegen/README.md Normal file
View File

@@ -0,0 +1,6 @@
This package aliases [`misc/codegen`](../misc/codegen) providing the Rust-specific options
in [`rust/codegen.conf`](../codegen.conf).
Running `bazel run //rust/codegen` will generate all checked in
files ([dbscheme](../ql/lib/swift.dbscheme), [QL generated code](../ql/lib/codeql/swift/generated),
[generated QL stubs](../ql/lib/codeql/swift/elements), [generated QL tests](../ql/test/extractor-tests/generated)).

6
rust/prefix.dbscheme Normal file
View File

@@ -0,0 +1,6 @@
/**
* The source location of the snapshot.
*/
sourceLocationPrefix(
string prefix: string ref
);

16
rust/ql/lib/codeql/rust/elements.qll generated Normal file
View File

@@ -0,0 +1,16 @@
// generated by codegen
/**
* This module exports all modules providing `Element` subclasses.
*/
import codeql.rust.elements.DbFile
import codeql.rust.elements.DbLocation
import codeql.rust.elements.Declaration
import codeql.rust.elements.Element
import codeql.rust.elements.File
import codeql.rust.elements.Function
import codeql.rust.elements.Locatable
import codeql.rust.elements.Location
import codeql.rust.elements.Module
import codeql.rust.elements.UnknownFile
import codeql.rust.elements.UnknownLocation

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `DbFile`.
*/
private import codeql.rust.generated.DbFile
class DbFile extends Generated::DbFile { }

View File

@@ -0,0 +1,14 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module defines the hook used internally to tweak the characteristic predicate of
* `DbFile` synthesized instances.
* INTERNAL: Do not use.
*/
private import codeql.rust.generated.Raw
/**
* The characteristic predicate of `DbFile` synthesized instances.
* INTERNAL: Do not use.
*/
predicate constructDbFile(Raw::DbFile id) { any() }

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `DbLocation`.
*/
private import codeql.rust.generated.DbLocation
class DbLocation extends Generated::DbLocation { }

View File

@@ -0,0 +1,14 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module defines the hook used internally to tweak the characteristic predicate of
* `DbLocation` synthesized instances.
* INTERNAL: Do not use.
*/
private import codeql.rust.generated.Raw
/**
* The characteristic predicate of `DbLocation` synthesized instances.
* INTERNAL: Do not use.
*/
predicate constructDbLocation(Raw::DbLocation id) { any() }

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `Declaration`.
*/
private import codeql.rust.generated.Declaration
class Declaration extends Generated::Declaration { }

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `Element`.
*/
private import codeql.rust.generated.Element
class Element extends Generated::Element { }

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `File`.
*/
private import codeql.rust.generated.File
class File extends Generated::File { }

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `Function`.
*/
private import codeql.rust.generated.Function
class Function extends Generated::Function { }

View File

@@ -0,0 +1,14 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module defines the hook used internally to tweak the characteristic predicate of
* `Function` synthesized instances.
* INTERNAL: Do not use.
*/
private import codeql.rust.generated.Raw
/**
* The characteristic predicate of `Function` synthesized instances.
* INTERNAL: Do not use.
*/
predicate constructFunction(Raw::Function id) { any() }

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `Locatable`.
*/
private import codeql.rust.generated.Locatable
class Locatable extends Generated::Locatable { }

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `Location`.
*/
private import codeql.rust.generated.Location
class Location extends Generated::Location { }

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `Module`.
*/
private import codeql.rust.generated.Module
class Module extends Generated::Module { }

View File

@@ -0,0 +1,14 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module defines the hook used internally to tweak the characteristic predicate of
* `Module` synthesized instances.
* INTERNAL: Do not use.
*/
private import codeql.rust.generated.Raw
/**
* The characteristic predicate of `Module` synthesized instances.
* INTERNAL: Do not use.
*/
predicate constructModule(Raw::Module id) { any() }

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `UnknownFile`.
*/
private import codeql.rust.generated.UnknownFile
class UnknownFile extends Generated::UnknownFile { }

View File

@@ -0,0 +1,8 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `UnknownLocation`.
*/
private import codeql.rust.generated.UnknownLocation
class UnknownLocation extends Generated::UnknownLocation { }

View File

@@ -0,0 +1,23 @@
// generated by codegen
/**
* This module provides the generated definition of `DbFile`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
import codeql.rust.elements.File
/**
* INTERNAL: This module contains the fully generated definition of `DbFile` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::DbFile` class directly.
* Use the subclass `DbFile`, where the following predicates are available.
*/
class DbFile extends Synth::TDbFile, File {
override string getAPrimaryQlClass() { result = "DbFile" }
}
}

View File

@@ -0,0 +1,23 @@
// generated by codegen
/**
* This module provides the generated definition of `DbLocation`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
import codeql.rust.elements.Location
/**
* INTERNAL: This module contains the fully generated definition of `DbLocation` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::DbLocation` class directly.
* Use the subclass `DbLocation`, where the following predicates are available.
*/
class DbLocation extends Synth::TDbLocation, Location {
override string getAPrimaryQlClass() { result = "DbLocation" }
}
}

View File

@@ -0,0 +1,21 @@
// generated by codegen
/**
* This module provides the generated definition of `Declaration`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
import codeql.rust.elements.Locatable
/**
* INTERNAL: This module contains the fully generated definition of `Declaration` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::Declaration` class directly.
* Use the subclass `Declaration`, where the following predicates are available.
*/
class Declaration extends Synth::TDeclaration, Locatable { }
}

View File

@@ -0,0 +1,57 @@
// generated by codegen
/**
* This module provides the generated definition of `Element`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
/**
* INTERNAL: This module contains the fully generated definition of `Element` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::Element` class directly.
* Use the subclass `Element`, where the following predicates are available.
*/
class Element extends Synth::TElement {
/**
* Gets the string representation of this element.
*/
string toString() { none() } // overridden by subclasses
/**
* Gets the name of a primary CodeQL class to which this element belongs.
*
* This is the most precise syntactic category to which they belong; for
* example, `CallExpr` is a primary class, but `ApplyExpr` is not.
*
* There might be some corner cases when this returns multiple classes, or none.
*/
string getAPrimaryQlClass() { none() } // overridden by subclasses
/**
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
*/
final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
/**
* Gets the most immediate element that should substitute this element in the explicit AST, if any.
* Classes can override this to indicate this node should be in the "hidden" AST, mostly reserved
* for conversions and syntactic sugar nodes like parentheses.
*/
Element getResolveStep() { none() } // overridden by subclasses
/**
* Gets the element that should substitute this element in the explicit AST, applying `getResolveStep`
* transitively.
*/
final Element resolve() {
not exists(this.getResolveStep()) and result = this
or
result = this.getResolveStep().resolve()
}
}
}

View File

@@ -0,0 +1,26 @@
// generated by codegen
/**
* This module provides the generated definition of `File`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
import codeql.rust.elements.Element
/**
* INTERNAL: This module contains the fully generated definition of `File` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::File` class directly.
* Use the subclass `File`, where the following predicates are available.
*/
class File extends Synth::TFile, Element {
/**
* Gets the name of this file.
*/
string getName() { result = Synth::convertFileToRaw(this).(Raw::File).getName() }
}
}

View File

@@ -0,0 +1,28 @@
// generated by codegen
/**
* This module provides the generated definition of `Function`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
import codeql.rust.elements.Declaration
/**
* INTERNAL: This module contains the fully generated definition of `Function` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::Function` class directly.
* Use the subclass `Function`, where the following predicates are available.
*/
class Function extends Synth::TFunction, Declaration {
override string getAPrimaryQlClass() { result = "Function" }
/**
* Gets the name of this function.
*/
string getName() { result = Synth::convertFunctionToRaw(this).(Raw::Function).getName() }
}
}

View File

@@ -0,0 +1,37 @@
// generated by codegen
/**
* This module provides the generated definition of `Locatable`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
import codeql.rust.elements.Element
import codeql.rust.elements.Location
/**
* INTERNAL: This module contains the fully generated definition of `Locatable` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::Locatable` class directly.
* Use the subclass `Locatable`, where the following predicates are available.
*/
class Locatable extends Synth::TLocatable, Element {
/**
* Gets the location of this locatable, if it exists.
*/
Location getLocation() {
result =
Synth::convertLocationFromRaw(Synth::convertLocatableToRaw(this)
.(Raw::Locatable)
.getLocation())
}
/**
* Holds if `getLocation()` exists.
*/
final predicate hasLocation() { exists(this.getLocation()) }
}
}

View File

@@ -0,0 +1,52 @@
// generated by codegen
/**
* This module provides the generated definition of `Location`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
import codeql.rust.elements.Element
import codeql.rust.elements.File
/**
* INTERNAL: This module contains the fully generated definition of `Location` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::Location` class directly.
* Use the subclass `Location`, where the following predicates are available.
*/
class Location extends Synth::TLocation, Element {
/**
* Gets the file of this location.
*/
File getFile() {
result =
Synth::convertFileFromRaw(Synth::convertLocationToRaw(this).(Raw::Location).getFile())
}
/**
* Gets the start line of this location.
*/
int getStartLine() { result = Synth::convertLocationToRaw(this).(Raw::Location).getStartLine() }
/**
* Gets the start column of this location.
*/
int getStartColumn() {
result = Synth::convertLocationToRaw(this).(Raw::Location).getStartColumn()
}
/**
* Gets the end line of this location.
*/
int getEndLine() { result = Synth::convertLocationToRaw(this).(Raw::Location).getEndLine() }
/**
* Gets the end column of this location.
*/
int getEndColumn() { result = Synth::convertLocationToRaw(this).(Raw::Location).getEndColumn() }
}
}

View File

@@ -0,0 +1,43 @@
// generated by codegen
/**
* This module provides the generated definition of `Module`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
import codeql.rust.elements.Declaration
/**
* INTERNAL: This module contains the fully generated definition of `Module` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::Module` class directly.
* Use the subclass `Module`, where the following predicates are available.
*/
class Module extends Synth::TModule, Declaration {
override string getAPrimaryQlClass() { result = "Module" }
/**
* Gets the `index`th declaration of this module (0-based).
*/
Declaration getDeclaration(int index) {
result =
Synth::convertDeclarationFromRaw(Synth::convertModuleToRaw(this)
.(Raw::Module)
.getDeclaration(index))
}
/**
* Gets any of the declarations of this module.
*/
final Declaration getADeclaration() { result = this.getDeclaration(_) }
/**
* Gets the number of declarations of this module.
*/
final int getNumberOfDeclarations() { result = count(int i | exists(this.getDeclaration(i))) }
}
}

View File

@@ -0,0 +1,203 @@
// generated by codegen
/**
* This module provides the generated parent/child relationship.
*/
import codeql.rust.elements
private module Impl {
private Element getImmediateChildOfElement(Element e, int index, string partialPredicateCall) {
none()
}
private Element getImmediateChildOfFile(File e, int index, string partialPredicateCall) {
exists(int b, int bElement, int n |
b = 0 and
bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and
n = bElement and
(
none()
or
result = getImmediateChildOfElement(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfLocatable(Locatable e, int index, string partialPredicateCall) {
exists(int b, int bElement, int n |
b = 0 and
bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and
n = bElement and
(
none()
or
result = getImmediateChildOfElement(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfLocation(Location e, int index, string partialPredicateCall) {
exists(int b, int bElement, int n |
b = 0 and
bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and
n = bElement and
(
none()
or
result = getImmediateChildOfElement(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfDbFile(DbFile e, int index, string partialPredicateCall) {
exists(int b, int bFile, int n |
b = 0 and
bFile = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFile(e, i, _)) | i) and
n = bFile and
(
none()
or
result = getImmediateChildOfFile(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfDbLocation(DbLocation e, int index, string partialPredicateCall) {
exists(int b, int bLocation, int n |
b = 0 and
bLocation = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocation(e, i, _)) | i) and
n = bLocation and
(
none()
or
result = getImmediateChildOfLocation(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfDeclaration(
Declaration e, int index, string partialPredicateCall
) {
exists(int b, int bLocatable, int n |
b = 0 and
bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and
n = bLocatable and
(
none()
or
result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfUnknownFile(
UnknownFile e, int index, string partialPredicateCall
) {
exists(int b, int bFile, int n |
b = 0 and
bFile = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFile(e, i, _)) | i) and
n = bFile and
(
none()
or
result = getImmediateChildOfFile(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfUnknownLocation(
UnknownLocation e, int index, string partialPredicateCall
) {
exists(int b, int bLocation, int n |
b = 0 and
bLocation = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocation(e, i, _)) | i) and
n = bLocation and
(
none()
or
result = getImmediateChildOfLocation(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfFunction(Function e, int index, string partialPredicateCall) {
exists(int b, int bDeclaration, int n |
b = 0 and
bDeclaration =
b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDeclaration(e, i, _)) | i) and
n = bDeclaration and
(
none()
or
result = getImmediateChildOfDeclaration(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfModule(Module e, int index, string partialPredicateCall) {
exists(int b, int bDeclaration, int n, int nDeclaration |
b = 0 and
bDeclaration =
b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDeclaration(e, i, _)) | i) and
n = bDeclaration and
nDeclaration = n + 1 + max(int i | i = -1 or exists(e.getDeclaration(i)) | i) and
(
none()
or
result = getImmediateChildOfDeclaration(e, index - b, partialPredicateCall)
or
result = e.getDeclaration(index - n) and
partialPredicateCall = "Declaration(" + (index - n).toString() + ")"
)
)
}
cached
Element getImmediateChild(Element e, int index, string partialAccessor) {
// why does this look more complicated than it should?
// * none() simplifies generation, as we can append `or ...` without a special case for the first item
none()
or
result = getImmediateChildOfDbFile(e, index, partialAccessor)
or
result = getImmediateChildOfDbLocation(e, index, partialAccessor)
or
result = getImmediateChildOfUnknownFile(e, index, partialAccessor)
or
result = getImmediateChildOfUnknownLocation(e, index, partialAccessor)
or
result = getImmediateChildOfFunction(e, index, partialAccessor)
or
result = getImmediateChildOfModule(e, index, partialAccessor)
}
}
/**
* Gets the "immediate" parent of `e`. "Immediate" means not taking into account node resolution: for example
* if `e` has conversions, `getImmediateParent(e)` will give the innermost conversion in the hidden AST.
*/
Element getImmediateParent(Element e) {
// `unique` is used here to tell the optimizer that there is in fact only one result
// this is tested by the `library-tests/parent/no_double_parents.ql` test
result = unique(Element x | e = Impl::getImmediateChild(x, _, _) | x)
}
/**
* Gets the immediate child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child.
*/
Element getImmediateChildAndAccessor(Element e, int index, string accessor) {
exists(string partialAccessor |
result = Impl::getImmediateChild(e, index, partialAccessor) and
accessor = "get" + partialAccessor
)
}
/**
* Gets the child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child.
*/
Element getChildAndAccessor(Element e, int index, string accessor) {
exists(string partialAccessor |
result = Impl::getImmediateChild(e, index, partialAccessor).resolve() and
accessor = "get" + partialAccessor
)
}

View File

@@ -0,0 +1,5 @@
// generated by codegen
/**
* This module exports all modules providing `Element` subclasses.
*/

105
rust/ql/lib/codeql/rust/generated/Raw.qll generated Normal file
View File

@@ -0,0 +1,105 @@
/**
* INTERNAL: Do not use.
* This module holds thin fully generated class definitions around DB entities.
*/
module Raw {
/**
* INTERNAL: Do not use.
*/
class Element extends @element {
string toString() { none() }
}
/**
* INTERNAL: Do not use.
*/
class File extends @file, Element {
/**
* Gets the name of this file.
*/
string getName() { files(this, result) }
}
/**
* INTERNAL: Do not use.
*/
class Locatable extends @locatable, Element {
/**
* Gets the location of this locatable, if it exists.
*/
Location getLocation() { locatable_locations(this, result) }
}
/**
* INTERNAL: Do not use.
*/
class Location extends @location, Element {
/**
* Gets the file of this location.
*/
File getFile() { locations(this, result, _, _, _, _) }
/**
* Gets the start line of this location.
*/
int getStartLine() { locations(this, _, result, _, _, _) }
/**
* Gets the start column of this location.
*/
int getStartColumn() { locations(this, _, _, result, _, _) }
/**
* Gets the end line of this location.
*/
int getEndLine() { locations(this, _, _, _, result, _) }
/**
* Gets the end column of this location.
*/
int getEndColumn() { locations(this, _, _, _, _, result) }
}
/**
* INTERNAL: Do not use.
*/
class DbFile extends @db_file, File {
override string toString() { result = "DbFile" }
}
/**
* INTERNAL: Do not use.
*/
class DbLocation extends @db_location, Location {
override string toString() { result = "DbLocation" }
}
/**
* INTERNAL: Do not use.
*/
class Declaration extends @declaration, Locatable { }
/**
* INTERNAL: Do not use.
*/
class Function extends @function, Declaration {
override string toString() { result = "Function" }
/**
* Gets the name of this function.
*/
string getName() { functions(this, result) }
}
/**
* INTERNAL: Do not use.
*/
class Module extends @module, Declaration {
override string toString() { result = "Module" }
/**
* Gets the `index`th declaration of this module (0-based).
*/
Declaration getDeclaration(int index) { module_declarations(this, index, result) }
}
}

View File

@@ -0,0 +1,252 @@
/**
* INTERNAL: Do not use.
* This module defines the IPA layer on top of raw DB entities, and the conversions between the two
* layers.
*/
private import codeql.rust.generated.SynthConstructors
private import codeql.rust.generated.Raw
cached
module Synth {
/**
* INTERNAL: Do not use.
* The synthesized type of all elements.
*/
cached
newtype TElement =
/**
* INTERNAL: Do not use.
*/
TDbFile(Raw::DbFile id) { constructDbFile(id) } or
/**
* INTERNAL: Do not use.
*/
TDbLocation(Raw::DbLocation id) { constructDbLocation(id) } or
/**
* INTERNAL: Do not use.
*/
TFunction(Raw::Function id) { constructFunction(id) } or
/**
* INTERNAL: Do not use.
*/
TModule(Raw::Module id) { constructModule(id) } or
/**
* INTERNAL: Do not use.
*/
TUnknownFile() or
/**
* INTERNAL: Do not use.
*/
TUnknownLocation()
/**
* INTERNAL: Do not use.
*/
class TDeclaration = TFunction or TModule;
/**
* INTERNAL: Do not use.
*/
class TFile = TDbFile or TUnknownFile;
/**
* INTERNAL: Do not use.
*/
class TLocatable = TDeclaration;
/**
* INTERNAL: Do not use.
*/
class TLocation = TDbLocation or TUnknownLocation;
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TDbFile`, if possible.
*/
cached
TDbFile convertDbFileFromRaw(Raw::Element e) { result = TDbFile(e) }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TDbLocation`, if possible.
*/
cached
TDbLocation convertDbLocationFromRaw(Raw::Element e) { result = TDbLocation(e) }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TFunction`, if possible.
*/
cached
TFunction convertFunctionFromRaw(Raw::Element e) { result = TFunction(e) }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TModule`, if possible.
*/
cached
TModule convertModuleFromRaw(Raw::Element e) { result = TModule(e) }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TUnknownFile`, if possible.
*/
cached
TUnknownFile convertUnknownFileFromRaw(Raw::Element e) { none() }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TUnknownLocation`, if possible.
*/
cached
TUnknownLocation convertUnknownLocationFromRaw(Raw::Element e) { none() }
/**
* INTERNAL: Do not use.
* Converts a raw DB element to a synthesized `TDeclaration`, if possible.
*/
cached
TDeclaration convertDeclarationFromRaw(Raw::Element e) {
result = convertFunctionFromRaw(e)
or
result = convertModuleFromRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a raw DB element to a synthesized `TElement`, if possible.
*/
cached
TElement convertElementFromRaw(Raw::Element e) {
result = convertFileFromRaw(e)
or
result = convertLocatableFromRaw(e)
or
result = convertLocationFromRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a raw DB element to a synthesized `TFile`, if possible.
*/
cached
TFile convertFileFromRaw(Raw::Element e) {
result = convertDbFileFromRaw(e)
or
result = convertUnknownFileFromRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a raw DB element to a synthesized `TLocatable`, if possible.
*/
cached
TLocatable convertLocatableFromRaw(Raw::Element e) { result = convertDeclarationFromRaw(e) }
/**
* INTERNAL: Do not use.
* Converts a raw DB element to a synthesized `TLocation`, if possible.
*/
cached
TLocation convertLocationFromRaw(Raw::Element e) {
result = convertDbLocationFromRaw(e)
or
result = convertUnknownLocationFromRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a synthesized `TDbFile` to a raw DB element, if possible.
*/
cached
Raw::Element convertDbFileToRaw(TDbFile e) { e = TDbFile(result) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TDbLocation` to a raw DB element, if possible.
*/
cached
Raw::Element convertDbLocationToRaw(TDbLocation e) { e = TDbLocation(result) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TFunction` to a raw DB element, if possible.
*/
cached
Raw::Element convertFunctionToRaw(TFunction e) { e = TFunction(result) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TModule` to a raw DB element, if possible.
*/
cached
Raw::Element convertModuleToRaw(TModule e) { e = TModule(result) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TUnknownFile` to a raw DB element, if possible.
*/
cached
Raw::Element convertUnknownFileToRaw(TUnknownFile e) { none() }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TUnknownLocation` to a raw DB element, if possible.
*/
cached
Raw::Element convertUnknownLocationToRaw(TUnknownLocation e) { none() }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TDeclaration` to a raw DB element, if possible.
*/
cached
Raw::Element convertDeclarationToRaw(TDeclaration e) {
result = convertFunctionToRaw(e)
or
result = convertModuleToRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a synthesized `TElement` to a raw DB element, if possible.
*/
cached
Raw::Element convertElementToRaw(TElement e) {
result = convertFileToRaw(e)
or
result = convertLocatableToRaw(e)
or
result = convertLocationToRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a synthesized `TFile` to a raw DB element, if possible.
*/
cached
Raw::Element convertFileToRaw(TFile e) {
result = convertDbFileToRaw(e)
or
result = convertUnknownFileToRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a synthesized `TLocatable` to a raw DB element, if possible.
*/
cached
Raw::Element convertLocatableToRaw(TLocatable e) { result = convertDeclarationToRaw(e) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TLocation` to a raw DB element, if possible.
*/
cached
Raw::Element convertLocationToRaw(TLocation e) {
result = convertDbLocationToRaw(e)
or
result = convertUnknownLocationToRaw(e)
}
}

View File

@@ -0,0 +1,9 @@
// generated by codegen
/**
* This module exports all modules providing `Element` subclasses.
*/
import codeql.rust.elements.DbFileConstructor
import codeql.rust.elements.DbLocationConstructor
import codeql.rust.elements.FunctionConstructor
import codeql.rust.elements.ModuleConstructor

View File

@@ -0,0 +1,23 @@
// generated by codegen
/**
* This module provides the generated definition of `UnknownFile`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
import codeql.rust.elements.File
/**
* INTERNAL: This module contains the fully generated definition of `UnknownFile` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::UnknownFile` class directly.
* Use the subclass `UnknownFile`, where the following predicates are available.
*/
class UnknownFile extends Synth::TUnknownFile, File {
override string getAPrimaryQlClass() { result = "UnknownFile" }
}
}

View File

@@ -0,0 +1,23 @@
// generated by codegen
/**
* This module provides the generated definition of `UnknownLocation`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.generated.Synth
private import codeql.rust.generated.Raw
import codeql.rust.elements.Location
/**
* INTERNAL: This module contains the fully generated definition of `UnknownLocation` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::UnknownLocation` class directly.
* Use the subclass `UnknownLocation`, where the following predicates are available.
*/
class UnknownLocation extends Synth::TUnknownLocation, Location {
override string getAPrimaryQlClass() { result = "UnknownLocation" }
}
}

81
rust/ql/lib/rust.dbscheme Normal file
View File

@@ -0,0 +1,81 @@
// generated by codegen
// from prefix.dbscheme
/**
* The source location of the snapshot.
*/
sourceLocationPrefix(
string prefix: string ref
);
// from schema.py
@element =
@file
| @locatable
| @location
;
@file =
@db_file
;
#keyset[id]
files(
int id: @file ref,
string name: string ref
);
@locatable =
@declaration
;
#keyset[id]
locatable_locations(
int id: @locatable ref,
int location: @location ref
);
@location =
@db_location
;
#keyset[id]
locations(
int id: @location ref,
int file: @file ref,
int start_line: int ref,
int start_column: int ref,
int end_line: int ref,
int end_column: int ref
);
db_files(
unique int id: @db_file
);
db_locations(
unique int id: @db_location
);
@declaration =
@function
| @module
;
functions(
unique int id: @function,
string name: string ref
);
modules(
unique int id: @module
);
#keyset[id, index]
module_declarations(
int id: @module ref,
int index: int ref,
int declaration: @declaration ref
);

View File

@@ -0,0 +1,4 @@
// generated by codegen
After a source file is added in this directory and codegen is run again, test queries
will appear and this file will be deleted

View File

@@ -0,0 +1,4 @@
// generated by codegen
After a source file is added in this directory and codegen is run again, test queries
will appear and this file will be deleted

View File

@@ -0,0 +1,4 @@
// generated by codegen
After a source file is added in this directory and codegen is run again, test queries
will appear and this file will be deleted

60
rust/schema.py Normal file
View File

@@ -0,0 +1,60 @@
"""
Schema description
This file should be kept simple:
* no flow control
* no aliases
* only class definitions with annotations and `include` calls
For how documentation of generated QL code works, please read `misc/codegen/schema_documentation.md`.
"""
from misc.codegen.lib.schemadefs import *
include("prefix.dbscheme")
@qltest.skip
class Element:
pass
@qltest.collapse_hierarchy
class File(Element):
name: string
@qltest.skip
@qltest.collapse_hierarchy
class Location(Element):
file: File
start_line: int
start_column: int
end_line: int
end_column: int
class DbFile(File):
pass
class DbLocation(Location):
pass
@synth.on_arguments()
class UnknownFile(File):
pass
@synth.on_arguments()
class UnknownLocation(Location):
pass
@qltest.skip
class Locatable(Element):
location: optional[Location]
class Declaration(Locatable):
pass
class Module(Declaration):
# TODO name
declarations: list[Declaration] | child
class Function(Declaration):
name: string

View File

@@ -19,7 +19,9 @@ impl Archiver {
let mut dest = self.root.clone();
dest.push(path::key(source));
let parent = dest.parent().unwrap();
if fs::exists(&dest)? {
return Ok(())
}
fs::create_dir_all(parent)?;
fs::copy(source, dest)?;
debug!("archived {}", source.display());

87
rust/src/generated/top.rs Normal file
View File

@@ -0,0 +1,87 @@
// generated by codegen
use crate::trap::{TrapLabel, TrapId, TrapEntry, quoted};
use std::io::Write;
#[derive(Debug)]
pub struct DbFile {
pub id: TrapId,
pub name: String,
}
impl TrapEntry for DbFile {
fn extract_id(&mut self) -> TrapId {
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", quoted(&self.name))?;
Ok(())
}
}
#[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,
}
impl TrapEntry for DbLocation {
fn extract_id(&mut self) -> TrapId {
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", self.file, self.start_line, self.start_column, self.end_line, self.end_column)?;
Ok(())
}
}
#[derive(Debug)]
pub struct Function {
pub id: TrapId,
pub location: Option<TrapLabel>,
pub name: String,
}
impl TrapEntry for Function {
fn extract_id(&mut self) -> TrapId {
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, "function_locations({id}, {})\n", v)?;
}
Ok(())
}
}
#[derive(Debug)]
pub struct Module {
pub id: TrapId,
pub location: Option<TrapLabel>,
pub declarations: Vec<TrapLabel>,
}
impl TrapEntry for Module {
fn extract_id(&mut self) -> TrapId {
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, "module_locations({id}, {})\n", v)?;
}
for (i, &ref v) in self.declarations.iter().enumerate() {
write!(out, "module_declarations({id}, {}, {})\n", i, v)?;
}
Ok(())
}
}

View File

@@ -1,19 +1,20 @@
#![feature(path_add_extension)]
use std::fs;
use std::path::{PathBuf, Path};
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::{Crate, 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};
use crate::trap::{TrapId};
mod config;
pub mod trap;
mod generated;
pub mod generated;
mod translate;
mod archive;
pub mod path;
@@ -40,11 +41,25 @@ fn main() -> anyhow::Result<()> {
{
let mut trap = traps.create("input", &path)?;
let name = String::from(path.to_string_lossy());
trap.emit(generated::DbFile{key: Some(name.clone()), name })?;
trap.emit(generated::DbFile { id: name.clone().into(), name })?;
archiver.archive(&path);
}
load_workspace_at(&path, &config, &load_config, &no_progress)?;
todo!()
let (db, vfs, _macro_server) = load_workspace_at(&path, &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())))?;
translate::CrateTranslator::new(
&db,
trap,
&krate,
&vfs,
&archiver,
).emit_crate()?;
}
}
Ok(())
}

View File

@@ -1,35 +1,152 @@
use crate::trap::TrapFile;
use ra_ap_hir::{ModuleDefId, db::{DefDatabase, ExpandDatabase}, AdtId::{EnumId, UnionId, StructId}};
use ra_ap_ide_db::RootDatabase;
use std::collections::HashMap;
use std::fs;
use std::path::{PathBuf};
use crate::trap::{KeyPart, TrapFile, TrapId, TrapLabel};
use crate::{generated, trap_key};
use ra_ap_hir::{Crate, Module, ModuleDef};
use anyhow;
use ra_ap_ide_db::base_db::Upcast;
use ra_ap_base_db::{CrateId};
use ra_ap_hir::{HasSource};
use ra_ap_vfs::{AbsPath, FileId, Vfs};
use ra_ap_syntax::ast::HasName;
use crate::archive::Archiver;
use std::io::Result;
use triomphe::Arc;
use ra_ap_ide_db::{LineIndexDatabase, RootDatabase};
use ra_ap_ide_db::line_index::LineIndex;
use ra_ap_syntax::AstNode;
struct Translator<'a> {
pub db: &'a dyn DefDatabase,
pub trap: TrapFile,
#[derive(Clone)]
struct FileData {
label: TrapLabel,
line_index: Arc<LineIndex>,
}
pub struct CrateTranslator<'a> {
db: &'a RootDatabase,
trap: TrapFile,
krate: &'a Crate,
vfs: &'a Vfs,
archiver: &'a Archiver,
file_labels: HashMap<PathBuf, FileData>,
}
impl Translator<'_> {
pub fn emit_definition(&mut self, id: &ModuleDefId) -> anyhow::Result<()> {
impl CrateTranslator<'_> {
pub fn new<'a>(
db: &'a RootDatabase,
trap: TrapFile,
krate: &'a Crate,
vfs: &'a Vfs,
archiver: &'a Archiver,
) -> CrateTranslator<'a> {
CrateTranslator {
db,
trap,
krate,
vfs,
archiver,
file_labels: HashMap::new(),
}
}
fn emit_file(&mut self, file_id: FileId) -> Result<Option<FileData>> {
if let Some(abs_path) = self.vfs.file_path(file_id).as_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 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)
}
}
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, format!(":{}:{}:{}:{}", 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_definition(&mut self, module_label: TrapLabel, id: ModuleDef, labels: &mut Vec<TrapLabel>) -> 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}");
ModuleDef::Module(_) => {}
ModuleDef::Function(function) => {
let name = function.name(self.db);
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(),
})?);
}
// 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);
// }
_ => {}
ModuleDef::Adt(_) => {}
ModuleDef::Variant(_) => {}
ModuleDef::Const(_) => {}
ModuleDef::Static(_) => {}
ModuleDef::Trait(_) => {}
ModuleDef::TraitAlias(_) => {}
ModuleDef::TypeAlias(_) => {}
ModuleDef::BuiltinType(_) => {}
ModuleDef::Macro(_) => {}
}
Ok(())
}
fn emit_module(&mut self, label: TrapLabel, module: Module) -> Result<()> {
let mut children = Vec::new();
for id in module.declarations(self.db) {
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();
for module in self.krate.modules(self.db) {
let mut key = Vec::<KeyPart>::new();
if let Some(parent) = module.parent(self.db) {
// assumption: parent was already listed
let parent_label = *map.get(&parent).unwrap();
key.push(parent_label.into());
}
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())? {
key.push(data.label.into());
}
}
if let Some(name) = module.name(self.db) {
key.push(name.as_str().into());
}
let label = self.trap.label(TrapId::Key(key))?;
map.insert(module, label);
self.emit_module(label, module)?;
}
Ok(())
}

View File

@@ -8,11 +8,74 @@ use crate::{config, path};
#[derive(Debug, Clone, Copy)]
pub struct TrapLabel(u64);
impl Display for TrapLabel {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "#{:x}", self.0)
}
}
//TODO: typed labels
impl From<u64> for TrapLabel {
fn from(value: u64) -> Self {
TrapLabel(value)
#[derive(Debug, Clone)]
pub enum KeyPart {
Label(TrapLabel),
Text(String),
}
impl From<String> for KeyPart {
fn from(value: String) -> Self {
KeyPart::Text(value)
}
}
impl From<&str> for KeyPart {
fn from(value: &str) -> Self {
KeyPart::Text(value.into())
}
}
impl From<TrapLabel> for KeyPart {
fn from(value: TrapLabel) -> Self {
KeyPart::Label(value)
}
}
#[derive(Debug, Clone)]
pub enum TrapId {
Star,
Key(Vec<KeyPart>),
Label(TrapLabel),
}
impl<T: Into<KeyPart>> From<T> for TrapId {
fn from(value: T) -> Self {
TrapId::Key(vec![value.into()])
}
}
#[macro_export]
macro_rules! trap_key {
($($x:expr),+ $(,)?) => (
$crate::trap::TrapId::Key(vec![$($x.into()),+])
);
}
impl Display for TrapId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
TrapId::Star => write!(f, "*"),
TrapId::Key(k) => {
f.write_str("@\"")?;
for p in k {
match p {
KeyPart::Label(l) => write!(f, "{{{l}}}")?,
KeyPart::Text(s) => f.write_str(&escaped(s))?,
}
}
f.write_str("\"")
}
TrapId::Label(l) => Display::fmt(&l, f)
}
}
}
@@ -24,20 +87,10 @@ 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)
}
}
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<()>;
fn extract_id(&mut self) -> TrapId;
fn emit<W: Write>(self, id: TrapLabel, out: &mut W) -> std::io::Result<()>;
}
#[derive(Debug)]
@@ -56,28 +109,27 @@ impl TrapFile {
Ok(())
}
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)?,
};
pub fn label(&mut self, id: TrapId) -> std::io::Result<TrapLabel> {
if let TrapId::Label(l) = id {
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);
entry.emit(&ret, &mut self.file)?;
Ok(ret)
let id = self.label(entry.extract_id())?;
entry.emit(id, &mut self.file)?;
Ok(id)
}
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")?;
fn create_label(&mut self) -> TrapLabel {
let ret = TrapLabel(self.label_index);
self.label_index += 1;
Ok(ret)
}
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)
ret
}
}