diff --git a/tooling/lsp/src/requests/completion.rs b/tooling/lsp/src/requests/completion.rs index 0d1d7af7ae6..c59544a36ea 100644 --- a/tooling/lsp/src/requests/completion.rs +++ b/tooling/lsp/src/requests/completion.rs @@ -113,6 +113,7 @@ struct NodeFinder<'a> { /// The line where an auto_import must be inserted auto_import_line: usize, self_type: Option, + in_comptime: bool, } impl<'a> NodeFinder<'a> { @@ -156,6 +157,7 @@ impl<'a> NodeFinder<'a> { nesting: 0, auto_import_line: 0, self_type: None, + in_comptime: false, } } @@ -1056,8 +1058,12 @@ impl<'a> Visitor for NodeFinder<'a> { self.collect_local_variables(¶m.pattern); } + let old_in_comptime = self.in_comptime; + self.in_comptime = noir_function.def.is_comptime; + noir_function.def.body.accept(Some(span), self); + self.in_comptime = old_in_comptime; self.type_parameters = old_type_parameters; self.self_type = None; @@ -1278,8 +1284,12 @@ impl<'a> Visitor for NodeFinder<'a> { let old_local_variables = self.local_variables.clone(); self.local_variables.clear(); + let old_in_comptime = self.in_comptime; + self.in_comptime = true; + statement.accept(self); + self.in_comptime = old_in_comptime; self.local_variables = old_local_variables; false @@ -1424,8 +1434,12 @@ impl<'a> Visitor for NodeFinder<'a> { let old_local_variables = self.local_variables.clone(); self.local_variables.clear(); + let old_in_comptime = self.in_comptime; + self.in_comptime = true; + block_expression.accept(Some(span), self); + self.in_comptime = old_in_comptime; self.local_variables = old_local_variables; false diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs index 5273e49d4b4..c0155096dc8 100644 --- a/tooling/lsp/src/requests/completion/completion_items.rs +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -232,7 +232,13 @@ impl<'a> NodeFinder<'a> { if modifiers.is_comptime && matches!(func_meta.return_type(), Type::Quoted(QuotedType::Quoted)) { - vec![make_completion_item(false), make_completion_item(true)] + if self.in_comptime { + vec![make_completion_item(false), make_completion_item(true)] + } else { + // If not in a comptime block we can't operate with comptime values so the only thing + // we can do is call a macro. + vec![make_completion_item(true)] + } } else { vec![make_completion_item(false)] } diff --git a/tooling/lsp/src/requests/completion/tests.rs b/tooling/lsp/src/requests/completion/tests.rs index 23d137c1647..7c596bccd11 100644 --- a/tooling/lsp/src/requests/completion/tests.rs +++ b/tooling/lsp/src/requests/completion/tests.rs @@ -2126,7 +2126,9 @@ mod completion_tests { comptime fn foobar() -> Quoted {} fn main() { - fooba>|< + comptime { + fooba>|< + } } "#; @@ -2140,6 +2142,24 @@ mod completion_tests { .await; } + #[test] + async fn test_suggests_only_macro_call_if_comptime_function_returns_quoted_and_outside_comptime( + ) { + let src = r#" + comptime fn foobar() -> Quoted {} + + fn main() { + fooba>|< + } + "#; + + assert_completion_excluding_auto_import( + src, + vec![function_completion_item("foobar!()", "foobar!()", "fn() -> Quoted")], + ) + .await; + } + #[test] async fn test_only_suggests_macro_call_for_unquote() { let src = r#"