aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/source_binder.rs15
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs19
-rw-r--r--crates/ra_ide_api/src/name_ref_kind.rs2
-rw-r--r--crates/ra_ide_api/src/snapshots/rainbow_highlighting.html4
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs109
-rw-r--r--crates/ra_syntax/src/ptr.rs11
6 files changed, 92 insertions, 68 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index e7bc4df97..55eb7da35 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -181,7 +181,7 @@ pub enum PathResolution {
181 /// An item 181 /// An item
182 Def(crate::ModuleDef), 182 Def(crate::ModuleDef),
183 /// A local binding (only value namespace) 183 /// A local binding (only value namespace)
184 LocalBinding(Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>), 184 LocalBinding(Either<AstPtr<ast::BindPat>, AstPtr<ast::SelfParam>>),
185 /// A generic parameter 185 /// A generic parameter
186 GenericParam(u32), 186 GenericParam(u32),
187 SelfType(crate::ImplBlock), 187 SelfType(crate::ImplBlock),
@@ -307,7 +307,18 @@ impl SourceAnalyzer {
307 let res = match res { 307 let res = match res {
308 crate::Resolution::Def(it) => PathResolution::Def(it), 308 crate::Resolution::Def(it) => PathResolution::Def(it),
309 crate::Resolution::LocalBinding(it) => { 309 crate::Resolution::LocalBinding(it) => {
310 PathResolution::LocalBinding(self.body_source_map.as_ref()?.pat_syntax(it)?) 310 // We get a `PatId` from resolver, but it actually can only
311 // point at `BindPat`, and not at the arbitrary pattern.
312 let pat_ptr = self.body_source_map.as_ref()?.pat_syntax(it)?;
313 let pat_ptr = match pat_ptr {
314 Either::A(pat) => {
315 let pat: AstPtr<ast::BindPat> =
316 pat.cast_checking_kind(|kind| kind == BIND_PAT).unwrap();
317 Either::A(pat)
318 }
319 Either::B(self_param) => Either::B(self_param),
320 };
321 PathResolution::LocalBinding(pat_ptr)
311 } 322 }
312 crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it), 323 crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it),
313 crate::Resolution::SelfType(it) => PathResolution::SelfType(it), 324 crate::Resolution::SelfType(it) => PathResolution::SelfType(it),
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index 8cc853dd1..8aff5f2cd 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -91,24 +91,11 @@ impl NavigationTarget {
91 pub(crate) fn from_pat( 91 pub(crate) fn from_pat(
92 db: &RootDatabase, 92 db: &RootDatabase,
93 file_id: FileId, 93 file_id: FileId,
94 pat: AstPtr<ast::Pat>, 94 pat: AstPtr<ast::BindPat>,
95 ) -> NavigationTarget { 95 ) -> NavigationTarget {
96 let parse = db.parse(file_id); 96 let parse = db.parse(file_id);
97 let (name, full_range) = match pat.to_node(parse.tree().syntax()).kind() { 97 let pat = pat.to_node(parse.tree().syntax());
98 ast::PatKind::BindPat(pat) => return NavigationTarget::from_bind_pat(file_id, &pat), 98 NavigationTarget::from_bind_pat(file_id, &pat)
99 _ => ("_".into(), pat.syntax_node_ptr().range()),
100 };
101
102 NavigationTarget {
103 file_id,
104 name,
105 full_range,
106 focus_range: None,
107 kind: NAME,
108 container_name: None,
109 description: None, //< No documentation for Description
110 docs: None, //< No documentation for Pattern
111 }
112 } 99 }
113 100
114 pub(crate) fn from_self_param( 101 pub(crate) fn from_self_param(
diff --git a/crates/ra_ide_api/src/name_ref_kind.rs b/crates/ra_ide_api/src/name_ref_kind.rs
index 6832acf5d..f7db6c826 100644
--- a/crates/ra_ide_api/src/name_ref_kind.rs
+++ b/crates/ra_ide_api/src/name_ref_kind.rs
@@ -11,7 +11,7 @@ pub enum NameRefKind {
11 AssocItem(hir::ImplItem), 11 AssocItem(hir::ImplItem),
12 Def(hir::ModuleDef), 12 Def(hir::ModuleDef),
13 SelfType(hir::Ty), 13 SelfType(hir::Ty),
14 Pat(AstPtr<ast::Pat>), 14 Pat(AstPtr<ast::BindPat>),
15 SelfParam(AstPtr<ast::SelfParam>), 15 SelfParam(AstPtr<ast::SelfParam>),
16 GenericParam(u32), 16 GenericParam(u32),
17} 17}
diff --git a/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html b/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html
index c625d47bf..ed664817e 100644
--- a/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html
+++ b/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html
@@ -26,4 +26,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
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="1903207544374197704" style="color: hsl(58,61%,61%);">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="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>();
29}
30
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>;
29}</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 16a728789..0e5253025 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -4,10 +4,17 @@ use hir::{Mutability, Ty};
4use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
5use ra_prof::profile; 5use ra_prof::profile;
6use ra_syntax::{ 6use ra_syntax::{
7 ast, AstNode, Direction, SmolStr, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T, 7 ast::{self, NameOwner},
8 AstNode, Direction, SmolStr, SyntaxElement, SyntaxKind,
9 SyntaxKind::*,
10 TextRange, T,
8}; 11};
9 12
10use crate::{db::RootDatabase, FileId}; 13use crate::{
14 db::RootDatabase,
15 name_ref_kind::{classify_name_ref, NameRefKind::*},
16 FileId,
17};
11 18
12#[derive(Debug)] 19#[derive(Debug)]
13pub struct HighlightedRange { 20pub struct HighlightedRange {
@@ -31,25 +38,24 @@ fn is_control_keyword(kind: SyntaxKind) -> bool {
31 } 38 }
32} 39}
33 40
34fn is_variable_mutable(db: &RootDatabase, analyzer: &hir::SourceAnalyzer, pat: ast::Pat) -> bool { 41fn is_variable_mutable(
35 let ty = analyzer.type_of_pat(db, &pat).unwrap_or(Ty::Unknown); 42 db: &RootDatabase,
36 let is_ty_mut = { 43 analyzer: &hir::SourceAnalyzer,
37 if let Some((_, mutability)) = ty.as_reference() { 44 pat: ast::BindPat,
38 match mutability { 45) -> bool {
39 Mutability::Shared => false, 46 if pat.is_mutable() {
40 Mutability::Mut => true, 47 return true;
41 } 48 }
42 } else {
43 false
44 }
45 };
46
47 let is_pat_mut = match pat.kind() {
48 ast::PatKind::BindPat(bind_pat) => bind_pat.is_mutable(),
49 _ => false,
50 };
51 49
52 is_ty_mut || is_pat_mut 50 let ty = analyzer.type_of_pat(db, &pat.into()).unwrap_or(Ty::Unknown);
51 if let Some((_, mutability)) = ty.as_reference() {
52 match mutability {
53 Mutability::Shared => false,
54 Mutability::Mut => true,
55 }
56 } else {
57 false
58 }
53} 59}
54 60
55pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { 61pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> {
@@ -81,44 +87,45 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
81 } 87 }
82 let mut binding_hash = None; 88 let mut binding_hash = None;
83 let tag = match node.kind() { 89 let tag = match node.kind() {
90 FN_DEF => {
91 bindings_shadow_count.clear();
92 continue;
93 }
84 COMMENT => "comment", 94 COMMENT => "comment",
85 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string", 95 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string",
86 ATTR => "attribute", 96 ATTR => "attribute",
87 NAME_REF => { 97 NAME_REF => {
88 if let Some(name_ref) = node.as_node().cloned().and_then(ast::NameRef::cast) { 98 if let Some(name_ref) = node.as_node().cloned().and_then(ast::NameRef::cast) {
89 // FIXME: revisit this after #1340
90 use crate::name_ref_kind::{classify_name_ref, NameRefKind::*};
91 use hir::{ImplItem, ModuleDef};
92
93 // FIXME: try to reuse the SourceAnalyzers 99 // FIXME: try to reuse the SourceAnalyzers
94 let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); 100 let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None);
95 match classify_name_ref(db, &analyzer, &name_ref) { 101 match classify_name_ref(db, &analyzer, &name_ref) {
96 Some(Method(_)) => "function", 102 Some(Method(_)) => "function",
97 Some(Macro(_)) => "macro", 103 Some(Macro(_)) => "macro",
98 Some(FieldAccess(_)) => "field", 104 Some(FieldAccess(_)) => "field",
99 Some(AssocItem(ImplItem::Method(_))) => "function", 105 Some(AssocItem(hir::ImplItem::Method(_))) => "function",
100 Some(AssocItem(ImplItem::Const(_))) => "constant", 106 Some(AssocItem(hir::ImplItem::Const(_))) => "constant",
101 Some(AssocItem(ImplItem::TypeAlias(_))) => "type", 107 Some(AssocItem(hir::ImplItem::TypeAlias(_))) => "type",
102 Some(Def(ModuleDef::Module(_))) => "module", 108 Some(Def(hir::ModuleDef::Module(_))) => "module",
103 Some(Def(ModuleDef::Function(_))) => "function", 109 Some(Def(hir::ModuleDef::Function(_))) => "function",
104 Some(Def(ModuleDef::Struct(_))) => "type", 110 Some(Def(hir::ModuleDef::Struct(_))) => "type",
105 Some(Def(ModuleDef::Union(_))) => "type", 111 Some(Def(hir::ModuleDef::Union(_))) => "type",
106 Some(Def(ModuleDef::Enum(_))) => "type", 112 Some(Def(hir::ModuleDef::Enum(_))) => "type",
107 Some(Def(ModuleDef::EnumVariant(_))) => "constant", 113 Some(Def(hir::ModuleDef::EnumVariant(_))) => "constant",
108 Some(Def(ModuleDef::Const(_))) => "constant", 114 Some(Def(hir::ModuleDef::Const(_))) => "constant",
109 Some(Def(ModuleDef::Static(_))) => "constant", 115 Some(Def(hir::ModuleDef::Static(_))) => "constant",
110 Some(Def(ModuleDef::Trait(_))) => "type", 116 Some(Def(hir::ModuleDef::Trait(_))) => "type",
111 Some(Def(ModuleDef::TypeAlias(_))) => "type", 117 Some(Def(hir::ModuleDef::TypeAlias(_))) => "type",
112 Some(Def(ModuleDef::BuiltinType(_))) => "type", 118 Some(Def(hir::ModuleDef::BuiltinType(_))) => "type",
113 Some(SelfType(_)) => "type", 119 Some(SelfType(_)) => "type",
114 Some(Pat(ptr)) => { 120 Some(Pat(ptr)) => {
115 binding_hash = Some({ 121 let pat = ptr.to_node(&root);
116 let text = 122 if let Some(name) = pat.name() {
117 ptr.syntax_node_ptr().to_node(&root).text().to_smol_string(); 123 let text = name.text();
118 let shadow_count = 124 let shadow_count =
119 bindings_shadow_count.entry(text.clone()).or_default(); 125 bindings_shadow_count.entry(text.clone()).or_default();
120 calc_binding_hash(file_id, &text, *shadow_count) 126 binding_hash =
121 }); 127 Some(calc_binding_hash(file_id, &text, *shadow_count))
128 }
122 129
123 if is_variable_mutable(db, &analyzer, ptr.to_node(&root)) { 130 if is_variable_mutable(db, &analyzer, ptr.to_node(&root)) {
124 "variable.mut" 131 "variable.mut"
@@ -137,14 +144,14 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
137 NAME => { 144 NAME => {
138 if let Some(name) = node.as_node().cloned().and_then(ast::Name::cast) { 145 if let Some(name) = node.as_node().cloned().and_then(ast::Name::cast) {
139 let analyzer = hir::SourceAnalyzer::new(db, file_id, name.syntax(), None); 146 let analyzer = hir::SourceAnalyzer::new(db, file_id, name.syntax(), None);
140 if let Some(pat) = name.syntax().ancestors().find_map(ast::Pat::cast) { 147 if let Some(pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) {
141 binding_hash = Some({ 148 if let Some(name) = pat.name() {
142 let text = name.syntax().text().to_smol_string(); 149 let text = name.text();
143 let shadow_count = 150 let shadow_count =
144 bindings_shadow_count.entry(text.clone()).or_insert(0); 151 bindings_shadow_count.entry(text.clone()).or_default();
145 *shadow_count += 1; 152 *shadow_count += 1;
146 calc_binding_hash(file_id, &text, *shadow_count) 153 binding_hash = Some(calc_binding_hash(file_id, &text, *shadow_count))
147 }); 154 }
148 155
149 if is_variable_mutable(db, &analyzer, pat) { 156 if is_variable_mutable(db, &analyzer, pat) {
150 "variable.mut" 157 "variable.mut"
@@ -353,6 +360,10 @@ fn main() {
353 let x = "other color please!"; 360 let x = "other color please!";
354 let y = x.to_string(); 361 let y = x.to_string();
355} 362}
363
364fn bar() {
365 let mut hello = "hello";
366}
356"# 367"#
357 .trim(), 368 .trim(),
358 ); 369 );
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs
index 016256075..25824722f 100644
--- a/crates/ra_syntax/src/ptr.rs
+++ b/crates/ra_syntax/src/ptr.rs
@@ -60,6 +60,17 @@ impl<N: AstNode> AstPtr<N> {
60 pub fn syntax_node_ptr(self) -> SyntaxNodePtr { 60 pub fn syntax_node_ptr(self) -> SyntaxNodePtr {
61 self.raw 61 self.raw
62 } 62 }
63
64 // FIXME: extend AstNode to do this safely
65 pub fn cast_checking_kind<U: AstNode>(
66 self,
67 cond: impl FnOnce(SyntaxKind) -> bool,
68 ) -> Option<AstPtr<U>> {
69 if !cond(self.raw.kind()) {
70 return None;
71 }
72 Some(AstPtr { raw: self.raw, _ty: PhantomData })
73 }
63} 74}
64 75
65impl<N: AstNode> From<AstPtr<N>> for SyntaxNodePtr { 76impl<N: AstNode> From<AstPtr<N>> for SyntaxNodePtr {