diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 6e9fc3996c..d96f8777e0 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -52,7 +52,6 @@ use crate::{ const CONTINUE_NO_BREAKS: ControlFlow = ControlFlow::Continue(()); pub enum DescendPreference { - SameKind, None, } @@ -675,20 +674,9 @@ impl<'db> SemanticsImpl<'db> { token: SyntaxToken, ) -> SmallVec<[SyntaxToken; 1]> { enum Dp { - // SameText(&'t str), - SameKind(SyntaxKind), None, } - let fetch_kind = |token: &SyntaxToken| match token.parent() { - Some(node) => match node.kind() { - kind @ (SyntaxKind::NAME | SyntaxKind::NAME_REF) => kind, - _ => token.kind(), - }, - None => token.kind(), - }; let mode = match mode { - // DescendPreference::SameText => Dp::SameText(token.text()), - DescendPreference::SameKind => Dp::SameKind(fetch_kind(&token)), DescendPreference::None => Dp::None, }; let mut res = smallvec![]; @@ -696,13 +684,6 @@ impl<'db> SemanticsImpl<'db> { token.clone(), &mut |InFile { value, .. }| { let is_a_match = match mode { - // Dp::SameText(text) => value.text() == text, - Dp::SameKind(preferred_kind) => { - let kind = fetch_kind(&value); - kind == preferred_kind - // special case for derive macros - || (preferred_kind == SyntaxKind::IDENT && kind == SyntaxKind::NAME_REF) - } Dp::None => true, }; if is_a_match { @@ -733,7 +714,7 @@ impl<'db> SemanticsImpl<'db> { token: SyntaxToken, mut cb: impl FnMut(InFile) -> ControlFlow, ) -> Option { - self.descend_into_macros_impl(token.clone(), &mut |t| cb(t)) + self.descend_into_macros_impl(token.clone(), &mut cb) } /// Descends the token into expansions, returning the tokens that matches the input diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 5443b50575..77c56b3b3a 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -186,7 +186,7 @@ fn hover_simple( }); let descended = || descended.iter(); - // FIXME: WE should not try these step by step, instead to accommodate for macros we should run + // TODO: WE should not try these step by step, instead to accommodate for macros we should run // all of these in "parallel" and rank their results let result = None // try lint hover diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 94df794ccb..a4dc91b2fc 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -13,7 +13,9 @@ mod html; #[cfg(test)] mod tests; -use hir::{DescendPreference, Name, Semantics}; +use std::ops::ControlFlow; + +use hir::{Name, Semantics}; use ide_db::{FxHashMap, RootDatabase, SymbolKind}; use span::EditionedFileId; use syntax::{ @@ -399,20 +401,53 @@ fn traverse( // Attempt to descend tokens into macro-calls. let res = match element { NodeOrToken::Token(token) if token.kind() != COMMENT => { - let token = if token.kind() == STRING { - // for strings, try to prefer a string that has not been lost in a token - // tree - // FIXME: This should be done for everything, but check perf first - sema.descend_into_macros(DescendPreference::SameKind, token) - .into_iter() - .max_by_key(|it| { - it.parent().map_or(false, |it| it.kind() != TOKEN_TREE) - }) - .unwrap() - } else { - // FIXME: We should probably rank the tokens and find the most suitable? - sema.descend_into_macros_single_exact(token) - }; + let kind = token.kind(); + let text = token.text(); + let ident_kind = kind.is_any_identifier(); + + let mut t = None; + let mut r = 0; + // FIXME: Add an extra API that takes the file id of this. That is a simple way + // to prevent us constantly walking up the tree to fetch the file + sema.descend_into_macros_ng_b(token.clone(), |tok| { + let tok = tok.value; + let tok_kind = tok.kind(); + + let exact_same_kind = tok_kind == kind; + let both_idents = + exact_same_kind || (tok_kind.is_any_identifier() && ident_kind); + let same_text = tok.text() == text; + // anything that mapped into a token tree has likely no semantic information + let no_tt_parent = tok.parent().map_or(false, |it| it.kind() != TOKEN_TREE); + let my_rank = (both_idents as usize) + | ((exact_same_kind as usize) << 1) + | ((same_text as usize) << 2) + | ((no_tt_parent as usize) << 3); + + if my_rank > 0b1110 { + // a rank of 0b1110 means that we have found a maximally interesting + // token so stop early. + t = Some(tok); + return ControlFlow::Break(()); + } + + // r = r.max(my_rank); + // t = Some(t.take_if(|_| r < my_rank).unwrap_or(tok)); + match &mut t { + Some(prev) if r < my_rank => { + *prev = tok; + r = my_rank; + } + Some(_) => (), + None => { + r = my_rank; + t = Some(tok) + } + } + ControlFlow::Continue(()) + }); + + let token = t.unwrap_or(token); match token.parent().and_then(ast::NameLike::cast) { // Remap the token into the wrapping single token nodes Some(parent) => match (token.kind(), parent.syntax().kind()) { diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html index d6b7012a1f..196552020a 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html @@ -58,7 +58,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd } def_fn! { - fn bar() -> u32 { + fn bar() -> u32 { 100 } }