@@ -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
49120fn 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