@@ -46,106 +46,97 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
46
46
let our_path = source_root. path_for_file ( & file_id) ?;
47
47
let parent = our_path. parent ( ) ?;
48
48
let ( module_name, _) = our_path. name_and_extension ( ) ?;
49
- let ( parent, module_name) = if module_name == "mod" {
49
+ let ( parent, module_name) = match module_name {
50
50
// for mod.rs we need to actually look up one higher
51
51
// and take the parent as our to be module name
52
- let ( name, _) = parent. name_and_extension ( ) ?;
53
- ( parent. parent ( ) ?, name. to_owned ( ) )
54
- } else {
55
- ( parent, module_name. to_owned ( ) )
52
+ "mod" => {
53
+ let ( name, _) = parent. name_and_extension ( ) ?;
54
+ ( parent. parent ( ) ?, name. to_owned ( ) )
55
+ }
56
+ _ => ( parent, module_name. to_owned ( ) ) ,
56
57
} ;
57
58
58
59
// check crate roots, i.e. main.rs, lib.rs, ...
59
- ' outer : for & krate in & * ctx. sema . db . relevant_crates ( file_id) {
60
+ ' crates : for & krate in & * ctx. sema . db . relevant_crates ( file_id) {
60
61
let crate_def_map = ctx. sema . db . crate_def_map ( krate) ;
61
- if let Some ( root_file_id) = crate_def_map[ crate_def_map. root ( ) ] . origin . file_id ( ) {
62
- if let Some ( path) = source_root. path_for_file ( & root_file_id) {
63
- let parent2 = path. parent ( ) ?;
64
- if let Some ( rel) = parent. strip_prefix ( & parent2) {
65
- let mut current = & crate_def_map[ crate_def_map. root ( ) ] ;
66
- for ele in rel. as_ref ( ) . components ( ) {
67
- let seg = match ele {
68
- std:: path:: Component :: Normal ( seg) => seg. to_str ( ) ?,
69
- std:: path:: Component :: RootDir => continue ,
70
- // shouldn't occur
71
- _ => continue ' outer,
72
- } ;
73
- match current. children . iter ( ) . find ( |( name, _) | name. to_smol_str ( ) == seg) {
74
- Some ( ( _, child) ) => {
75
- current = & crate_def_map[ * child] ;
76
- }
77
- None => continue ' outer,
78
- }
79
- }
80
- let InFile { file_id : parent_file_id, value : source } =
81
- current. definition_source ( ctx. sema . db ) ;
82
- if let Some ( parent_file_id) = parent_file_id. file_id ( ) {
83
- return make_fixes (
84
- ctx. sema . db ,
85
- parent_file_id,
86
- source,
87
- & module_name,
88
- file_id,
89
- ) ;
90
- }
91
- }
62
+
63
+ let root_module = & crate_def_map[ crate_def_map. root ( ) ] ;
64
+ let Some ( root_file_id) = root_module. origin . file_id ( ) else { continue } ;
65
+ let Some ( crate_root_path) = source_root. path_for_file ( & root_file_id) else { continue } ;
66
+ let Some ( rel) = parent. strip_prefix ( & crate_root_path. parent ( ) ?) else { continue } ;
67
+
68
+ // try resolving the relative difference of the paths as inline modules
69
+ let mut current = root_module;
70
+ for ele in rel. as_ref ( ) . components ( ) {
71
+ let seg = match ele {
72
+ std:: path:: Component :: Normal ( seg) => seg. to_str ( ) ?,
73
+ std:: path:: Component :: RootDir => continue ,
74
+ // shouldn't occur
75
+ _ => continue ' crates,
76
+ } ;
77
+ match current. children . iter ( ) . find ( |( name, _) | name. to_smol_str ( ) == seg) {
78
+ Some ( ( _, & child) ) => current = & crate_def_map[ child] ,
79
+ None => continue ' crates,
80
+ }
81
+ if !current. origin . is_inline ( ) {
82
+ continue ' crates;
92
83
}
93
84
}
85
+
86
+ let InFile { file_id : parent_file_id, value : source } =
87
+ current. definition_source ( ctx. sema . db ) ;
88
+ let parent_file_id = parent_file_id. file_id ( ) ?;
89
+ return make_fixes ( ctx. sema . db , parent_file_id, source, & module_name, file_id) ;
94
90
}
91
+
92
+ // if we aren't adding to a crate root, walk backwards such that we support `#[path = ...]` overrides if possible
93
+
95
94
// build all parent paths of the form `../module_name/mod.rs` and `../module_name.rs`
96
95
let paths = iter:: successors ( Some ( parent. clone ( ) ) , |prev| prev. parent ( ) ) . filter_map ( |path| {
97
96
let parent = path. parent ( ) ?;
98
97
let ( name, _) = path. name_and_extension ( ) ?;
99
98
Some ( ( [ parent. join ( & format ! ( "{name}.rs" ) ) ?, path. join ( "mod.rs" ) ?] , name. to_owned ( ) ) )
100
99
} ) ;
101
100
let mut stack = vec ! [ ] ;
102
- if let Some ( & parent_id) = paths
103
- . inspect ( |( _, name) | stack. push ( name. clone ( ) ) )
104
- . find_map ( |( paths, _) | paths. into_iter ( ) . find_map ( |path| source_root. file_for_path ( & path) ) )
105
- {
106
- stack. pop ( ) ;
107
- for & krate in ctx. sema . db . relevant_crates ( parent_id) . iter ( ) {
108
- let crate_def_map = ctx. sema . db . crate_def_map ( krate) ;
109
- ' outer: for ( _, module) in crate_def_map. modules ( ) {
110
- if module. origin . file_id ( ) == Some ( parent_id) {
111
- if module. origin . is_inline ( ) {
112
- continue ;
113
- }
114
- if stack. is_empty ( ) {
115
- return make_fixes (
116
- ctx. sema . db ,
117
- parent_id,
118
- module. definition_source ( ctx. sema . db ) . value ,
119
- & module_name,
120
- file_id,
121
- ) ;
122
- } else {
123
- let mut current = module;
124
- for s in stack. iter ( ) . rev ( ) {
125
- match module. children . iter ( ) . find ( |( name, _) | name. to_smol_str ( ) == s) {
126
- Some ( ( _, child) ) => {
127
- current = & crate_def_map[ * child] ;
128
- }
129
- None => break ' outer,
130
- }
131
- }
132
- let InFile { file_id : parent_file_id, value : source } =
133
- current. definition_source ( ctx. sema . db ) ;
134
- if let Some ( parent_file_id) = parent_file_id. file_id ( ) {
135
- if current. origin . is_inline ( ) {
136
- return make_fixes (
137
- ctx. sema . db ,
138
- parent_file_id,
139
- source,
140
- & module_name,
141
- file_id,
142
- ) ;
143
- }
144
- }
145
- break ;
101
+ let & parent_id =
102
+ paths. inspect ( |( _, name) | stack. push ( name. clone ( ) ) ) . find_map ( |( paths, _) | {
103
+ paths. into_iter ( ) . find_map ( |path| source_root. file_for_path ( & path) )
104
+ } ) ?;
105
+ stack. pop ( ) ;
106
+ ' crates: for & krate in ctx. sema . db . relevant_crates ( parent_id) . iter ( ) {
107
+ let crate_def_map = ctx. sema . db . crate_def_map ( krate) ;
108
+ let Some ( ( _, module) ) =
109
+ crate_def_map. modules ( )
110
+ . find ( |( _, module) | module. origin . file_id ( ) == Some ( parent_id) && !module. origin . is_inline ( ) )
111
+ else { continue } ;
112
+
113
+ if stack. is_empty ( ) {
114
+ return make_fixes (
115
+ ctx. sema . db ,
116
+ parent_id,
117
+ module. definition_source ( ctx. sema . db ) . value ,
118
+ & module_name,
119
+ file_id,
120
+ ) ;
121
+ } else {
122
+ // direct parent file is missing,
123
+ // try finding a parent that has an inline tree from here on
124
+ let mut current = module;
125
+ for s in stack. iter ( ) . rev ( ) {
126
+ match module. children . iter ( ) . find ( |( name, _) | name. to_smol_str ( ) == s) {
127
+ Some ( ( _, child) ) => {
128
+ current = & crate_def_map[ * child] ;
146
129
}
130
+ None => continue ' crates,
131
+ }
132
+ if !current. origin . is_inline ( ) {
133
+ continue ' crates;
147
134
}
148
135
}
136
+ let InFile { file_id : parent_file_id, value : source } =
137
+ current. definition_source ( ctx. sema . db ) ;
138
+ let parent_file_id = parent_file_id. file_id ( ) ?;
139
+ return make_fixes ( ctx. sema . db , parent_file_id, source, & module_name, file_id) ;
149
140
}
150
141
}
151
142
0 commit comments