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 "go to definition" for modules #5406

Merged
merged 11 commits into from
Jul 4, 2024
6 changes: 3 additions & 3 deletions compiler/noirc_frontend/src/elaborator/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::{
HirLiteral, HirStatement, Ident, IndexExpression, Literal, MemberAccessExpression,
MethodCallExpression, PrefixExpression,
},
node_interner::{DefinitionKind, DependencyId, ExprId, FuncId},
node_interner::{DefinitionKind, ExprId, FuncId, ReferenceId},
token::Tokens,
Kind, QuotedType, Shared, StructType, Type,
};
Expand Down Expand Up @@ -432,8 +432,8 @@ impl<'context> Elaborator<'context> {
struct_generics,
});

let referenced = DependencyId::Struct(struct_type.borrow().id);
let reference = DependencyId::Variable(Location::new(span, self.file));
let referenced = ReferenceId::Struct(struct_type.borrow().id);
let reference = ReferenceId::Variable(Location::new(span, self.file));
self.interner.add_reference(referenced, reference);

(expr, Type::Struct(struct_type, generics))
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ impl<'context> Elaborator<'context> {
fn resolve_trait_by_path(&mut self, path: Path) -> Option<TraitId> {
let path_resolver = StandardPathResolver::new(self.module_id());

let error = match path_resolver.resolve(self.def_maps, path.clone()) {
let error = match path_resolver.resolve(self.def_maps, path.clone(), &mut None) {
Ok(PathResolution { module_def_id: ModuleDefId::TraitId(trait_id), error }) => {
if let Some(error) = error {
self.push_err(error);
Expand Down
14 changes: 7 additions & 7 deletions compiler/noirc_frontend/src/elaborator/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
stmt::HirPattern,
},
macros_api::{HirExpression, Ident, Path, Pattern},
node_interner::{DefinitionId, DefinitionKind, DependencyId, ExprId, GlobalId, TraitImplKind},
node_interner::{DefinitionId, DefinitionKind, ExprId, GlobalId, ReferenceId, TraitImplKind},
Shared, StructType, Type, TypeBindings,
};

Expand Down Expand Up @@ -199,8 +199,8 @@ impl<'context> Elaborator<'context> {
new_definitions,
);

let referenced = DependencyId::Struct(struct_type.borrow().id);
let reference = DependencyId::Variable(Location::new(name_span, self.file));
let referenced = ReferenceId::Struct(struct_type.borrow().id);
let reference = ReferenceId::Variable(Location::new(name_span, self.file));
self.interner.add_reference(referenced, reference);

HirPattern::Struct(expected_type, fields, location)
Expand Down Expand Up @@ -446,8 +446,8 @@ impl<'context> Elaborator<'context> {
self.interner.add_function_dependency(current_item, func_id);
}

let variable = DependencyId::Variable(hir_ident.location);
let function = DependencyId::Function(func_id);
let variable = ReferenceId::Variable(hir_ident.location);
let function = ReferenceId::Function(func_id);
self.interner.add_reference(function, variable);
}
DefinitionKind::Global(global_id) => {
Expand All @@ -458,8 +458,8 @@ impl<'context> Elaborator<'context> {
self.interner.add_global_dependency(current_item, global_id);
}

let variable = DependencyId::Variable(hir_ident.location);
let global = DependencyId::Global(global_id);
let variable = ReferenceId::Variable(hir_ident.location);
let global = ReferenceId::Global(global_id);
self.interner.add_reference(global, variable);
}
DefinitionKind::GenericType(_) => {
Expand Down
18 changes: 16 additions & 2 deletions compiler/noirc_frontend/src/elaborator/scope.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use noirc_errors::Spanned;
use noirc_errors::{Location, Spanned};

use crate::ast::ERROR_IDENT;
use crate::hir::def_map::{LocalModuleId, ModuleId};
use crate::hir::resolution::path_resolver::{PathResolver, StandardPathResolver};
use crate::hir::resolution::resolver::SELF_TYPE_NAME;
use crate::hir::scope::{Scope as GenericScope, ScopeTree as GenericScopeTree};
use crate::macros_api::Ident;
use crate::node_interner::ReferenceId;
use crate::{
hir::{
def_map::{ModuleDefId, TryFromModuleDefId},
Expand Down Expand Up @@ -44,7 +45,20 @@ impl<'context> Elaborator<'context> {

pub(super) fn resolve_path(&mut self, path: Path) -> Result<ModuleDefId, ResolverError> {
let resolver = StandardPathResolver::new(self.module_id());
let path_resolution = resolver.resolve(self.def_maps, path)?;
let path_resolution;

if self.interner.track_references {
let mut references: Vec<ReferenceId> = Vec::new();
path_resolution =
resolver.resolve(self.def_maps, path.clone(), &mut Some(&mut references))?;

for (referenced, ident) in references.iter().zip(path.segments) {
let reference = ReferenceId::Variable(Location::new(ident.span(), self.file));
self.interner.add_reference(*referenced, reference);
}
} else {
path_resolution = resolver.resolve(self.def_maps, path, &mut None)?;
}

if let Some(error) = path_resolution.error {
self.push_err(error);
Expand Down
16 changes: 7 additions & 9 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ use crate::{
UnaryOp, UnresolvedType, UnresolvedTypeData,
},
node_interner::{
DefinitionKind, DependencyId, ExprId, GlobalId, TraitId, TraitImplKind, TraitMethodId,
DefinitionKind, DependencyId, ExprId, GlobalId, ReferenceId, TraitId, TraitImplKind,
TraitMethodId,
},
Generics, Kind, ResolvedGeneric, Type, TypeBinding, TypeVariable, TypeVariableKind,
};
Expand Down Expand Up @@ -146,13 +147,17 @@ impl<'context> Elaborator<'context> {
Resolved(id) => self.interner.get_quoted_type(id).clone(),
};

if let Type::Struct(_, _) = resolved_type {
if let Type::Struct(ref struct_type, _) = 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),
);

let referenced = ReferenceId::Struct(struct_type.borrow().id);
let reference = ReferenceId::Variable(Location::new(unresolved_span, self.file));
self.interner.add_reference(referenced, reference);
}
}

Expand Down Expand Up @@ -244,8 +249,6 @@ impl<'context> Elaborator<'context> {
return Type::Alias(alias, args);
}

let last_segment = path.last_segment();

match self.lookup_struct_or_error(path) {
Some(struct_type) => {
if self.resolving_ids.contains(&struct_type.borrow().id) {
Expand Down Expand Up @@ -283,11 +286,6 @@ impl<'context> Elaborator<'context> {
self.interner.add_type_dependency(current_item, dependency_id);
}

let referenced = DependencyId::Struct(struct_type.borrow().id);
let reference =
DependencyId::Variable(Location::new(last_segment.span(), self.file));
self.interner.add_reference(referenced, reference);

Type::Struct(struct_type, args)
}
None => Type::Error,
Expand Down
36 changes: 30 additions & 6 deletions compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::hir::Context;

use crate::macros_api::{MacroError, MacroProcessor};
use crate::node_interner::{
DependencyId, FuncId, GlobalId, NodeInterner, StructId, TraitId, TraitImplId, TypeAliasId,
FuncId, GlobalId, NodeInterner, ReferenceId, StructId, TraitId, TraitImplId, TypeAliasId,
};

use crate::ast::{
Expand Down Expand Up @@ -330,7 +330,30 @@ impl DefCollector {
// Resolve unresolved imports collected from the crate, one by one.
for collected_import in std::mem::take(&mut def_collector.imports) {
let module_id = collected_import.module_id;
match resolve_import(crate_id, &collected_import, &context.def_maps) {
let resolved_import = if context.def_interner.track_references {
let mut references: Vec<ReferenceId> = Vec::new();
let resolved_import = resolve_import(
crate_id,
&collected_import,
&context.def_maps,
&mut Some(&mut references),
);

let current_def_map = context.def_maps.get(&crate_id).unwrap();
let file_id = current_def_map.file_id(module_id);

for (referenced, ident) in
references.iter().zip(collected_import.clone().path.segments)
asterite marked this conversation as resolved.
Show resolved Hide resolved
{
let reference = ReferenceId::Variable(Location::new(ident.span(), file_id));
context.def_interner.add_reference(*referenced, reference);
}

resolved_import
} else {
resolve_import(crate_id, &collected_import, &context.def_maps, &mut None)
};
match resolved_import {
Ok(resolved_import) => {
if let Some(error) = resolved_import.error {
errors.push((
Expand Down Expand Up @@ -491,12 +514,12 @@ fn add_import_reference(

match def_id {
crate::macros_api::ModuleDefId::FunctionId(func_id) => {
let variable = DependencyId::Variable(Location::new(name.span(), file_id));
interner.add_reference(DependencyId::Function(func_id), variable);
let variable = ReferenceId::Variable(Location::new(name.span(), file_id));
interner.add_reference(ReferenceId::Function(func_id), variable);
}
crate::macros_api::ModuleDefId::TypeId(struct_id) => {
let variable = DependencyId::Variable(Location::new(name.span(), file_id));
interner.add_reference(DependencyId::Struct(struct_id), variable);
let variable = ReferenceId::Variable(Location::new(name.span(), file_id));
interner.add_reference(ReferenceId::Struct(struct_id), variable);
}
_ => (),
}
Expand Down Expand Up @@ -524,6 +547,7 @@ fn inject_prelude(
&context.def_maps,
ModuleId { krate: crate_id, local_id: crate_root },
path,
&mut None,
) {
assert!(error.is_none(), "Tried to add private item to prelude");
let module_id = module_def_id.as_module().expect("std::prelude should be a module");
Expand Down
74 changes: 53 additions & 21 deletions compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use acvm::{AcirField, FieldElement};
use fm::{FileId, FileManager, FILE_EXTENSION};
use noirc_errors::Location;
use noirc_errors::{Location, Span};
use num_bigint::BigUint;
use num_traits::Num;
use rustc_hash::FxHashMap as HashMap;
Expand All @@ -14,7 +14,7 @@
TypeImpl,
};
use crate::macros_api::NodeInterner;
use crate::node_interner::DependencyId;
use crate::node_interner::ReferenceId;
use crate::{
graph::CrateId,
hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait},
Expand Down Expand Up @@ -283,12 +283,18 @@
);

// Create the corresponding module for the struct namespace
let id = match self.push_child_module(&name, self.file_id, false, false) {
Ok(local_id) => context.def_interner.new_struct(
let id = match self.push_child_module(
context,
&name,
Location::new(name.span(), self.file_id),
false,
false,
) {
Ok(module_id) => context.def_interner.new_struct(
&unresolved,
resolved_generics,
krate,
local_id,
module_id.local_id,
self.file_id,
),
Err(error) => {
Expand All @@ -314,7 +320,7 @@
self.def_collector.items.types.insert(id, unresolved);

context.def_interner.add_struct_location(id, name_location);
context.def_interner.add_definition_location(DependencyId::Struct(id));
context.def_interner.add_definition_location(ReferenceId::Struct(id));
}
definition_errors
}
Expand Down Expand Up @@ -377,8 +383,14 @@
let name = trait_definition.name.clone();

// Create the corresponding module for the trait namespace
let trait_id = match self.push_child_module(&name, self.file_id, false, false) {
Ok(local_id) => TraitId(ModuleId { krate, local_id }),
let trait_id = match self.push_child_module(
context,
&name,
Location::new(name.span(), self.file_id),
false,
false,
) {
Ok(module_id) => TraitId(ModuleId { krate, local_id: module_id.local_id }),
Err(error) => {
errors.push((error.into(), self.file_id));
continue;
Expand Down Expand Up @@ -490,7 +502,7 @@
}
}
TraitItem::Type { name } => {
// TODO(nickysn or alexvitkov): implement context.def_interner.push_empty_type_alias and get an id, instead of using TypeAliasId::dummy_id()

Check warning on line 505 in compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (nickysn)

Check warning on line 505 in compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (alexvitkov)
if let Err((first_def, second_def)) = self.def_collector.def_map.modules
[trait_id.0.local_id.0]
.declare_type_alias(name.clone(), TypeAliasId::dummy_id())
Expand Down Expand Up @@ -535,13 +547,19 @@
) -> Vec<(CompilationError, FileId)> {
let mut errors: Vec<(CompilationError, FileId)> = vec![];
for submodule in submodules {
match self.push_child_module(&submodule.name, file_id, true, submodule.is_contract) {
match self.push_child_module(
context,
&submodule.name,
Location::new(submodule.name.span(), file_id),
true,
submodule.is_contract,
) {
Ok(child) => {
errors.extend(collect_defs(
self.def_collector,
submodule.contents,
file_id,
child,
child.local_id,
crate_id,
context,
macro_processors,
Expand Down Expand Up @@ -620,13 +638,24 @@
);

// Add module into def collector and get a ModuleId
match self.push_child_module(&mod_decl.ident, child_file_id, true, false) {
match self.push_child_module(
context,
&mod_decl.ident,
Location::new(Span::empty(0), child_file_id),
true,
false,
) {
Ok(child_mod_id) => {
// Track that the "foo" in `mod foo;` points to the module "foo"
let referenced = ReferenceId::Module(child_mod_id);
let reference = ReferenceId::Variable(location);
context.def_interner.add_reference(referenced, reference);

errors.extend(collect_defs(
self.def_collector,
ast,
child_file_id,
child_mod_id,
child_mod_id.local_id,
crate_id,
context,
macro_processors,
Expand All @@ -643,13 +672,14 @@
/// On error this returns None and pushes to `errors`
fn push_child_module(
&mut self,
context: &mut Context,
mod_name: &Ident,
file_id: FileId,
mod_location: Location,
add_to_parent_scope: bool,
is_contract: bool,
) -> Result<LocalModuleId, DefCollectorErrorKind> {
) -> Result<ModuleId, DefCollectorErrorKind> {
let parent = Some(self.module_id);
let location = Location::new(mod_name.span(), file_id);
let location = Location::new(mod_name.span(), mod_location.file);
asterite marked this conversation as resolved.
Show resolved Hide resolved
let new_module = ModuleData::new(parent, location, is_contract);
let module_id = self.def_collector.def_map.modules.insert(new_module);

Expand All @@ -658,6 +688,11 @@
// Update the parent module to reference the child
modules[self.module_id.0].children.insert(mod_name.clone(), LocalModuleId(module_id));

let mod_id = ModuleId {
krate: self.def_collector.def_map.krate,
local_id: LocalModuleId(module_id),
};

// Add this child module into the scope of the parent module as a module definition
// module definitions are definitions which can only exist at the module level.
// ModuleDefinitionIds can be used across crates since they contain the CrateId
Expand All @@ -666,11 +701,6 @@
// to a child module containing its methods) since the module name should not shadow
// the struct name.
if add_to_parent_scope {
let mod_id = ModuleId {
krate: self.def_collector.def_map.krate,
local_id: LocalModuleId(module_id),
};

if let Err((first_def, second_def)) =
modules[self.module_id.0].declare_child_module(mod_name.to_owned(), mod_id)
{
Expand All @@ -681,9 +711,11 @@
};
return Err(err);
}

context.def_interner.add_module_location(mod_id, mod_location);
}

Ok(LocalModuleId(module_id))
Ok(mod_id)
}
}

Expand Down
Loading
Loading