Skip to content

Commit 8fdf289

Browse files
xFrednetflip1995
authored andcommitted
Updated cargo dev setup intellij for cleaner user messages
1 parent b48f041 commit 8fdf289

File tree

2 files changed

+114
-39
lines changed

2 files changed

+114
-39
lines changed

clippy_dev/src/main.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ fn main() {
3737
stderr_length_check::check();
3838
},
3939
("setup", Some(sub_command)) => match sub_command.subcommand() {
40-
("intellij", Some(matches)) => setup::intellij::run(matches.value_of("rustc-repo-path")),
40+
("intellij", Some(matches)) => setup::intellij::setup_rustc_src(
41+
matches
42+
.value_of("rustc-repo-path")
43+
.expect("this field is mandatory and therefore always valid"),
44+
),
4145
("git-hook", Some(matches)) => setup::git_hook::install_hook(matches.is_present("force-override")),
4246
_ => {},
4347
},

clippy_dev/src/setup/intellij.rs

Lines changed: 109 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,113 @@ use std::path::{Path, PathBuf};
88
// This allows rust analyzer to analyze rustc internals and show proper information inside clippy
99
// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details
1010

11-
/// # Panics
12-
///
13-
/// Panics if `rustc_path` does not lead to a rustc repo or the files could not be read
14-
pub fn run(rustc_path: Option<&str>) {
15-
// we can unwrap here because the arg is required by clap
16-
let rustc_path = PathBuf::from(rustc_path.unwrap())
17-
.canonicalize()
18-
.expect("failed to get the absolute repo path");
19-
assert!(rustc_path.is_dir(), "path is not a directory");
20-
let rustc_source_basedir = rustc_path.join("compiler");
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-
.expect("Failed to inject deps into ./Cargo.toml");
35-
36-
let clippy_lints_manifest =
37-
fs::read_to_string("clippy_lints/Cargo.toml").expect("failed to read ./clippy_lints/Cargo.toml");
38-
let clippy_lints_lib_rs =
39-
fs::read_to_string("clippy_lints/src/lib.rs").expect("failed to read ./clippy_lints/src/lib.rs");
40-
inject_deps_into_manifest(
41-
&rustc_source_basedir,
42-
"clippy_lints/Cargo.toml",
43-
&clippy_lints_manifest,
44-
&clippy_lints_lib_rs,
45-
)
46-
.expect("Failed to inject deps into ./clippy_lints/Cargo.toml");
11+
const CLIPPY_PROJECTS: &[ClippyProjectInfo] = &[
12+
ClippyProjectInfo::new("root", "Cargo.toml", "src/driver.rs"),
13+
ClippyProjectInfo::new("clippy_lints", "clippy_lints/Cargo.toml", "clippy_lints/src/lib.rs"),
14+
ClippyProjectInfo::new("clippy_utils", "clippy_utils/Cargo.toml", "clippy_utils/src/lib.rs"),
15+
];
16+
17+
/// Used to store clippy project information to later inject the dependency into.
18+
struct ClippyProjectInfo {
19+
/// Only used to display information to the user
20+
name: &'static str,
21+
cargo_file: &'static str,
22+
lib_rs_file: &'static str,
23+
}
24+
25+
impl ClippyProjectInfo {
26+
const fn new(name: &'static str, cargo_file: &'static str, lib_rs_file: &'static str) -> Self {
27+
Self {
28+
name,
29+
cargo_file,
30+
lib_rs_file,
31+
}
32+
}
33+
}
34+
35+
pub fn setup_rustc_src(rustc_path: &str) {
36+
let rustc_source_dir = match check_and_get_rustc_dir(rustc_path) {
37+
Ok(path) => path,
38+
Err(_) => return,
39+
};
40+
41+
for project in CLIPPY_PROJECTS {
42+
if inject_deps_into_project(&rustc_source_dir, project).is_err() {
43+
return;
44+
}
45+
}
46+
}
47+
48+
fn check_and_get_rustc_dir(rustc_path: &str) -> Result<PathBuf, ()> {
49+
let mut path = PathBuf::from(rustc_path);
50+
51+
if path.is_relative() {
52+
match path.canonicalize() {
53+
Ok(absolute_path) => {
54+
println!("note: the rustc path was resolved to: `{}`", absolute_path.display());
55+
path = absolute_path;
56+
},
57+
Err(err) => {
58+
println!("error: unable to get the absolute path of rustc ({})", err);
59+
return Err(());
60+
},
61+
};
62+
}
63+
64+
let path = path.join("compiler");
65+
println!("note: looking for compiler sources at: {}", path.display());
66+
67+
if !path.exists() {
68+
println!("error: the given path does not exist");
69+
return Err(());
70+
}
71+
72+
if !path.is_dir() {
73+
println!("error: the given path is a file and not a directory");
74+
return Err(());
75+
}
76+
77+
Ok(path)
78+
}
79+
80+
fn inject_deps_into_project(rustc_source_dir: &Path, project: &ClippyProjectInfo) -> Result<(), ()> {
81+
let cargo_content = read_project_file(project.cargo_file, "Cargo.toml", project.name)?;
82+
let lib_content = read_project_file(project.lib_rs_file, "lib.rs", project.name)?;
83+
84+
if inject_deps_into_manifest(rustc_source_dir, project.cargo_file, &cargo_content, &lib_content).is_err() {
85+
println!(
86+
"error: unable to inject dependencies into {} with the Cargo file {}",
87+
project.name, project.cargo_file
88+
);
89+
Err(())
90+
} else {
91+
Ok(())
92+
}
93+
}
94+
95+
/// `clippy_dev` expects to be executed in the root directory of Clippy. This function
96+
/// loads the given file or returns an error. Having it in this extra function ensures
97+
/// that the error message looks nice.
98+
fn read_project_file(file_path: &str, file_name: &str, project: &str) -> Result<String, ()> {
99+
let path = Path::new(file_path);
100+
if !path.exists() {
101+
println!(
102+
"error: unable to find the `{}` file for the project {}",
103+
file_name, project
104+
);
105+
return Err(());
106+
}
107+
108+
match fs::read_to_string(path) {
109+
Ok(content) => Ok(content),
110+
Err(err) => {
111+
println!(
112+
"error: the `{}` file for the project {} could not be read ({})",
113+
file_name, project, err
114+
);
115+
Err(())
116+
},
117+
}
47118
}
48119

49120
fn inject_deps_into_manifest(
@@ -55,7 +126,7 @@ fn inject_deps_into_manifest(
55126
// do not inject deps if we have aleady done so
56127
if cargo_toml.contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") {
57128
eprintln!(
58-
"cargo dev setup intellij: warning: deps already found inside {}, doing nothing.",
129+
"warn: dependencies are already setup inside {}, skipping file.",
59130
manifest_path
60131
);
61132
return Ok(());
@@ -97,7 +168,7 @@ fn inject_deps_into_manifest(
97168
let mut file = File::create(manifest_path)?;
98169
file.write_all(new_manifest.as_bytes())?;
99170

100-
println!("Dependency paths injected: {}", manifest_path);
171+
println!("note: successfully setup dependencies inside {}", manifest_path);
101172

102173
Ok(())
103174
}

0 commit comments

Comments
 (0)