mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Fix highlighting of const patterns
This commit is contained in:
parent
209eb32796
commit
5ebfcb9cb7
5 changed files with 60 additions and 15 deletions
|
@ -18,8 +18,8 @@ use crate::{
|
|||
db::HirDatabase,
|
||||
source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer},
|
||||
source_binder::{ChildContainer, SourceBinder},
|
||||
Function, HirFileId, InFile, Local, MacroDef, Module, Name, Origin, Path, PathResolution,
|
||||
ScopeDef, StructField, Trait, Type, TypeParam, VariantDef,
|
||||
Function, HirFileId, InFile, Local, MacroDef, Module, ModuleDef, Name, Origin, Path,
|
||||
PathResolution, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef,
|
||||
};
|
||||
use ra_prof::profile;
|
||||
|
||||
|
@ -129,6 +129,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
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?
|
||||
// pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ use either::Either;
|
|||
use hir_def::{
|
||||
body::{
|
||||
scope::{ExprScopes, ScopeId},
|
||||
BodySourceMap,
|
||||
Body, BodySourceMap,
|
||||
},
|
||||
expr::{ExprId, PatId},
|
||||
expr::{ExprId, Pat, PatId},
|
||||
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
|
||||
AsMacroCall, DefWithBodyId,
|
||||
};
|
||||
|
@ -25,8 +25,8 @@ use ra_syntax::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, Path, Static, Struct,
|
||||
Trait, Type, TypeAlias, TypeParam,
|
||||
db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, ModuleDef, Path, Static,
|
||||
Struct, Trait, Type, TypeAlias, TypeParam,
|
||||
};
|
||||
|
||||
/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
|
||||
|
@ -35,6 +35,7 @@ use crate::{
|
|||
pub(crate) struct SourceAnalyzer {
|
||||
file_id: HirFileId,
|
||||
pub(crate) resolver: Resolver,
|
||||
body: Option<Arc<Body>>,
|
||||
body_source_map: Option<Arc<BodySourceMap>>,
|
||||
infer: Option<Arc<InferenceResult>>,
|
||||
scopes: Option<Arc<ExprScopes>>,
|
||||
|
@ -66,7 +67,7 @@ impl SourceAnalyzer {
|
|||
node: InFile<&SyntaxNode>,
|
||||
offset: Option<TextUnit>,
|
||||
) -> 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 scope = match offset {
|
||||
None => scope_for(&scopes, &source_map, node),
|
||||
|
@ -75,6 +76,7 @@ impl SourceAnalyzer {
|
|||
let resolver = resolver_for_scope(db, def, scope);
|
||||
SourceAnalyzer {
|
||||
resolver,
|
||||
body: Some(body),
|
||||
body_source_map: Some(source_map),
|
||||
infer: Some(db.infer(def)),
|
||||
scopes: Some(scopes),
|
||||
|
@ -88,6 +90,7 @@ impl SourceAnalyzer {
|
|||
) -> SourceAnalyzer {
|
||||
SourceAnalyzer {
|
||||
resolver,
|
||||
body: None,
|
||||
body_source_map: None,
|
||||
infer: None,
|
||||
scopes: None,
|
||||
|
@ -197,6 +200,24 @@ impl SourceAnalyzer {
|
|||
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(
|
||||
&self,
|
||||
db: &impl HirDatabase,
|
||||
|
|
|
@ -65,10 +65,17 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
|||
<span class="variable mutable">y</span>;
|
||||
}
|
||||
|
||||
<span class="keyword">enum</span> <span class="enum">E</span><<span class="type_param">X</span>> {
|
||||
<span class="enum_variant">V</span>(<span class="type_param">X</span>)
|
||||
<span class="keyword">enum</span> <span class="enum">Option</span><<span class="type_param">T</span>> {
|
||||
<span class="enum_variant">Some</span>(<span class="type_param">T</span>),
|
||||
<span class="enum_variant">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">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">impl</span><<span class="type_param">T</span>> <span class="enum">Option</span><<span class="type_param">T</span>> {
|
||||
<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>)> {
|
||||
<span class="keyword control">match</span> <span class="variable">other</span> {
|
||||
<span class="enum_variant">None</span> => <span class="macro">todo</span><span class="macro">!</span>(),
|
||||
<span class="variable">Nope</span> => <span class="variable">Nope</span>,
|
||||
}
|
||||
}
|
||||
}</code></pre>
|
|
@ -50,12 +50,19 @@ fn main() {
|
|||
y;
|
||||
}
|
||||
|
||||
enum E<X> {
|
||||
V(X)
|
||||
enum Option<T> {
|
||||
Some(T),
|
||||
None,
|
||||
}
|
||||
use Option::*;
|
||||
|
||||
impl<X> E<X> {
|
||||
fn new<T>() -> E<T> {}
|
||||
impl<T> Option<T> {
|
||||
fn and<U>(self, other: Option<U>) -> Option<(T, U)> {
|
||||
match other {
|
||||
None => todo!(),
|
||||
Nope => Nope,
|
||||
}
|
||||
}
|
||||
}
|
||||
"#
|
||||
.trim(),
|
||||
|
|
|
@ -90,6 +90,12 @@ impl NameClass {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue