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 hover #5491

Merged
merged 23 commits into from
Jul 12, 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
9 changes: 7 additions & 2 deletions compiler/noirc_frontend/src/elaborator/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ impl<'context> Elaborator<'context> {
let (mut object, mut object_type) = self.elaborate_expression(method_call.object);
object_type = object_type.follow_bindings();

let method_name_span = method_call.method_name.span();
let method_name = method_call.method_name.0.contents.as_str();
match self.lookup_method(&object_type, method_name, span) {
Some(method_ref) => {
Expand Down Expand Up @@ -385,6 +386,9 @@ impl<'context> Elaborator<'context> {

self.interner.push_expr_type(function_id, func_type.clone());

self.interner
.add_function_reference(func_id, Location::new(method_name_span, self.file));

// Type check the new call now that it has been changed from a method call
// to a function call. This way we avoid duplicating code.
let typ = self.type_check_call(&function_call, func_type, function_args, span);
Expand All @@ -399,7 +403,8 @@ impl<'context> Elaborator<'context> {
constructor: ConstructorExpression,
) -> (HirExpression, Type) {
let span = constructor.type_name.span();
let is_self_type = constructor.type_name.last_segment().is_self_type_name();
let last_segment = constructor.type_name.last_segment();
let is_self_type = last_segment.is_self_type_name();

let (r#type, struct_generics) = if let Some(struct_id) = constructor.struct_type {
let typ = self.interner.get_struct(struct_id);
Expand Down Expand Up @@ -430,7 +435,7 @@ impl<'context> Elaborator<'context> {
});

let struct_id = struct_type.borrow().id;
let reference_location = Location::new(span, self.file);
let reference_location = Location::new(last_segment.span(), self.file);
self.interner.add_struct_reference(struct_id, reference_location, is_self_type);

(expr, Type::Struct(struct_type, generics))
Expand Down
12 changes: 10 additions & 2 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -718,13 +718,20 @@ impl<'context> Elaborator<'context> {
let statements = std::mem::take(&mut func.def.body.statements);
let body = BlockExpression { statements };

let struct_id = if let Some(Type::Struct(struct_type, _)) = &self.self_type {
Some(struct_type.borrow().id)
} else {
None
};

let meta = FuncMeta {
name: name_ident,
kind: func.kind,
location,
typ,
direct_generics,
all_generics: self.generics.clone(),
struct_id,
trait_impl: self.current_trait_impl,
parameters: parameters.into(),
parameter_idents,
Expand Down Expand Up @@ -1230,7 +1237,7 @@ impl<'context> Elaborator<'context> {

for field_index in 0..fields_len {
self.interner
.add_definition_location(ReferenceId::StructMember(type_id, field_index));
.add_definition_location(ReferenceId::StructMember(type_id, field_index), None);
}

self.run_comptime_attributes_on_struct(attributes, type_id, span, &mut generated_items);
Expand Down Expand Up @@ -1365,7 +1372,8 @@ impl<'context> Elaborator<'context> {
self.elaborate_comptime_global(global_id);
}

self.interner.add_definition_location(ReferenceId::Global(global_id));
self.interner
.add_definition_location(ReferenceId::Global(global_id), Some(self.module_id()));

self.local_module = old_module;
self.file = old_file;
Expand Down
16 changes: 14 additions & 2 deletions compiler/noirc_frontend/src/elaborator/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ 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 @@ -48,17 +47,30 @@ impl<'context> Elaborator<'context> {
let path_resolution;

if self.interner.track_references {
let mut references: Vec<ReferenceId> = Vec::new();
let last_segment = path.last_segment();
let location = Location::new(last_segment.span(), self.file);
let is_self_type_name = last_segment.is_self_type_name();

let mut references: Vec<_> = 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 Some(referenced) = referenced else {
continue;
};
self.interner.add_reference(
*referenced,
Location::new(ident.span(), self.file),
ident.is_self_type_name(),
);
}

self.interner.add_module_def_id_reference(
path_resolution.module_def_id,
location,
is_self_type_name,
);
} else {
path_resolution = resolver.resolve(self.def_maps, path, &mut None)?;
}
Expand Down
18 changes: 11 additions & 7 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,16 @@ impl<'context> Elaborator<'context> {
use crate::ast::UnresolvedTypeData::*;

let span = typ.span;
let (is_self_type_name, is_synthetic) = if let Named(ref named_path, _, synthetic) = typ.typ
{
(named_path.last_segment().is_self_type_name(), synthetic)
} else {
(false, false)
};
let (named_path_span, is_self_type_name, is_synthetic) =
if let Named(ref named_path, _, synthetic) = typ.typ {
(
Some(named_path.last_segment().span()),
named_path.last_segment().is_self_type_name(),
synthetic,
)
} else {
(None, false, false)
};

let resolved_type = match typ.typ {
FieldElement => Type::FieldElement,
Expand Down Expand Up @@ -153,7 +157,7 @@ impl<'context> Elaborator<'context> {
};

if let Some(unresolved_span) = typ.span {
let location = Location::new(unresolved_span, self.file);
let location = Location::new(named_path_span.unwrap_or(unresolved_span), self.file);

match resolved_type {
Type::Struct(ref struct_type, _) => {
Expand Down
27 changes: 5 additions & 22 deletions compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ impl DefCollector {
for collected_import in std::mem::take(&mut def_collector.imports) {
let module_id = collected_import.module_id;
let resolved_import = if context.def_interner.track_references {
let mut references: Vec<ReferenceId> = Vec::new();
let mut references: Vec<Option<ReferenceId>> = Vec::new();
let resolved_import = resolve_import(
crate_id,
&collected_import,
Expand All @@ -359,6 +359,9 @@ impl DefCollector {
let file_id = current_def_map.file_id(module_id);

for (referenced, ident) in references.iter().zip(&collected_import.path.segments) {
let Some(referenced) = referenced else {
continue;
};
context.def_interner.add_reference(
*referenced,
Location::new(ident.span(), file_id),
Expand Down Expand Up @@ -548,27 +551,7 @@ fn add_import_reference(
}

let location = Location::new(name.span(), file_id);

match def_id {
crate::macros_api::ModuleDefId::ModuleId(module_id) => {
interner.add_module_reference(module_id, location);
}
crate::macros_api::ModuleDefId::FunctionId(func_id) => {
interner.add_function_reference(func_id, location);
}
crate::macros_api::ModuleDefId::TypeId(struct_id) => {
interner.add_struct_reference(struct_id, location, false);
}
crate::macros_api::ModuleDefId::TraitId(trait_id) => {
interner.add_trait_reference(trait_id, location, false);
}
crate::macros_api::ModuleDefId::TypeAliasId(type_alias_id) => {
interner.add_alias_reference(type_alias_id, location);
}
crate::macros_api::ModuleDefId::GlobalId(global_id) => {
interner.add_global_reference(global_id, location);
}
};
interner.add_module_def_id_reference(def_id, location, false);
}

fn inject_prelude(
Expand Down
29 changes: 23 additions & 6 deletions compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
TypeImpl,
};
use crate::macros_api::NodeInterner;
use crate::node_interner::ReferenceId;
use crate::node_interner::{ModuleAttributes, ReferenceId};
use crate::{
graph::CrateId,
hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait},
Expand Down Expand Up @@ -90,7 +90,7 @@

errors.extend(collector.collect_structs(context, ast.types, crate_id));

errors.extend(collector.collect_type_aliases(context, ast.type_aliases));
errors.extend(collector.collect_type_aliases(context, ast.type_aliases, crate_id));

errors.extend(collector.collect_functions(context, ast.functions, crate_id));

Expand Down Expand Up @@ -318,7 +318,10 @@
// And store the TypeId -> StructType mapping somewhere it is reachable
self.def_collector.items.types.insert(id, unresolved);

context.def_interner.add_definition_location(ReferenceId::Struct(id));
context.def_interner.add_definition_location(
ReferenceId::Struct(id),
Some(ModuleId { krate, local_id: self.module_id }),
);
}
definition_errors
}
Expand All @@ -329,6 +332,7 @@
&mut self,
context: &mut Context,
type_aliases: Vec<NoirTypeAlias>,
krate: CrateId,
) -> Vec<(CompilationError, FileId)> {
let mut errors: Vec<(CompilationError, FileId)> = vec![];
for type_alias in type_aliases {
Expand Down Expand Up @@ -365,7 +369,10 @@

self.def_collector.items.type_aliases.insert(type_alias_id, unresolved);

context.def_interner.add_definition_location(ReferenceId::Alias(type_alias_id));
context.def_interner.add_definition_location(
ReferenceId::Alias(type_alias_id),
Some(ModuleId { krate, local_id: self.module_id }),
);
}
errors
}
Expand Down Expand Up @@ -502,7 +509,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 512 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 512 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 @@ -532,7 +539,10 @@
};
context.def_interner.push_empty_trait(trait_id, &unresolved, resolved_generics);

context.def_interner.add_definition_location(ReferenceId::Trait(trait_id));
context.def_interner.add_definition_location(
ReferenceId::Trait(trait_id),
Some(ModuleId { krate, local_id: self.module_id }),
);

self.def_collector.items.traits.insert(trait_id, unresolved);
}
Expand Down Expand Up @@ -685,7 +695,7 @@
// if it's an inline module, or the first char of a the file if it's an external module.
// - `location` will always point to the token "foo" in `mod foo` regardless of whether
// it's inline or external.
// Eventually the location put in `ModuleData` is used for codelenses about `contract`s,

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

View workflow job for this annotation

GitHub Actions / Code

Unknown word (codelenses)
// so we keep using `location` so that it continues to work as usual.
let location = Location::new(mod_name.span(), mod_location.file);
let new_module = ModuleData::new(parent, location, is_contract);
Expand Down Expand Up @@ -720,7 +730,14 @@
return Err(err);
}

context.def_interner.add_module_location(mod_id, mod_location);
context.def_interner.add_module_attributes(
mod_id,
ModuleAttributes {
name: mod_name.0.contents.clone(),
location: mod_location,
parent: self.module_id,
},
);
}

Ok(mod_id)
Expand Down
21 changes: 13 additions & 8 deletions compiler/noirc_frontend/src/hir/resolution/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub fn resolve_import(
crate_id: CrateId,
import_directive: &ImportDirective,
def_maps: &BTreeMap<CrateId, CrateDefMap>,
path_references: &mut Option<&mut Vec<ReferenceId>>,
path_references: &mut Option<&mut Vec<Option<ReferenceId>>>,
) -> Result<ResolvedImport, PathResolutionError> {
let module_scope = import_directive.module_id;
let NamespaceResolution {
Expand Down Expand Up @@ -126,7 +126,7 @@ fn resolve_path_to_ns(
crate_id: CrateId,
importing_crate: CrateId,
def_maps: &BTreeMap<CrateId, CrateDefMap>,
path_references: &mut Option<&mut Vec<ReferenceId>>,
path_references: &mut Option<&mut Vec<Option<ReferenceId>>>,
) -> NamespaceResolutionResult {
let import_path = &import_directive.path.segments;
let def_map = &def_maps[&crate_id];
Expand Down Expand Up @@ -196,7 +196,7 @@ fn resolve_path_from_crate_root(

import_path: &[Ident],
def_maps: &BTreeMap<CrateId, CrateDefMap>,
path_references: &mut Option<&mut Vec<ReferenceId>>,
path_references: &mut Option<&mut Vec<Option<ReferenceId>>>,
) -> NamespaceResolutionResult {
resolve_name_in_module(
crate_id,
Expand All @@ -214,7 +214,7 @@ fn resolve_name_in_module(
import_path: &[Ident],
starting_mod: LocalModuleId,
def_maps: &BTreeMap<CrateId, CrateDefMap>,
path_references: &mut Option<&mut Vec<ReferenceId>>,
path_references: &mut Option<&mut Vec<Option<ReferenceId>>>,
) -> NamespaceResolutionResult {
let def_map = &def_maps[&krate];
let mut current_mod_id = ModuleId { krate, local_id: starting_mod };
Expand Down Expand Up @@ -247,22 +247,22 @@ fn resolve_name_in_module(
current_mod_id = match typ {
ModuleDefId::ModuleId(id) => {
if let Some(path_references) = path_references {
path_references.push(ReferenceId::Module(id));
path_references.push(Some(ReferenceId::Module(id)));
}
id
}
ModuleDefId::FunctionId(_) => panic!("functions cannot be in the type namespace"),
// TODO: If impls are ever implemented, types can be used in a path
ModuleDefId::TypeId(id) => {
if let Some(path_references) = path_references {
path_references.push(ReferenceId::Struct(id));
path_references.push(Some(ReferenceId::Struct(id)));
}
id.module_id()
}
ModuleDefId::TypeAliasId(_) => panic!("type aliases cannot be used in type namespace"),
ModuleDefId::TraitId(id) => {
if let Some(path_references) = path_references {
path_references.push(ReferenceId::Trait(id));
path_references.push(Some(ReferenceId::Trait(id)));
}
id.0
}
Expand Down Expand Up @@ -309,7 +309,7 @@ fn resolve_external_dep(
current_def_map: &CrateDefMap,
directive: &ImportDirective,
def_maps: &BTreeMap<CrateId, CrateDefMap>,
path_references: &mut Option<&mut Vec<ReferenceId>>,
path_references: &mut Option<&mut Vec<Option<ReferenceId>>>,
asterite marked this conversation as resolved.
Show resolved Hide resolved
importing_crate: CrateId,
) -> NamespaceResolutionResult {
// Use extern_prelude to get the dep
Expand All @@ -327,6 +327,11 @@ fn resolve_external_dep(
// See `singleton_import.nr` test case for a check that such cases are handled elsewhere.
let path_without_crate_name = &path[1..];

// Given that we skipped the first segment, record that it doesn't refer to any module or type.
if let Some(path_references) = path_references {
path_references.push(None);
}

let path = Path {
segments: path_without_crate_name.to_vec(),
kind: PathKind::Plain,
Expand Down
9 changes: 5 additions & 4 deletions compiler/noirc_frontend/src/hir/resolution/path_resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleId};
pub trait PathResolver {
/// Resolve the given path returning the resolved ModuleDefId.
/// If `path_references` is `Some`, a `ReferenceId` for each segment in `path`
/// will be resolved and pushed.
/// will be resolved and pushed (some entries will be None if they don't refer to
/// a module or type).
fn resolve(
&self,
def_maps: &BTreeMap<CrateId, CrateDefMap>,
path: Path,
path_references: &mut Option<&mut Vec<ReferenceId>>,
path_references: &mut Option<&mut Vec<Option<ReferenceId>>>,
) -> PathResolutionResult;

fn local_module_id(&self) -> LocalModuleId;
Expand All @@ -38,7 +39,7 @@ impl PathResolver for StandardPathResolver {
&self,
def_maps: &BTreeMap<CrateId, CrateDefMap>,
path: Path,
path_references: &mut Option<&mut Vec<ReferenceId>>,
path_references: &mut Option<&mut Vec<Option<ReferenceId>>>,
) -> PathResolutionResult {
resolve_path(def_maps, self.module_id, path, path_references)
}
Expand All @@ -58,7 +59,7 @@ pub fn resolve_path(
def_maps: &BTreeMap<CrateId, CrateDefMap>,
module_id: ModuleId,
path: Path,
path_references: &mut Option<&mut Vec<ReferenceId>>,
path_references: &mut Option<&mut Vec<Option<ReferenceId>>>,
) -> PathResolutionResult {
// lets package up the path into an ImportDirective and resolve it using that
let import =
Expand Down
1 change: 1 addition & 0 deletions compiler/noirc_frontend/src/hir/resolution/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,7 @@ impl<'a> Resolver<'a> {
location,
typ,
direct_generics,
struct_id: None,
trait_impl: self.current_trait_impl,
parameters: parameters.into(),
return_type: func.def.return_type.clone(),
Expand Down
Loading
Loading