From 755140152ca2881903d62cfdedddcc367e8bf0f0 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Mon, 17 Feb 2025 15:09:35 +0100 Subject: [PATCH] Rust: support glob members in workspaces --- rust/extractor/src/rust_analyzer.rs | 19 +++++++++++++++---- .../workspace-with-glob/Cargo.toml | 4 ++++ .../workspace-with-glob/exe/Cargo.toml | 7 +++++++ .../workspace-with-glob/exe/src/main.rs | 5 +++++ .../workspace-with-glob/lib/Cargo.toml | 6 ++++++ .../workspace-with-glob/lib/src/lib.rs | 3 +++ .../workspace-with-glob/other/Cargo.toml | 6 ++++++ .../workspace-with-glob/other/src/lib.rs | 0 .../source_archive.expected | 3 +++ .../workspace-with-glob/steps.expected | 10 ++++++++++ .../workspace-with-glob/steps.ql | 4 ++++ .../workspace-with-glob/test_workspace.py | 5 +++++ 12 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 rust/ql/integration-tests/workspace-with-glob/Cargo.toml create mode 100644 rust/ql/integration-tests/workspace-with-glob/exe/Cargo.toml create mode 100644 rust/ql/integration-tests/workspace-with-glob/exe/src/main.rs create mode 100644 rust/ql/integration-tests/workspace-with-glob/lib/Cargo.toml create mode 100644 rust/ql/integration-tests/workspace-with-glob/lib/src/lib.rs create mode 100644 rust/ql/integration-tests/workspace-with-glob/other/Cargo.toml create mode 100644 rust/ql/integration-tests/workspace-with-glob/other/src/lib.rs create mode 100644 rust/ql/integration-tests/workspace-with-glob/source_archive.expected create mode 100644 rust/ql/integration-tests/workspace-with-glob/steps.expected create mode 100644 rust/ql/integration-tests/workspace-with-glob/steps.ql create mode 100644 rust/ql/integration-tests/workspace-with-glob/test_workspace.py diff --git a/rust/extractor/src/rust_analyzer.rs b/rust/extractor/src/rust_analyzer.rs index 21f62281e725..ac139d68e12b 100644 --- a/rust/extractor/src/rust_analyzer.rs +++ b/rust/extractor/src/rust_analyzer.rs @@ -3,7 +3,7 @@ use ra_ap_base_db::SourceDatabase; use ra_ap_hir::Semantics; use ra_ap_ide_db::RootDatabase; use ra_ap_load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice}; -use ra_ap_paths::Utf8PathBuf; +use ra_ap_paths::{AbsPath, Utf8PathBuf}; use ra_ap_project_model::ProjectManifest; use ra_ap_project_model::{CargoConfig, ManifestPath}; use ra_ap_span::Edition; @@ -136,6 +136,8 @@ impl<'a> RustAnalyzer<'a> { struct CargoManifestMembersSlice { #[serde(default)] members: Vec, + #[serde(default)] + exclude: Vec, } #[derive(Deserialize)] @@ -171,6 +173,12 @@ impl TomlReader { } } +fn workspace_members_match(workspace_dir: &AbsPath, members: &[String], target: &AbsPath) -> bool { + members.iter().any(|p| { + glob::Pattern::new(workspace_dir.join(p).as_str()).is_ok_and(|p| p.matches(target.as_str())) + }) +} + fn find_workspace(reader: &mut TomlReader, manifest: &ProjectManifest) -> Option { let ProjectManifest::CargoToml(cargo) = manifest else { return None; @@ -200,9 +208,12 @@ fn find_workspace(reader: &mut TomlReader, manifest: &ProjectManifest) -> Option if cargo.starts_with(other.parent()) && reader.read(other).is_ok_and(|it| { it.workspace.as_ref().is_some_and(|w| { - w.members - .iter() - .any(|m| other.parent().join(m) == cargo.parent()) + workspace_members_match(other.parent(), &w.members, cargo.parent()) + && !workspace_members_match( + other.parent(), + &w.exclude, + cargo.parent(), + ) }) }) => { diff --git a/rust/ql/integration-tests/workspace-with-glob/Cargo.toml b/rust/ql/integration-tests/workspace-with-glob/Cargo.toml new file mode 100644 index 000000000000..7ca762f8a4e2 --- /dev/null +++ b/rust/ql/integration-tests/workspace-with-glob/Cargo.toml @@ -0,0 +1,4 @@ +[workspace] +members = [ "*" ] +exclude = [ "other" ] +resolver = "2" diff --git a/rust/ql/integration-tests/workspace-with-glob/exe/Cargo.toml b/rust/ql/integration-tests/workspace-with-glob/exe/Cargo.toml new file mode 100644 index 000000000000..b63ccfd5da54 --- /dev/null +++ b/rust/ql/integration-tests/workspace-with-glob/exe/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "exe" +version = "0.1.0" +edition = "2021" + +[dependencies] +lib = { path = "../lib" } diff --git a/rust/ql/integration-tests/workspace-with-glob/exe/src/main.rs b/rust/ql/integration-tests/workspace-with-glob/exe/src/main.rs new file mode 100644 index 000000000000..7e409cee919e --- /dev/null +++ b/rust/ql/integration-tests/workspace-with-glob/exe/src/main.rs @@ -0,0 +1,5 @@ +use lib::hello; + +fn main() { + hello(); +} diff --git a/rust/ql/integration-tests/workspace-with-glob/lib/Cargo.toml b/rust/ql/integration-tests/workspace-with-glob/lib/Cargo.toml new file mode 100644 index 000000000000..e8fc5405b71f --- /dev/null +++ b/rust/ql/integration-tests/workspace-with-glob/lib/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "lib" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/rust/ql/integration-tests/workspace-with-glob/lib/src/lib.rs b/rust/ql/integration-tests/workspace-with-glob/lib/src/lib.rs new file mode 100644 index 000000000000..fda8464098ec --- /dev/null +++ b/rust/ql/integration-tests/workspace-with-glob/lib/src/lib.rs @@ -0,0 +1,3 @@ +pub fn hello() { + println!("Hello, world!"); +} diff --git a/rust/ql/integration-tests/workspace-with-glob/other/Cargo.toml b/rust/ql/integration-tests/workspace-with-glob/other/Cargo.toml new file mode 100644 index 000000000000..65034739acae --- /dev/null +++ b/rust/ql/integration-tests/workspace-with-glob/other/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "other" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/rust/ql/integration-tests/workspace-with-glob/other/src/lib.rs b/rust/ql/integration-tests/workspace-with-glob/other/src/lib.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/rust/ql/integration-tests/workspace-with-glob/source_archive.expected b/rust/ql/integration-tests/workspace-with-glob/source_archive.expected new file mode 100644 index 000000000000..9cc896fc7d6b --- /dev/null +++ b/rust/ql/integration-tests/workspace-with-glob/source_archive.expected @@ -0,0 +1,3 @@ +exe/src/main.rs +lib/src/lib.rs +other/src/lib.rs diff --git a/rust/ql/integration-tests/workspace-with-glob/steps.expected b/rust/ql/integration-tests/workspace-with-glob/steps.expected new file mode 100644 index 000000000000..26ac51d87bd1 --- /dev/null +++ b/rust/ql/integration-tests/workspace-with-glob/steps.expected @@ -0,0 +1,10 @@ +| Cargo.toml:0:0:0:0 | LoadManifest(Cargo.toml) | +| exe/src/main.rs:0:0:0:0 | Extract(exe/src/main.rs) | +| exe/src/main.rs:0:0:0:0 | Parse(exe/src/main.rs) | +| file://:0:0:0:0 | FindManifests | +| lib/src/lib.rs:0:0:0:0 | Extract(lib/src/lib.rs) | +| lib/src/lib.rs:0:0:0:0 | Parse(lib/src/lib.rs) | +| other/Cargo.toml:0:0:0:0 | LoadManifest(other/Cargo.toml) | +| other/src/lib.rs:0:0:0:0 | Extract(other/src/lib.rs) | +| other/src/lib.rs:0:0:0:0 | LoadSource(other/src/lib.rs) | +| other/src/lib.rs:0:0:0:0 | Parse(other/src/lib.rs) | diff --git a/rust/ql/integration-tests/workspace-with-glob/steps.ql b/rust/ql/integration-tests/workspace-with-glob/steps.ql new file mode 100644 index 000000000000..17358a1c1000 --- /dev/null +++ b/rust/ql/integration-tests/workspace-with-glob/steps.ql @@ -0,0 +1,4 @@ +import codeql.rust.elements.internal.ExtractorStep + +from ExtractorStep step +select step diff --git a/rust/ql/integration-tests/workspace-with-glob/test_workspace.py b/rust/ql/integration-tests/workspace-with-glob/test_workspace.py new file mode 100644 index 000000000000..15b2c5832614 --- /dev/null +++ b/rust/ql/integration-tests/workspace-with-glob/test_workspace.py @@ -0,0 +1,5 @@ +import pytest + + +def test_cargo(codeql, rust, check_source_archive): + codeql.database.create()