mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
Merge #3367
3367: Fix highlighting of const patterns r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
c692e07b4f
13 changed files with 143 additions and 70 deletions
|
@ -17,8 +17,8 @@ use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer},
|
source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer},
|
||||||
source_binder::{ChildContainer, SourceBinder},
|
source_binder::{ChildContainer, SourceBinder},
|
||||||
Function, HirFileId, InFile, Local, MacroDef, Module, Name, Origin, Path, PathResolution,
|
Function, HirFileId, InFile, Local, MacroDef, Module, ModuleDef, Name, Origin, Path,
|
||||||
ScopeDef, StructField, Trait, Type, TypeParam, VariantDef,
|
PathResolution, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef,
|
||||||
};
|
};
|
||||||
use hir_expand::ExpansionInfo;
|
use hir_expand::ExpansionInfo;
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
|
@ -129,6 +129,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
||||||
self.analyze(path.syntax()).resolve_path(self.db, path)
|
self.analyze(path.syntax()).resolve_path(self.db, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> {
|
||||||
|
self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat)
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: use this instead?
|
// FIXME: use this instead?
|
||||||
// pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
|
// pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@ use either::Either;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
body::{
|
body::{
|
||||||
scope::{ExprScopes, ScopeId},
|
scope::{ExprScopes, ScopeId},
|
||||||
BodySourceMap,
|
Body, BodySourceMap,
|
||||||
},
|
},
|
||||||
expr::{ExprId, PatId},
|
expr::{ExprId, Pat, PatId},
|
||||||
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
|
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
|
||||||
AsMacroCall, DefWithBodyId,
|
AsMacroCall, DefWithBodyId,
|
||||||
};
|
};
|
||||||
|
@ -25,8 +25,8 @@ use ra_syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, Path, Static, Struct,
|
db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, ModuleDef, Path, Static,
|
||||||
Trait, Type, TypeAlias, TypeParam,
|
Struct, Trait, Type, TypeAlias, TypeParam,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
|
/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
|
||||||
|
@ -35,6 +35,7 @@ use crate::{
|
||||||
pub(crate) struct SourceAnalyzer {
|
pub(crate) struct SourceAnalyzer {
|
||||||
file_id: HirFileId,
|
file_id: HirFileId,
|
||||||
pub(crate) resolver: Resolver,
|
pub(crate) resolver: Resolver,
|
||||||
|
body: Option<Arc<Body>>,
|
||||||
body_source_map: Option<Arc<BodySourceMap>>,
|
body_source_map: Option<Arc<BodySourceMap>>,
|
||||||
infer: Option<Arc<InferenceResult>>,
|
infer: Option<Arc<InferenceResult>>,
|
||||||
scopes: Option<Arc<ExprScopes>>,
|
scopes: Option<Arc<ExprScopes>>,
|
||||||
|
@ -66,7 +67,7 @@ impl SourceAnalyzer {
|
||||||
node: InFile<&SyntaxNode>,
|
node: InFile<&SyntaxNode>,
|
||||||
offset: Option<TextUnit>,
|
offset: Option<TextUnit>,
|
||||||
) -> SourceAnalyzer {
|
) -> SourceAnalyzer {
|
||||||
let (_body, source_map) = db.body_with_source_map(def);
|
let (body, source_map) = db.body_with_source_map(def);
|
||||||
let scopes = db.expr_scopes(def);
|
let scopes = db.expr_scopes(def);
|
||||||
let scope = match offset {
|
let scope = match offset {
|
||||||
None => scope_for(&scopes, &source_map, node),
|
None => scope_for(&scopes, &source_map, node),
|
||||||
|
@ -75,6 +76,7 @@ impl SourceAnalyzer {
|
||||||
let resolver = resolver_for_scope(db, def, scope);
|
let resolver = resolver_for_scope(db, def, scope);
|
||||||
SourceAnalyzer {
|
SourceAnalyzer {
|
||||||
resolver,
|
resolver,
|
||||||
|
body: Some(body),
|
||||||
body_source_map: Some(source_map),
|
body_source_map: Some(source_map),
|
||||||
infer: Some(db.infer(def)),
|
infer: Some(db.infer(def)),
|
||||||
scopes: Some(scopes),
|
scopes: Some(scopes),
|
||||||
|
@ -88,6 +90,7 @@ impl SourceAnalyzer {
|
||||||
) -> SourceAnalyzer {
|
) -> SourceAnalyzer {
|
||||||
SourceAnalyzer {
|
SourceAnalyzer {
|
||||||
resolver,
|
resolver,
|
||||||
|
body: None,
|
||||||
body_source_map: None,
|
body_source_map: None,
|
||||||
infer: None,
|
infer: None,
|
||||||
scopes: None,
|
scopes: None,
|
||||||
|
@ -197,6 +200,24 @@ impl SourceAnalyzer {
|
||||||
self.resolver.resolve_path_as_macro(db, path.mod_path()).map(|it| it.into())
|
self.resolver.resolve_path_as_macro(db, path.mod_path()).map(|it| it.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn resolve_bind_pat_to_const(
|
||||||
|
&self,
|
||||||
|
db: &impl HirDatabase,
|
||||||
|
pat: &ast::BindPat,
|
||||||
|
) -> Option<ModuleDef> {
|
||||||
|
let pat_id = self.pat_id(&pat.clone().into())?;
|
||||||
|
let body = self.body.as_ref()?;
|
||||||
|
let path = match &body[pat_id] {
|
||||||
|
Pat::Path(path) => path,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
let res = resolve_hir_path(db, &self.resolver, &path)?;
|
||||||
|
match res {
|
||||||
|
PathResolution::Def(def) => Some(def),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn resolve_path(
|
pub(crate) fn resolve_path(
|
||||||
&self,
|
&self,
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
|
|
|
@ -30,7 +30,9 @@ pub(crate) fn goto_definition(
|
||||||
reference_definition(&sema, &name_ref).to_vec()
|
reference_definition(&sema, &name_ref).to_vec()
|
||||||
},
|
},
|
||||||
ast::Name(name) => {
|
ast::Name(name) => {
|
||||||
name_definition(&sema, &name)?
|
let def = classify_name(&sema, &name)?.definition();
|
||||||
|
let nav = def.try_to_nav(sema.db)?;
|
||||||
|
vec![nav]
|
||||||
},
|
},
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
|
@ -88,15 +90,6 @@ pub(crate) fn reference_definition(
|
||||||
Approximate(navs)
|
Approximate(navs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name_definition(
|
|
||||||
sema: &Semantics<RootDatabase>,
|
|
||||||
name: &ast::Name,
|
|
||||||
) -> Option<Vec<NavigationTarget>> {
|
|
||||||
let def = classify_name(sema, name)?;
|
|
||||||
let nav = def.try_to_nav(sema.db)?;
|
|
||||||
Some(vec![nav])
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use test_utils::{assert_eq_text, covers};
|
use test_utils::{assert_eq_text, covers};
|
||||||
|
|
|
@ -156,7 +156,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
|
||||||
classify_name_ref(&sema, &name_ref).map(|d| (name_ref.syntax().clone(), d))
|
classify_name_ref(&sema, &name_ref).map(|d| (name_ref.syntax().clone(), d))
|
||||||
},
|
},
|
||||||
ast::Name(name) => {
|
ast::Name(name) => {
|
||||||
classify_name(&sema, &name).map(|d| (name.syntax().clone(), d))
|
classify_name(&sema, &name).map(|d| (name.syntax().clone(), d.definition()))
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -785,13 +785,13 @@ fn func(foo: i32) { if true { <|>foo; }; }
|
||||||
fn test_hover_through_literal_string_in_builtin_macro() {
|
fn test_hover_through_literal_string_in_builtin_macro() {
|
||||||
check_hover_no_result(
|
check_hover_no_result(
|
||||||
r#"
|
r#"
|
||||||
//- /lib.rs
|
//- /lib.rs
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
macro_rules! assert {
|
macro_rules! assert {
|
||||||
($cond:expr) => {{ /* compiler built-in */ }};
|
($cond:expr) => {{ /* compiler built-in */ }};
|
||||||
($cond:expr,) => {{ /* compiler built-in */ }};
|
($cond:expr,) => {{ /* compiler built-in */ }};
|
||||||
($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
|
($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo() {
|
fn foo() {
|
||||||
assert!("hel<|>lo");
|
assert!("hel<|>lo");
|
||||||
|
|
|
@ -155,7 +155,7 @@ fn find_name(
|
||||||
opt_name: Option<ast::Name>,
|
opt_name: Option<ast::Name>,
|
||||||
) -> Option<RangeInfo<(String, NameDefinition)>> {
|
) -> Option<RangeInfo<(String, NameDefinition)>> {
|
||||||
if let Some(name) = opt_name {
|
if let Some(name) = opt_name {
|
||||||
let def = classify_name(sema, &name)?;
|
let def = classify_name(sema, &name)?.definition();
|
||||||
let range = name.syntax().text_range();
|
let range = name.syntax().text_range();
|
||||||
return Some(RangeInfo::new(range, (name.text().to_string(), def)));
|
return Some(RangeInfo::new(range, (name.text().to_string(), def)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
body { margin: 0; }
|
body { margin: 0; }
|
||||||
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
|
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
|
||||||
|
|
||||||
|
.lifetime { color: #DFAF8F; font-style: italic; }
|
||||||
.comment { color: #7F9F7F; }
|
.comment { color: #7F9F7F; }
|
||||||
.struct, .enum { color: #7CB8BB; }
|
.struct, .enum { color: #7CB8BB; }
|
||||||
.enum_variant { color: #BDE0F3; }
|
.enum_variant { color: #BDE0F3; }
|
||||||
|
@ -27,14 +27,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="attribute">#</span><span class="attribute">[</span><span class="attribute">derive</span><span class="attribute">(</span><span class="attribute">Clone</span><span class="attribute">,</span><span class="attribute"> </span><span class="attribute">Debug</span><span class="attribute">)</span><span class="attribute">]</span>
|
<pre><code><span class="attribute">#</span><span class="attribute">[</span><span class="attribute">derive</span><span class="attribute">(</span><span class="attribute">Clone</span><span class="attribute">,</span><span class="attribute"> </span><span class="attribute">Debug</span><span class="attribute">)</span><span class="attribute">]</span>
|
||||||
<span class="keyword">struct</span> <span class="struct">Foo</span> {
|
<span class="keyword">struct</span> <span class="struct declaration">Foo</span> {
|
||||||
<span class="keyword">pub</span> <span class="field">x</span>: <span class="builtin_type">i32</span>,
|
<span class="keyword">pub</span> <span class="field declaration">x</span>: <span class="builtin_type">i32</span>,
|
||||||
<span class="keyword">pub</span> <span class="field">y</span>: <span class="builtin_type">i32</span>,
|
<span class="keyword">pub</span> <span class="field declaration">y</span>: <span class="builtin_type">i32</span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="keyword">fn</span> <span class="function">foo</span><<span class="type_param">T</span>>() -> <span class="type_param">T</span> {
|
<span class="keyword">fn</span> <span class="function declaration">foo</span><<span class="lifetime declaration">'a</span>, <span class="type_param declaration">T</span>>() -> <span class="type_param">T</span> {
|
||||||
<span class="macro">unimplemented</span><span class="macro">!</span>();
|
<span class="function">foo</span>::<<span class="lifetime">'a</span>, <span class="builtin_type">i32</span>>()
|
||||||
<span class="function">foo</span>::<<span class="builtin_type">i32</span>>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="macro">macro_rules</span><span class="macro">!</span> def_fn {
|
<span class="macro">macro_rules</span><span class="macro">!</span> def_fn {
|
||||||
|
@ -42,33 +41,40 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="macro">def_fn</span><span class="macro">!</span> {
|
<span class="macro">def_fn</span><span class="macro">!</span> {
|
||||||
<span class="keyword">fn</span> <span class="function">bar</span>() -> <span class="builtin_type">u32</span> {
|
<span class="keyword">fn</span> <span class="function declaration">bar</span>() -> <span class="builtin_type">u32</span> {
|
||||||
<span class="numeric_literal">100</span>
|
<span class="numeric_literal">100</span>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="comment">// comment</span>
|
<span class="comment">// comment</span>
|
||||||
<span class="keyword">fn</span> <span class="function">main</span>() {
|
<span class="keyword">fn</span> <span class="function declaration">main</span>() {
|
||||||
<span class="macro">println</span><span class="macro">!</span>(<span class="string_literal">"Hello, {}!"</span>, <span class="numeric_literal">92</span>);
|
<span class="macro">println</span><span class="macro">!</span>(<span class="string_literal">"Hello, {}!"</span>, <span class="numeric_literal">92</span>);
|
||||||
|
|
||||||
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable mutable">vec</span> = Vec::new();
|
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">vec</span> = Vec::new();
|
||||||
<span class="keyword control">if</span> <span class="keyword">true</span> {
|
<span class="keyword control">if</span> <span class="keyword">true</span> {
|
||||||
<span class="keyword">let</span> <span class="variable">x</span> = <span class="numeric_literal">92</span>;
|
<span class="keyword">let</span> <span class="variable declaration">x</span> = <span class="numeric_literal">92</span>;
|
||||||
<span class="variable mutable">vec</span>.push(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> });
|
<span class="variable mutable">vec</span>.push(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> });
|
||||||
}
|
}
|
||||||
<span class="keyword unsafe">unsafe</span> { <span class="variable mutable">vec</span>.set_len(<span class="numeric_literal">0</span>); }
|
<span class="keyword unsafe">unsafe</span> { <span class="variable mutable">vec</span>.set_len(<span class="numeric_literal">0</span>); }
|
||||||
|
|
||||||
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable mutable">x</span> = <span class="numeric_literal">42</span>;
|
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>;
|
||||||
<span class="keyword">let</span> <span class="variable mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>;
|
<span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>;
|
||||||
<span class="keyword">let</span> <span class="variable">z</span> = &<span class="variable mutable">y</span>;
|
<span class="keyword">let</span> <span class="variable declaration">z</span> = &<span class="variable mutable">y</span>;
|
||||||
|
|
||||||
<span class="variable mutable">y</span>;
|
<span class="variable mutable">y</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="keyword">enum</span> <span class="enum">E</span><<span class="type_param">X</span>> {
|
<span class="keyword">enum</span> <span class="enum declaration">Option</span><<span class="type_param declaration">T</span>> {
|
||||||
<span class="enum_variant">V</span>(<span class="type_param">X</span>)
|
<span class="enum_variant declaration">Some</span>(<span class="type_param">T</span>),
|
||||||
|
<span class="enum_variant declaration">None</span>,
|
||||||
}
|
}
|
||||||
|
<span class="keyword">use</span> <span class="enum">Option</span>::*;
|
||||||
|
|
||||||
<span class="keyword">impl</span><<span class="type_param">X</span>> <span class="enum">E</span><<span class="type_param">X</span>> {
|
<span class="keyword">impl</span><<span class="type_param declaration">T</span>> <span class="enum">Option</span><<span class="type_param">T</span>> {
|
||||||
<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>> {}
|
<span class="keyword">fn</span> <span class="function declaration">and</span><<span class="type_param declaration">U</span>>(<span class="keyword">self</span>, <span class="variable declaration">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>)> {
|
||||||
|
<span class="keyword control">match</span> <span class="variable">other</span> {
|
||||||
|
<span class="enum_variant">None</span> => <span class="macro">unimplemented</span><span class="macro">!</span>(),
|
||||||
|
<span class="variable declaration">Nope</span> => <span class="variable">Nope</span>,
|
||||||
|
}
|
||||||
|
}
|
||||||
}</code></pre>
|
}</code></pre>
|
|
@ -3,7 +3,7 @@
|
||||||
body { margin: 0; }
|
body { margin: 0; }
|
||||||
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
|
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
|
||||||
|
|
||||||
|
.lifetime { color: #DFAF8F; font-style: italic; }
|
||||||
.comment { color: #7F9F7F; }
|
.comment { color: #7F9F7F; }
|
||||||
.struct, .enum { color: #7CB8BB; }
|
.struct, .enum { color: #7CB8BB; }
|
||||||
.enum_variant { color: #BDE0F3; }
|
.enum_variant { color: #BDE0F3; }
|
||||||
|
@ -26,15 +26,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.keyword.unsafe { color: #BC8383; font-weight: bold; }
|
.keyword.unsafe { color: #BC8383; font-weight: bold; }
|
||||||
.control { font-style: italic; }
|
.control { font-style: italic; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">fn</span> <span class="function">main</span>() {
|
<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span>() {
|
||||||
<span class="keyword">let</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> = <span class="string_literal">"hello"</span>;
|
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> = <span class="string_literal">"hello"</span>;
|
||||||
<span class="keyword">let</span> <span class="variable" data-binding-hash="2705725358298919760" style="color: hsl(17,51%,74%);">x</span> = <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span>.to_string();
|
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2705725358298919760" style="color: hsl(17,51%,74%);">x</span> = <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span>.to_string();
|
||||||
<span class="keyword">let</span> <span class="variable" data-binding-hash="3365759661443752373" style="color: hsl(127,76%,66%);">y</span> = <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span>.to_string();
|
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="3365759661443752373" style="color: hsl(127,76%,66%);">y</span> = <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span>.to_string();
|
||||||
|
|
||||||
<span class="keyword">let</span> <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span> = <span class="string_literal">"other color please!"</span>;
|
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span> = <span class="string_literal">"other color please!"</span>;
|
||||||
<span class="keyword">let</span> <span class="variable" data-binding-hash="6717528807933952652" style="color: hsl(85,49%,84%);">y</span> = <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span>.to_string();
|
<span class="keyword">let</span> <span class="variable declaration" data-binding-hash="6717528807933952652" style="color: hsl(85,49%,84%);">y</span> = <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span>.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="keyword">fn</span> <span class="function">bar</span>() {
|
<span class="keyword">fn</span> <span class="function declaration">bar</span>() {
|
||||||
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable mutable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> = <span class="string_literal">"hello"</span>;
|
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> = <span class="string_literal">"hello"</span>;
|
||||||
}</code></pre>
|
}</code></pre>
|
|
@ -7,7 +7,7 @@ mod tests;
|
||||||
|
|
||||||
use hir::{Name, Semantics};
|
use hir::{Name, Semantics};
|
||||||
use ra_ide_db::{
|
use ra_ide_db::{
|
||||||
defs::{classify_name, NameDefinition},
|
defs::{classify_name, NameClass, NameDefinition},
|
||||||
RootDatabase,
|
RootDatabase,
|
||||||
};
|
};
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
|
@ -169,7 +169,7 @@ fn highlight_element(
|
||||||
let name = element.into_node().and_then(ast::Name::cast).unwrap();
|
let name = element.into_node().and_then(ast::Name::cast).unwrap();
|
||||||
let name_kind = classify_name(sema, &name);
|
let name_kind = classify_name(sema, &name);
|
||||||
|
|
||||||
if let Some(NameDefinition::Local(local)) = &name_kind {
|
if let Some(NameClass::NameDefinition(NameDefinition::Local(local))) = &name_kind {
|
||||||
if let Some(name) = local.name(db) {
|
if let Some(name) = local.name(db) {
|
||||||
let shadow_count = bindings_shadow_count.entry(name.clone()).or_default();
|
let shadow_count = bindings_shadow_count.entry(name.clone()).or_default();
|
||||||
*shadow_count += 1;
|
*shadow_count += 1;
|
||||||
|
@ -177,11 +177,13 @@ fn highlight_element(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let h = match name_kind {
|
match name_kind {
|
||||||
Some(name_kind) => highlight_name(db, name_kind),
|
Some(NameClass::NameDefinition(def)) => {
|
||||||
None => highlight_name_by_syntax(name),
|
highlight_name(db, def) | HighlightModifier::Definition
|
||||||
};
|
}
|
||||||
h | HighlightModifier::Definition
|
Some(NameClass::ConstReference(def)) => highlight_name(db, def),
|
||||||
|
None => highlight_name_by_syntax(name) | HighlightModifier::Definition,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Highlight references like the definitions they resolve to
|
// Highlight references like the definitions they resolve to
|
||||||
|
@ -212,8 +214,13 @@ fn highlight_element(
|
||||||
INT_NUMBER | FLOAT_NUMBER => HighlightTag::NumericLiteral.into(),
|
INT_NUMBER | FLOAT_NUMBER => HighlightTag::NumericLiteral.into(),
|
||||||
BYTE => HighlightTag::ByteLiteral.into(),
|
BYTE => HighlightTag::ByteLiteral.into(),
|
||||||
CHAR => HighlightTag::CharLiteral.into(),
|
CHAR => HighlightTag::CharLiteral.into(),
|
||||||
// FIXME: set Declaration for decls
|
LIFETIME => {
|
||||||
LIFETIME => HighlightTag::Lifetime.into(),
|
let h = Highlight::new(HighlightTag::Lifetime);
|
||||||
|
dbg!(match element.parent().map(|it| it.kind()) {
|
||||||
|
Some(LIFETIME_PARAM) | Some(LABEL) => h | HighlightModifier::Definition,
|
||||||
|
_ => h,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
k if k.is_keyword() => {
|
k if k.is_keyword() => {
|
||||||
let h = Highlight::new(HighlightTag::Keyword);
|
let h = Highlight::new(HighlightTag::Keyword);
|
||||||
|
|
|
@ -80,7 +80,7 @@ const STYLE: &str = "
|
||||||
body { margin: 0; }
|
body { margin: 0; }
|
||||||
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
|
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
|
||||||
|
|
||||||
|
.lifetime { color: #DFAF8F; font-style: italic; }
|
||||||
.comment { color: #7F9F7F; }
|
.comment { color: #7F9F7F; }
|
||||||
.struct, .enum { color: #7CB8BB; }
|
.struct, .enum { color: #7CB8BB; }
|
||||||
.enum_variant { color: #BDE0F3; }
|
.enum_variant { color: #BDE0F3; }
|
||||||
|
|
|
@ -90,8 +90,12 @@ impl fmt::Display for HighlightTag {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HighlightModifier {
|
impl HighlightModifier {
|
||||||
const ALL: &'static [HighlightModifier] =
|
const ALL: &'static [HighlightModifier] = &[
|
||||||
&[HighlightModifier::Mutable, HighlightModifier::Unsafe, HighlightModifier::Control];
|
HighlightModifier::Control,
|
||||||
|
HighlightModifier::Definition,
|
||||||
|
HighlightModifier::Mutable,
|
||||||
|
HighlightModifier::Unsafe,
|
||||||
|
];
|
||||||
|
|
||||||
fn as_str(self) -> &'static str {
|
fn as_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -17,9 +17,8 @@ struct Foo {
|
||||||
pub y: i32,
|
pub y: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo<T>() -> T {
|
fn foo<'a, T>() -> T {
|
||||||
unimplemented!();
|
foo::<'a, i32>()
|
||||||
foo::<i32>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! def_fn {
|
macro_rules! def_fn {
|
||||||
|
@ -50,12 +49,19 @@ fn main() {
|
||||||
y;
|
y;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum E<X> {
|
enum Option<T> {
|
||||||
V(X)
|
Some(T),
|
||||||
|
None,
|
||||||
}
|
}
|
||||||
|
use Option::*;
|
||||||
|
|
||||||
impl<X> E<X> {
|
impl<T> Option<T> {
|
||||||
fn new<T>() -> E<T> {}
|
fn and<U>(self, other: Option<U>) -> Option<(T, U)> {
|
||||||
|
match other {
|
||||||
|
None => unimplemented!(),
|
||||||
|
Nope => Nope,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"#
|
"#
|
||||||
.trim(),
|
.trim(),
|
||||||
|
@ -123,5 +129,5 @@ fn test_ranges() {
|
||||||
.highlight_range(FileRange { file_id, range: TextRange::offset_len(82.into(), 1.into()) })
|
.highlight_range(FileRange { file_id, range: TextRange::offset_len(82.into(), 1.into()) })
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(&highlights[0].highlight.to_string(), "field");
|
assert_eq!(&highlights[0].highlight.to_string(), "field.declaration");
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,38 @@ impl NameDefinition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameDefinition> {
|
pub enum NameClass {
|
||||||
|
NameDefinition(NameDefinition),
|
||||||
|
/// `None` in `if let None = Some(82) {}`
|
||||||
|
ConstReference(NameDefinition),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NameClass {
|
||||||
|
pub fn into_definition(self) -> Option<NameDefinition> {
|
||||||
|
match self {
|
||||||
|
NameClass::NameDefinition(it) => Some(it),
|
||||||
|
NameClass::ConstReference(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn definition(self) -> NameDefinition {
|
||||||
|
match self {
|
||||||
|
NameClass::NameDefinition(it) | NameClass::ConstReference(it) => it,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> {
|
||||||
|
if let Some(bind_pat) = name.syntax().parent().and_then(ast::BindPat::cast) {
|
||||||
|
if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) {
|
||||||
|
return Some(NameClass::ConstReference(NameDefinition::ModuleDef(def)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
classify_name_inner(sema, name).map(NameClass::NameDefinition)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameDefinition> {
|
||||||
let _p = profile("classify_name");
|
let _p = profile("classify_name");
|
||||||
let parent = name.syntax().parent()?;
|
let parent = name.syntax().parent()?;
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ impl<'a> ImportsLocator<'a> {
|
||||||
} else {
|
} else {
|
||||||
candidate_node
|
candidate_node
|
||||||
};
|
};
|
||||||
classify_name(&self.sema, &ast::Name::cast(candidate_name_node)?)
|
let name = ast::Name::cast(candidate_name_node)?;
|
||||||
|
classify_name(&self.sema, &name)?.into_definition()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue