11
11
use { CrateLint , PathResult } ;
12
12
use macros:: ParentScope ;
13
13
14
- use std:: collections:: BTreeSet ;
15
-
16
14
use syntax:: ast:: Ident ;
17
- use syntax:: symbol:: { keywords, Symbol } ;
15
+ use syntax:: symbol:: keywords;
18
16
use syntax_pos:: Span ;
19
17
20
18
use resolve_imports:: ImportResolver ;
19
+ use std:: cmp:: Reverse ;
21
20
22
21
impl < ' a , ' b : ' a , ' c : ' b > ImportResolver < ' a , ' b , ' c > {
23
22
/// Add suggestions for a path that cannot be resolved.
24
23
pub ( crate ) fn make_path_suggestion (
25
24
& mut self ,
26
25
span : Span ,
27
- path : Vec < Ident > ,
26
+ mut path : Vec < Ident > ,
28
27
parent_scope : & ParentScope < ' b > ,
29
28
) -> Option < ( Vec < Ident > , Option < String > ) > {
30
29
debug ! ( "make_path_suggestion: span={:?} path={:?}" , span, path) ;
31
- // If we don't have a path to suggest changes to, then return.
32
- if path. is_empty ( ) {
33
- return None ;
34
- }
35
-
36
- // Check whether a ident is a path segment that is not root.
37
- let is_special = |ident : Ident | ident. is_path_segment_keyword ( ) &&
38
- ident. name != keywords:: CrateRoot . name ( ) ;
39
30
40
31
match ( path. get ( 0 ) , path. get ( 1 ) ) {
41
- // Make suggestions that require at least two non-special path segments.
42
- ( Some ( fst) , Some ( snd) ) if !is_special ( * fst) && !is_special ( * snd) => {
43
- debug ! ( "make_path_suggestion: fst={:?} snd={:?}" , fst, snd) ;
44
-
45
- self . make_missing_self_suggestion ( span, path. clone ( ) , parent_scope)
46
- . or_else ( || self . make_missing_crate_suggestion ( span, path. clone ( ) ,
47
- parent_scope) )
48
- . or_else ( || self . make_missing_super_suggestion ( span, path. clone ( ) ,
49
- parent_scope) )
50
- . or_else ( || self . make_external_crate_suggestion ( span, path, parent_scope) )
51
- } ,
52
- _ => None ,
32
+ // `{{root}}::ident::...` on both editions.
33
+ // On 2015 `{{root}}` is usually added implicitly.
34
+ ( Some ( fst) , Some ( snd) ) if fst. name == keywords:: CrateRoot . name ( ) &&
35
+ !snd. is_path_segment_keyword ( ) => { }
36
+ // `ident::...` on 2018
37
+ ( Some ( fst) , _) if self . session . rust_2018 ( ) && !fst. is_path_segment_keyword ( ) => {
38
+ // Insert a placeholder that's later replaced by `self`/`super`/etc.
39
+ path. insert ( 0 , keywords:: Invalid . ident ( ) ) ;
40
+ }
41
+ _ => return None ,
53
42
}
43
+
44
+ self . make_missing_self_suggestion ( span, path. clone ( ) , parent_scope)
45
+ . or_else ( || self . make_missing_crate_suggestion ( span, path. clone ( ) , parent_scope) )
46
+ . or_else ( || self . make_missing_super_suggestion ( span, path. clone ( ) , parent_scope) )
47
+ . or_else ( || self . make_external_crate_suggestion ( span, path, parent_scope) )
54
48
}
55
49
56
50
/// Suggest a missing `self::` if that resolves to an correct module.
@@ -148,22 +142,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
148
142
mut path : Vec < Ident > ,
149
143
parent_scope : & ParentScope < ' b > ,
150
144
) -> Option < ( Vec < Ident > , Option < String > ) > {
151
- // Need to clone else we can't call `resolve_path` without a borrow error. We also store
152
- // into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic)
153
- // each time.
154
- let external_crate_names: BTreeSet < Symbol > = self . resolver . extern_prelude
155
- . iter ( ) . map ( |( ident, _) | ident. name ) . collect ( ) ;
145
+ if !self . session . rust_2018 ( ) {
146
+ return None ;
147
+ }
156
148
157
- // Insert a new path segment that we can replace.
158
- let new_path_segment = path[ 0 ] . clone ( ) ;
159
- path. insert ( 1 , new_path_segment) ;
149
+ // Sort extern crate names in reverse order to get
150
+ // 1) some consistent ordering for emitted dignostics and
151
+ // 2) `std` suggestions before `core` suggestions.
152
+ let mut extern_crate_names =
153
+ self . resolver . extern_prelude . iter ( ) . map ( |( ident, _) | ident. name ) . collect :: < Vec < _ > > ( ) ;
154
+ extern_crate_names. sort_by_key ( |name| Reverse ( name. as_str ( ) ) ) ;
160
155
161
- // Iterate in reverse so that we start with crates at the end of the alphabet. This means
162
- // that we'll always get `std` before `core`.
163
- for name in external_crate_names. iter ( ) . rev ( ) {
164
- // Replace the first after root (a placeholder we inserted) with a crate name
165
- // and check if that is valid.
166
- path[ 1 ] . name = * name;
156
+ for name in extern_crate_names. into_iter ( ) {
157
+ // Replace first ident with a crate name and check if that is valid.
158
+ path[ 0 ] . name = name;
167
159
let result = self . resolve_path ( & path, None , parent_scope, false , span, CrateLint :: No ) ;
168
160
debug ! ( "make_external_crate_suggestion: name={:?} path={:?} result={:?}" ,
169
161
name, path, result) ;
@@ -172,8 +164,6 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
172
164
}
173
165
}
174
166
175
- // Remove our placeholder segment.
176
- path. remove ( 1 ) ;
177
167
None
178
168
}
179
169
}
0 commit comments