mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 21:35:20 +00:00
feat: Support macro calls in eager macros for IDE features
This commit is contained in:
parent
9767156a29
commit
d2f8eae2ec
22 changed files with 420 additions and 226 deletions
|
@ -1,10 +1,10 @@
|
|||
use std::mem::discriminant;
|
||||
use std::{iter, mem::discriminant};
|
||||
|
||||
use crate::{
|
||||
doc_links::token_as_doc_comment, navigation_target::ToNav, FilePosition, NavigationTarget,
|
||||
RangeInfo, TryToNav,
|
||||
};
|
||||
use hir::{AsAssocItem, AssocItem, DescendPreference, ModuleDef, Semantics};
|
||||
use hir::{AsAssocItem, AssocItem, DescendPreference, MacroFileIdExt, ModuleDef, Semantics};
|
||||
use ide_db::{
|
||||
base_db::{AnchoredPath, FileId, FileLoader},
|
||||
defs::{Definition, IdentClass},
|
||||
|
@ -74,11 +74,13 @@ pub(crate) fn goto_definition(
|
|||
.filter_map(|token| {
|
||||
let parent = token.parent()?;
|
||||
|
||||
if let Some(tt) = ast::TokenTree::cast(parent.clone()) {
|
||||
if let Some(x) = try_lookup_include_path(sema, tt, token.clone(), file_id) {
|
||||
if let Some(token) = ast::String::cast(token.clone()) {
|
||||
if let Some(x) = try_lookup_include_path(sema, token, file_id) {
|
||||
return Some(vec![x]);
|
||||
}
|
||||
}
|
||||
|
||||
if ast::TokenTree::can_cast(parent.kind()) {
|
||||
if let Some(x) = try_lookup_macro_def_in_macro_use(sema, token) {
|
||||
return Some(vec![x]);
|
||||
}
|
||||
|
@ -111,24 +113,17 @@ pub(crate) fn goto_definition(
|
|||
|
||||
fn try_lookup_include_path(
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
tt: ast::TokenTree,
|
||||
token: SyntaxToken,
|
||||
token: ast::String,
|
||||
file_id: FileId,
|
||||
) -> Option<NavigationTarget> {
|
||||
let token = ast::String::cast(token)?;
|
||||
let path = token.value()?.into_owned();
|
||||
let macro_call = tt.syntax().parent().and_then(ast::MacroCall::cast)?;
|
||||
let name = macro_call.path()?.segment()?.name_ref()?;
|
||||
if !matches!(&*name.text(), "include" | "include_str" | "include_bytes") {
|
||||
let file = sema.hir_file_for(&token.syntax().parent()?).macro_file()?;
|
||||
if !iter::successors(Some(file), |file| file.parent(sema.db).macro_file())
|
||||
// Check that we are in the eager argument expansion of an include macro
|
||||
.any(|file| file.is_include_like_macro(sema.db) && file.eager_arg(sema.db).is_none())
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
// Ignore non-built-in macros to account for shadowing
|
||||
if let Some(it) = sema.resolve_macro_call(¯o_call) {
|
||||
if !matches!(it.kind(sema.db), hir::MacroKind::BuiltIn) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
let path = token.value()?;
|
||||
|
||||
let file_id = sema.db.resolve_path(AnchoredPath { anchor: file_id, path: &path })?;
|
||||
let size = sema.db.file_text(file_id).len().try_into().ok()?;
|
||||
|
@ -1531,6 +1526,26 @@ fn main() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_include_has_eager_input() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs
|
||||
#[rustc_builtin_macro]
|
||||
macro_rules! include_str {}
|
||||
#[rustc_builtin_macro]
|
||||
macro_rules! concat {}
|
||||
|
||||
fn main() {
|
||||
let str = include_str!(concat!("foo", ".tx$0t"));
|
||||
}
|
||||
//- /foo.txt
|
||||
// empty
|
||||
//^file
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_doc_include_str() {
|
||||
check(
|
||||
|
|
|
@ -94,7 +94,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
|||
<span class="brace">}</span>
|
||||
|
||||
|
||||
<span class="macro default_library library">include</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">concat</span><span class="punctuation macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"foo/"</span><span class="comma macro">,</span> <span class="string_literal macro">"foo.rs"</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||
<span class="macro default_library library">include</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"foo/"</span><span class="string_literal macro">,</span> <span class="string_literal macro">"foo.rs"</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
|
||||
<span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">92</span><span class="comma macro">,</span><span class="parenthesis macro">)</span><span class="operator macro">.</span><span class="field library macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue