diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-11-11 11:48:02 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-11-11 11:48:02 +0000 |
commit | a599147b4232c0d4f6b071a3a96e86f903f4cf52 (patch) | |
tree | fc8ddd1428c4be2babbdd713c852b31276a315f2 /crates | |
parent | ef2a9aedb6ac7f0b79e636cff7947935fecb909d (diff) | |
parent | 8b7f853cc19d0940ec542e10bc23aa78455bbb3b (diff) |
Merge #2200
2200: Add variables to HIR r=matklad a=matklad
Introduce a `hir::Variable`, which should cover locals, parameters and `self`. Unlike `PatId`, variable knows it's owner so it is self-contained, and should be more convenient to use from `ra_ide_api`.
The goal here is to hide more details about `Body` from hir, which should make it easier to move `Body` into `hir_def`. I don't think that `ra_ide_api` intrracts with bodies directly at the moment anyway, but the glue layer is based basically on `ast::BindPat`, which seems pretty brittle.
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 55 | ||||
-rw-r--r-- | crates/ra_hir/src/expr/scope.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/from_source.rs | 30 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 20 | ||||
-rw-r--r-- | crates/ra_ide_api/src/display/navigation_target.rs | 70 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide_api/src/hover.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/classify.rs | 22 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/name_definition.rs | 38 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/search_scope.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide_api/src/snapshots/rainbow_highlighting.html | 12 | ||||
-rw-r--r-- | crates/ra_ide_api/src/syntax_highlighting.rs | 79 |
14 files changed, 171 insertions, 173 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index e5bfad3ca..09c4e97fa 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -22,7 +22,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | |||
22 | use crate::{ | 22 | use crate::{ |
23 | adt::VariantDef, | 23 | adt::VariantDef, |
24 | db::{AstDatabase, DefDatabase, HirDatabase}, | 24 | db::{AstDatabase, DefDatabase, HirDatabase}, |
25 | expr::{validation::ExprValidator, Body, BodySourceMap}, | 25 | expr::{validation::ExprValidator, BindingAnnotation, Body, BodySourceMap, Pat, PatId}, |
26 | generics::HasGenericParams, | 26 | generics::HasGenericParams, |
27 | ids::{ | 27 | ids::{ |
28 | AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, | 28 | AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, |
@@ -32,7 +32,7 @@ use crate::{ | |||
32 | resolve::{Resolver, Scope, TypeNs}, | 32 | resolve::{Resolver, Scope, TypeNs}, |
33 | traits::TraitData, | 33 | traits::TraitData, |
34 | ty::{InferenceResult, Namespace, TraitRef}, | 34 | ty::{InferenceResult, Namespace, TraitRef}, |
35 | Either, HasSource, ImportId, Name, ScopeDef, Ty, | 35 | Either, HasSource, ImportId, Name, ScopeDef, Source, Ty, |
36 | }; | 36 | }; |
37 | 37 | ||
38 | /// hir::Crate describes a single crate. It's the main interface with which | 38 | /// hir::Crate describes a single crate. It's the main interface with which |
@@ -1070,3 +1070,54 @@ impl AssocItem { | |||
1070 | .expect("AssocItem without container") | 1070 | .expect("AssocItem without container") |
1071 | } | 1071 | } |
1072 | } | 1072 | } |
1073 | |||
1074 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1075 | pub struct Local { | ||
1076 | pub(crate) parent: DefWithBody, | ||
1077 | pub(crate) pat_id: PatId, | ||
1078 | } | ||
1079 | |||
1080 | impl Local { | ||
1081 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { | ||
1082 | let body = db.body_hir(self.parent); | ||
1083 | match &body[self.pat_id] { | ||
1084 | Pat::Bind { name, .. } => Some(name.clone()), | ||
1085 | _ => None, | ||
1086 | } | ||
1087 | } | ||
1088 | |||
1089 | pub fn is_self(self, db: &impl HirDatabase) -> bool { | ||
1090 | self.name(db) == Some(name::SELF_PARAM) | ||
1091 | } | ||
1092 | |||
1093 | pub fn is_mut(self, db: &impl HirDatabase) -> bool { | ||
1094 | let body = db.body_hir(self.parent); | ||
1095 | match &body[self.pat_id] { | ||
1096 | Pat::Bind { mode, .. } => match mode { | ||
1097 | BindingAnnotation::Mutable | BindingAnnotation::RefMut => true, | ||
1098 | _ => false, | ||
1099 | }, | ||
1100 | _ => false, | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1104 | pub fn parent(self, _db: &impl HirDatabase) -> DefWithBody { | ||
1105 | self.parent | ||
1106 | } | ||
1107 | |||
1108 | pub fn module(self, db: &impl HirDatabase) -> Module { | ||
1109 | self.parent.module(db) | ||
1110 | } | ||
1111 | |||
1112 | pub fn ty(self, db: &impl HirDatabase) -> Ty { | ||
1113 | let infer = db.infer(self.parent); | ||
1114 | infer[self.pat_id].clone() | ||
1115 | } | ||
1116 | |||
1117 | pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { | ||
1118 | let (_body, source_map) = db.body_with_source_map(self.parent); | ||
1119 | let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm... | ||
1120 | let root = src.file_syntax(db); | ||
1121 | src.map(|ast| ast.map(|it| it.cast().unwrap().to_node(&root), |it| it.to_node(&root))) | ||
1122 | } | ||
1123 | } | ||
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 5a1eade2c..daf8d8d07 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs | |||
@@ -17,7 +17,7 @@ impl_arena_id!(ScopeId); | |||
17 | 17 | ||
18 | #[derive(Debug, PartialEq, Eq)] | 18 | #[derive(Debug, PartialEq, Eq)] |
19 | pub struct ExprScopes { | 19 | pub struct ExprScopes { |
20 | body: Arc<Body>, | 20 | pub(crate) body: Arc<Body>, |
21 | scopes: Arena<ScopeId, ScopeData>, | 21 | scopes: Arena<ScopeId, ScopeData>, |
22 | scope_by_expr: FxHashMap<ExprId, ScopeId>, | 22 | scope_by_expr: FxHashMap<ExprId, ScopeId>, |
23 | } | 23 | } |
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index c95d2cdd0..2c441b0f4 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs | |||
@@ -2,13 +2,17 @@ | |||
2 | 2 | ||
3 | use hir_def::{StructId, StructOrUnionId, UnionId}; | 3 | use hir_def::{StructId, StructOrUnionId, UnionId}; |
4 | use hir_expand::name::AsName; | 4 | use hir_expand::name::AsName; |
5 | use ra_syntax::ast::{self, AstNode, NameOwner}; | 5 | use ra_syntax::{ |
6 | ast::{self, AstNode, NameOwner}, | ||
7 | match_ast, | ||
8 | }; | ||
6 | 9 | ||
7 | use crate::{ | 10 | use crate::{ |
8 | db::{AstDatabase, DefDatabase, HirDatabase}, | 11 | db::{AstDatabase, DefDatabase, HirDatabase}, |
9 | ids::{AstItemDef, LocationCtx}, | 12 | ids::{AstItemDef, LocationCtx}, |
10 | AstId, Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module, | 13 | AstId, Const, Crate, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasSource, |
11 | ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, | 14 | ImplBlock, Local, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, |
15 | Union, VariantDef, | ||
12 | }; | 16 | }; |
13 | 17 | ||
14 | pub trait FromSource: Sized { | 18 | pub trait FromSource: Sized { |
@@ -126,6 +130,26 @@ impl FromSource for StructField { | |||
126 | } | 130 | } |
127 | } | 131 | } |
128 | 132 | ||
133 | impl Local { | ||
134 | pub fn from_source(db: &impl HirDatabase, src: Source<ast::BindPat>) -> Option<Self> { | ||
135 | let file_id = src.file_id; | ||
136 | let parent: DefWithBody = src.ast.syntax().ancestors().find_map(|it| { | ||
137 | let res = match_ast! { | ||
138 | match it { | ||
139 | ast::ConstDef(ast) => { Const::from_source(db, Source { ast, file_id})?.into() }, | ||
140 | ast::StaticDef(ast) => { Static::from_source(db, Source { ast, file_id})?.into() }, | ||
141 | ast::FnDef(ast) => { Function::from_source(db, Source { ast, file_id})?.into() }, | ||
142 | _ => return None, | ||
143 | } | ||
144 | }; | ||
145 | Some(res) | ||
146 | })?; | ||
147 | let (_body, source_map) = db.body_with_source_map(parent); | ||
148 | let pat_id = source_map.node_pat(&src.ast.into())?; | ||
149 | Some(Local { parent, pat_id }) | ||
150 | } | ||
151 | } | ||
152 | |||
129 | impl Module { | 153 | impl Module { |
130 | pub fn from_declaration(db: &impl HirDatabase, src: Source<ast::Module>) -> Option<Self> { | 154 | pub fn from_declaration(db: &impl HirDatabase, src: Source<ast::Module>) -> Option<Self> { |
131 | let src_parent = Source { | 155 | let src_parent = Source { |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 9dc8d139b..806f1daed 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -65,7 +65,7 @@ pub use crate::{ | |||
65 | docs::{DocDef, Docs, Documentation}, | 65 | docs::{DocDef, Docs, Documentation}, |
66 | src::{HasBodySource, HasSource}, | 66 | src::{HasBodySource, HasSource}, |
67 | Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum, | 67 | Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum, |
68 | EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, ModuleDef, | 68 | EnumVariant, FieldSource, FnData, Function, HasBody, Local, MacroDef, Module, ModuleDef, |
69 | ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, | 69 | ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, |
70 | }, | 70 | }, |
71 | expr::ExprScopes, | 71 | expr::ExprScopes, |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 66cb4b357..c5fdf3bab 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -28,7 +28,7 @@ use crate::{ | |||
28 | ids::LocationCtx, | 28 | ids::LocationCtx, |
29 | resolve::{ScopeDef, TypeNs, ValueNs}, | 29 | resolve::{ScopeDef, TypeNs, ValueNs}, |
30 | ty::method_resolution::{self, implements_trait}, | 30 | ty::method_resolution::{self, implements_trait}, |
31 | AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, | 31 | AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, Local, |
32 | MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, | 32 | MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, |
33 | }; | 33 | }; |
34 | 34 | ||
@@ -94,6 +94,7 @@ fn def_with_body_from_child_node( | |||
94 | #[derive(Debug)] | 94 | #[derive(Debug)] |
95 | pub struct SourceAnalyzer { | 95 | pub struct SourceAnalyzer { |
96 | resolver: Resolver, | 96 | resolver: Resolver, |
97 | body_owner: Option<DefWithBody>, | ||
97 | body_source_map: Option<Arc<BodySourceMap>>, | 98 | body_source_map: Option<Arc<BodySourceMap>>, |
98 | infer: Option<Arc<crate::ty::InferenceResult>>, | 99 | infer: Option<Arc<crate::ty::InferenceResult>>, |
99 | scopes: Option<Arc<crate::expr::ExprScopes>>, | 100 | scopes: Option<Arc<crate::expr::ExprScopes>>, |
@@ -104,7 +105,7 @@ pub enum PathResolution { | |||
104 | /// An item | 105 | /// An item |
105 | Def(crate::ModuleDef), | 106 | Def(crate::ModuleDef), |
106 | /// A local binding (only value namespace) | 107 | /// A local binding (only value namespace) |
107 | LocalBinding(Either<AstPtr<ast::BindPat>, AstPtr<ast::SelfParam>>), | 108 | Local(Local), |
108 | /// A generic parameter | 109 | /// A generic parameter |
109 | GenericParam(u32), | 110 | GenericParam(u32), |
110 | SelfType(crate::ImplBlock), | 111 | SelfType(crate::ImplBlock), |
@@ -152,6 +153,7 @@ impl SourceAnalyzer { | |||
152 | let resolver = expr::resolver_for_scope(def.body(db), db, scope); | 153 | let resolver = expr::resolver_for_scope(def.body(db), db, scope); |
153 | SourceAnalyzer { | 154 | SourceAnalyzer { |
154 | resolver, | 155 | resolver, |
156 | body_owner: Some(def), | ||
155 | body_source_map: Some(source_map), | 157 | body_source_map: Some(source_map), |
156 | infer: Some(def.infer(db)), | 158 | infer: Some(def.infer(db)), |
157 | scopes: Some(scopes), | 159 | scopes: Some(scopes), |
@@ -162,6 +164,7 @@ impl SourceAnalyzer { | |||
162 | .ancestors() | 164 | .ancestors() |
163 | .find_map(|node| try_get_resolver_for_node(db, file_id, &node)) | 165 | .find_map(|node| try_get_resolver_for_node(db, file_id, &node)) |
164 | .unwrap_or_default(), | 166 | .unwrap_or_default(), |
167 | body_owner: None, | ||
165 | body_source_map: None, | 168 | body_source_map: None, |
166 | infer: None, | 169 | infer: None, |
167 | scopes: None, | 170 | scopes: None, |
@@ -233,16 +236,9 @@ impl SourceAnalyzer { | |||
233 | }); | 236 | }); |
234 | let values = self.resolver.resolve_path_in_value_ns_fully(db, &path).and_then(|val| { | 237 | let values = self.resolver.resolve_path_in_value_ns_fully(db, &path).and_then(|val| { |
235 | let res = match val { | 238 | let res = match val { |
236 | ValueNs::LocalBinding(it) => { | 239 | ValueNs::LocalBinding(pat_id) => { |
237 | // We get a `PatId` from resolver, but it actually can only | 240 | let var = Local { parent: self.body_owner?, pat_id }; |
238 | // point at `BindPat`, and not at the arbitrary pattern. | 241 | PathResolution::Local(var) |
239 | let pat_ptr = self | ||
240 | .body_source_map | ||
241 | .as_ref()? | ||
242 | .pat_syntax(it)? | ||
243 | .ast // FIXME: ignoring file_id here is definitelly wrong | ||
244 | .map_a(|ptr| ptr.cast::<ast::BindPat>().unwrap()); | ||
245 | PathResolution::LocalBinding(pat_ptr) | ||
246 | } | 242 | } |
247 | ValueNs::Function(it) => PathResolution::Def(it.into()), | 243 | ValueNs::Function(it) => PathResolution::Def(it.into()), |
248 | ValueNs::Const(it) => PathResolution::Def(it.into()), | 244 | ValueNs::Const(it) => PathResolution::Def(it.into()), |
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs index 41d467564..f7ad08515 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs | |||
@@ -1,11 +1,11 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{AssocItem, FieldSource, HasSource, ModuleSource}; | 3 | use hir::{AssocItem, Either, FieldSource, HasSource, ModuleSource}; |
4 | use ra_db::{FileId, SourceDatabase}; | 4 | use ra_db::{FileId, SourceDatabase}; |
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | ast::{self, DocCommentsOwner}, | 6 | ast::{self, DocCommentsOwner, NameOwner}, |
7 | match_ast, AstNode, AstPtr, SmolStr, | 7 | match_ast, AstNode, SmolStr, |
8 | SyntaxKind::{self, NAME}, | 8 | SyntaxKind::{self, BIND_PAT}, |
9 | SyntaxNode, TextRange, | 9 | SyntaxNode, TextRange, |
10 | }; | 10 | }; |
11 | 11 | ||
@@ -76,42 +76,6 @@ impl NavigationTarget { | |||
76 | self.focus_range | 76 | self.focus_range |
77 | } | 77 | } |
78 | 78 | ||
79 | pub(crate) fn from_bind_pat( | ||
80 | db: &RootDatabase, | ||
81 | file_id: FileId, | ||
82 | pat: &ast::BindPat, | ||
83 | ) -> NavigationTarget { | ||
84 | NavigationTarget::from_named(db, file_id.into(), pat, None, None) | ||
85 | } | ||
86 | |||
87 | pub(crate) fn from_pat( | ||
88 | db: &RootDatabase, | ||
89 | file_id: FileId, | ||
90 | pat: AstPtr<ast::BindPat>, | ||
91 | ) -> NavigationTarget { | ||
92 | let parse = db.parse(file_id); | ||
93 | let pat = pat.to_node(parse.tree().syntax()); | ||
94 | NavigationTarget::from_bind_pat(db, file_id, &pat) | ||
95 | } | ||
96 | |||
97 | pub(crate) fn from_self_param( | ||
98 | file_id: FileId, | ||
99 | par: AstPtr<ast::SelfParam>, | ||
100 | ) -> NavigationTarget { | ||
101 | let (name, full_range) = ("self".into(), par.syntax_node_ptr().range()); | ||
102 | |||
103 | NavigationTarget { | ||
104 | file_id, | ||
105 | name, | ||
106 | full_range, | ||
107 | focus_range: None, | ||
108 | kind: NAME, | ||
109 | container_name: None, | ||
110 | description: None, //< No document node for SelfParam | ||
111 | docs: None, //< No document node for SelfParam | ||
112 | } | ||
113 | } | ||
114 | |||
115 | pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { | 79 | pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { |
116 | let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); | 80 | let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); |
117 | if let Some(src) = module.declaration_source(db) { | 81 | if let Some(src) = module.declaration_source(db) { |
@@ -370,6 +334,32 @@ impl ToNav for hir::AssocItem { | |||
370 | } | 334 | } |
371 | } | 335 | } |
372 | 336 | ||
337 | impl ToNav for hir::Local { | ||
338 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | ||
339 | let src = self.source(db); | ||
340 | let (full_range, focus_range) = match src.ast { | ||
341 | Either::A(it) => { | ||
342 | (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range())) | ||
343 | } | ||
344 | Either::B(it) => (it.syntax().text_range(), Some(it.self_kw_token().text_range())), | ||
345 | }; | ||
346 | let name = match self.name(db) { | ||
347 | Some(it) => it.to_string().into(), | ||
348 | None => "".into(), | ||
349 | }; | ||
350 | NavigationTarget { | ||
351 | file_id: src.file_id.original_file(db), | ||
352 | name, | ||
353 | kind: BIND_PAT, | ||
354 | full_range, | ||
355 | focus_range, | ||
356 | container_name: None, | ||
357 | description: None, | ||
358 | docs: None, | ||
359 | } | ||
360 | } | ||
361 | } | ||
362 | |||
373 | fn find_range_from_node( | 363 | fn find_range_from_node( |
374 | db: &RootDatabase, | 364 | db: &RootDatabase, |
375 | src: hir::HirFileId, | 365 | src: hir::HirFileId, |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 713b61d5e..6c8387f6c 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -68,8 +68,7 @@ pub(crate) fn reference_definition( | |||
68 | return Exact(adt.to_nav(db)); | 68 | return Exact(adt.to_nav(db)); |
69 | } | 69 | } |
70 | } | 70 | } |
71 | Some(Pat((_, pat))) => return Exact(NavigationTarget::from_pat(db, file_id, pat)), | 71 | Some(Local(local)) => return Exact(local.to_nav(db)), |
72 | Some(SelfParam(par)) => return Exact(NavigationTarget::from_self_param(file_id, par)), | ||
73 | Some(GenericParam(_)) => { | 72 | Some(GenericParam(_)) => { |
74 | // FIXME: go to the generic param def | 73 | // FIXME: go to the generic param def |
75 | } | 74 | } |
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index cc41390b2..086e6dec3 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -143,7 +143,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
143 | }) | 143 | }) |
144 | } | 144 | } |
145 | } | 145 | } |
146 | Some(Pat(_)) | Some(SelfParam(_)) => { | 146 | Some(Local(_)) => { |
147 | // Hover for these shows type names | 147 | // Hover for these shows type names |
148 | no_fallback = true; | 148 | no_fallback = true; |
149 | } | 149 | } |
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 0a76bf484..9cb9433e7 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs | |||
@@ -86,8 +86,7 @@ pub(crate) fn find_all_refs( | |||
86 | Some((adt, _)) => adt.to_nav(db), | 86 | Some((adt, _)) => adt.to_nav(db), |
87 | None => return None, | 87 | None => return None, |
88 | }, | 88 | }, |
89 | NameKind::Pat((_, pat)) => NavigationTarget::from_pat(db, position.file_id, pat), | 89 | NameKind::Local(local) => local.to_nav(db), |
90 | NameKind::SelfParam(par) => NavigationTarget::from_self_param(position.file_id, par), | ||
91 | NameKind::GenericParam(_) => return None, | 90 | NameKind::GenericParam(_) => return None, |
92 | }; | 91 | }; |
93 | 92 | ||
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 153082d5b..217f9951e 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs | |||
@@ -1,13 +1,13 @@ | |||
1 | //! Functions that are used to classify an element from its definition or reference. | 1 | //! Functions that are used to classify an element from its definition or reference. |
2 | 2 | ||
3 | use hir::{Either, FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; | 3 | use hir::{FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; |
4 | use ra_db::FileId; | 4 | use ra_db::FileId; |
5 | use ra_prof::profile; | 5 | use ra_prof::profile; |
6 | use ra_syntax::{ast, match_ast, AstNode, AstPtr}; | 6 | use ra_syntax::{ast, match_ast, AstNode}; |
7 | use test_utils::tested_by; | 7 | use test_utils::tested_by; |
8 | 8 | ||
9 | use super::{ | 9 | use super::{ |
10 | name_definition::{from_assoc_item, from_module_def, from_pat, from_struct_field}, | 10 | name_definition::{from_assoc_item, from_module_def, from_struct_field}, |
11 | NameDefinition, NameKind, | 11 | NameDefinition, NameKind, |
12 | }; | 12 | }; |
13 | use crate::db::RootDatabase; | 13 | use crate::db::RootDatabase; |
@@ -25,7 +25,13 @@ pub(crate) fn classify_name( | |||
25 | match_ast! { | 25 | match_ast! { |
26 | match parent { | 26 | match parent { |
27 | ast::BindPat(it) => { | 27 | ast::BindPat(it) => { |
28 | from_pat(db, file_id, AstPtr::new(&it)) | 28 | let src = hir::Source { file_id, ast: it }; |
29 | let local = hir::Local::from_source(db, src)?; | ||
30 | Some(NameDefinition { | ||
31 | visibility: None, | ||
32 | container: local.module(db), | ||
33 | kind: NameKind::Local(local), | ||
34 | }) | ||
29 | }, | 35 | }, |
30 | ast::RecordFieldDef(it) => { | 36 | ast::RecordFieldDef(it) => { |
31 | let ast = hir::FieldSource::Named(it); | 37 | let ast = hir::FieldSource::Named(it); |
@@ -159,10 +165,10 @@ pub(crate) fn classify_name_ref( | |||
159 | match resolved { | 165 | match resolved { |
160 | Def(def) => Some(from_module_def(db, def, Some(container))), | 166 | Def(def) => Some(from_module_def(db, def, Some(container))), |
161 | AssocItem(item) => Some(from_assoc_item(db, item)), | 167 | AssocItem(item) => Some(from_assoc_item(db, item)), |
162 | LocalBinding(Either::A(pat)) => from_pat(db, file_id, pat), | 168 | Local(local) => { |
163 | LocalBinding(Either::B(par)) => { | 169 | let container = local.module(db); |
164 | let kind = NameKind::SelfParam(par); | 170 | let kind = NameKind::Local(local); |
165 | Some(NameDefinition { kind, container, visibility }) | 171 | Some(NameDefinition { kind, container, visibility: None }) |
166 | } | 172 | } |
167 | GenericParam(par) => { | 173 | GenericParam(par) => { |
168 | // FIXME: get generic param def | 174 | // FIXME: get generic param def |
diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs index 4580bc789..450f7ea9b 100644 --- a/crates/ra_ide_api/src/references/name_definition.rs +++ b/crates/ra_ide_api/src/references/name_definition.rs | |||
@@ -4,10 +4,9 @@ | |||
4 | //! Note that the reference search is possible for not all of the classified items. | 4 | //! Note that the reference search is possible for not all of the classified items. |
5 | 5 | ||
6 | use hir::{ | 6 | use hir::{ |
7 | db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef, | 7 | Adt, AssocItem, HasSource, Local, MacroDef, Module, ModuleDef, StructField, Ty, VariantDef, |
8 | Module, ModuleDef, StructField, Ty, VariantDef, | ||
9 | }; | 8 | }; |
10 | use ra_syntax::{ast, ast::VisibilityOwner, match_ast, AstNode, AstPtr}; | 9 | use ra_syntax::{ast, ast::VisibilityOwner}; |
11 | 10 | ||
12 | use crate::db::RootDatabase; | 11 | use crate::db::RootDatabase; |
13 | 12 | ||
@@ -18,8 +17,7 @@ pub enum NameKind { | |||
18 | AssocItem(AssocItem), | 17 | AssocItem(AssocItem), |
19 | Def(ModuleDef), | 18 | Def(ModuleDef), |
20 | SelfType(Ty), | 19 | SelfType(Ty), |
21 | Pat((DefWithBody, AstPtr<ast::BindPat>)), | 20 | Local(Local), |
22 | SelfParam(AstPtr<ast::SelfParam>), | ||
23 | GenericParam(u32), | 21 | GenericParam(u32), |
24 | } | 22 | } |
25 | 23 | ||
@@ -30,36 +28,6 @@ pub(crate) struct NameDefinition { | |||
30 | pub kind: NameKind, | 28 | pub kind: NameKind, |
31 | } | 29 | } |
32 | 30 | ||
33 | pub(super) fn from_pat( | ||
34 | db: &RootDatabase, | ||
35 | file_id: HirFileId, | ||
36 | pat: AstPtr<ast::BindPat>, | ||
37 | ) -> Option<NameDefinition> { | ||
38 | let root = db.parse_or_expand(file_id)?; | ||
39 | let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { | ||
40 | match_ast! { | ||
41 | match node { | ||
42 | ast::FnDef(it) => { | ||
43 | let src = hir::Source { file_id, ast: it }; | ||
44 | Some(hir::Function::from_source(db, src)?.into()) | ||
45 | }, | ||
46 | ast::ConstDef(it) => { | ||
47 | let src = hir::Source { file_id, ast: it }; | ||
48 | Some(hir::Const::from_source(db, src)?.into()) | ||
49 | }, | ||
50 | ast::StaticDef(it) => { | ||
51 | let src = hir::Source { file_id, ast: it }; | ||
52 | Some(hir::Static::from_source(db, src)?.into()) | ||
53 | }, | ||
54 | _ => None, | ||
55 | } | ||
56 | } | ||
57 | })?; | ||
58 | let kind = NameKind::Pat((def, pat)); | ||
59 | let container = def.module(db); | ||
60 | Some(NameDefinition { kind, container, visibility: None }) | ||
61 | } | ||
62 | |||
63 | pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition { | 31 | pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition { |
64 | let container = item.module(db); | 32 | let container = item.module(db); |
65 | let visibility = match item { | 33 | let visibility = match item { |
diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide_api/src/references/search_scope.rs index f2789e0b2..2907787c2 100644 --- a/crates/ra_ide_api/src/references/search_scope.rs +++ b/crates/ra_ide_api/src/references/search_scope.rs | |||
@@ -71,13 +71,13 @@ impl NameDefinition { | |||
71 | let module_src = self.container.definition_source(db); | 71 | let module_src = self.container.definition_source(db); |
72 | let file_id = module_src.file_id.original_file(db); | 72 | let file_id = module_src.file_id.original_file(db); |
73 | 73 | ||
74 | if let NameKind::Pat((def, _)) = self.kind { | 74 | if let NameKind::Local(var) = self.kind { |
75 | let mut res = FxHashMap::default(); | 75 | let range = match var.parent(db) { |
76 | let range = match def { | ||
77 | DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), | 76 | DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), |
78 | DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), | 77 | DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), |
79 | DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), | 78 | DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), |
80 | }; | 79 | }; |
80 | let mut res = FxHashMap::default(); | ||
81 | res.insert(file_id, Some(range)); | 81 | res.insert(file_id, Some(range)); |
82 | return SearchScope::new(res); | 82 | return SearchScope::new(res); |
83 | } | 83 | } |
diff --git a/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html b/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html index ed664817e..79f11ea80 100644 --- a/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html | |||
@@ -20,14 +20,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
20 | .keyword\.control { color: #F0DFAF; font-weight: bold; } | 20 | .keyword\.control { color: #F0DFAF; font-weight: bold; } |
21 | </style> | 21 | </style> |
22 | <pre><code><span class="keyword">fn</span> <span class="function">main</span>() { | 22 | <pre><code><span class="keyword">fn</span> <span class="function">main</span>() { |
23 | <span class="keyword">let</span> <span class="variable" data-binding-hash="3888301305669440875" style="color: hsl(242,59%,59%);">hello</span> = <span class="string">"hello"</span>; | 23 | <span class="keyword">let</span> <span class="variable" data-binding-hash="8723171760279909834" style="color: hsl(307,91%,75%);">hello</span> = <span class="string">"hello"</span>; |
24 | <span class="keyword">let</span> <span class="variable" data-binding-hash="5695551762718493399" style="color: hsl(272,48%,45%);">x</span> = <span class="variable" data-binding-hash="3888301305669440875" style="color: hsl(242,59%,59%);">hello</span>.<span class="text">to_string</span>(); | 24 | <span class="keyword">let</span> <span class="variable" data-binding-hash="14702933417323009544" style="color: hsl(108,90%,49%);">x</span> = <span class="variable" data-binding-hash="8723171760279909834" style="color: hsl(307,91%,75%);">hello</span>.<span class="text">to_string</span>(); |
25 | <span class="keyword">let</span> <span class="variable" data-binding-hash="5435401749617022797" style="color: hsl(353,77%,74%);">y</span> = <span class="variable" data-binding-hash="3888301305669440875" style="color: hsl(242,59%,59%);">hello</span>.<span class="text">to_string</span>(); | 25 | <span class="keyword">let</span> <span class="variable" data-binding-hash="5443150872754369068" style="color: hsl(215,43%,43%);">y</span> = <span class="variable" data-binding-hash="8723171760279909834" style="color: hsl(307,91%,75%);">hello</span>.<span class="text">to_string</span>(); |
26 | 26 | ||
27 | <span class="keyword">let</span> <span class="variable" data-binding-hash="1903207544374197704" style="color: hsl(58,61%,61%);">x</span> = <span class="string">"other color please!"</span>; | 27 | <span class="keyword">let</span> <span class="variable" data-binding-hash="17358108296605513516" style="color: hsl(331,46%,60%);">x</span> = <span class="string">"other color please!"</span>; |
28 | <span class="keyword">let</span> <span class="variable" data-binding-hash="14878783531007968800" style="color: hsl(265,73%,83%);">y</span> = <span class="variable" data-binding-hash="1903207544374197704" style="color: hsl(58,61%,61%);">x</span>.<span class="text">to_string</span>(); | 28 | <span class="keyword">let</span> <span class="variable" data-binding-hash="2073121142529774969" style="color: hsl(320,43%,74%);">y</span> = <span class="variable" data-binding-hash="17358108296605513516" style="color: hsl(331,46%,60%);">x</span>.<span class="text">to_string</span>(); |
29 | } | 29 | } |
30 | 30 | ||
31 | <span class="keyword">fn</span> <span class="function">bar</span>() { | 31 | <span class="keyword">fn</span> <span class="function">bar</span>() { |
32 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable.mut" data-binding-hash="3888301305669440875" style="color: hsl(242,59%,59%);">hello</span> = <span class="string">"hello"</span>; | 32 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable.mut" data-binding-hash="8723171760279909834" style="color: hsl(307,91%,75%);">hello</span> = <span class="string">"hello"</span>; |
33 | }</code></pre> \ No newline at end of file | 33 | }</code></pre> \ No newline at end of file |
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 1ee68abe2..d53a759ee 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs | |||
@@ -2,15 +2,10 @@ | |||
2 | 2 | ||
3 | use rustc_hash::{FxHashMap, FxHashSet}; | 3 | use rustc_hash::{FxHashMap, FxHashSet}; |
4 | 4 | ||
5 | use hir::{Mutability, Ty}; | 5 | use hir::{Mutability, Name}; |
6 | use ra_db::SourceDatabase; | 6 | use ra_db::SourceDatabase; |
7 | use ra_prof::profile; | 7 | use ra_prof::profile; |
8 | use ra_syntax::{ | 8 | use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T}; |
9 | ast::{self, NameOwner}, | ||
10 | AstNode, Direction, SmolStr, SyntaxElement, SyntaxKind, | ||
11 | SyntaxKind::*, | ||
12 | SyntaxNode, TextRange, T, | ||
13 | }; | ||
14 | 9 | ||
15 | use crate::{ | 10 | use crate::{ |
16 | db::RootDatabase, | 11 | db::RootDatabase, |
@@ -43,32 +38,12 @@ fn is_control_keyword(kind: SyntaxKind) -> bool { | |||
43 | } | 38 | } |
44 | } | 39 | } |
45 | 40 | ||
46 | fn is_variable_mutable( | ||
47 | db: &RootDatabase, | ||
48 | analyzer: &hir::SourceAnalyzer, | ||
49 | pat: ast::BindPat, | ||
50 | ) -> bool { | ||
51 | if pat.is_mutable() { | ||
52 | return true; | ||
53 | } | ||
54 | |||
55 | let ty = analyzer.type_of_pat(db, &pat.into()).unwrap_or(Ty::Unknown); | ||
56 | if let Some((_, mutability)) = ty.as_reference() { | ||
57 | match mutability { | ||
58 | Mutability::Shared => false, | ||
59 | Mutability::Mut => true, | ||
60 | } | ||
61 | } else { | ||
62 | false | ||
63 | } | ||
64 | } | ||
65 | |||
66 | pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { | 41 | pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { |
67 | let _p = profile("highlight"); | 42 | let _p = profile("highlight"); |
68 | let parse = db.parse(file_id); | 43 | let parse = db.parse(file_id); |
69 | let root = parse.tree().syntax().clone(); | 44 | let root = parse.tree().syntax().clone(); |
70 | 45 | ||
71 | fn calc_binding_hash(file_id: FileId, text: &SmolStr, shadow_count: u32) -> u64 { | 46 | fn calc_binding_hash(file_id: FileId, name: &Name, shadow_count: u32) -> u64 { |
72 | fn hash<T: std::hash::Hash + std::fmt::Debug>(x: T) -> u64 { | 47 | fn hash<T: std::hash::Hash + std::fmt::Debug>(x: T) -> u64 { |
73 | use std::{collections::hash_map::DefaultHasher, hash::Hasher}; | 48 | use std::{collections::hash_map::DefaultHasher, hash::Hasher}; |
74 | 49 | ||
@@ -77,13 +52,13 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
77 | hasher.finish() | 52 | hasher.finish() |
78 | } | 53 | } |
79 | 54 | ||
80 | hash((file_id, text, shadow_count)) | 55 | hash((file_id, name, shadow_count)) |
81 | } | 56 | } |
82 | 57 | ||
83 | // Visited nodes to handle highlighting priorities | 58 | // Visited nodes to handle highlighting priorities |
84 | // FIXME: retain only ranges here | 59 | // FIXME: retain only ranges here |
85 | let mut highlighted: FxHashSet<SyntaxElement> = FxHashSet::default(); | 60 | let mut highlighted: FxHashSet<SyntaxElement> = FxHashSet::default(); |
86 | let mut bindings_shadow_count: FxHashMap<SmolStr, u32> = FxHashMap::default(); | 61 | let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default(); |
87 | 62 | ||
88 | let mut res = Vec::new(); | 63 | let mut res = Vec::new(); |
89 | for node in root.descendants_with_tokens() { | 64 | for node in root.descendants_with_tokens() { |
@@ -107,34 +82,29 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
107 | let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); | 82 | let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); |
108 | let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); | 83 | let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); |
109 | 84 | ||
110 | if let Some(Pat((_, ptr))) = &name_kind { | 85 | if let Some(Local(local)) = &name_kind { |
111 | let pat = ptr.to_node(&root); | 86 | if let Some(name) = local.name(db) { |
112 | if let Some(name) = pat.name() { | 87 | let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); |
113 | let text = name.text(); | 88 | binding_hash = Some(calc_binding_hash(file_id, &name, *shadow_count)) |
114 | let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); | ||
115 | binding_hash = Some(calc_binding_hash(file_id, &text, *shadow_count)) | ||
116 | } | 89 | } |
117 | }; | 90 | }; |
118 | 91 | ||
119 | name_kind | 92 | name_kind.map_or("text", |it| highlight_name(db, it)) |
120 | .map_or("text", |it| highlight_name(db, file_id, name_ref.syntax(), &root, it)) | ||
121 | } | 93 | } |
122 | NAME => { | 94 | NAME => { |
123 | let name = node.as_node().cloned().and_then(ast::Name::cast).unwrap(); | 95 | let name = node.as_node().cloned().and_then(ast::Name::cast).unwrap(); |
124 | let name_kind = classify_name(db, file_id, &name).map(|d| d.kind); | 96 | let name_kind = classify_name(db, file_id, &name).map(|d| d.kind); |
125 | 97 | ||
126 | if let Some(Pat((_, ptr))) = &name_kind { | 98 | if let Some(Local(local)) = &name_kind { |
127 | let pat = ptr.to_node(&root); | 99 | if let Some(name) = local.name(db) { |
128 | if let Some(name) = pat.name() { | 100 | let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); |
129 | let text = name.text(); | ||
130 | let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); | ||
131 | *shadow_count += 1; | 101 | *shadow_count += 1; |
132 | binding_hash = Some(calc_binding_hash(file_id, &text, *shadow_count)) | 102 | binding_hash = Some(calc_binding_hash(file_id, &name, *shadow_count)) |
133 | } | 103 | } |
134 | }; | 104 | }; |
135 | 105 | ||
136 | match name_kind { | 106 | match name_kind { |
137 | Some(name_kind) => highlight_name(db, file_id, name.syntax(), &root, name_kind), | 107 | Some(name_kind) => highlight_name(db, name_kind), |
138 | None => name.syntax().parent().map_or("function", |x| match x.kind() { | 108 | None => name.syntax().parent().map_or("function", |x| match x.kind() { |
139 | TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => "type", | 109 | TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => "type", |
140 | RECORD_FIELD_DEF => "field", | 110 | RECORD_FIELD_DEF => "field", |
@@ -237,13 +207,7 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo | |||
237 | buf | 207 | buf |
238 | } | 208 | } |
239 | 209 | ||
240 | fn highlight_name( | 210 | fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str { |
241 | db: &RootDatabase, | ||
242 | file_id: FileId, | ||
243 | node: &SyntaxNode, | ||
244 | root: &SyntaxNode, | ||
245 | name_kind: NameKind, | ||
246 | ) -> &'static str { | ||
247 | match name_kind { | 211 | match name_kind { |
248 | Macro(_) => "macro", | 212 | Macro(_) => "macro", |
249 | Field(_) => "field", | 213 | Field(_) => "field", |
@@ -260,14 +224,15 @@ fn highlight_name( | |||
260 | Def(hir::ModuleDef::TypeAlias(_)) => "type", | 224 | Def(hir::ModuleDef::TypeAlias(_)) => "type", |
261 | Def(hir::ModuleDef::BuiltinType(_)) => "type", | 225 | Def(hir::ModuleDef::BuiltinType(_)) => "type", |
262 | SelfType(_) => "type", | 226 | SelfType(_) => "type", |
263 | SelfParam(_) => "type", | ||
264 | GenericParam(_) => "type", | 227 | GenericParam(_) => "type", |
265 | Pat((_, ptr)) => { | 228 | Local(local) => { |
266 | let analyzer = hir::SourceAnalyzer::new(db, file_id, node, None); | 229 | if local.is_mut(db) { |
267 | if is_variable_mutable(db, &analyzer, ptr.to_node(&root)) { | ||
268 | "variable.mut" | 230 | "variable.mut" |
269 | } else { | 231 | } else { |
270 | "variable" | 232 | match local.ty(db).as_reference() { |
233 | Some((_, Mutability::Mut)) => "variable.mut", | ||
234 | _ => "variable", | ||
235 | } | ||
271 | } | 236 | } |
272 | } | 237 | } |
273 | } | 238 | } |