Skip to content

Commit 2ba355c

Browse files
committed
source injector: add the crate
This crate takes an absolute path to a rustc repo and adds path-dependencies that point towards the respective rustc subcrates into the Cargo.tomls of the clippy and clippy_lints crate. This allows rustc-analyzer to show proper type annotations etc on rustc-internals inside the clippy repo. Usage: ./souce_injector/target/debug/souce_injector /absolute/path/to/rust/ cc rust-lang/rust-analyzer#3517 cc #5514
1 parent ee3088f commit 2ba355c

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ out
2121
/clippy_workspace_tests/target
2222
/clippy_dev/target
2323
/rustc_tools_util/target
24+
/souce_injector/target
2425

2526
# Generated by dogfood
2627
/target_recur/

Diff for: souce_injector/Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "souce_injector"
3+
version = "0.1.0"
4+
authors = ["Matthias Krüger <matthias.krueger@famsik.de>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]

Diff for: souce_injector/src/main.rs

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use std::env;
2+
use std::fs;
3+
use std::fs::File;
4+
use std::io::prelude::*;
5+
use std::path::PathBuf;
6+
7+
// This crate takes an absolute path to a rustc repo and alters the dependencies to point towards
8+
// the respective rustc subcrates instead of using extern crate xyz.
9+
// This allows rust analyzer to analyze rustc internals and show proper information inside clippy
10+
// code. See https://github.com/rust-lang/rust-clippy/issues/5514 and https://github.com/rust-lang/rust-clippy/issues/5514 for details
11+
12+
fn main() -> std::io::Result<()> {
13+
// first arg is the path to a rust repo
14+
let rustc_path = env::args()
15+
.nth(1)
16+
.expect("First argument must be the path to a rustc repo root");
17+
18+
let rustc_path = PathBuf::from(rustc_path);
19+
assert!(rustc_path.is_dir(), "path is not a directory");
20+
let rustc_source_basedir = rustc_path.join("src");
21+
assert!(
22+
rustc_source_basedir.is_dir(),
23+
"are you sure the path leads to a rustc repo?"
24+
);
25+
26+
let clippy_root_manifest = fs::read_to_string("Cargo.toml").expect("failed to read ./Cargo.toml");
27+
let clippy_root_lib_rs = fs::read_to_string("src/driver.rs").expect("failed to read ./src/driver.rs");
28+
inject_deps_into_manifest(
29+
&rustc_source_basedir,
30+
"Cargo.toml",
31+
clippy_root_manifest,
32+
clippy_root_lib_rs,
33+
)?;
34+
35+
let clippy_lints_manifest =
36+
fs::read_to_string("clippy_lints/Cargo.toml").expect("failed to read ./clippy_lints/Cargo.toml");
37+
let clippy_lints_lib_rs =
38+
fs::read_to_string("clippy_lints/src/lib.rs").expect("failed to read ./clippy_lints/src/lib.rs");
39+
inject_deps_into_manifest(
40+
&rustc_source_basedir,
41+
"clippy_lints/Cargo.toml",
42+
clippy_lints_manifest,
43+
clippy_lints_lib_rs,
44+
)?;
45+
46+
Ok(())
47+
}
48+
49+
fn inject_deps_into_manifest(
50+
rustc_source_dir: &PathBuf,
51+
manifest_path: &str,
52+
cargo_toml: String,
53+
lib_rs: String,
54+
) -> std::io::Result<()> {
55+
let extern_crates = lib_rs
56+
.lines()
57+
// get the deps
58+
.filter(|line| line.starts_with("extern crate"))
59+
// we have something like "extern crate foo;", we only care about the "foo"
60+
// ↓ ↓
61+
// extern crate rustc_middle;
62+
.map(|s| &s[13..(s.len() - 1)]);
63+
64+
let new_deps = extern_crates.map(|dep| {
65+
// format the dependencies that are going to be put inside the Cargo.toml
66+
format!(
67+
"{dep} = {{ path = \"{source_path}/lib{dep}\" }}\n",
68+
dep = dep,
69+
source_path = rustc_source_dir.display()
70+
)
71+
});
72+
73+
// format a new [dependencies]-block with the new deps we need to inject
74+
let mut all_deps = String::from("[dependencies]\n");
75+
new_deps.for_each(|dep_line| {
76+
all_deps.push_str(&dep_line);
77+
});
78+
79+
// replace "[dependencies]" with
80+
// [dependencies]
81+
// dep1 = { path = ... }
82+
// dep2 = { path = ... }
83+
// etc
84+
let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1);
85+
86+
// println!("{}", new_manifest);
87+
let mut file = File::create(manifest_path)?;
88+
file.write_all(new_manifest.as_bytes())?;
89+
90+
println!("Dependency paths injected: {}", manifest_path);
91+
92+
Ok(())
93+
}

0 commit comments

Comments
 (0)