diff options
| -rw-r--r-- | crates/hir/src/semantics.rs | 10 | ||||
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 12 | ||||
| -rw-r--r-- | crates/ide/src/syntax_highlighting/test_data/highlighting.html | 2 | ||||
| -rw-r--r-- | crates/ide_db/src/defs.rs | 26 |
4 files changed, 36 insertions, 14 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 0f63de9e725..b09c0e753b5 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -329,6 +329,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.resolve_path(path) } + pub fn resolve_path_as_macro(&self, path: &ast::Path) -> Option<MacroDef> { + self.imp.resolve_path_as_macro(path) + } + pub fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> { self.imp.resolve_extern_crate(extern_crate) } @@ -845,6 +849,12 @@ impl<'db> SemanticsImpl<'db> { self.analyze(path.syntax()).resolve_path(self.db, path) } + // FIXME: This shouldn't exist, but is currently required to always resolve attribute paths in + // the IDE layer due to namespace collisions + fn resolve_path_as_macro(&self, path: &ast::Path) -> Option<MacroDef> { + self.analyze(path.syntax()).resolve_path_as_macro(self.db, path) + } + fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> { let krate = self.scope(extern_crate.syntax()).krate()?; krate.dependencies(self.db).into_iter().find_map(|dep| { diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 08d0a02d796..b12461818e9 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -246,6 +246,18 @@ impl SourceAnalyzer { } } + pub(crate) fn resolve_path_as_macro( + &self, + db: &dyn HirDatabase, + path: &ast::Path, + ) -> Option<MacroDef> { + // This must be a normal source file rather than macro file. + let hygiene = Hygiene::new(db.upcast(), self.file_id); + let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene); + let hir_path = Path::from_src(path.clone(), &ctx)?; + resolve_hir_path_as_macro(db, &self.resolver, &hir_path) + } + pub(crate) fn resolve_path( &self, db: &dyn HirDatabase, diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 1a10a78d247..ab810aceca3 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html @@ -43,7 +43,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="brace">}</span><span class="semicolon">;</span> <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span> -<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="module attribute">proc_macros</span><span class="operator attribute">::</span><span class="builtin_attr attribute">identity</span><span class="attribute attribute">]</span> +<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="module attribute">proc_macros</span><span class="operator attribute">::</span><span class="macro attribute">identity</span><span class="attribute attribute">]</span> <span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration public">ops</span> <span class="brace">{</span> <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute">lang</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"fn_once"</span><span class="attribute attribute">]</span> <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration public">FnOnce</span><span class="angle"><</span><span class="type_param declaration">Args</span><span class="angle">></span> <span class="brace">{</span><span class="brace">}</span> diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index d95bca515fb..e4874c7c482 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -433,20 +433,20 @@ impl NameRefClass { .find_map(ast::Attr::cast) .map(|attr| attr.path().as_ref() == Some(&top_path)); return match is_attribute_path { - Some(true) => sema.resolve_path(&path).and_then(|resolved| { - match resolved { - // Don't wanna collide with builtin attributes here like `test` hence guard - // so only resolve to modules that aren't the last segment - PathResolution::Def(module @ ModuleDef::Module(_)) if path != top_path => { - cov_mark::hit!(name_ref_classify_attr_path_qualifier); - Some(NameRefClass::Definition(Definition::ModuleDef(module))) - } - PathResolution::Macro(mac) if mac.kind() == hir::MacroKind::Attr => { - Some(NameRefClass::Definition(Definition::Macro(mac))) - } - _ => None, + Some(true) if path == top_path => sema + .resolve_path_as_macro(&path) + .filter(|mac| mac.kind() == hir::MacroKind::Attr) + .map(Definition::Macro) + .map(NameRefClass::Definition), + // in case of the path being a qualifier, don't resolve to anything but a module + Some(true) => match sema.resolve_path(&path)? { + PathResolution::Def(module @ ModuleDef::Module(_)) => { + cov_mark::hit!(name_ref_classify_attr_path_qualifier); + Some(NameRefClass::Definition(Definition::ModuleDef(module))) } - }), + _ => None, + }, + // inside attribute, but our path isn't part of the attribute's path(might be in its expression only) Some(false) => None, None => sema.resolve_path(&path).map(Into::into).map(NameRefClass::Definition), }; |
