Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/goto_definition.rs')
-rw-r--r--crates/ide/src/goto_definition.rs51
1 files changed, 33 insertions, 18 deletions
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 1bda15255d..ddeeca5f7b 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -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(&macro_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()?;
@@ -1532,6 +1527,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(
r#"