From 97568ffe195a674a7518d2cd40771efb9fed865a Mon Sep 17 00:00:00 2001 From: Koby Date: Thu, 18 Jan 2024 18:55:51 +0100 Subject: [PATCH 1/4] feat(lsp): goto type reference --- .../noirc_frontend/src/hir/resolution/resolver.rs | 9 +++++++++ compiler/noirc_frontend/src/node_interner.rs | 9 +++++++++ compiler/noirc_frontend/src/resolve_locations.rs | 12 ++++++++++++ 3 files changed, 30 insertions(+) diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 8f656751fe..3f6d50e01d 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -710,6 +710,15 @@ impl<'a> Resolver<'a> { if resolved_type.is_nested_slice() { self.errors.push(ResolverError::NestedSlices { span: span.unwrap() }); } + + if let Some(unresolved_span) = span { + // Record the location of the type reference + self.interner.push_type_ref_location( + resolved_type.clone(), + Location::new(unresolved_span, self.file), + ); + } + resolved_type } diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 193f3fe043..34c144106a 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -142,6 +142,9 @@ pub struct NodeInterner { // For trait implementation functions, this is their self type and trait they belong to func_id_to_trait: HashMap, + + /// Stores the [Location] of a [Type] reference + pub(crate) type_ref_locations: Vec<(Type, Location)>, } /// A trait implementation is either a normal implementation that is present in the source @@ -450,6 +453,7 @@ impl Default for NodeInterner { globals: HashMap::new(), struct_methods: HashMap::new(), primitive_methods: HashMap::new(), + type_ref_locations: Vec::new(), }; // An empty block expression is used often, we add this into the `node` on startup @@ -597,6 +601,11 @@ impl NodeInterner { self.id_to_type.insert(definition_id.into(), typ); } + /// Store [Location] of [Type] reference + pub fn push_type_ref_location(&mut self, typ: Type, location: Location) { + self.type_ref_locations.push((typ, location)); + } + pub fn push_global(&mut self, stmt_id: StmtId, ident: Ident, local_id: LocalModuleId) { self.globals.insert(stmt_id, GlobalInfo { ident, local_id }); } diff --git a/compiler/noirc_frontend/src/resolve_locations.rs b/compiler/noirc_frontend/src/resolve_locations.rs index c6834a4361..c7800a3ee1 100644 --- a/compiler/noirc_frontend/src/resolve_locations.rs +++ b/compiler/noirc_frontend/src/resolve_locations.rs @@ -42,6 +42,7 @@ impl NodeInterner { .and_then(|index| self.resolve_location(index, return_type_location_instead)) .or_else(|| self.try_resolve_trait_impl_location(location)) .or_else(|| self.try_resolve_trait_method_declaration(location)) + .or_else(|| self.try_resolve_type_ref(location)) } pub fn get_declaration_location_from(&self, location: Location) -> Option { @@ -194,4 +195,15 @@ impl NodeInterner { method.map(|method| method.location) }) } + + /// Attempts to resolve [Location] of [Type] based on [Location] of reference in code + pub(crate) fn try_resolve_type_ref(&self, location: Location) -> Option { + self.type_ref_locations + .iter() + .find(|(_typ, type_ref_location)| type_ref_location.contains(&location)) + .and_then(|(typ, _)| match typ { + Type::Struct(struct_typ, _) => Some(struct_typ.borrow().location), + _ => None, + }) + } } From 659bedaaa9d1cb78110f2d5b3e14147b57b1de76 Mon Sep 17 00:00:00 2001 From: Koby Date: Thu, 18 Jan 2024 18:56:14 +0100 Subject: [PATCH 2/4] chore: typo --- compiler/noirc_frontend/src/hir_def/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index cc22a91de7..7a71dad23f 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -64,7 +64,7 @@ pub enum Type { TypeVariable(TypeVariable, TypeVariableKind), /// `impl Trait` when used in a type position. - /// These are only matched based on the TraitId. The trait name paramer is only + /// These are only matched based on the TraitId. The trait name parameter is only /// used for displaying error messages using the name of the trait. TraitAsType(TraitId, /*name:*/ Rc, /*generics:*/ Vec), From 8da3170f544f0605c91d1f54188c3f0bf0ff7b83 Mon Sep 17 00:00:00 2001 From: Koby Date: Mon, 22 Jan 2024 12:15:25 +0100 Subject: [PATCH 3/4] chore: consider only structs for type ref location --- .../src/hir/resolution/resolver.rs | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 3f6d50e01d..a11688a539 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -449,7 +449,7 @@ impl<'a> Resolver<'a> { fn resolve_type_inner(&mut self, typ: UnresolvedType, new_variables: &mut Generics) -> Type { use UnresolvedTypeData::*; - match typ.typ { + let resolved_type = match typ.typ { FieldElement => Type::FieldElement, Array(size, elem) => { let elem = Box::new(self.resolve_type_inner(*elem, new_variables)); @@ -510,7 +510,22 @@ impl<'a> Resolver<'a> { Type::MutableReference(Box::new(self.resolve_type_inner(*element, new_variables))) } Parenthesized(typ) => self.resolve_type_inner(*typ, new_variables), - } + }; + + match resolved_type { + Type::Struct(_, _) => { + if let Some(unresolved_span) = typ.span { + // Record the location of the type reference + self.interner.push_type_ref_location( + resolved_type.clone(), + Location::new(unresolved_span, self.file), + ); + } + } + _ => (), + }; + + resolved_type } fn find_generic(&self, target_name: &str) -> Option<&(Rc, TypeVariable, Span)> { @@ -711,14 +726,6 @@ impl<'a> Resolver<'a> { self.errors.push(ResolverError::NestedSlices { span: span.unwrap() }); } - if let Some(unresolved_span) = span { - // Record the location of the type reference - self.interner.push_type_ref_location( - resolved_type.clone(), - Location::new(unresolved_span, self.file), - ); - } - resolved_type } From cd894fdf4ecbc125b116a3d0c400f69c79b2b2e0 Mon Sep 17 00:00:00 2001 From: Koby Date: Mon, 22 Jan 2024 13:31:12 +0100 Subject: [PATCH 4/4] chore: address clippy --- .../src/hir/resolution/resolver.rs | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index adfb3e74c9..492e96a471 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -512,19 +512,15 @@ impl<'a> Resolver<'a> { Parenthesized(typ) => self.resolve_type_inner(*typ, new_variables), }; - match resolved_type { - Type::Struct(_, _) => { - if let Some(unresolved_span) = typ.span { - // Record the location of the type reference - self.interner.push_type_ref_location( - resolved_type.clone(), - Location::new(unresolved_span, self.file), - ); - } + if let Type::Struct(_, _) = resolved_type { + if let Some(unresolved_span) = typ.span { + // Record the location of the type reference + self.interner.push_type_ref_location( + resolved_type.clone(), + Location::new(unresolved_span, self.file), + ); } - _ => (), - }; - + } resolved_type }