Skip to content

Commit d616a6a

Browse files
bors[bot]Veykril
andauthored
Merge #9149
9149: feat: Support goto-definition for include macros input path r=Veykril a=Veykril ![0l6l9iWPNE](https://user-images.githubusercontent.com/3757771/120891155-3fa85800-c607-11eb-9b20-7ac330dceb4b.gif) Fixes #5871 Co-authored-by: Lukas Wirth <[email protected]>
2 parents b68407f + 5391f9c commit d616a6a

File tree

1 file changed

+49
-3
lines changed

1 file changed

+49
-3
lines changed

crates/ide/src/goto_definition.rs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
use std::convert::TryInto;
2+
13
use either::Either;
24
use hir::{InFile, Semantics};
35
use ide_db::{
6+
base_db::{AnchoredPath, FileId, FileLoader},
47
defs::{NameClass, NameRefClass},
58
RootDatabase,
69
};
7-
use syntax::{ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
10+
use syntax::{
11+
ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, TokenAtOffset, T,
12+
};
813

914
use crate::{
1015
display::TryToNav,
@@ -32,7 +37,7 @@ pub(crate) fn goto_definition(
3237
let original_token = pick_best(file.token_at_offset(position.offset))?;
3338
let token = sema.descend_into_macros(original_token.clone());
3439
let parent = token.parent()?;
35-
if let Some(_) = ast::Comment::cast(token) {
40+
if let Some(_) = ast::Comment::cast(token.clone()) {
3641
let (attributes, def) = doc_attributes(&sema, &parent)?;
3742

3843
let (docs, doc_mapping) = attributes.docs_with_rangemap(db)?;
@@ -45,7 +50,6 @@ pub(crate) fn goto_definition(
4550
let nav = resolve_doc_path_for_def(db, def, &link, ns)?.try_to_nav(db)?;
4651
return Some(RangeInfo::new(original_token.text_range(), vec![nav]));
4752
}
48-
4953
let nav = match_ast! {
5054
match parent {
5155
ast::NameRef(name_ref) => {
@@ -61,13 +65,40 @@ pub(crate) fn goto_definition(
6165
} else {
6266
reference_definition(&sema, Either::Left(&lt))
6367
},
68+
ast::TokenTree(tt) => try_lookup_include_path(sema.db, tt, token, position.file_id),
6469
_ => return None,
6570
}
6671
};
6772

6873
Some(RangeInfo::new(original_token.text_range(), nav.into_iter().collect()))
6974
}
7075

76+
fn try_lookup_include_path(
77+
db: &RootDatabase,
78+
tt: ast::TokenTree,
79+
token: SyntaxToken,
80+
file_id: FileId,
81+
) -> Option<NavigationTarget> {
82+
let path = ast::String::cast(token)?.value()?.into_owned();
83+
let macro_call = tt.syntax().parent().and_then(ast::MacroCall::cast)?;
84+
let name = macro_call.path()?.segment()?.name_ref()?;
85+
if !matches!(&*name.text(), "include" | "include_str" | "include_bytes") {
86+
return None;
87+
}
88+
let file_id = db.resolve_path(AnchoredPath { anchor: file_id, path: &path })?;
89+
let size = db.file_text(file_id).len().try_into().ok()?;
90+
Some(NavigationTarget {
91+
file_id,
92+
full_range: TextRange::new(0.into(), size),
93+
name: path.into(),
94+
focus_range: None,
95+
kind: None,
96+
container_name: None,
97+
description: None,
98+
docs: None,
99+
})
100+
}
101+
71102
fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
72103
return tokens.max_by_key(priority);
73104
fn priority(n: &SyntaxToken) -> usize {
@@ -1213,6 +1244,21 @@ fn f(e: Enum) {
12131244
Enum::Variant2 => {}
12141245
}
12151246
}
1247+
"#,
1248+
);
1249+
}
1250+
1251+
#[test]
1252+
fn goto_include() {
1253+
check(
1254+
r#"
1255+
//- /main.rs
1256+
fn main() {
1257+
let str = include_str!("foo.txt$0");
1258+
}
1259+
//- /foo.txt
1260+
// empty
1261+
//^ file
12161262
"#,
12171263
);
12181264
}

0 commit comments

Comments
 (0)