diff --git a/tooling/lsp/src/requests/completion.rs b/tooling/lsp/src/requests/completion.rs index ad2082d75a8..3074a3db335 100644 --- a/tooling/lsp/src/requests/completion.rs +++ b/tooling/lsp/src/requests/completion.rs @@ -11,13 +11,11 @@ use lsp_types::{CompletionItem, CompletionItemKind, CompletionParams, Completion use noirc_errors::{Location, Span}; use noirc_frontend::{ ast::{ - ArrayLiteral, AsTraitPath, BlockExpression, CallExpression, CastExpression, - ConstrainStatement, ConstructorExpression, Expression, ForLoopStatement, ForRange, - FunctionReturnType, Ident, IfExpression, IndexExpression, InfixExpression, LValue, Lambda, - LetStatement, Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, - NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Path, PathKind, PathSegment, Pattern, - Statement, TraitImplItem, TraitItem, TypeImpl, UnresolvedGeneric, UnresolvedGenerics, - UnresolvedType, UseTree, UseTreeKind, + AsTraitPath, BlockExpression, ConstructorExpression, Expression, ExpressionKind, + ForLoopStatement, Ident, IfExpression, LValue, Lambda, LetStatement, + MemberAccessExpression, NoirFunction, NoirStruct, NoirTraitImpl, Path, PathKind, + PathSegment, Pattern, Statement, StatementKind, TraitItem, TypeImpl, UnresolvedGeneric, + UnresolvedGenerics, UnresolvedType, UnresolvedTypeData, UseTree, UseTreeKind, }, graph::{CrateId, Dependency}, hir::{ @@ -40,6 +38,7 @@ mod completion_items; mod kinds; mod sort_text; mod tests; +mod traversal; pub(crate) fn on_completion_request( state: &mut LspState, @@ -154,12 +153,6 @@ impl<'a> NodeFinder<'a> { } } - fn find_in_parsed_module(&mut self, parsed_module: &ParsedModule) { - for item in &parsed_module.items { - self.find_in_item(item); - } - } - fn find_in_item(&mut self, item: &Item) { if !self.includes_span(item.span) { return; @@ -230,14 +223,6 @@ impl<'a> NodeFinder<'a> { self.type_parameters.clear(); } - fn find_in_trait_impl_item(&mut self, item: &TraitImplItem) { - match item { - TraitImplItem::Function(noir_function) => self.find_in_noir_function(noir_function), - TraitImplItem::Constant(_, _, _) => (), - TraitImplItem::Type { .. } => (), - } - } - fn find_in_type_impl(&mut self, type_impl: &TypeImpl) { self.type_parameters.clear(); self.collect_type_parameters_in_generics(&type_impl.generics); @@ -254,10 +239,6 @@ impl<'a> NodeFinder<'a> { self.type_parameters.clear(); } - fn find_in_noir_type_alias(&mut self, noir_type_alias: &NoirTypeAlias) { - self.find_in_unresolved_type(&noir_type_alias.typ); - } - fn find_in_noir_struct(&mut self, noir_struct: &NoirStruct) { self.type_parameters.clear(); self.collect_type_parameters_in_generics(&noir_struct.generics); @@ -269,12 +250,6 @@ impl<'a> NodeFinder<'a> { self.type_parameters.clear(); } - fn find_in_noir_trait(&mut self, noir_trait: &NoirTrait) { - for item in &noir_trait.items { - self.find_in_trait_item(item); - } - } - fn find_in_trait_item(&mut self, trait_item: &TraitItem) { match trait_item { TraitItem::Function { @@ -334,22 +309,22 @@ impl<'a> NodeFinder<'a> { fn find_in_statement(&mut self, statement: &Statement) { match &statement.kind { - noirc_frontend::ast::StatementKind::Let(let_statement) => { + StatementKind::Let(let_statement) => { self.find_in_let_statement(let_statement, true); } - noirc_frontend::ast::StatementKind::Constrain(constrain_statement) => { + StatementKind::Constrain(constrain_statement) => { self.find_in_constrain_statement(constrain_statement); } - noirc_frontend::ast::StatementKind::Expression(expression) => { + StatementKind::Expression(expression) => { self.find_in_expression(expression); } - noirc_frontend::ast::StatementKind::Assign(assign_statement) => { + StatementKind::Assign(assign_statement) => { self.find_in_assign_statement(assign_statement); } - noirc_frontend::ast::StatementKind::For(for_loop_statement) => { + StatementKind::For(for_loop_statement) => { self.find_in_for_loop_statement(for_loop_statement); } - noirc_frontend::ast::StatementKind::Comptime(statement) => { + StatementKind::Comptime(statement) => { // When entering a comptime block, regular local variables shouldn't be offered anymore let old_local_variables = self.local_variables.clone(); self.local_variables.clear(); @@ -358,12 +333,10 @@ impl<'a> NodeFinder<'a> { self.local_variables = old_local_variables; } - noirc_frontend::ast::StatementKind::Semi(expression) => { + StatementKind::Semi(expression) => { self.find_in_expression(expression); } - noirc_frontend::ast::StatementKind::Break - | noirc_frontend::ast::StatementKind::Continue - | noirc_frontend::ast::StatementKind::Error => (), + StatementKind::Break | StatementKind::Continue | StatementKind::Error => (), } } @@ -380,22 +353,6 @@ impl<'a> NodeFinder<'a> { } } - fn find_in_constrain_statement(&mut self, constrain_statement: &ConstrainStatement) { - self.find_in_expression(&constrain_statement.0); - - if let Some(exp) = &constrain_statement.1 { - self.find_in_expression(exp); - } - } - - fn find_in_assign_statement( - &mut self, - assign_statement: &noirc_frontend::ast::AssignStatement, - ) { - self.find_in_lvalue(&assign_statement.lvalue); - self.find_in_expression(&assign_statement.expression); - } - fn find_in_for_loop_statement(&mut self, for_loop_statement: &ForLoopStatement) { let old_local_variables = self.local_variables.clone(); let ident = &for_loop_statement.identifier; @@ -430,69 +387,53 @@ impl<'a> NodeFinder<'a> { } } - fn find_in_for_range(&mut self, for_range: &ForRange) { - match for_range { - ForRange::Range(start, end) => { - self.find_in_expression(start); - self.find_in_expression(end); - } - ForRange::Array(expression) => self.find_in_expression(expression), - } - } - - fn find_in_expressions(&mut self, expressions: &[Expression]) { - for expression in expressions { - self.find_in_expression(expression); - } - } - fn find_in_expression(&mut self, expression: &Expression) { match &expression.kind { - noirc_frontend::ast::ExpressionKind::Literal(literal) => self.find_in_literal(literal), - noirc_frontend::ast::ExpressionKind::Block(block_expression) => { + ExpressionKind::Literal(literal) => self.find_in_literal(literal), + ExpressionKind::Block(block_expression) => { self.find_in_block_expression(block_expression); } - noirc_frontend::ast::ExpressionKind::Prefix(prefix_expression) => { + ExpressionKind::Prefix(prefix_expression) => { self.find_in_expression(&prefix_expression.rhs); } - noirc_frontend::ast::ExpressionKind::Index(index_expression) => { + ExpressionKind::Index(index_expression) => { self.find_in_index_expression(index_expression); } - noirc_frontend::ast::ExpressionKind::Call(call_expression) => { + ExpressionKind::Call(call_expression) => { self.find_in_call_expression(call_expression); } - noirc_frontend::ast::ExpressionKind::MethodCall(method_call_expression) => { + ExpressionKind::MethodCall(method_call_expression) => { self.find_in_method_call_expression(method_call_expression); } - noirc_frontend::ast::ExpressionKind::Constructor(constructor_expression) => { + ExpressionKind::Constructor(constructor_expression) => { self.find_in_constructor_expression(constructor_expression); } - noirc_frontend::ast::ExpressionKind::MemberAccess(member_access_expression) => { + ExpressionKind::MemberAccess(member_access_expression) => { self.find_in_member_access_expression(member_access_expression); } - noirc_frontend::ast::ExpressionKind::Cast(cast_expression) => { + ExpressionKind::Cast(cast_expression) => { self.find_in_cast_expression(cast_expression); } - noirc_frontend::ast::ExpressionKind::Infix(infix_expression) => { + ExpressionKind::Infix(infix_expression) => { self.find_in_infix_expression(infix_expression); } - noirc_frontend::ast::ExpressionKind::If(if_expression) => { + ExpressionKind::If(if_expression) => { self.find_in_if_expression(if_expression); } - noirc_frontend::ast::ExpressionKind::Variable(path) => { + ExpressionKind::Variable(path) => { self.find_in_path(path, RequestedItems::AnyItems); } - noirc_frontend::ast::ExpressionKind::Tuple(expressions) => { + ExpressionKind::Tuple(expressions) => { self.find_in_expressions(expressions); } - noirc_frontend::ast::ExpressionKind::Lambda(lambda) => self.find_in_lambda(lambda), - noirc_frontend::ast::ExpressionKind::Parenthesized(expression) => { + ExpressionKind::Lambda(lambda) => self.find_in_lambda(lambda), + ExpressionKind::Parenthesized(expression) => { self.find_in_expression(expression); } - noirc_frontend::ast::ExpressionKind::Unquote(expression) => { + ExpressionKind::Unquote(expression) => { self.find_in_expression(expression); } - noirc_frontend::ast::ExpressionKind::Comptime(block_expression, _) => { + ExpressionKind::Comptime(block_expression, _) => { // When entering a comptime block, regular local variables shouldn't be offered anymore let old_local_variables = self.local_variables.clone(); self.local_variables.clear(); @@ -501,15 +442,13 @@ impl<'a> NodeFinder<'a> { self.local_variables = old_local_variables; } - noirc_frontend::ast::ExpressionKind::Unsafe(block_expression, _) => { + ExpressionKind::Unsafe(block_expression, _) => { self.find_in_block_expression(block_expression); } - noirc_frontend::ast::ExpressionKind::AsTraitPath(as_trait_path) => { + ExpressionKind::AsTraitPath(as_trait_path) => { self.find_in_as_trait_path(as_trait_path); } - noirc_frontend::ast::ExpressionKind::Quote(_) - | noirc_frontend::ast::ExpressionKind::Resolved(_) - | noirc_frontend::ast::ExpressionKind::Error => (), + ExpressionKind::Quote(_) | ExpressionKind::Resolved(_) | ExpressionKind::Error => (), } // "foo." (no identifier afterwards) is parsed as the expression on the left hand-side of the dot. @@ -530,44 +469,6 @@ impl<'a> NodeFinder<'a> { } } - fn find_in_literal(&mut self, literal: &Literal) { - match literal { - Literal::Array(array_literal) => self.find_in_array_literal(array_literal), - Literal::Slice(array_literal) => self.find_in_array_literal(array_literal), - Literal::Bool(_) - | Literal::Integer(_, _) - | Literal::Str(_) - | Literal::RawStr(_, _) - | Literal::FmtStr(_) - | Literal::Unit => (), - } - } - - fn find_in_array_literal(&mut self, array_literal: &ArrayLiteral) { - match array_literal { - ArrayLiteral::Standard(expressions) => self.find_in_expressions(expressions), - ArrayLiteral::Repeated { repeated_element, length } => { - self.find_in_expression(repeated_element); - self.find_in_expression(length); - } - } - } - - fn find_in_index_expression(&mut self, index_expression: &IndexExpression) { - self.find_in_expression(&index_expression.collection); - self.find_in_expression(&index_expression.index); - } - - fn find_in_call_expression(&mut self, call_expression: &CallExpression) { - self.find_in_expression(&call_expression.func); - self.find_in_expressions(&call_expression.arguments); - } - - fn find_in_method_call_expression(&mut self, method_call_expression: &MethodCallExpression) { - self.find_in_expression(&method_call_expression.object); - self.find_in_expressions(&method_call_expression.arguments); - } - fn find_in_constructor_expression(&mut self, constructor_expression: &ConstructorExpression) { self.find_in_path(&constructor_expression.type_name, RequestedItems::OnlyTypes); @@ -596,15 +497,6 @@ impl<'a> NodeFinder<'a> { self.find_in_expression(&member_access_expression.lhs); } - fn find_in_cast_expression(&mut self, cast_expression: &CastExpression) { - self.find_in_expression(&cast_expression.lhs); - } - - fn find_in_infix_expression(&mut self, infix_expression: &InfixExpression) { - self.find_in_expression(&infix_expression.lhs); - self.find_in_expression(&infix_expression.rhs); - } - fn find_in_if_expression(&mut self, if_expression: &IfExpression) { self.find_in_expression(&if_expression.condition); @@ -638,21 +530,6 @@ impl<'a> NodeFinder<'a> { self.find_in_path(&as_trait_path.trait_path, RequestedItems::OnlyTypes); } - fn find_in_function_return_type(&mut self, return_type: &FunctionReturnType) { - match return_type { - noirc_frontend::ast::FunctionReturnType::Default(_) => (), - noirc_frontend::ast::FunctionReturnType::Ty(unresolved_type) => { - self.find_in_unresolved_type(unresolved_type); - } - } - } - - fn find_in_unresolved_types(&mut self, unresolved_type: &[UnresolvedType]) { - for unresolved_type in unresolved_type { - self.find_in_unresolved_type(unresolved_type); - } - } - fn find_in_unresolved_type(&mut self, unresolved_type: &UnresolvedType) { if let Some(span) = unresolved_type.span { if !self.includes_span(span) { @@ -661,48 +538,48 @@ impl<'a> NodeFinder<'a> { } match &unresolved_type.typ { - noirc_frontend::ast::UnresolvedTypeData::Array(_, unresolved_type) => { + UnresolvedTypeData::Array(_, unresolved_type) => { self.find_in_unresolved_type(unresolved_type); } - noirc_frontend::ast::UnresolvedTypeData::Slice(unresolved_type) => { + UnresolvedTypeData::Slice(unresolved_type) => { self.find_in_unresolved_type(unresolved_type); } - noirc_frontend::ast::UnresolvedTypeData::Parenthesized(unresolved_type) => { + UnresolvedTypeData::Parenthesized(unresolved_type) => { self.find_in_unresolved_type(unresolved_type); } - noirc_frontend::ast::UnresolvedTypeData::Named(path, unresolved_types, _) => { + UnresolvedTypeData::Named(path, unresolved_types, _) => { self.find_in_path(path, RequestedItems::OnlyTypes); self.find_in_unresolved_types(unresolved_types); } - noirc_frontend::ast::UnresolvedTypeData::TraitAsType(path, unresolved_types) => { + UnresolvedTypeData::TraitAsType(path, unresolved_types) => { self.find_in_path(path, RequestedItems::OnlyTypes); self.find_in_unresolved_types(unresolved_types); } - noirc_frontend::ast::UnresolvedTypeData::MutableReference(unresolved_type) => { + UnresolvedTypeData::MutableReference(unresolved_type) => { self.find_in_unresolved_type(unresolved_type); } - noirc_frontend::ast::UnresolvedTypeData::Tuple(unresolved_types) => { + UnresolvedTypeData::Tuple(unresolved_types) => { self.find_in_unresolved_types(unresolved_types); } - noirc_frontend::ast::UnresolvedTypeData::Function(args, ret, env, _) => { + UnresolvedTypeData::Function(args, ret, env, _) => { self.find_in_unresolved_types(args); self.find_in_unresolved_type(ret); self.find_in_unresolved_type(env); } - noirc_frontend::ast::UnresolvedTypeData::AsTraitPath(as_trait_path) => { + UnresolvedTypeData::AsTraitPath(as_trait_path) => { self.find_in_as_trait_path(as_trait_path); } - noirc_frontend::ast::UnresolvedTypeData::Expression(_) - | noirc_frontend::ast::UnresolvedTypeData::FormatString(_, _) - | noirc_frontend::ast::UnresolvedTypeData::String(_) - | noirc_frontend::ast::UnresolvedTypeData::Unspecified - | noirc_frontend::ast::UnresolvedTypeData::Quoted(_) - | noirc_frontend::ast::UnresolvedTypeData::FieldElement - | noirc_frontend::ast::UnresolvedTypeData::Integer(_, _) - | noirc_frontend::ast::UnresolvedTypeData::Bool - | noirc_frontend::ast::UnresolvedTypeData::Unit - | noirc_frontend::ast::UnresolvedTypeData::Resolved(_) - | noirc_frontend::ast::UnresolvedTypeData::Error => (), + UnresolvedTypeData::Expression(_) + | UnresolvedTypeData::FormatString(_, _) + | UnresolvedTypeData::String(_) + | UnresolvedTypeData::Unspecified + | UnresolvedTypeData::Quoted(_) + | UnresolvedTypeData::FieldElement + | UnresolvedTypeData::Integer(_, _) + | UnresolvedTypeData::Bool + | UnresolvedTypeData::Unit + | UnresolvedTypeData::Resolved(_) + | UnresolvedTypeData::Error => (), } } @@ -977,6 +854,9 @@ impl<'a> NodeFinder<'a> { let type_alias = type_alias.borrow(); return self.complete_type_fields_and_methods(&type_alias.typ, prefix); } + Type::Tuple(types) => { + self.complete_tuple_fields(types); + } Type::FieldElement | Type::Array(_, _) | Type::Slice(_) @@ -985,7 +865,6 @@ impl<'a> NodeFinder<'a> { | Type::String(_) | Type::FmtString(_, _) | Type::Unit - | Type::Tuple(_) | Type::TypeVariable(_, _) | Type::TraitAsType(_, _, _) | Type::NamedGeneric(_, _, _) @@ -1037,6 +916,16 @@ impl<'a> NodeFinder<'a> { } } + fn complete_tuple_fields(&mut self, types: &[Type]) { + for (index, typ) in types.iter().enumerate() { + self.completion_items.push(simple_completion_item( + index.to_string(), + CompletionItemKind::FIELD, + Some(typ.to_string()), + )); + } + } + #[allow(clippy::too_many_arguments)] fn complete_in_module( &mut self, diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs index a5848bf2a72..f967845e184 100644 --- a/tooling/lsp/src/requests/completion/completion_items.rs +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -90,7 +90,7 @@ impl<'a> NodeFinder<'a> { let func_meta = self.interner.function_meta(&func_id); let name = &self.interner.function_name(&func_id).to_string(); - let func_self_type = if let Some((pattern, typ, _)) = func_meta.parameters.0.get(0) { + let func_self_type = if let Some((pattern, typ, _)) = func_meta.parameters.0.first() { if self.hir_pattern_is_self_type(pattern) { if let Type::MutableReference(mut_typ) = typ { let typ: &Type = mut_typ; @@ -123,6 +123,14 @@ impl<'a> NodeFinder<'a> { if self_type != func_self_type { return None; } + } else if let Type::Tuple(self_tuple_types) = self_type { + // Tuple types of different lengths seem to also have methods defined on all of them, + // so here we reject methods for tuples where the length doesn't match. + if let Type::Tuple(func_self_tuple_types) = func_self_type { + if self_tuple_types.len() != func_self_tuple_types.len() { + return None; + } + } } } else { return None; diff --git a/tooling/lsp/src/requests/completion/tests.rs b/tooling/lsp/src/requests/completion/tests.rs index 42632a2f445..ed8331c3417 100644 --- a/tooling/lsp/src/requests/completion/tests.rs +++ b/tooling/lsp/src/requests/completion/tests.rs @@ -23,7 +23,7 @@ mod completion_tests { }; use tokio::test; - async fn assert_completion(src: &str, expected: Vec) { + async fn get_completions(src: &str) -> Vec { let (mut state, noir_text_document) = test_utils::init_lsp_server("document_symbol").await; let (line, column) = src @@ -49,8 +49,6 @@ mod completion_tests { }, ); - // Get inlay hints. These should now be relative to the changed text, - // not the saved file's text. let response = on_completion_request( &mut state, CompletionParams { @@ -71,10 +69,12 @@ mod completion_tests { panic!("Expected response to be CompletionResponse::Array"); }; - let mut items = items.clone(); + items + } + + fn assert_items_match(mut items: Vec, mut expected: Vec) { items.sort_by_key(|item| item.label.clone()); - let mut expected = expected.clone(); expected.sort_by_key(|item| item.label.clone()); if items != expected { @@ -91,6 +91,11 @@ mod completion_tests { assert_eq!(items, expected); } + async fn assert_completion(src: &str, expected: Vec) { + let items = get_completions(src).await; + assert_items_match(items, expected); + } + pub(super) fn function_completion_item( label: impl Into, kind: CompletionItemKind, @@ -1363,4 +1368,26 @@ mod completion_tests { ) .await; } + + #[test] + async fn test_completes_tuple_fields() { + let src = r#" + fn main() { + let tuple = (1, true); + tuple.>|< + } + "#; + + let items = get_completions(src).await; + let items = items.into_iter().filter(|item| item.kind == Some(CompletionItemKind::FIELD)); + let items = items.collect(); + + assert_items_match( + items, + vec![ + simple_completion_item("0", CompletionItemKind::FIELD, Some("Field".to_string())), + simple_completion_item("1", CompletionItemKind::FIELD, Some("bool".to_string())), + ], + ); + } } diff --git a/tooling/lsp/src/requests/completion/traversal.rs b/tooling/lsp/src/requests/completion/traversal.rs new file mode 100644 index 00000000000..b487c8baf36 --- /dev/null +++ b/tooling/lsp/src/requests/completion/traversal.rs @@ -0,0 +1,132 @@ +/// This file includes the completion logic that's just about +/// traversing the AST without any additional logic. +use noirc_frontend::{ + ast::{ + ArrayLiteral, AssignStatement, CallExpression, CastExpression, ConstrainStatement, + Expression, ForRange, FunctionReturnType, IndexExpression, InfixExpression, Literal, + MethodCallExpression, NoirTrait, NoirTypeAlias, TraitImplItem, UnresolvedType, + }, + ParsedModule, +}; + +use super::NodeFinder; + +impl<'a> NodeFinder<'a> { + pub(super) fn find_in_parsed_module(&mut self, parsed_module: &ParsedModule) { + for item in &parsed_module.items { + self.find_in_item(item); + } + } + + pub(super) fn find_in_trait_impl_item(&mut self, item: &TraitImplItem) { + match item { + TraitImplItem::Function(noir_function) => self.find_in_noir_function(noir_function), + TraitImplItem::Constant(_, _, _) => (), + TraitImplItem::Type { .. } => (), + } + } + + pub(super) fn find_in_noir_trait(&mut self, noir_trait: &NoirTrait) { + for item in &noir_trait.items { + self.find_in_trait_item(item); + } + } + + pub(super) fn find_in_constrain_statement(&mut self, constrain_statement: &ConstrainStatement) { + self.find_in_expression(&constrain_statement.0); + + if let Some(exp) = &constrain_statement.1 { + self.find_in_expression(exp); + } + } + + pub(super) fn find_in_assign_statement(&mut self, assign_statement: &AssignStatement) { + self.find_in_lvalue(&assign_statement.lvalue); + self.find_in_expression(&assign_statement.expression); + } + + pub(super) fn find_in_for_range(&mut self, for_range: &ForRange) { + match for_range { + ForRange::Range(start, end) => { + self.find_in_expression(start); + self.find_in_expression(end); + } + ForRange::Array(expression) => self.find_in_expression(expression), + } + } + + pub(super) fn find_in_expressions(&mut self, expressions: &[Expression]) { + for expression in expressions { + self.find_in_expression(expression); + } + } + + pub(super) fn find_in_literal(&mut self, literal: &Literal) { + match literal { + Literal::Array(array_literal) => self.find_in_array_literal(array_literal), + Literal::Slice(array_literal) => self.find_in_array_literal(array_literal), + Literal::Bool(_) + | Literal::Integer(_, _) + | Literal::Str(_) + | Literal::RawStr(_, _) + | Literal::FmtStr(_) + | Literal::Unit => (), + } + } + + pub(super) fn find_in_array_literal(&mut self, array_literal: &ArrayLiteral) { + match array_literal { + ArrayLiteral::Standard(expressions) => self.find_in_expressions(expressions), + ArrayLiteral::Repeated { repeated_element, length } => { + self.find_in_expression(repeated_element); + self.find_in_expression(length); + } + } + } + + pub(super) fn find_in_index_expression(&mut self, index_expression: &IndexExpression) { + self.find_in_expression(&index_expression.collection); + self.find_in_expression(&index_expression.index); + } + + pub(super) fn find_in_call_expression(&mut self, call_expression: &CallExpression) { + self.find_in_expression(&call_expression.func); + self.find_in_expressions(&call_expression.arguments); + } + + pub(super) fn find_in_method_call_expression( + &mut self, + method_call_expression: &MethodCallExpression, + ) { + self.find_in_expression(&method_call_expression.object); + self.find_in_expressions(&method_call_expression.arguments); + } + + pub(super) fn find_in_cast_expression(&mut self, cast_expression: &CastExpression) { + self.find_in_expression(&cast_expression.lhs); + } + + pub(super) fn find_in_infix_expression(&mut self, infix_expression: &InfixExpression) { + self.find_in_expression(&infix_expression.lhs); + self.find_in_expression(&infix_expression.rhs); + } + + pub(super) fn find_in_unresolved_types(&mut self, unresolved_type: &[UnresolvedType]) { + for unresolved_type in unresolved_type { + self.find_in_unresolved_type(unresolved_type); + } + } + + pub(super) fn find_in_function_return_type(&mut self, return_type: &FunctionReturnType) { + match return_type { + noirc_frontend::ast::FunctionReturnType::Default(_) => (), + noirc_frontend::ast::FunctionReturnType::Ty(unresolved_type) => { + self.find_in_unresolved_type(unresolved_type); + } + } + } + + pub(super) fn find_in_noir_type_alias(&mut self, noir_type_alias: &NoirTypeAlias) { + self.find_in_unresolved_type(&noir_type_alias.typ); + } +} diff --git a/tooling/lsp/src/requests/signature_help/traversal.rs b/tooling/lsp/src/requests/signature_help/traversal.rs index ecb3bf46487..22f92a86124 100644 --- a/tooling/lsp/src/requests/signature_help/traversal.rs +++ b/tooling/lsp/src/requests/signature_help/traversal.rs @@ -4,10 +4,11 @@ use super::SignatureFinder; use noirc_frontend::{ ast::{ - ArrayLiteral, BlockExpression, CastExpression, ConstrainStatement, ConstructorExpression, - Expression, ForLoopStatement, ForRange, IfExpression, IndexExpression, InfixExpression, - LValue, Lambda, LetStatement, Literal, MemberAccessExpression, NoirFunction, NoirTrait, - NoirTraitImpl, Statement, TraitImplItem, TraitItem, TypeImpl, + ArrayLiteral, AssignStatement, BlockExpression, CastExpression, ConstrainStatement, + ConstructorExpression, Expression, ExpressionKind, ForLoopStatement, ForRange, + IfExpression, IndexExpression, InfixExpression, LValue, Lambda, LetStatement, Literal, + MemberAccessExpression, NoirFunction, NoirTrait, NoirTraitImpl, Statement, StatementKind, + TraitImplItem, TraitItem, TypeImpl, }, parser::{Item, ItemKind}, ParsedModule, @@ -103,30 +104,28 @@ impl<'a> SignatureFinder<'a> { } match &statement.kind { - noirc_frontend::ast::StatementKind::Let(let_statement) => { + StatementKind::Let(let_statement) => { self.find_in_let_statement(let_statement); } - noirc_frontend::ast::StatementKind::Constrain(constrain_statement) => { + StatementKind::Constrain(constrain_statement) => { self.find_in_constrain_statement(constrain_statement); } - noirc_frontend::ast::StatementKind::Expression(expression) => { + StatementKind::Expression(expression) => { self.find_in_expression(expression); } - noirc_frontend::ast::StatementKind::Assign(assign_statement) => { + StatementKind::Assign(assign_statement) => { self.find_in_assign_statement(assign_statement); } - noirc_frontend::ast::StatementKind::For(for_loop_statement) => { + StatementKind::For(for_loop_statement) => { self.find_in_for_loop_statement(for_loop_statement); } - noirc_frontend::ast::StatementKind::Comptime(statement) => { + StatementKind::Comptime(statement) => { self.find_in_statement(statement); } - noirc_frontend::ast::StatementKind::Semi(expression) => { + StatementKind::Semi(expression) => { self.find_in_expression(expression); } - noirc_frontend::ast::StatementKind::Break - | noirc_frontend::ast::StatementKind::Continue - | noirc_frontend::ast::StatementKind::Error => (), + StatementKind::Break | StatementKind::Continue | StatementKind::Error => (), } } @@ -142,10 +141,7 @@ impl<'a> SignatureFinder<'a> { } } - pub(super) fn find_in_assign_statement( - &mut self, - assign_statement: &noirc_frontend::ast::AssignStatement, - ) { + pub(super) fn find_in_assign_statement(&mut self, assign_statement: &AssignStatement) { self.find_in_lvalue(&assign_statement.lvalue); self.find_in_expression(&assign_statement.expression); } @@ -185,58 +181,58 @@ impl<'a> SignatureFinder<'a> { pub(super) fn find_in_expression(&mut self, expression: &Expression) { match &expression.kind { - noirc_frontend::ast::ExpressionKind::Literal(literal) => self.find_in_literal(literal), - noirc_frontend::ast::ExpressionKind::Block(block_expression) => { + ExpressionKind::Literal(literal) => self.find_in_literal(literal), + ExpressionKind::Block(block_expression) => { self.find_in_block_expression(block_expression); } - noirc_frontend::ast::ExpressionKind::Prefix(prefix_expression) => { + ExpressionKind::Prefix(prefix_expression) => { self.find_in_expression(&prefix_expression.rhs); } - noirc_frontend::ast::ExpressionKind::Index(index_expression) => { + ExpressionKind::Index(index_expression) => { self.find_in_index_expression(index_expression); } - noirc_frontend::ast::ExpressionKind::Call(call_expression) => { + ExpressionKind::Call(call_expression) => { self.find_in_call_expression(call_expression, expression.span); } - noirc_frontend::ast::ExpressionKind::MethodCall(method_call_expression) => { + ExpressionKind::MethodCall(method_call_expression) => { self.find_in_method_call_expression(method_call_expression, expression.span); } - noirc_frontend::ast::ExpressionKind::Constructor(constructor_expression) => { + ExpressionKind::Constructor(constructor_expression) => { self.find_in_constructor_expression(constructor_expression); } - noirc_frontend::ast::ExpressionKind::MemberAccess(member_access_expression) => { + ExpressionKind::MemberAccess(member_access_expression) => { self.find_in_member_access_expression(member_access_expression); } - noirc_frontend::ast::ExpressionKind::Cast(cast_expression) => { + ExpressionKind::Cast(cast_expression) => { self.find_in_cast_expression(cast_expression); } - noirc_frontend::ast::ExpressionKind::Infix(infix_expression) => { + ExpressionKind::Infix(infix_expression) => { self.find_in_infix_expression(infix_expression); } - noirc_frontend::ast::ExpressionKind::If(if_expression) => { + ExpressionKind::If(if_expression) => { self.find_in_if_expression(if_expression); } - noirc_frontend::ast::ExpressionKind::Tuple(expressions) => { + ExpressionKind::Tuple(expressions) => { self.find_in_expressions(expressions); } - noirc_frontend::ast::ExpressionKind::Lambda(lambda) => self.find_in_lambda(lambda), - noirc_frontend::ast::ExpressionKind::Parenthesized(expression) => { + ExpressionKind::Lambda(lambda) => self.find_in_lambda(lambda), + ExpressionKind::Parenthesized(expression) => { self.find_in_expression(expression); } - noirc_frontend::ast::ExpressionKind::Unquote(expression) => { + ExpressionKind::Unquote(expression) => { self.find_in_expression(expression); } - noirc_frontend::ast::ExpressionKind::Comptime(block_expression, _) => { + ExpressionKind::Comptime(block_expression, _) => { self.find_in_block_expression(block_expression); } - noirc_frontend::ast::ExpressionKind::Unsafe(block_expression, _) => { + ExpressionKind::Unsafe(block_expression, _) => { self.find_in_block_expression(block_expression); } - noirc_frontend::ast::ExpressionKind::Variable(_) - | noirc_frontend::ast::ExpressionKind::AsTraitPath(_) - | noirc_frontend::ast::ExpressionKind::Quote(_) - | noirc_frontend::ast::ExpressionKind::Resolved(_) - | noirc_frontend::ast::ExpressionKind::Error => (), + ExpressionKind::Variable(_) + | ExpressionKind::AsTraitPath(_) + | ExpressionKind::Quote(_) + | ExpressionKind::Resolved(_) + | ExpressionKind::Error => (), } }