diff options
author | Aleksey Kladov <[email protected]> | 2020-02-28 15:36:14 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-02-28 15:38:36 +0000 |
commit | 5ebfcb9cb757ece936f631cf69136e1d38cb6afc (patch) | |
tree | 2fe6a843fb15a62e3177b473e99118778619ca39 | |
parent | 209eb32796c6fd56d1b378690c807cf73ce54235 (diff) |
Fix highlighting of const patterns
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 31 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlighting.html | 15 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tests.rs | 17 | ||||
-rw-r--r-- | crates/ra_ide_db/src/defs.rs | 6 |
5 files changed, 61 insertions, 16 deletions
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index c3d8ee1ae..154adedb3 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -18,8 +18,8 @@ use crate::{ | |||
18 | db::HirDatabase, | 18 | db::HirDatabase, |
19 | source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer}, | 19 | source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer}, |
20 | source_binder::{ChildContainer, SourceBinder}, | 20 | source_binder::{ChildContainer, SourceBinder}, |
21 | Function, HirFileId, InFile, Local, MacroDef, Module, Name, Origin, Path, PathResolution, | 21 | Function, HirFileId, InFile, Local, MacroDef, Module, ModuleDef, Name, Origin, Path, |
22 | ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, | 22 | PathResolution, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, |
23 | }; | 23 | }; |
24 | use ra_prof::profile; | 24 | use ra_prof::profile; |
25 | 25 | ||
@@ -129,6 +129,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
129 | self.analyze(path.syntax()).resolve_path(self.db, path) | 129 | self.analyze(path.syntax()).resolve_path(self.db, path) |
130 | } | 130 | } |
131 | 131 | ||
132 | pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> { | ||
133 | self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat) | ||
134 | } | ||
135 | |||
132 | // FIXME: use this instead? | 136 | // FIXME: use this instead? |
133 | // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>; | 137 | // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>; |
134 | 138 | ||
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index b655e2c32..c650a9e08 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -11,9 +11,9 @@ use either::Either; | |||
11 | use hir_def::{ | 11 | use hir_def::{ |
12 | body::{ | 12 | body::{ |
13 | scope::{ExprScopes, ScopeId}, | 13 | scope::{ExprScopes, ScopeId}, |
14 | BodySourceMap, | 14 | Body, BodySourceMap, |
15 | }, | 15 | }, |
16 | expr::{ExprId, PatId}, | 16 | expr::{ExprId, Pat, PatId}, |
17 | resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, | 17 | resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, |
18 | AsMacroCall, DefWithBodyId, | 18 | AsMacroCall, DefWithBodyId, |
19 | }; | 19 | }; |
@@ -25,8 +25,8 @@ use ra_syntax::{ | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | use crate::{ | 27 | use crate::{ |
28 | db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, Path, Static, Struct, | 28 | db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, ModuleDef, Path, Static, |
29 | Trait, Type, TypeAlias, TypeParam, | 29 | Struct, Trait, Type, TypeAlias, TypeParam, |
30 | }; | 30 | }; |
31 | 31 | ||
32 | /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of | 32 | /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of |
@@ -35,6 +35,7 @@ use crate::{ | |||
35 | pub(crate) struct SourceAnalyzer { | 35 | pub(crate) struct SourceAnalyzer { |
36 | file_id: HirFileId, | 36 | file_id: HirFileId, |
37 | pub(crate) resolver: Resolver, | 37 | pub(crate) resolver: Resolver, |
38 | body: Option<Arc<Body>>, | ||
38 | body_source_map: Option<Arc<BodySourceMap>>, | 39 | body_source_map: Option<Arc<BodySourceMap>>, |
39 | infer: Option<Arc<InferenceResult>>, | 40 | infer: Option<Arc<InferenceResult>>, |
40 | scopes: Option<Arc<ExprScopes>>, | 41 | scopes: Option<Arc<ExprScopes>>, |
@@ -66,7 +67,7 @@ impl SourceAnalyzer { | |||
66 | node: InFile<&SyntaxNode>, | 67 | node: InFile<&SyntaxNode>, |
67 | offset: Option<TextUnit>, | 68 | offset: Option<TextUnit>, |
68 | ) -> SourceAnalyzer { | 69 | ) -> SourceAnalyzer { |
69 | let (_body, source_map) = db.body_with_source_map(def); | 70 | let (body, source_map) = db.body_with_source_map(def); |
70 | let scopes = db.expr_scopes(def); | 71 | let scopes = db.expr_scopes(def); |
71 | let scope = match offset { | 72 | let scope = match offset { |
72 | None => scope_for(&scopes, &source_map, node), | 73 | None => scope_for(&scopes, &source_map, node), |
@@ -75,6 +76,7 @@ impl SourceAnalyzer { | |||
75 | let resolver = resolver_for_scope(db, def, scope); | 76 | let resolver = resolver_for_scope(db, def, scope); |
76 | SourceAnalyzer { | 77 | SourceAnalyzer { |
77 | resolver, | 78 | resolver, |
79 | body: Some(body), | ||
78 | body_source_map: Some(source_map), | 80 | body_source_map: Some(source_map), |
79 | infer: Some(db.infer(def)), | 81 | infer: Some(db.infer(def)), |
80 | scopes: Some(scopes), | 82 | scopes: Some(scopes), |
@@ -88,6 +90,7 @@ impl SourceAnalyzer { | |||
88 | ) -> SourceAnalyzer { | 90 | ) -> SourceAnalyzer { |
89 | SourceAnalyzer { | 91 | SourceAnalyzer { |
90 | resolver, | 92 | resolver, |
93 | body: None, | ||
91 | body_source_map: None, | 94 | body_source_map: None, |
92 | infer: None, | 95 | infer: None, |
93 | scopes: None, | 96 | scopes: None, |
@@ -197,6 +200,24 @@ impl SourceAnalyzer { | |||
197 | self.resolver.resolve_path_as_macro(db, path.mod_path()).map(|it| it.into()) | 200 | self.resolver.resolve_path_as_macro(db, path.mod_path()).map(|it| it.into()) |
198 | } | 201 | } |
199 | 202 | ||
203 | pub(crate) fn resolve_bind_pat_to_const( | ||
204 | &self, | ||
205 | db: &impl HirDatabase, | ||
206 | pat: &ast::BindPat, | ||
207 | ) -> Option<ModuleDef> { | ||
208 | let pat_id = self.pat_id(&pat.clone().into())?; | ||
209 | let body = self.body.as_ref()?; | ||
210 | let path = match &body[pat_id] { | ||
211 | Pat::Path(path) => path, | ||
212 | _ => return None, | ||
213 | }; | ||
214 | let res = resolve_hir_path(db, &self.resolver, &path)?; | ||
215 | match res { | ||
216 | PathResolution::Def(def) => Some(def), | ||
217 | _ => None, | ||
218 | } | ||
219 | } | ||
220 | |||
200 | pub(crate) fn resolve_path( | 221 | pub(crate) fn resolve_path( |
201 | &self, | 222 | &self, |
202 | db: &impl HirDatabase, | 223 | db: &impl HirDatabase, |
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 8c372ad27..cb4097e05 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html | |||
@@ -65,10 +65,17 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
65 | <span class="variable mutable">y</span>; | 65 | <span class="variable mutable">y</span>; |
66 | } | 66 | } |
67 | 67 | ||
68 | <span class="keyword">enum</span> <span class="enum">E</span><<span class="type_param">X</span>> { | 68 | <span class="keyword">enum</span> <span class="enum">Option</span><<span class="type_param">T</span>> { |
69 | <span class="enum_variant">V</span>(<span class="type_param">X</span>) | 69 | <span class="enum_variant">Some</span>(<span class="type_param">T</span>), |
70 | <span class="enum_variant">None</span>, | ||
70 | } | 71 | } |
72 | <span class="keyword">use</span> <span class="enum">Option</span>::*; | ||
71 | 73 | ||
72 | <span class="keyword">impl</span><<span class="type_param">X</span>> <span class="enum">E</span><<span class="type_param">X</span>> { | 74 | <span class="keyword">impl</span><<span class="type_param">T</span>> <span class="enum">Option</span><<span class="type_param">T</span>> { |
73 | <span class="keyword">fn</span> <span class="function">new</span><<span class="type_param">T</span>>() -> <span class="enum">E</span><<span class="type_param">T</span>> {} | 75 | <span class="keyword">fn</span> <span class="function">and</span><<span class="type_param">U</span>>(<span class="keyword">self</span>, <span class="variable">other</span>: <span class="enum">Option</span><<span class="type_param">U</span>>) -> <span class="enum">Option</span><(<span class="type_param">T</span>, <span class="type_param">U</span>)> { |
76 | <span class="keyword control">match</span> <span class="variable">other</span> { | ||
77 | <span class="enum_variant">None</span> => <span class="macro">todo</span><span class="macro">!</span>(), | ||
78 | <span class="variable">Nope</span> => <span class="variable">Nope</span>, | ||
79 | } | ||
80 | } | ||
74 | }</code></pre> \ No newline at end of file | 81 | }</code></pre> \ No newline at end of file |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index 2d90a072f..21c4dd818 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -50,12 +50,19 @@ fn main() { | |||
50 | y; | 50 | y; |
51 | } | 51 | } |
52 | 52 | ||
53 | enum E<X> { | 53 | enum Option<T> { |
54 | V(X) | 54 | Some(T), |
55 | None, | ||
55 | } | 56 | } |
56 | 57 | use Option::*; | |
57 | impl<X> E<X> { | 58 | |
58 | fn new<T>() -> E<T> {} | 59 | impl<T> Option<T> { |
60 | fn and<U>(self, other: Option<U>) -> Option<(T, U)> { | ||
61 | match other { | ||
62 | None => todo!(), | ||
63 | Nope => Nope, | ||
64 | } | ||
65 | } | ||
59 | } | 66 | } |
60 | "# | 67 | "# |
61 | .trim(), | 68 | .trim(), |
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 3079d1197..93f32ba85 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs | |||
@@ -90,6 +90,12 @@ impl NameClass { | |||
90 | } | 90 | } |
91 | 91 | ||
92 | pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { | 92 | pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { |
93 | if let Some(bind_pat) = name.syntax().parent().and_then(ast::BindPat::cast) { | ||
94 | if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { | ||
95 | return Some(NameClass::ConstReference(NameDefinition::ModuleDef(def))); | ||
96 | } | ||
97 | } | ||
98 | |||
93 | classify_name_inner(sema, name).map(NameClass::NameDefinition) | 99 | classify_name_inner(sema, name).map(NameClass::NameDefinition) |
94 | } | 100 | } |
95 | 101 | ||