Skip to content

Commit

Permalink
internal: Improve macro token mapping heuristics
Browse files Browse the repository at this point in the history
  • Loading branch information
Veykril committed Aug 17, 2024
1 parent f90bdfc commit 9014f2e
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 155 deletions.
7 changes: 7 additions & 0 deletions crates/hir-expand/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ pub enum MacroCallKind {
}

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

Expand All @@ -293,6 +294,12 @@ pub trait HirFileIdExt {
}

impl HirFileIdExt for HirFileId {
fn edition(self, db: &dyn ExpandDatabase) -> Edition {
match self.repr() {
HirFileIdRepr::FileId(file_id) => file_id.edition(),
HirFileIdRepr::MacroFile(m) => m.macro_call_id.lookup(db).def.edition,
}
}
fn original_file(self, db: &dyn ExpandDatabase) -> EditionedFileId {
let mut file_id = self;
loop {
Expand Down
263 changes: 170 additions & 93 deletions crates/hir/src/semantics.rs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{utils, AssistContext, Assists};
use hir::DescendPreference;
use ide_db::{
assists::{AssistId, AssistKind},
syntax_helpers::{
Expand Down Expand Up @@ -40,10 +39,8 @@ pub(crate) fn extract_expressions_from_format_string(
let tt = fmt_string.syntax().parent().and_then(ast::TokenTree::cast)?;
let tt_delimiter = tt.left_delimiter_token()?.kind();

let expanded_t = ast::String::cast(
ctx.sema
.descend_into_macros_single(DescendPreference::SameKind, fmt_string.syntax().clone()),
)?;
let expanded_t =
ast::String::cast(ctx.sema.descend_into_macros_single_exact(fmt_string.syntax().clone()))?;
if !is_format_string(&expanded_t) {
return None;
}
Expand Down
2 changes: 1 addition & 1 deletion crates/ide/src/doc_links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub(crate) fn external_docs(
kind if kind.is_trivia() => 0,
_ => 1,
})?;
let token = sema.descend_into_macros_single(DescendPreference::None, token);
let token = sema.descend_into_macros_single_exact(token);

let node = token.parent()?;
let definition = match_ast! {
Expand Down
10 changes: 4 additions & 6 deletions crates/ide/src/extend_selection.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::iter::successors;

use hir::{DescendPreference, Semantics};
use hir::Semantics;
use ide_db::RootDatabase;
use syntax::{
algo::{self, skip_trivia_token},
Expand Down Expand Up @@ -140,10 +140,8 @@ fn extend_tokens_from_range(

// compute original mapped token range
let extended = {
let fst_expanded =
sema.descend_into_macros_single(DescendPreference::None, first_token.clone());
let lst_expanded =
sema.descend_into_macros_single(DescendPreference::None, last_token.clone());
let fst_expanded = sema.descend_into_macros_single_exact(first_token.clone());
let lst_expanded = sema.descend_into_macros_single_exact(last_token.clone());
let mut lca =
algo::least_common_ancestor(&fst_expanded.parent()?, &lst_expanded.parent()?)?;
lca = shallowest_node(&lca);
Expand All @@ -157,7 +155,7 @@ fn extend_tokens_from_range(
let validate = || {
let extended = &extended;
move |token: &SyntaxToken| -> bool {
let expanded = sema.descend_into_macros_single(DescendPreference::None, token.clone());
let expanded = sema.descend_into_macros_single_exact(token.clone());
let parent = match expanded.parent() {
Some(it) => it,
None => return false,
Expand Down
91 changes: 49 additions & 42 deletions crates/ide/src/goto_implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};

// Feature: Go to Implementation
//
// Navigates to the impl blocks of types.
// Navigates to the impl items of types.
//
// |===
// | Editor | Shortcut
Expand All @@ -32,48 +32,55 @@ pub(crate) fn goto_implementation(
_ => 0,
})?;
let range = original_token.text_range();
let navs =
sema.descend_into_macros_single(DescendPreference::SameText, original_token)
.parent()
.and_then(ast::NameLike::cast)
.and_then(|node| match &node {
ast::NameLike::Name(name) => {
NameClass::classify(&sema, name).and_then(|class| match class {
NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it),
NameClass::PatFieldShorthand { .. } => None,
})
}
ast::NameLike::NameRef(name_ref) => NameRefClass::classify(&sema, name_ref)
.and_then(|class| match class {
NameRefClass::Definition(def) => Some(def),
NameRefClass::FieldShorthand { .. }
| NameRefClass::ExternCrateShorthand { .. } => None,
}),
ast::NameLike::Lifetime(_) => None,
})
.and_then(|def| {
let navs = match def {
Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
Definition::BuiltinType(builtin) => impls_for_ty(&sema, builtin.ty(sema.db)),
Definition::Function(f) => {
let assoc = f.as_assoc_item(sema.db)?;
let name = assoc.name(sema.db)?;
let trait_ = assoc.container_or_implemented_trait(sema.db)?;
impls_for_trait_item(&sema, trait_, name)
let navs = sema
.descend_into_macros(DescendPreference::SameText, original_token)
.iter()
.filter_map(|token| {
token
.parent()
.and_then(ast::NameLike::cast)
.and_then(|node| match &node {
ast::NameLike::Name(name) => {
NameClass::classify(&sema, name).and_then(|class| match class {
NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it),
NameClass::PatFieldShorthand { .. } => None,
})
}
Definition::Const(c) => {
let assoc = c.as_assoc_item(sema.db)?;
let name = assoc.name(sema.db)?;
let trait_ = assoc.container_or_implemented_trait(sema.db)?;
impls_for_trait_item(&sema, trait_, name)
}
_ => return None,
};
Some(navs)
})
.unwrap_or_default();
ast::NameLike::NameRef(name_ref) => NameRefClass::classify(&sema, name_ref)
.and_then(|class| match class {
NameRefClass::Definition(def) => Some(def),
NameRefClass::FieldShorthand { .. }
| NameRefClass::ExternCrateShorthand { .. } => None,
}),
ast::NameLike::Lifetime(_) => None,
})
.and_then(|def| {
let navs = match def {
Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
Definition::BuiltinType(builtin) => {
impls_for_ty(&sema, builtin.ty(sema.db))
}
Definition::Function(f) => {
let assoc = f.as_assoc_item(sema.db)?;
let name = assoc.name(sema.db)?;
let trait_ = assoc.container_or_implemented_trait(sema.db)?;
impls_for_trait_item(&sema, trait_, name)
}
Definition::Const(c) => {
let assoc = c.as_assoc_item(sema.db)?;
let name = assoc.name(sema.db)?;
let trait_ = assoc.container_or_implemented_trait(sema.db)?;
impls_for_trait_item(&sema, trait_, name)
}
_ => return None,
};
Some(navs)
})
})
.flatten()
.collect();

Some(RangeInfo { range, info: navs })
}
Expand Down
7 changes: 2 additions & 5 deletions crates/ide/src/signature_help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
use std::collections::BTreeSet;

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

for node in token.parent_ancestors() {
match_ast! {
Expand Down
3 changes: 2 additions & 1 deletion crates/ide/src/syntax_highlighting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ fn traverse(
})
.unwrap()
} else {
sema.descend_into_macros_single(DescendPreference::SameKind, token)
// FIXME: We should probably rank the tokens and find the most suitable?
sema.descend_into_macros_single_exact(token)
};
match token.parent().and_then(ast::NameLike::cast) {
// Remap the token into the wrapping single token nodes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
<span class="brace">}</span>

<span class="macro">def_fn</span><span class="macro_bang">!</span> <span class="brace macro">{</span>
<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>
<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>
<span class="numeric_literal macro">100</span>
<span class="brace macro">}</span>
<span class="brace macro">}</span>
Expand Down Expand Up @@ -100,7 +100,7 @@
<span class="brace">}</span><span class="semicolon">;</span>
<span class="brace">}</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="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>

<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>
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
Expand Down

0 comments on commit 9014f2e

Please sign in to comment.