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 trait from trait impl #3956

Merged
merged 3 commits into from
Jan 4, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/hir_def/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
Generics, Ident, NoirFunction, Type, TypeVariable, TypeVariableId,
};
use fm::FileId;
use noirc_errors::Span;
use noirc_errors::{Location, Span};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TraitFunction {
Expand Down Expand Up @@ -56,7 +56,7 @@ pub struct Trait {

pub name: Ident,
pub generics: Generics,
pub span: Span,
pub location: Location,

/// When resolving the types of Trait elements, all references to `Self` resolve
/// to this TypeVariable. Then when we check if the types of trait impl elements
Expand Down
26 changes: 24 additions & 2 deletions compiler/noirc_frontend/src/node_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ impl NodeInterner {
/// The [Location] may not necessarily point to the beginning of the item
/// so we check if the location's span is contained within the start or end
/// of each items [Span]
#[tracing::instrument(skip(self))]
pub fn find_location_index(&self, location: Location) -> Option<impl Into<Index>> {
let mut location_candidate: Option<(&Index, &Location)> = None;

Expand Down Expand Up @@ -504,7 +505,7 @@ impl NodeInterner {
id: type_id,
name: unresolved_trait.trait_def.name.clone(),
crate_id: unresolved_trait.crate_id,
span: unresolved_trait.trait_def.span,
location: Location::new(unresolved_trait.trait_def.span, unresolved_trait.file_id),
generics: vecmap(&unresolved_trait.trait_def.generics, |_| {
// Temporary type variable ids before the trait is resolved to its actual ids.
// This lets us record how many arguments the type expects so that other types
Expand Down Expand Up @@ -1142,6 +1143,7 @@ impl NodeInterner {
}

/// Adds a trait implementation to the list of known implementations.
#[tracing::instrument(skip(self))]
pub fn add_trait_implementation(
&mut self,
object_type: Type,
Expand Down Expand Up @@ -1274,7 +1276,9 @@ impl NodeInterner {
/// Returns the [Location] of the definition of the given Ident found at [Span] of the given [FileId].
/// Returns [None] when definition is not found.
pub fn get_definition_location_from(&self, location: Location) -> Option<Location> {
self.find_location_index(location).and_then(|index| self.resolve_location(index))
self.find_location_index(location)
.and_then(|index| self.resolve_location(index))
.or_else(|| self.try_resolve_trait_impl_location(location))
}

/// For a given [Index] we return [Location] to which we resolved to
Expand Down Expand Up @@ -1429,6 +1433,24 @@ impl NodeInterner {
pub(crate) fn ordering_type(&self) -> Type {
self.ordering_type.clone().expect("Expected ordering_type to be set in the NodeInterner")
}

/// Attempts to resolve [Location] of [Trait] based on [Location] of [TraitImpl]
/// This is used by LSP to resolve the location of a trait based on the location of a trait impl.
///
/// Example:
/// impl Foo for Bar { ... } -> trait Foo { ... }
fn try_resolve_trait_impl_location(&self, location: Location) -> Option<Location> {
kobyhallx marked this conversation as resolved.
Show resolved Hide resolved
self.trait_implementations
.iter()
.find(|shared_trait_impl| {
let trait_impl = shared_trait_impl.borrow();
trait_impl.file == location.file && trait_impl.ident.span().contains(&location.span)
})
.and_then(|shared_trait_impl| {
let trait_impl = shared_trait_impl.borrow();
self.traits.get(&trait_impl.trait_id).map(|trait_| trait_.location)
})
}
}

impl Methods {
Expand Down
Loading