diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 8f656751fe1..1d4f60ffd51 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -558,6 +558,10 @@ impl<'a> Resolver<'a> { let result = self.interner.get_type_alias(id).get_type(&args); + // Collecting Type Alias references [Location]s to be used by LSP in order + // to resolve the definition of the type alias + self.interner.add_type_alias_ref(id, Location::new(span, self.file)); + // Because there is no ordering to when type aliases (and other globals) are resolved, // it is possible for one to refer to an Error type and issue no error if it is set // equal to another type alias. Fixing this fully requires an analysis to create a DFG diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index cc22a91de78..8979d60c005 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -314,7 +314,7 @@ pub struct TypeAliasType { pub id: TypeAliasId, pub typ: Type, pub generics: Generics, - pub span: Span, + pub location: Location, } impl std::hash::Hash for TypeAliasType { @@ -346,11 +346,11 @@ impl TypeAliasType { pub fn new( id: TypeAliasId, name: Ident, - span: Span, + location: Location, typ: Type, generics: Generics, ) -> TypeAliasType { - TypeAliasType { id, typ, name, span, generics } + TypeAliasType { id, typ, name, location, generics } } pub fn set_type_and_generics(&mut self, new_typ: Type, new_generics: Generics) { diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 193f3fe0436..e734161e360 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -78,7 +78,7 @@ pub struct NodeInterner { // // Map type aliases to the actual type. // When resolving types, check against this map to see if a type alias is defined. - type_aliases: Vec, + pub(crate) type_aliases: Vec, // Trait map. // @@ -142,6 +142,10 @@ pub struct NodeInterner { // For trait implementation functions, this is their self type and trait they belong to func_id_to_trait: HashMap, + + /// A list of all type aliases that are referenced in the program. + /// Searched by LSP to resolve [Location]s of [TypeAliasType]s + pub(crate) type_alias_ref: Vec<(TypeAliasId, Location)>, } /// A trait implementation is either a normal implementation that is present in the source @@ -450,6 +454,7 @@ impl Default for NodeInterner { globals: HashMap::new(), struct_methods: HashMap::new(), primitive_methods: HashMap::new(), + type_alias_ref: Vec::new(), }; // An empty block expression is used often, we add this into the `node` on startup @@ -545,7 +550,7 @@ impl NodeInterner { self.type_aliases.push(TypeAliasType::new( type_id, typ.type_alias_def.name.clone(), - typ.type_alias_def.span, + Location::new(typ.type_alias_def.span, typ.file_id), Type::Error, vecmap(&typ.type_alias_def.generics, |_| TypeVariable::unbound(TypeVariableId(0))), )); @@ -553,6 +558,11 @@ impl NodeInterner { type_id } + /// Adds [TypeLiasId] and [Location] to the type_alias_ref vector + /// So that we can later resolve [Location]s type aliases from the LSP requests + pub fn add_type_alias_ref(&mut self, type_id: TypeAliasId, location: Location) { + self.type_alias_ref.push((type_id, location)); + } pub fn update_struct(&mut self, type_id: StructId, f: impl FnOnce(&mut StructType)) { let mut value = self.structs.get_mut(&type_id).unwrap().borrow_mut(); f(&mut value); diff --git a/compiler/noirc_frontend/src/resolve_locations.rs b/compiler/noirc_frontend/src/resolve_locations.rs index c6834a4361e..02325de4da8 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_alias(location)) } pub fn get_declaration_location_from(&self, location: Location) -> Option { @@ -194,4 +195,12 @@ impl NodeInterner { method.map(|method| method.location) }) } + + #[tracing::instrument(skip(self), ret)] + fn try_resolve_type_alias(&self, location: Location) -> Option { + self.type_alias_ref + .iter() + .find(|(_, named_type_location)| named_type_location.span.contains(&location.span)) + .map(|(type_alias_id, _found_location)| self.get_type_alias(*type_alias_id).location) + } }