Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(lsp): goto type alias #4061

Merged
merged 5 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/noirc_frontend/src/hir/resolution/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
kobyhallx marked this conversation as resolved.
Show resolved Hide resolved

// 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
Expand Down
6 changes: 3 additions & 3 deletions compiler/noirc_frontend/src/hir_def/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down
14 changes: 12 additions & 2 deletions compiler/noirc_frontend/src/node_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<TypeAliasType>,
pub(crate) type_aliases: Vec<TypeAliasType>,

// Trait map.
//
Expand Down Expand Up @@ -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<FuncId, (Type, TraitId)>,

/// 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)>,
kobyhallx marked this conversation as resolved.
Show resolved Hide resolved
}

/// A trait implementation is either a normal implementation that is present in the source
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -545,14 +550,19 @@ 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))),
));

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) {
kobyhallx marked this conversation as resolved.
Show resolved Hide resolved
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);
Expand Down
9 changes: 9 additions & 0 deletions compiler/noirc_frontend/src/resolve_locations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Location> {
Expand Down Expand Up @@ -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<Location> {
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)
}
}