diff --git a/cargo/private/cargo_toml_info/BUILD.bazel b/cargo/private/cargo_toml_info/BUILD.bazel index bc689230e6..285f002720 100644 --- a/cargo/private/cargo_toml_info/BUILD.bazel +++ b/cargo/private/cargo_toml_info/BUILD.bazel @@ -1,5 +1,6 @@ """BUILD file for cargo info helper binary.""" +load("@rules_python//python:defs.bzl", "py_test") load("//rust:defs.bzl", "rust_binary", "rust_test") rust_binary( @@ -14,3 +15,11 @@ rust_test( name = "unit_test", crate = ":cargo_toml_info", ) + +py_test( + name = "declared_manifests_test", + srcs = ["declared_manifests_test.py"], + args = ["$(rlocationpath :cargo_toml_info)"], + data = [":cargo_toml_info"], + deps = ["@rules_python//python/runfiles"], +) diff --git a/cargo/private/cargo_toml_info/declared_manifests_test.py b/cargo/private/cargo_toml_info/declared_manifests_test.py new file mode 100644 index 0000000000..a06ab11c68 --- /dev/null +++ b/cargo/private/cargo_toml_info/declared_manifests_test.py @@ -0,0 +1,89 @@ +"""Lint extraction uses only the declared package and workspace manifests.""" + +import os +import subprocess +import sys +import tempfile +import unittest +from pathlib import Path + +from python.runfiles import runfiles + +WORKSPACE = """\ +[workspace] +members = ["missing-member"] + +[workspace.package] +version = "0.1.0" +readme = "missing-readme.md" + +[workspace.lints.rust] +unused = { level = "deny", priority = -1 } +unsafe_code = "forbid" + +[workspace.lints.clippy] +all = "warn" +""" + +PACKAGE = """\ +[package] +name = "example" +version.workspace = true +readme.workspace = true +edition = "2021" + +[lints] +workspace = true +""" + + +class DeclaredManifestsTest(unittest.TestCase): + def test_root_and_member_inherit_lints_without_workspace_sources(self): + lookup = runfiles.Create() + self.assertIsNotNone(lookup) + executable = lookup.Rlocation(EXTRACTOR) + self.assertIsNotNone(executable) + + with tempfile.TemporaryDirectory( + dir=os.environ.get("TEST_TMPDIR") + ) as directory: + root = Path(directory) + workspace = root / "Cargo.toml" + workspace.write_text(WORKSPACE + "\n" + PACKAGE) + member = root / "member" / "Cargo.toml" + member.parent.mkdir() + member.write_text(PACKAGE) + + for package in (workspace, member): + with self.subTest(package=package): + outputs = [ + root / f"{package.parent.name}.{group}.lints" + for group in ("rustc", "clippy", "rustdoc") + ] + result = subprocess.run( + [ + executable, + f"--manifest_toml={package.relative_to(root)}", + f"--workspace_toml={workspace.relative_to(root)}", + "lints", + *(str(path) for path in outputs), + ], + cwd=root, + capture_output=True, + text=True, + check=False, + ) + self.assertEqual(0, result.returncode, result.stderr) + self.assertEqual( + ["--deny=unused", "--forbid=unsafe_code"], + outputs[0].read_text().splitlines(), + ) + self.assertEqual( + ["--warn=clippy::all"], outputs[1].read_text().splitlines() + ) + self.assertEqual("", outputs[2].read_text()) + + +if __name__ == "__main__": + EXTRACTOR = sys.argv.pop(1) + unittest.main() diff --git a/cargo/private/cargo_toml_info/main.rs b/cargo/private/cargo_toml_info/main.rs index c0a9a06f48..67c0b76f50 100644 --- a/cargo/private/cargo_toml_info/main.rs +++ b/cargo/private/cargo_toml_info/main.rs @@ -21,18 +21,13 @@ pub fn main() -> Result<(), Box> { } = Args::try_from(std::env::args())?; let manifest_contents = std::fs::read_to_string(&manifest_toml)?; - let mut crate_manifest = Manifest::from_str(&manifest_contents)?; + let crate_manifest = Manifest::from_str(&manifest_contents)?; let mut workspace_manifest = None; - // Optionally populate the manifest with info from the parent workspace, if one is provided. + // Lint extraction only needs the declared manifests. Completing the package + // from disk would require undeclared sources and workspace members. if let Some(workspace_path) = workspace_toml { - let manifest = Manifest::from_path(&workspace_path)?; - let workspace_details = Some((&manifest, workspace_path.as_path())); - - // TODO(parkmycar): Fix cargo_toml so we inherit lints from our workspace. - // - // See: - crate_manifest.complete_from_path_and_workspace(&manifest_toml, workspace_details)?; + let manifest = Manifest::from_str(&std::fs::read_to_string(workspace_path)?)?; workspace_manifest = Some(manifest); }