Skip to content

Commit ba24cc6

Browse files
committed
Rust: add proc-macro capabilities to QL tests
This adds the possibility to add a special `proc_macro.rs` source file to QL tests, which will be generated into a `proc_macro` crate the usual `lib` crate depends on. This allow to define procedural macros in QL tests, and is here used to move the `macro-expansion` integration test to be a language test instead. As the generated manifests involved were starting to get a bit complex, they are now generated from a `mustache` template.
1 parent 17cd58b commit ba24cc6

File tree

33 files changed

+2428
-380
lines changed

33 files changed

+2428
-380
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

misc/bazel/3rdparty/tree_sitter_extractors_deps/defs.bzl

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/extractor/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ codeql_rust_binary(
77
name = "extractor",
88
srcs = glob(["src/**/*.rs"]),
99
aliases = aliases(),
10+
compile_data = ["src/qltest_cargo.mustache"],
1011
proc_macro_deps = all_crate_deps(
1112
proc_macro = True,
1213
) + [

rust/extractor/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,4 @@ tracing = "0.1.41"
4141
tracing-flame = "0.2.0"
4242
tracing-subscriber = "0.3.19"
4343
chalk-ir = "0.100.0"
44+
mustache = "0.9.0"

rust/extractor/src/qltest.rs

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,54 @@ fn dump_lib() -> anyhow::Result<()> {
1616
let lib = paths
1717
.iter()
1818
.map(|p| p.file_stem().expect("results of glob must have a name"))
19-
.filter(|&p| !["main", "lib"].map(OsStr::new).contains(&p))
19+
.filter(|&p| !["main", "lib", "proc_macro"].map(OsStr::new).contains(&p))
2020
.map(|p| format!("mod {};", p.to_string_lossy()))
2121
.join("\n");
2222
fs::write("lib.rs", lib).context("writing lib.rs")
2323
}
2424

25-
fn dump_cargo_manifest(dependencies: &[String]) -> anyhow::Result<()> {
26-
let mut manifest = String::from(
27-
r#"[workspace]
28-
[package]
29-
name = "test"
30-
version="0.0.1"
31-
edition="2021"
32-
[lib]
33-
path="lib.rs"
34-
"#,
35-
);
36-
if fs::exists("main.rs").context("checking existence of main.rs")? {
37-
manifest.push_str(
38-
r#"[[bin]]
39-
name = "main"
40-
path = "main.rs"
41-
"#,
42-
);
25+
#[derive(serde::Serialize)]
26+
enum TestCargoManifest<'a> {
27+
Workspace {},
28+
Lib {
29+
uses_proc_macro: bool,
30+
uses_main: bool,
31+
dependencies: &'a [String],
32+
},
33+
Macro {},
34+
}
35+
36+
impl TestCargoManifest<'_> {
37+
pub fn dump(&self, path: impl AsRef<Path>) -> anyhow::Result<()> {
38+
static TEMPLATE: std::sync::LazyLock<mustache::Template> = std::sync::LazyLock::new(|| {
39+
mustache::compile_str(include_str!("qltest_cargo.mustache"))
40+
.expect("compiling template")
41+
});
42+
43+
let path = path.as_ref();
44+
fs::create_dir_all(path).with_context(|| format!("creating {}", path.display()))?;
45+
let path = path.join("Cargo.toml");
46+
let rendered = TEMPLATE
47+
.render_to_string(&self)
48+
.with_context(|| format!("rendering {}", path.display()))?;
49+
fs::write(&path, rendered).with_context(|| format!("writing {}", path.display()))
4350
}
44-
if !dependencies.is_empty() {
45-
manifest.push_str("[dependencies]\n");
46-
for dep in dependencies {
47-
manifest.push_str(dep);
48-
manifest.push('\n');
49-
}
51+
}
52+
fn dump_cargo_manifest(dependencies: &[String]) -> anyhow::Result<()> {
53+
let uses_proc_macro =
54+
fs::exists("proc_macro.rs").context("checking existence of proc_macro.rs")?;
55+
let lib_manifest = TestCargoManifest::Lib {
56+
uses_proc_macro,
57+
uses_main: fs::exists("main.rs").context("checking existence of main.rs")?,
58+
dependencies,
59+
};
60+
if uses_proc_macro {
61+
TestCargoManifest::Workspace {}.dump("")?;
62+
lib_manifest.dump(".lib")?;
63+
TestCargoManifest::Macro {}.dump(".proc_macro")
64+
} else {
65+
lib_manifest.dump("")
5066
}
51-
fs::write("Cargo.toml", manifest).context("writing Cargo.toml")
5267
}
5368

5469
fn set_sources(config: &mut Config) -> anyhow::Result<()> {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{{#Workspace}}
2+
[workspace]
3+
resolver = "2"
4+
members = [".lib", ".proc_macro"]
5+
{{/Workspace}}
6+
7+
{{#Lib}}
8+
{{^uses_proc_macro}}
9+
[workspace]
10+
{{/uses_proc_macro}}
11+
[package]
12+
name = "test"
13+
version = "0.1.0"
14+
edition = "2021"
15+
[lib]
16+
path = "{{#uses_proc_macro}}../{{/uses_proc_macro}}lib.rs"
17+
{{#has_main}}
18+
[[bin]]
19+
name = "main"
20+
path = "{{#uses_proc_macro}}../{{/uses_proc_macro}}main.rs"
21+
{{/has_main}}
22+
[dependencies]
23+
{{#uses_proc_macro}}
24+
proc_macro = { path = "../.proc_macro" }
25+
{{/uses_proc_macro}}
26+
{{#dependencies}}
27+
{{.}}
28+
{{/dependencies}}
29+
{{/Lib}}
30+
31+
{{#Macro}}
32+
[package]
33+
name = "proc_macro"
34+
version = "0.1.0"
35+
edition = "2021"
36+
[lib]
37+
path = "../proc_macro.rs"
38+
proc_macro = true
39+
[dependencies]
40+
quote = "1.0.40"
41+
syn = { version = "2.0.100", features = ["full"] }
42+
{{/Macro}}

rust/ql/integration-tests/macro-expansion/Cargo.toml

Lines changed: 0 additions & 3 deletions
This file was deleted.

rust/ql/integration-tests/macro-expansion/attributes/Cargo.toml

Lines changed: 0 additions & 7 deletions
This file was deleted.

rust/ql/integration-tests/macro-expansion/attributes/src/lib.rs

Lines changed: 0 additions & 16 deletions
This file was deleted.

rust/ql/integration-tests/macro-expansion/calls/Cargo.toml

Lines changed: 0 additions & 6 deletions
This file was deleted.

rust/ql/integration-tests/macro-expansion/calls/src/lib.rs

Lines changed: 0 additions & 30 deletions
This file was deleted.

rust/ql/integration-tests/macro-expansion/diagnostics.expected

Lines changed: 0 additions & 55 deletions
This file was deleted.

rust/ql/integration-tests/macro-expansion/proc_macros/Cargo.toml

Lines changed: 0 additions & 11 deletions
This file was deleted.

rust/ql/integration-tests/macro-expansion/source_archive.expected

Lines changed: 0 additions & 4 deletions
This file was deleted.

rust/ql/integration-tests/macro-expansion/test.expected

Lines changed: 0 additions & 34 deletions
This file was deleted.

rust/ql/integration-tests/macro-expansion/test_macro_expansion.py

Lines changed: 0 additions & 2 deletions
This file was deleted.

rust/ql/test/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
Cargo.toml
22
lib.rs
33
target/
4+
.proc_macro/
5+
.lib/
6+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
multiplePathResolutions
2+
| macro_expansion.rs:1:5:1:14 | proc_macro | file://:0:0:0:0 | Crate([email protected]) |
3+
| macro_expansion.rs:1:5:1:14 | proc_macro | proc_macro.rs:0:0:0:0 | Crate([email protected]) |

rust/ql/test/extractor-tests/macro_expansion/Cargo.lock renamed to rust/ql/test/extractor-tests/macro-expansion/Cargo.lock

Lines changed: 10 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)