Skip to content

Commit 9014f2e

Browse files
committed
internal: Improve macro token mapping heuristics
1 parent f90bdfc commit 9014f2e

File tree

9 files changed

+239
-155
lines changed

9 files changed

+239
-155
lines changed

Diff for: crates/hir-expand/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ pub enum MacroCallKind {
279279
}
280280

281281
pub trait HirFileIdExt {
282+
fn edition(self, db: &dyn ExpandDatabase) -> Edition;
282283
/// Returns the original file of this macro call hierarchy.
283284
fn original_file(self, db: &dyn ExpandDatabase) -> EditionedFileId;
284285

@@ -293,6 +294,12 @@ pub trait HirFileIdExt {
293294
}
294295

295296
impl HirFileIdExt for HirFileId {
297+
fn edition(self, db: &dyn ExpandDatabase) -> Edition {
298+
match self.repr() {
299+
HirFileIdRepr::FileId(file_id) => file_id.edition(),
300+
HirFileIdRepr::MacroFile(m) => m.macro_call_id.lookup(db).def.edition,
301+
}
302+
}
296303
fn original_file(self, db: &dyn ExpandDatabase) -> EditionedFileId {
297304
let mut file_id = self;
298305
loop {

Diff for: crates/hir/src/semantics.rs

+170-93
Large diffs are not rendered by default.

Diff for: crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::{utils, AssistContext, Assists};
2-
use hir::DescendPreference;
32
use ide_db::{
43
assists::{AssistId, AssistKind},
54
syntax_helpers::{
@@ -40,10 +39,8 @@ pub(crate) fn extract_expressions_from_format_string(
4039
let tt = fmt_string.syntax().parent().and_then(ast::TokenTree::cast)?;
4140
let tt_delimiter = tt.left_delimiter_token()?.kind();
4241

43-
let expanded_t = ast::String::cast(
44-
ctx.sema
45-
.descend_into_macros_single(DescendPreference::SameKind, fmt_string.syntax().clone()),
46-
)?;
42+
let expanded_t =
43+
ast::String::cast(ctx.sema.descend_into_macros_single_exact(fmt_string.syntax().clone()))?;
4744
if !is_format_string(&expanded_t) {
4845
return None;
4946
}

Diff for: crates/ide/src/doc_links.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ pub(crate) fn external_docs(
144144
kind if kind.is_trivia() => 0,
145145
_ => 1,
146146
})?;
147-
let token = sema.descend_into_macros_single(DescendPreference::None, token);
147+
let token = sema.descend_into_macros_single_exact(token);
148148

149149
let node = token.parent()?;
150150
let definition = match_ast! {

Diff for: crates/ide/src/extend_selection.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::iter::successors;
22

3-
use hir::{DescendPreference, Semantics};
3+
use hir::Semantics;
44
use ide_db::RootDatabase;
55
use syntax::{
66
algo::{self, skip_trivia_token},
@@ -140,10 +140,8 @@ fn extend_tokens_from_range(
140140

141141
// compute original mapped token range
142142
let extended = {
143-
let fst_expanded =
144-
sema.descend_into_macros_single(DescendPreference::None, first_token.clone());
145-
let lst_expanded =
146-
sema.descend_into_macros_single(DescendPreference::None, last_token.clone());
143+
let fst_expanded = sema.descend_into_macros_single_exact(first_token.clone());
144+
let lst_expanded = sema.descend_into_macros_single_exact(last_token.clone());
147145
let mut lca =
148146
algo::least_common_ancestor(&fst_expanded.parent()?, &lst_expanded.parent()?)?;
149147
lca = shallowest_node(&lca);
@@ -157,7 +155,7 @@ fn extend_tokens_from_range(
157155
let validate = || {
158156
let extended = &extended;
159157
move |token: &SyntaxToken| -> bool {
160-
let expanded = sema.descend_into_macros_single(DescendPreference::None, token.clone());
158+
let expanded = sema.descend_into_macros_single_exact(token.clone());
161159
let parent = match expanded.parent() {
162160
Some(it) => it,
163161
None => return false,

Diff for: crates/ide/src/goto_implementation.rs

+49-42
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
1010

1111
// Feature: Go to Implementation
1212
//
13-
// Navigates to the impl blocks of types.
13+
// Navigates to the impl items of types.
1414
//
1515
// |===
1616
// | Editor | Shortcut
@@ -32,48 +32,55 @@ pub(crate) fn goto_implementation(
3232
_ => 0,
3333
})?;
3434
let range = original_token.text_range();
35-
let navs =
36-
sema.descend_into_macros_single(DescendPreference::SameText, original_token)
37-
.parent()
38-
.and_then(ast::NameLike::cast)
39-
.and_then(|node| match &node {
40-
ast::NameLike::Name(name) => {
41-
NameClass::classify(&sema, name).and_then(|class| match class {
42-
NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it),
43-
NameClass::PatFieldShorthand { .. } => None,
44-
})
45-
}
46-
ast::NameLike::NameRef(name_ref) => NameRefClass::classify(&sema, name_ref)
47-
.and_then(|class| match class {
48-
NameRefClass::Definition(def) => Some(def),
49-
NameRefClass::FieldShorthand { .. }
50-
| NameRefClass::ExternCrateShorthand { .. } => None,
51-
}),
52-
ast::NameLike::Lifetime(_) => None,
53-
})
54-
.and_then(|def| {
55-
let navs = match def {
56-
Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
57-
Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
58-
Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
59-
Definition::BuiltinType(builtin) => impls_for_ty(&sema, builtin.ty(sema.db)),
60-
Definition::Function(f) => {
61-
let assoc = f.as_assoc_item(sema.db)?;
62-
let name = assoc.name(sema.db)?;
63-
let trait_ = assoc.container_or_implemented_trait(sema.db)?;
64-
impls_for_trait_item(&sema, trait_, name)
35+
let navs = sema
36+
.descend_into_macros(DescendPreference::SameText, original_token)
37+
.iter()
38+
.filter_map(|token| {
39+
token
40+
.parent()
41+
.and_then(ast::NameLike::cast)
42+
.and_then(|node| match &node {
43+
ast::NameLike::Name(name) => {
44+
NameClass::classify(&sema, name).and_then(|class| match class {
45+
NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it),
46+
NameClass::PatFieldShorthand { .. } => None,
47+
})
6548
}
66-
Definition::Const(c) => {
67-
let assoc = c.as_assoc_item(sema.db)?;
68-
let name = assoc.name(sema.db)?;
69-
let trait_ = assoc.container_or_implemented_trait(sema.db)?;
70-
impls_for_trait_item(&sema, trait_, name)
71-
}
72-
_ => return None,
73-
};
74-
Some(navs)
75-
})
76-
.unwrap_or_default();
49+
ast::NameLike::NameRef(name_ref) => NameRefClass::classify(&sema, name_ref)
50+
.and_then(|class| match class {
51+
NameRefClass::Definition(def) => Some(def),
52+
NameRefClass::FieldShorthand { .. }
53+
| NameRefClass::ExternCrateShorthand { .. } => None,
54+
}),
55+
ast::NameLike::Lifetime(_) => None,
56+
})
57+
.and_then(|def| {
58+
let navs = match def {
59+
Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
60+
Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
61+
Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
62+
Definition::BuiltinType(builtin) => {
63+
impls_for_ty(&sema, builtin.ty(sema.db))
64+
}
65+
Definition::Function(f) => {
66+
let assoc = f.as_assoc_item(sema.db)?;
67+
let name = assoc.name(sema.db)?;
68+
let trait_ = assoc.container_or_implemented_trait(sema.db)?;
69+
impls_for_trait_item(&sema, trait_, name)
70+
}
71+
Definition::Const(c) => {
72+
let assoc = c.as_assoc_item(sema.db)?;
73+
let name = assoc.name(sema.db)?;
74+
let trait_ = assoc.container_or_implemented_trait(sema.db)?;
75+
impls_for_trait_item(&sema, trait_, name)
76+
}
77+
_ => return None,
78+
};
79+
Some(navs)
80+
})
81+
})
82+
.flatten()
83+
.collect();
7784

7885
Some(RangeInfo { range, info: navs })
7986
}

Diff for: crates/ide/src/signature_help.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
use std::collections::BTreeSet;
55

66
use either::Either;
7-
use hir::{
8-
AssocItem, DescendPreference, GenericParam, HirDisplay, ModuleDef, PathResolution, Semantics,
9-
Trait,
10-
};
7+
use hir::{AssocItem, GenericParam, HirDisplay, ModuleDef, PathResolution, Semantics, Trait};
118
use ide_db::{
129
active_parameter::{callable_for_node, generic_def_for_node},
1310
documentation::{Documentation, HasDocs},
@@ -81,7 +78,7 @@ pub(crate) fn signature_help(
8178
// if the cursor is sandwiched between two space tokens and the call is unclosed
8279
// this prevents us from leaving the CallExpression
8380
.and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?;
84-
let token = sema.descend_into_macros_single(DescendPreference::None, token);
81+
let token = sema.descend_into_macros_single_exact(token);
8582

8683
for node in token.parent_ancestors() {
8784
match_ast! {

Diff for: crates/ide/src/syntax_highlighting.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,8 @@ fn traverse(
410410
})
411411
.unwrap()
412412
} else {
413-
sema.descend_into_macros_single(DescendPreference::SameKind, token)
413+
// FIXME: We should probably rank the tokens and find the most suitable?
414+
sema.descend_into_macros_single_exact(token)
414415
};
415416
match token.parent().and_then(ast::NameLike::cast) {
416417
// Remap the token into the wrapping single token nodes

Diff for: crates/ide/src/syntax_highlighting/test_data/highlight_macros.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
<span class="brace">}</span>
5959

6060
<span class="macro">def_fn</span><span class="macro_bang">!</span> <span class="brace macro">{</span>
61-
<span class="keyword macro">fn</span> <span class="function declaration macro">bar</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="operator macro">-</span><span class="operator macro">&gt;</span> <span class="builtin_type macro">u32</span> <span class="brace macro">{</span>
61+
<span class="keyword macro">fn</span> <span class="function declaration macro">bar</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="punctuation macro">-</span><span class="angle macro">&gt;</span> <span class="builtin_type macro">u32</span> <span class="brace macro">{</span>
6262
<span class="numeric_literal macro">100</span>
6363
<span class="brace macro">}</span>
6464
<span class="brace macro">}</span>
@@ -100,7 +100,7 @@
100100
<span class="brace">}</span><span class="semicolon">;</span>
101101
<span class="brace">}</span>
102102

103-
<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>
103+
<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="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>
104104

105105
<span class="keyword">struct</span> <span class="struct declaration">S</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="parenthesis">)</span><span class="semicolon">;</span>
106106
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>

0 commit comments

Comments
 (0)