@@ -8,42 +8,113 @@ use std::path::{Path, PathBuf};
8
8
// This allows rust analyzer to analyze rustc internals and show proper information inside clippy
9
9
// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details
10
10
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
+ }
47
118
}
48
119
49
120
fn inject_deps_into_manifest (
@@ -55,7 +126,7 @@ fn inject_deps_into_manifest(
55
126
// do not inject deps if we have aleady done so
56
127
if cargo_toml. contains ( "[target.'cfg(NOT_A_PLATFORM)'.dependencies]" ) {
57
128
eprintln ! (
58
- "cargo dev setup intellij: warning: deps already found inside {}, doing nothing ." ,
129
+ "warn: dependencies are already setup inside {}, skipping file ." ,
59
130
manifest_path
60
131
) ;
61
132
return Ok ( ( ) ) ;
@@ -97,7 +168,7 @@ fn inject_deps_into_manifest(
97
168
let mut file = File :: create ( manifest_path) ?;
98
169
file. write_all ( new_manifest. as_bytes ( ) ) ?;
99
170
100
- println ! ( "Dependency paths injected: {}" , manifest_path) ;
171
+ println ! ( "note: successfully setup dependencies inside {}" , manifest_path) ;
101
172
102
173
Ok ( ( ) )
103
174
}
0 commit comments