Skip to content

Commit

Permalink
feat(lsp): goto type alias (#4061)
Browse files Browse the repository at this point in the history
# Description

## Problem\*

Resolves <!-- Link to GitHub Issue -->

feat(lsp): goto type definition #3729

## Summary\*

Allows to goto definition of type alias.

## Additional Context



## Documentation\*

Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[Exceptional Case]** Documentation to be submitted in a separate
PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
kobyhallx authored Jan 19, 2024
1 parent f5c4632 commit dc83385
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 5 deletions.
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));

// 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)>,
}

/// 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) {
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)
}
}

0 comments on commit dc83385

Please sign in to comment.