about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs114
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs2
2 files changed, 59 insertions, 57 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
index be99510af2a..2e49af49145 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -15,7 +15,7 @@ use span::{Edition, EditionedFileId};
 use stdx::never;
 use syntax::{
     ast::{self, AstNode, HasGenericParams},
-    format_smolstr, match_ast, NodeOrToken, SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent,
+    format_smolstr, match_ast, SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent,
 };
 use text_edit::TextEdit;
 
@@ -95,26 +95,27 @@ pub(crate) fn inlay_hints(
     let famous_defs = FamousDefs(&sema, scope.krate());
 
     let ctx = &mut InlayHintCtx::default();
-    let hints = |node| hints(&mut acc, ctx, &famous_defs, config, file_id, node);
-    match range_limit {
-        // FIXME: This can miss some hints that require the parent of the range to calculate
-        Some(range) => match file.covering_element(range) {
-            NodeOrToken::Token(_) => return acc,
-            NodeOrToken::Node(n) => n
-                .preorder()
-                .filter(|event| matches!(event, WalkEvent::Enter(node) if range.intersect(node.text_range()).is_some()))
-                .for_each(hints),
-        },
-        None => file.preorder().for_each(hints),
+    let mut hints = |event| {
+        if let Some(node) = handle_event(ctx, event) {
+            hints(&mut acc, ctx, &famous_defs, config, file_id, node);
+        }
     };
-
+    let mut preorder = file.preorder();
+    while let Some(event) = preorder.next() {
+        // FIXME: This can miss some hints that require the parent of the range to calculate
+        if matches!((&event, range_limit), (WalkEvent::Enter(node), Some(range)) if range.intersect(node.text_range()).is_none())
+        {
+            preorder.skip_subtree();
+            continue;
+        }
+        hints(event);
+    }
     acc
 }
 
 #[derive(Default)]
 struct InlayHintCtx {
     lifetime_stacks: Vec<Vec<SmolStr>>,
-    is_param_list: bool,
 }
 
 pub(crate) fn inlay_hints_resolve(
@@ -138,20 +139,52 @@ pub(crate) fn inlay_hints_resolve(
     let mut acc = Vec::new();
 
     let ctx = &mut InlayHintCtx::default();
-    let hints = |node| hints(&mut acc, ctx, &famous_defs, config, file_id, node);
-
-    let mut res = file.clone();
-    let res = loop {
-        res = match res.child_or_token_at_range(resolve_range) {
-            Some(NodeOrToken::Node(n)) if n.text_range() == resolve_range => break n,
-            Some(NodeOrToken::Node(n)) => n,
-            _ => break res,
-        };
+    let mut hints = |event| {
+        if let Some(node) = handle_event(ctx, event) {
+            hints(&mut acc, ctx, &famous_defs, config, file_id, node);
+        }
     };
-    res.preorder().for_each(hints);
+
+    let mut preorder = file.preorder();
+    while let Some(event) = preorder.next() {
+        // FIXME: This can miss some hints that require the parent of the range to calculate
+        if matches!(&event, WalkEvent::Enter(node) if resolve_range.intersect(node.text_range()).is_none())
+        {
+            preorder.skip_subtree();
+            continue;
+        }
+        hints(event);
+    }
     acc.into_iter().find(|hint| hasher(hint) == hash)
 }
 
+fn handle_event(ctx: &mut InlayHintCtx, node: WalkEvent<SyntaxNode>) -> Option<SyntaxNode> {
+    match node {
+        WalkEvent::Enter(node) => {
+            if let Some(node) = ast::AnyHasGenericParams::cast(node.clone()) {
+                let params = node
+                    .generic_param_list()
+                    .map(|it| {
+                        it.lifetime_params()
+                            .filter_map(|it| {
+                                it.lifetime().map(|it| format_smolstr!("{}", &it.text()[1..]))
+                            })
+                            .collect()
+                    })
+                    .unwrap_or_default();
+                ctx.lifetime_stacks.push(params);
+            }
+            Some(node)
+        }
+        WalkEvent::Leave(n) => {
+            if ast::AnyHasGenericParams::can_cast(n.kind()) {
+                ctx.lifetime_stacks.pop();
+            }
+            None
+        }
+    }
+}
+
 // FIXME: At some point when our hir infra is fleshed out enough we should flip this and traverse the
 // HIR instead of the syntax tree.
 fn hints(
@@ -160,35 +193,8 @@ fn hints(
     famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
     file_id: EditionedFileId,
-    node: WalkEvent<SyntaxNode>,
+    node: SyntaxNode,
 ) {
-    let node = match node {
-        WalkEvent::Enter(node) => node,
-        WalkEvent::Leave(n) => {
-            if ast::AnyHasGenericParams::can_cast(n.kind()) {
-                ctx.lifetime_stacks.pop();
-                // pop
-            }
-            if ast::ParamList::can_cast(n.kind()) {
-                ctx.is_param_list = false;
-                // pop
-            }
-            return;
-        }
-    };
-
-    if let Some(node) = ast::AnyHasGenericParams::cast(node.clone()) {
-        let params = node
-            .generic_param_list()
-            .map(|it| {
-                it.lifetime_params()
-                    .filter_map(|it| it.lifetime().map(|it| format_smolstr!("{}", &it.text()[1..])))
-                    .collect()
-            })
-            .unwrap_or_default();
-        ctx.lifetime_stacks.push(params);
-    }
-
     closing_brace::hints(hints, sema, config, file_id, node.clone());
     if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) {
         generic_param::hints(hints, sema, config, any_has_generic_args);
@@ -242,10 +248,6 @@ fn hints(
                 ast::Type::PathType(path) => lifetime::fn_path_hints(hints, ctx, famous_defs, config, file_id, path),
                 _ => Some(()),
             },
-            ast::ParamList(_) => {
-                ctx.is_param_list = true;
-                Some(())
-            },
             _ => Some(()),
         }
     };
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs
index de463670677..653e3a6ef1d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs
@@ -532,7 +532,7 @@ fn fn_ptr(a: fn(&()) -> &fn(&()) -> &()) {}
                        //^^ for<'1>
                           //^'1
                                   //^'1
-fn fn_ptr2(a: for<'a> fn(&()) -> &())) {}
+fn fn_ptr2(a: for<'a> fn(&()) -> &()) {}
                //^'0, $
                        //^'0
                                //^'0