diff --git a/aztec_macros/src/lib.rs b/aztec_macros/src/lib.rs index 580a132aa5a..ec1d395725d 100644 --- a/aztec_macros/src/lib.rs +++ b/aztec_macros/src/lib.rs @@ -62,18 +62,25 @@ fn transform( file_id: FileId, context: &HirContext, ) -> Result { + let empty_spans = context.def_interner.is_in_lsp_mode(); + // Usage -> mut ast -> aztec_library::transform(&mut ast) // Covers all functions in the ast for submodule in ast.submodules.iter_mut().filter(|submodule| submodule.is_contract) { - if transform_module(&file_id, &mut submodule.contents, submodule.name.0.contents.as_str()) - .map_err(|err| (err.into(), file_id))? + if transform_module( + &file_id, + &mut submodule.contents, + submodule.name.0.contents.as_str(), + empty_spans, + ) + .map_err(|err| (err.into(), file_id))? { check_for_aztec_dependency(crate_id, context)?; } } - generate_event_impls(&mut ast).map_err(|err| (err.into(), file_id))?; - generate_note_interface_impl(&mut ast).map_err(|err| (err.into(), file_id))?; + generate_event_impls(&mut ast, empty_spans).map_err(|err| (err.into(), file_id))?; + generate_note_interface_impl(&mut ast, empty_spans).map_err(|err| (err.into(), file_id))?; Ok(ast) } @@ -85,6 +92,7 @@ fn transform_module( file_id: &FileId, module: &mut SortedModule, module_name: &str, + empty_spans: bool, ) -> Result { let mut has_transformed_module = false; @@ -99,7 +107,7 @@ fn transform_module( if !check_for_storage_implementation(module, storage_struct_name) { generate_storage_implementation(module, storage_struct_name)?; } - generate_storage_layout(module, storage_struct_name.clone(), module_name)?; + generate_storage_layout(module, storage_struct_name.clone(), module_name, empty_spans)?; } let has_initializer = module.functions.iter().any(|func| { @@ -144,7 +152,7 @@ fn transform_module( let stub_src = stub_function(fn_type, func, is_static); stubs.push((stub_src, Location { file: *file_id, span: func.name_ident().span() })); - export_fn_abi(&mut module.types, func)?; + export_fn_abi(&mut module.types, func, empty_spans)?; transform_function( fn_type, func, @@ -200,7 +208,7 @@ fn transform_module( }); } - generate_contract_interface(module, module_name, &stubs, storage_defined)?; + generate_contract_interface(module, module_name, &stubs, storage_defined, empty_spans)?; } Ok(has_transformed_module) diff --git a/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs b/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs index 40fde39a06f..8983266dab9 100644 --- a/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs +++ b/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs @@ -3,9 +3,10 @@ use noirc_frontend::ast::{FunctionReturnType, NoirFunction, UnresolvedTypeData}; use noirc_frontend::{ graph::CrateId, macros_api::{FileId, HirContext}, - parse_program, Type, + Type, }; +use crate::utils::parse_utils::parse_program; use crate::utils::{ errors::AztecMacroError, hir_utils::{ @@ -125,8 +126,12 @@ pub fn inject_compute_note_hash_and_optionally_a_nullifier( notes_and_lengths.iter().map(|(note_type, _)| note_type.clone()).collect::>(); // We can now generate a version of compute_note_hash_and_optionally_a_nullifier tailored for the contract in this crate. - let func = - generate_compute_note_hash_and_optionally_a_nullifier(¬e_types, max_note_length); + let empty_spans = context.def_interner.is_in_lsp_mode(); + let func = generate_compute_note_hash_and_optionally_a_nullifier( + ¬e_types, + max_note_length, + empty_spans, + ); // And inject the newly created function into the contract. @@ -149,11 +154,12 @@ pub fn inject_compute_note_hash_and_optionally_a_nullifier( fn generate_compute_note_hash_and_optionally_a_nullifier( note_types: &[String], max_note_length: u128, + empty_spans: bool, ) -> NoirFunction { let function_source = generate_compute_note_hash_and_optionally_a_nullifier_source(note_types, max_note_length); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors.clone()); } diff --git a/aztec_macros/src/transforms/contract_interface.rs b/aztec_macros/src/transforms/contract_interface.rs index 56107de77c5..dd3ec7f6a75 100644 --- a/aztec_macros/src/transforms/contract_interface.rs +++ b/aztec_macros/src/transforms/contract_interface.rs @@ -5,13 +5,13 @@ use noirc_frontend::ast::{Ident, NoirFunction, UnresolvedTypeData}; use noirc_frontend::{ graph::CrateId, macros_api::{FieldElement, FileId, HirContext, HirExpression, HirLiteral, HirStatement}, - parse_program, parser::SortedModule, Type, }; use tiny_keccak::{Hasher, Keccak}; +use crate::utils::parse_utils::parse_program; use crate::utils::{ errors::AztecMacroError, hir_utils::{collect_crate_structs, get_contract_module_data, signature_of_type}, @@ -203,6 +203,7 @@ pub fn generate_contract_interface( module_name: &str, stubs: &[(String, Location)], has_storage_layout: bool, + empty_spans: bool, ) -> Result<(), AztecMacroError> { let storage_layout_getter = format!( "#[contract_library_method] @@ -253,7 +254,7 @@ pub fn generate_contract_interface( if has_storage_layout { format!("#[contract_library_method]\n{}", storage_layout_getter) } else { "".to_string() } ); - let (contract_interface_ast, errors) = parse_program(&contract_interface); + let (contract_interface_ast, errors) = parse_program(&contract_interface, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotGenerateContractInterface { secondary_message: Some("Failed to parse Noir macro code during contract interface generation. This is either a bug in the compiler or the Noir macro code".to_string()), }); diff --git a/aztec_macros/src/transforms/events.rs b/aztec_macros/src/transforms/events.rs index ecfca40189d..8b71bd77ae6 100644 --- a/aztec_macros/src/transforms/events.rs +++ b/aztec_macros/src/transforms/events.rs @@ -4,16 +4,19 @@ use noirc_frontend::token::SecondaryAttribute; use noirc_frontend::{ graph::CrateId, macros_api::{FileId, HirContext}, - parse_program, parser::SortedModule, }; use crate::utils::hir_utils::collect_crate_structs; +use crate::utils::parse_utils::parse_program; use crate::utils::{ast_utils::is_custom_attribute, errors::AztecMacroError}; // Automatic implementation of most of the methods in the EventInterface trait, guiding the user with meaningful error messages in case some // methods must be implemented manually. -pub fn generate_event_impls(module: &mut SortedModule) -> Result<(), AztecMacroError> { +pub fn generate_event_impls( + module: &mut SortedModule, + empty_spans: bool, +) -> Result<(), AztecMacroError> { // Find structs annotated with #[aztec(event)] // Why doesn't this work ? Events are not tagged and do not appear, it seems only going through the submodule works // let annotated_event_structs = module @@ -56,28 +59,39 @@ pub fn generate_event_impls(module: &mut SortedModule) -> Result<(), AztecMacroE )); } - let mut event_interface_trait_impl = - generate_trait_impl_stub_event_interface(event_type.as_str(), event_byte_len)?; + let mut event_interface_trait_impl = generate_trait_impl_stub_event_interface( + event_type.as_str(), + event_byte_len, + empty_spans, + )?; event_interface_trait_impl.items.push(TraitImplItem::Function( - generate_fn_get_event_type_id(event_type.as_str(), event_len)?, + generate_fn_get_event_type_id(event_type.as_str(), event_len, empty_spans)?, )); event_interface_trait_impl.items.push(TraitImplItem::Function( - generate_fn_private_to_be_bytes(event_type.as_str(), event_byte_len)?, + generate_fn_private_to_be_bytes(event_type.as_str(), event_byte_len, empty_spans)?, )); event_interface_trait_impl.items.push(TraitImplItem::Function( - generate_fn_to_be_bytes(event_type.as_str(), event_byte_len)?, + generate_fn_to_be_bytes(event_type.as_str(), event_byte_len, empty_spans)?, )); event_interface_trait_impl .items - .push(TraitImplItem::Function(generate_fn_emit(event_type.as_str())?)); + .push(TraitImplItem::Function(generate_fn_emit(event_type.as_str(), empty_spans)?)); submodule.contents.trait_impls.push(event_interface_trait_impl); - let serialize_trait_impl = - generate_trait_impl_serialize(event_type.as_str(), event_len, &event_fields)?; + let serialize_trait_impl = generate_trait_impl_serialize( + event_type.as_str(), + event_len, + &event_fields, + empty_spans, + )?; submodule.contents.trait_impls.push(serialize_trait_impl); - let deserialize_trait_impl = - generate_trait_impl_deserialize(event_type.as_str(), event_len, &event_fields)?; + let deserialize_trait_impl = generate_trait_impl_deserialize( + event_type.as_str(), + event_len, + &event_fields, + empty_spans, + )?; submodule.contents.trait_impls.push(deserialize_trait_impl); } } @@ -88,6 +102,7 @@ pub fn generate_event_impls(module: &mut SortedModule) -> Result<(), AztecMacroE fn generate_trait_impl_stub_event_interface( event_type: &str, byte_length: u32, + empty_spans: bool, ) -> Result { let byte_length_without_randomness = byte_length - 32; let trait_impl_source = format!( @@ -98,7 +113,7 @@ impl dep::aztec::event::event_interface::EventInterface<{byte_length}, {byte_len ) .to_string(); - let (parsed_ast, errors) = parse_program(&trait_impl_source); + let (parsed_ast, errors) = parse_program(&trait_impl_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementEventInterface { @@ -116,6 +131,7 @@ fn generate_trait_impl_serialize( event_type: &str, event_len: u32, event_fields: &[(String, String)], + empty_spans: bool, ) -> Result { let field_names = event_fields .iter() @@ -143,7 +159,7 @@ fn generate_trait_impl_serialize( ) .to_string(); - let (parsed_ast, errors) = parse_program(&trait_impl_source); + let (parsed_ast, errors) = parse_program(&trait_impl_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementEventInterface { @@ -161,6 +177,7 @@ fn generate_trait_impl_deserialize( event_type: &str, event_len: u32, event_fields: &[(String, String)], + empty_spans: bool, ) -> Result { let field_names: Vec = event_fields .iter() @@ -189,7 +206,7 @@ fn generate_trait_impl_deserialize( ) .to_string(); - let (parsed_ast, errors) = parse_program(&trait_impl_source); + let (parsed_ast, errors) = parse_program(&trait_impl_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementEventInterface { @@ -206,6 +223,7 @@ fn generate_trait_impl_deserialize( fn generate_fn_get_event_type_id( event_type: &str, field_length: u32, + empty_spans: bool, ) -> Result { let from_signature_input = std::iter::repeat("Field").take(field_length as usize).collect::>().join(","); @@ -218,7 +236,7 @@ fn generate_fn_get_event_type_id( ) .to_string(); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementEventInterface { @@ -235,6 +253,7 @@ fn generate_fn_get_event_type_id( fn generate_fn_private_to_be_bytes( event_type: &str, byte_length: u32, + empty_spans: bool, ) -> Result { let function_source = format!( " @@ -264,7 +283,7 @@ fn generate_fn_private_to_be_bytes( ) .to_string(); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementEventInterface { @@ -281,6 +300,7 @@ fn generate_fn_private_to_be_bytes( fn generate_fn_to_be_bytes( event_type: &str, byte_length: u32, + empty_spans: bool, ) -> Result { let byte_length_without_randomness = byte_length - 32; let function_source = format!( @@ -308,7 +328,7 @@ fn generate_fn_to_be_bytes( ") .to_string(); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementEventInterface { @@ -322,7 +342,7 @@ fn generate_fn_to_be_bytes( Ok(noir_fn) } -fn generate_fn_emit(event_type: &str) -> Result { +fn generate_fn_emit(event_type: &str, empty_spans: bool) -> Result { let function_source = format!( " fn emit(self: {event_type}, _emit: fn[Env](Self) -> ()) {{ @@ -332,7 +352,7 @@ fn generate_fn_emit(event_type: &str) -> Result { ) .to_string(); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementEventInterface { diff --git a/aztec_macros/src/transforms/functions.rs b/aztec_macros/src/transforms/functions.rs index 1f6bc2dfc62..cd3fdd1fc62 100644 --- a/aztec_macros/src/transforms/functions.rs +++ b/aztec_macros/src/transforms/functions.rs @@ -8,9 +8,10 @@ use noirc_frontend::ast::{ UnresolvedTypeData, Visibility, }; -use noirc_frontend::{macros_api::FieldElement, parse_program}; +use noirc_frontend::macros_api::FieldElement; use crate::utils::ast_utils::member_access; +use crate::utils::parse_utils::parse_program; use crate::{ chained_dep, chained_path, utils::{ @@ -132,6 +133,7 @@ pub fn transform_function( pub fn export_fn_abi( types: &mut Vec, func: &NoirFunction, + empty_spans: bool, ) -> Result<(), AztecMacroError> { let mut parameters_struct_source: Option<&str> = None; @@ -198,7 +200,7 @@ pub fn export_fn_abi( program.push_str(&export_struct_source); - let (ast, errors) = parse_program(&program); + let (ast, errors) = parse_program(&program, empty_spans); if !errors.is_empty() { return Err(AztecMacroError::CouldNotExportFunctionAbi { span: None, diff --git a/aztec_macros/src/transforms/note_interface.rs b/aztec_macros/src/transforms/note_interface.rs index 1bf84779a45..6fccded45ef 100644 --- a/aztec_macros/src/transforms/note_interface.rs +++ b/aztec_macros/src/transforms/note_interface.rs @@ -6,7 +6,6 @@ use noirc_frontend::ast::{ use noirc_frontend::{ graph::CrateId, macros_api::{FileId, HirContext, HirExpression, HirLiteral, HirStatement}, - parse_program, parser::SortedModule, Type, }; @@ -16,6 +15,7 @@ use regex::Regex; // TODO(#7165): nuke the following dependency from here and Cargo.toml use tiny_keccak::{Hasher, Keccak}; +use crate::utils::parse_utils::parse_program; use crate::{ chained_dep, utils::{ @@ -30,7 +30,10 @@ use crate::{ // Automatic implementation of most of the methods in the NoteInterface trait, guiding the user with meaningful error messages in case some // methods must be implemented manually. -pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), AztecMacroError> { +pub fn generate_note_interface_impl( + module: &mut SortedModule, + empty_spans: bool, +) -> Result<(), AztecMacroError> { // Find structs annotated with #[aztec(note)] let annotated_note_structs = module .types @@ -59,7 +62,8 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt note_struct.name.0.contents )), })?; - let note_interface_impl_span: Option = trait_impl.object_type.span; + let note_interface_impl_span: Option = + if empty_spans { None } else { trait_impl.object_type.span }; // Look for the note struct implementation, generate a default one if it doesn't exist (in order to append methods to it) let existing_impl = module.impls.iter_mut().find(|r#impl| match &r#impl.object_type.typ { UnresolvedTypeData::Named(path, _, _) => path.last_ident().eq(¬e_struct.name), @@ -140,6 +144,7 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt ¬e_serialized_len, &header_field_name.0.contents, note_interface_impl_span, + empty_spans, )?; trait_impl.items.push(TraitImplItem::Function(note_serialize_content_fn)); @@ -149,6 +154,7 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt ¬e_serialized_len, &header_field_name.0.contents, note_interface_impl_span, + empty_spans, )?; trait_impl.items.push(TraitImplItem::Function(note_deserialize_content_fn)); @@ -157,6 +163,7 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt ¬e_fields, &header_field_name.0.contents, note_interface_impl_span, + empty_spans, )?; structs_to_inject.push(note_properties_struct); let note_properties_fn = generate_note_properties_fn( @@ -164,6 +171,7 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt ¬e_fields, &header_field_name.0.contents, note_interface_impl_span, + empty_spans, )?; note_impl.methods.push((note_properties_fn, note_impl.type_span)); } @@ -173,6 +181,7 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt ¬e_type, &header_field_name.0.contents, note_interface_impl_span, + empty_spans, )?; trait_impl.items.push(TraitImplItem::Function(get_header_fn)); } @@ -181,6 +190,7 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt ¬e_type, &header_field_name.0.contents, note_interface_impl_span, + empty_spans, )?; trait_impl.items.push(TraitImplItem::Function(set_header_fn)); } @@ -188,13 +198,16 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt if !check_trait_method_implemented(trait_impl, "get_note_type_id") { let note_type_id = compute_note_type_id(¬e_type); let get_note_type_id_fn = - generate_get_note_type_id(note_type_id, note_interface_impl_span)?; + generate_get_note_type_id(note_type_id, note_interface_impl_span, empty_spans)?; trait_impl.items.push(TraitImplItem::Function(get_note_type_id_fn)); } if !check_trait_method_implemented(trait_impl, "compute_note_content_hash") { - let compute_note_content_hash_fn = - generate_compute_note_content_hash(¬e_type, note_interface_impl_span)?; + let compute_note_content_hash_fn = generate_compute_note_content_hash( + ¬e_type, + note_interface_impl_span, + empty_spans, + )?; trait_impl.items.push(TraitImplItem::Function(compute_note_content_hash_fn)); } @@ -204,6 +217,7 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt note_bytes_len.as_str(), note_serialized_len.as_str(), note_interface_impl_span, + empty_spans, )?; trait_impl.items.push(TraitImplItem::Function(to_be_bytes_fn)); } @@ -218,6 +232,7 @@ fn generate_note_to_be_bytes( byte_length: &str, serialized_length: &str, impl_span: Option, + empty_spans: bool, ) -> Result { let function_source = format!( " @@ -248,7 +263,7 @@ fn generate_note_to_be_bytes( ) .to_string(); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { @@ -259,7 +274,7 @@ fn generate_note_to_be_bytes( let mut function_ast = function_ast.into_sorted(); let mut noir_fn = function_ast.functions.remove(0); - noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.span = impl_span.unwrap_or_default(); noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -268,6 +283,7 @@ fn generate_note_get_header( note_type: &String, note_header_field_name: &String, impl_span: Option, + empty_spans: bool, ) -> Result { let function_source = format!( " @@ -279,7 +295,7 @@ fn generate_note_get_header( ) .to_string(); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { @@ -290,7 +306,7 @@ fn generate_note_get_header( let mut function_ast = function_ast.into_sorted(); let mut noir_fn = function_ast.functions.remove(0); - noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.span = impl_span.unwrap_or_default(); noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -299,6 +315,7 @@ fn generate_note_set_header( note_type: &String, note_header_field_name: &String, impl_span: Option, + empty_spans: bool, ) -> Result { let function_source = format!( " @@ -309,7 +326,7 @@ fn generate_note_set_header( note_type, note_header_field_name ); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { @@ -320,7 +337,7 @@ fn generate_note_set_header( let mut function_ast = function_ast.into_sorted(); let mut noir_fn = function_ast.functions.remove(0); - noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.span = impl_span.unwrap_or_default(); noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -330,6 +347,7 @@ fn generate_note_set_header( fn generate_get_note_type_id( note_type_id: u32, impl_span: Option, + empty_spans: bool, ) -> Result { // TODO(#7165): replace {} with dep::aztec::protocol_types::abis::note_selector::compute_note_selector(\"{}\") in the function source below let function_source = format!( @@ -342,7 +360,7 @@ fn generate_get_note_type_id( ) .to_string(); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { @@ -353,7 +371,7 @@ fn generate_get_note_type_id( let mut function_ast = function_ast.into_sorted(); let mut noir_fn = function_ast.functions.remove(0); - noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.span = impl_span.unwrap_or_default(); noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -372,11 +390,12 @@ fn generate_note_properties_struct( note_fields: &[(String, String)], note_header_field_name: &String, impl_span: Option, + empty_spans: bool, ) -> Result { let struct_source = generate_note_properties_struct_source(note_type, note_fields, note_header_field_name); - let (struct_ast, errors) = parse_program(&struct_source); + let (struct_ast, errors) = parse_program(&struct_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { @@ -405,6 +424,7 @@ fn generate_note_deserialize_content( note_serialize_len: &String, note_header_field_name: &String, impl_span: Option, + empty_spans: bool, ) -> Result { let function_source = generate_note_deserialize_content_source( note_type, @@ -413,7 +433,7 @@ fn generate_note_deserialize_content( note_header_field_name, ); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { @@ -424,7 +444,7 @@ fn generate_note_deserialize_content( let mut function_ast = function_ast.into_sorted(); let mut noir_fn = function_ast.functions.remove(0); - noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.span = impl_span.unwrap_or_default(); noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -442,6 +462,7 @@ fn generate_note_serialize_content( note_serialize_len: &String, note_header_field_name: &String, impl_span: Option, + empty_spans: bool, ) -> Result { let function_source = generate_note_serialize_content_source( note_type, @@ -450,7 +471,7 @@ fn generate_note_serialize_content( note_header_field_name, ); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { @@ -461,7 +482,7 @@ fn generate_note_serialize_content( let mut function_ast = function_ast.into_sorted(); let mut noir_fn = function_ast.functions.remove(0); - noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.span = impl_span.unwrap_or_default(); noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -472,10 +493,11 @@ fn generate_note_properties_fn( note_fields: &[(String, String)], note_header_field_name: &String, impl_span: Option, + empty_spans: bool, ) -> Result { let function_source = generate_note_properties_fn_source(note_type, note_fields, note_header_field_name); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { @@ -485,7 +507,7 @@ fn generate_note_properties_fn( } let mut function_ast = function_ast.into_sorted(); let mut noir_fn = function_ast.functions.remove(0); - noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.span = impl_span.unwrap_or_default(); noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -498,6 +520,7 @@ fn generate_note_properties_fn( fn generate_compute_note_content_hash( note_type: &String, impl_span: Option, + empty_spans: bool, ) -> Result { let function_source = format!( " @@ -507,7 +530,7 @@ fn generate_compute_note_content_hash( ", note_type ); - let (function_ast, errors) = parse_program(&function_source); + let (function_ast, errors) = parse_program(&function_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { @@ -517,7 +540,7 @@ fn generate_compute_note_content_hash( } let mut function_ast = function_ast.into_sorted(); let mut noir_fn = function_ast.functions.remove(0); - noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.span = impl_span.unwrap_or_default(); noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -525,6 +548,7 @@ fn generate_compute_note_content_hash( fn generate_note_exports_global( note_type: &str, note_type_id: &str, + empty_spans: bool, ) -> Result { let struct_source = format!( " @@ -537,7 +561,7 @@ fn generate_note_exports_global( ) .to_string(); - let (global_ast, errors) = parse_program(&struct_source); + let (global_ast, errors) = parse_program(&struct_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { @@ -779,9 +803,11 @@ pub fn inject_note_exports( file_id, )), }?; + let empty_spans = context.def_interner.is_in_lsp_mode(); let global = generate_note_exports_global( ¬e.borrow().name.0.contents, ¬e_type_id.to_hex(), + empty_spans, ) .map_err(|err| (err, file_id))?; diff --git a/aztec_macros/src/transforms/storage.rs b/aztec_macros/src/transforms/storage.rs index 6999234919f..dacea1a95e3 100644 --- a/aztec_macros/src/transforms/storage.rs +++ b/aztec_macros/src/transforms/storage.rs @@ -10,12 +10,12 @@ use noirc_frontend::{ FieldElement, FileId, HirContext, HirExpression, HirLiteral, HirStatement, NodeInterner, }, node_interner::TraitId, - parse_program, parser::SortedModule, token::SecondaryAttribute, Type, }; +use crate::utils::parse_utils::parse_program; use crate::{ chained_path, utils::{ @@ -498,6 +498,7 @@ pub fn generate_storage_layout( module: &mut SortedModule, storage_struct_name: String, module_name: &str, + empty_spans: bool, ) -> Result<(), AztecMacroError> { let definition = module .types @@ -530,7 +531,7 @@ pub fn generate_storage_layout( storable_fields_impl.join(",\n") ); - let (struct_ast, errors) = parse_program(&storage_fields_source); + let (struct_ast, errors) = parse_program(&storage_fields_source, empty_spans); if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotExportStorageLayout { diff --git a/aztec_macros/src/utils/mod.rs b/aztec_macros/src/utils/mod.rs index c8914f83025..6809fe9f154 100644 --- a/aztec_macros/src/utils/mod.rs +++ b/aztec_macros/src/utils/mod.rs @@ -3,3 +3,4 @@ pub mod checks; pub mod constants; pub mod errors; pub mod hir_utils; +pub mod parse_utils; diff --git a/aztec_macros/src/utils/parse_utils.rs b/aztec_macros/src/utils/parse_utils.rs new file mode 100644 index 00000000000..06093a4753e --- /dev/null +++ b/aztec_macros/src/utils/parse_utils.rs @@ -0,0 +1,533 @@ +use noirc_frontend::{ + ast::{ + ArrayLiteral, AssignStatement, BlockExpression, CallExpression, CastExpression, + ConstrainStatement, ConstructorExpression, Expression, ExpressionKind, ForLoopStatement, + ForRange, FunctionReturnType, Ident, IfExpression, IndexExpression, InfixExpression, + LValue, Lambda, LetStatement, Literal, MemberAccessExpression, MethodCallExpression, + ModuleDeclaration, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Path, + PathSegment, Pattern, PrefixExpression, Statement, StatementKind, TraitImplItem, TraitItem, + TypeImpl, UnresolvedGeneric, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, + UnresolvedTypeData, UnresolvedTypeExpression, UseTree, UseTreeKind, + }, + parser::{Item, ItemKind, ParsedSubModule, ParserError}, + ParsedModule, +}; + +/// Parses a program and will clear out (set them to a default) any spans in it if `empty_spans` is true. +/// We want to do this in code generated by macros when running in LSP mode so that the generated +/// code doesn't end up overlapping real code, messing with how inlay hints, hover, etc., work. +pub fn parse_program(source_program: &str, empty_spans: bool) -> (ParsedModule, Vec) { + let (mut parsed_program, errors) = noirc_frontend::parse_program(source_program); + if empty_spans { + empty_parsed_module(&mut parsed_program); + } + (parsed_program, errors) +} + +fn empty_parsed_module(parsed_module: &mut ParsedModule) { + for item in parsed_module.items.iter_mut() { + empty_item(item); + } +} + +fn empty_item(item: &mut Item) { + item.span = Default::default(); + + match &mut item.kind { + ItemKind::Function(noir_function) => empty_noir_function(noir_function), + ItemKind::Trait(noir_trait) => { + empty_noir_trait(noir_trait); + } + ItemKind::TraitImpl(noir_trait_impl) => { + empty_noir_trait_impl(noir_trait_impl); + } + ItemKind::Impl(type_impl) => { + empty_type_impl(type_impl); + } + ItemKind::Global(let_statement) => empty_let_statement(let_statement), + ItemKind::Submodules(parsed_submodule) => { + empty_parsed_submodule(parsed_submodule); + } + ItemKind::ModuleDecl(module_declaration) => empty_module_declaration(module_declaration), + ItemKind::Import(use_tree) => empty_use_tree(use_tree), + ItemKind::Struct(noir_struct) => empty_noir_struct(noir_struct), + ItemKind::TypeAlias(noir_type_alias) => empty_noir_type_alias(noir_type_alias), + } +} + +fn empty_noir_trait(noir_trait: &mut NoirTrait) { + noir_trait.span = Default::default(); + + empty_ident(&mut noir_trait.name); + empty_unresolved_generics(&mut noir_trait.generics); + empty_unresolved_trait_constraints(&mut noir_trait.where_clause); + for item in noir_trait.items.iter_mut() { + empty_trait_item(item); + } +} + +fn empty_noir_trait_impl(noir_trait_impl: &mut NoirTraitImpl) { + empty_path(&mut noir_trait_impl.trait_name); + empty_unresolved_generics(&mut noir_trait_impl.impl_generics); + empty_unresolved_type(&mut noir_trait_impl.object_type); + empty_unresolved_trait_constraints(&mut noir_trait_impl.where_clause); + for item in noir_trait_impl.items.iter_mut() { + empty_trait_impl_item(item); + } +} + +fn empty_type_impl(type_impl: &mut TypeImpl) { + empty_unresolved_type(&mut type_impl.object_type); + type_impl.type_span = Default::default(); + empty_unresolved_generics(&mut type_impl.generics); + empty_unresolved_trait_constraints(&mut type_impl.where_clause); + for (noir_function, _) in type_impl.methods.iter_mut() { + empty_noir_function(noir_function); + } +} + +fn empty_noir_function(noir_function: &mut NoirFunction) { + let def = &mut noir_function.def; + + def.span = Default::default(); + empty_ident(&mut def.name); + empty_unresolved_generics(&mut def.generics); + + for param in def.parameters.iter_mut() { + param.span = Default::default(); + empty_unresolved_type(&mut param.typ); + empty_pattern(&mut param.pattern); + } + + empty_unresolved_trait_constraints(&mut def.where_clause); + empty_function_return_type(&mut def.return_type); + empty_block_expression(&mut def.body); +} + +fn empty_trait_item(trait_item: &mut TraitItem) { + match trait_item { + TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => { + empty_ident(name); + empty_unresolved_generics(generics); + for (name, typ) in parameters.iter_mut() { + empty_ident(name); + empty_unresolved_type(typ); + } + empty_function_return_type(return_type); + for trait_constraint in where_clause.iter_mut() { + empty_unresolved_trait_constraint(trait_constraint); + } + if let Some(body) = body { + empty_block_expression(body); + } + } + TraitItem::Constant { name, typ, default_value } => { + empty_ident(name); + empty_unresolved_type(typ); + if let Some(default_value) = default_value { + empty_expression(default_value); + } + } + TraitItem::Type { name } => { + empty_ident(name); + } + } +} + +fn empty_trait_impl_item(trait_impl_item: &mut TraitImplItem) { + match trait_impl_item { + TraitImplItem::Function(noir_function) => empty_noir_function(noir_function), + TraitImplItem::Constant(name, typ, default_value) => { + empty_ident(name); + empty_unresolved_type(typ); + empty_expression(default_value); + } + TraitImplItem::Type { name, alias } => { + empty_ident(name); + empty_unresolved_type(alias); + } + } +} + +fn empty_let_statement(let_statement: &mut LetStatement) { + empty_pattern(&mut let_statement.pattern); + empty_unresolved_type(&mut let_statement.r#type); + empty_expression(&mut let_statement.expression); +} + +fn empty_parsed_submodule(parsed_submodule: &mut ParsedSubModule) { + empty_ident(&mut parsed_submodule.name); + empty_parsed_module(&mut parsed_submodule.contents); +} + +fn empty_module_declaration(module_declaration: &mut ModuleDeclaration) { + empty_ident(&mut module_declaration.ident); +} + +fn empty_use_tree(use_tree: &mut UseTree) { + empty_path(&mut use_tree.prefix); + + match &mut use_tree.kind { + UseTreeKind::Path(name, alias) => { + empty_ident(name); + if let Some(alias) = alias { + empty_ident(alias); + } + } + UseTreeKind::List(use_trees) => { + for use_tree in use_trees.iter_mut() { + empty_use_tree(use_tree); + } + } + } +} + +fn empty_noir_struct(noir_struct: &mut NoirStruct) { + noir_struct.span = Default::default(); + empty_ident(&mut noir_struct.name); + for (name, typ) in noir_struct.fields.iter_mut() { + empty_ident(name); + empty_unresolved_type(typ); + } + empty_unresolved_generics(&mut noir_struct.generics); +} + +fn empty_noir_type_alias(noir_type_alias: &mut NoirTypeAlias) { + noir_type_alias.span = Default::default(); + empty_ident(&mut noir_type_alias.name); + empty_unresolved_type(&mut noir_type_alias.typ); +} + +fn empty_block_expression(block_expression: &mut BlockExpression) { + for statement in block_expression.statements.iter_mut() { + empty_statement(statement); + } +} + +fn empty_statement(statement: &mut Statement) { + statement.span = Default::default(); + + match &mut statement.kind { + StatementKind::Let(let_statement) => empty_let_statement(let_statement), + StatementKind::Constrain(constrain_statement) => { + empty_constrain_statement(constrain_statement) + } + StatementKind::Expression(expression) => empty_expression(expression), + StatementKind::Assign(assign_statement) => empty_assign_statement(assign_statement), + StatementKind::For(for_loop_statement) => empty_for_loop_statement(for_loop_statement), + StatementKind::Comptime(statement) => empty_statement(statement), + StatementKind::Semi(expression) => empty_expression(expression), + StatementKind::Break | StatementKind::Continue | StatementKind::Error => (), + } +} + +fn empty_constrain_statement(constrain_statement: &mut ConstrainStatement) { + empty_expression(&mut constrain_statement.0); + if let Some(expression) = &mut constrain_statement.1 { + empty_expression(expression); + } +} + +fn empty_expressions(expressions: &mut [Expression]) { + for expression in expressions.iter_mut() { + empty_expression(expression); + } +} + +fn empty_expression(expression: &mut Expression) { + expression.span = Default::default(); + + match &mut expression.kind { + ExpressionKind::Literal(literal) => empty_literal(literal), + ExpressionKind::Block(block_expression) => empty_block_expression(block_expression), + ExpressionKind::Prefix(prefix_expression) => empty_prefix_expression(prefix_expression), + ExpressionKind::Index(index_expression) => empty_index_expression(index_expression), + ExpressionKind::Call(call_expression) => empty_call_expression(call_expression), + ExpressionKind::MethodCall(method_call_expression) => { + empty_method_call_expression(method_call_expression) + } + ExpressionKind::Constructor(constructor_expression) => { + empty_constructor_expression(constructor_expression) + } + ExpressionKind::MemberAccess(member_access_expression) => { + empty_member_access_expression(member_access_expression) + } + ExpressionKind::Cast(cast_expression) => empty_cast_expression(cast_expression), + ExpressionKind::Infix(infix_expression) => empty_infix_expression(infix_expression), + ExpressionKind::If(if_expression) => empty_if_expression(if_expression), + ExpressionKind::Variable(path) => empty_path(path), + ExpressionKind::Tuple(expressions) => { + empty_expressions(expressions); + } + ExpressionKind::Lambda(lambda) => empty_lambda(lambda), + ExpressionKind::Parenthesized(expression) => empty_expression(expression), + ExpressionKind::Unquote(expression) => { + empty_expression(expression); + } + ExpressionKind::Comptime(block_expression, _span) => { + empty_block_expression(block_expression); + } + ExpressionKind::Quote(..) | ExpressionKind::Resolved(_) | ExpressionKind::Error => (), + } +} + +fn empty_assign_statement(assign_statement: &mut AssignStatement) { + empty_lvalue(&mut assign_statement.lvalue); + empty_expression(&mut assign_statement.expression); +} + +fn empty_for_loop_statement(for_loop_statement: &mut ForLoopStatement) { + for_loop_statement.span = Default::default(); + empty_ident(&mut for_loop_statement.identifier); + empty_for_range(&mut for_loop_statement.range); + empty_expression(&mut for_loop_statement.block); +} + +fn empty_unresolved_types(unresolved_types: &mut [UnresolvedType]) { + for unresolved_type in unresolved_types.iter_mut() { + empty_unresolved_type(unresolved_type); + } +} + +fn empty_unresolved_type(unresolved_type: &mut UnresolvedType) { + unresolved_type.span = Default::default(); + + match &mut unresolved_type.typ { + UnresolvedTypeData::Array(unresolved_type_expression, unresolved_type) => { + empty_unresolved_type_expression(unresolved_type_expression); + empty_unresolved_type(unresolved_type); + } + UnresolvedTypeData::Slice(unresolved_type) => empty_unresolved_type(unresolved_type), + UnresolvedTypeData::Expression(unresolved_type_expression) => { + empty_unresolved_type_expression(unresolved_type_expression) + } + UnresolvedTypeData::FormatString(unresolved_type_expression, unresolved_type) => { + empty_unresolved_type_expression(unresolved_type_expression); + empty_unresolved_type(unresolved_type); + } + UnresolvedTypeData::Parenthesized(unresolved_type) => { + empty_unresolved_type(unresolved_type) + } + UnresolvedTypeData::Named(path, unresolved_types, _) => { + empty_path(path); + empty_unresolved_types(unresolved_types); + } + UnresolvedTypeData::TraitAsType(path, unresolved_types) => { + empty_path(path); + empty_unresolved_types(unresolved_types); + } + UnresolvedTypeData::MutableReference(unresolved_type) => { + empty_unresolved_type(unresolved_type) + } + UnresolvedTypeData::Tuple(unresolved_types) => empty_unresolved_types(unresolved_types), + UnresolvedTypeData::Function(args, ret, _env) => { + empty_unresolved_types(args); + empty_unresolved_type(ret); + } + UnresolvedTypeData::FieldElement + | UnresolvedTypeData::Integer(_, _) + | UnresolvedTypeData::Bool + | UnresolvedTypeData::String(_) + | UnresolvedTypeData::Unit + | UnresolvedTypeData::Quoted(_) + | UnresolvedTypeData::Resolved(_) + | UnresolvedTypeData::Unspecified + | UnresolvedTypeData::Error => (), + } +} + +fn empty_unresolved_generics(unresolved_generic: &mut UnresolvedGenerics) { + for generic in unresolved_generic.iter_mut() { + empty_unresolved_generic(generic); + } +} + +fn empty_unresolved_generic(unresolved_generic: &mut UnresolvedGeneric) { + match unresolved_generic { + UnresolvedGeneric::Variable(ident) => empty_ident(ident), + UnresolvedGeneric::Numeric { ident, typ } => { + empty_ident(ident); + empty_unresolved_type(typ); + } + } +} + +fn empty_pattern(pattern: &mut Pattern) { + match pattern { + Pattern::Identifier(ident) => empty_ident(ident), + Pattern::Mutable(pattern, _span, _) => { + empty_pattern(pattern); + } + Pattern::Tuple(patterns, _) => { + for pattern in patterns.iter_mut() { + empty_pattern(pattern); + } + } + Pattern::Struct(path, patterns, _) => { + empty_path(path); + for (name, pattern) in patterns.iter_mut() { + empty_ident(name); + empty_pattern(pattern); + } + } + } +} + +fn empty_unresolved_trait_constraints( + unresolved_trait_constriants: &mut [UnresolvedTraitConstraint], +) { + for trait_constraint in unresolved_trait_constriants.iter_mut() { + empty_unresolved_trait_constraint(trait_constraint); + } +} + +fn empty_unresolved_trait_constraint(unresolved_trait_constraint: &mut UnresolvedTraitConstraint) { + empty_unresolved_type(&mut unresolved_trait_constraint.typ); +} + +fn empty_function_return_type(function_return_type: &mut FunctionReturnType) { + match function_return_type { + FunctionReturnType::Ty(unresolved_type) => empty_unresolved_type(unresolved_type), + FunctionReturnType::Default(_) => (), + } +} + +fn empty_ident(ident: &mut Ident) { + ident.0.set_span(Default::default()); +} + +fn empty_path(path: &mut Path) { + path.span = Default::default(); + for segment in path.segments.iter_mut() { + empty_path_segment(segment); + } +} + +fn empty_path_segment(segment: &mut PathSegment) { + segment.span = Default::default(); + empty_ident(&mut segment.ident); +} + +fn empty_literal(literal: &mut Literal) { + match literal { + Literal::Array(array_literal) => empty_array_literal(array_literal), + Literal::Slice(array_literal) => empty_array_literal(array_literal), + Literal::Bool(_) + | Literal::Integer(_, _) + | Literal::Str(_) + | Literal::RawStr(_, _) + | Literal::FmtStr(_) + | Literal::Unit => (), + } +} + +fn empty_array_literal(array_literal: &mut ArrayLiteral) { + match array_literal { + ArrayLiteral::Standard(expressions) => { + empty_expressions(expressions); + } + ArrayLiteral::Repeated { repeated_element, length } => { + empty_expression(repeated_element); + empty_expression(length); + } + } +} + +fn empty_prefix_expression(prefix_expression: &mut PrefixExpression) { + empty_expression(&mut prefix_expression.rhs); +} + +fn empty_index_expression(index_expression: &mut IndexExpression) { + empty_expression(&mut index_expression.collection); + empty_expression(&mut index_expression.index); +} + +fn empty_call_expression(call_expression: &mut CallExpression) { + empty_expression(&mut call_expression.func); + empty_expressions(&mut call_expression.arguments); +} + +fn empty_method_call_expression(method_call_expression: &mut MethodCallExpression) { + empty_expression(&mut method_call_expression.object); + empty_ident(&mut method_call_expression.method_name); + if let Some(generics) = &mut method_call_expression.generics { + empty_unresolved_types(generics); + } + empty_expressions(&mut method_call_expression.arguments); +} + +fn empty_constructor_expression(constructor_expression: &mut ConstructorExpression) { + empty_path(&mut constructor_expression.type_name); + for (name, expression) in constructor_expression.fields.iter_mut() { + empty_ident(name); + empty_expression(expression); + } +} + +fn empty_member_access_expression(member_access_expression: &mut MemberAccessExpression) { + empty_expression(&mut member_access_expression.lhs); + empty_ident(&mut member_access_expression.rhs); +} + +fn empty_cast_expression(cast_expression: &mut CastExpression) { + empty_expression(&mut cast_expression.lhs); + empty_unresolved_type(&mut cast_expression.r#type); +} + +fn empty_infix_expression(infix_expression: &mut InfixExpression) { + empty_expression(&mut infix_expression.lhs); + empty_expression(&mut infix_expression.rhs); +} + +fn empty_if_expression(if_expression: &mut IfExpression) { + empty_expression(&mut if_expression.condition); + empty_expression(&mut if_expression.consequence); + if let Some(alternative) = &mut if_expression.alternative { + empty_expression(alternative); + } +} + +fn empty_lambda(lambda: &mut Lambda) { + for (name, typ) in lambda.parameters.iter_mut() { + empty_pattern(name); + empty_unresolved_type(typ); + } + empty_unresolved_type(&mut lambda.return_type); + empty_expression(&mut lambda.body); +} + +fn empty_lvalue(lvalue: &mut LValue) { + match lvalue { + LValue::Ident(ident) => empty_ident(ident), + LValue::MemberAccess { ref mut object, ref mut field_name, span: _ } => { + empty_lvalue(object); + empty_ident(field_name); + } + LValue::Index { ref mut array, ref mut index, span: _ } => { + empty_lvalue(array); + empty_expression(index); + } + LValue::Dereference(lvalue, _) => empty_lvalue(lvalue), + } +} + +fn empty_for_range(for_range: &mut ForRange) { + match for_range { + ForRange::Range(from, to) => { + empty_expression(from); + empty_expression(to); + } + ForRange::Array(expression) => empty_expression(expression), + } +} + +fn empty_unresolved_type_expression(unresolved_type_expression: &mut UnresolvedTypeExpression) { + match unresolved_type_expression { + UnresolvedTypeExpression::Variable(path) => empty_path(path), + UnresolvedTypeExpression::BinaryOperation(lhs, _, rhs, _) => { + empty_unresolved_type_expression(lhs); + empty_unresolved_type_expression(rhs); + } + UnresolvedTypeExpression::Constant(_, _) => (), + } +} diff --git a/compiler/noirc_errors/src/position.rs b/compiler/noirc_errors/src/position.rs index 9f9879e1d1b..02b242e8b4d 100644 --- a/compiler/noirc_errors/src/position.rs +++ b/compiler/noirc_errors/src/position.rs @@ -43,6 +43,10 @@ impl Spanned { pub fn span(&self) -> Span { self.span } + + pub fn set_span(&mut self, span: Span) { + self.span = span; + } } impl std::borrow::Borrow for Spanned { diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs index d224e38372f..490e1b9c3c4 100644 --- a/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -969,7 +969,16 @@ impl<'context> Elaborator<'context> { self.collect_trait_impl_methods(trait_id, trait_impl, &where_clause); - let span = trait_impl.object_type.span.expect("All trait self types should have spans"); + let span = trait_impl.object_type.span; + + let span = if let Some(span) = span { + span + } else if self.interner.is_in_lsp_mode() { + // A span might not be set if this was generated by a macro + Default::default() + } else { + span.expect("All trait self types should have spans") + }; self.declare_methods_on_struct(true, &mut trait_impl.methods, span); let methods = trait_impl.methods.function_ids(); diff --git a/compiler/noirc_frontend/src/elaborator/scope.rs b/compiler/noirc_frontend/src/elaborator/scope.rs index 258c32d4427..ae9a2c75ab6 100644 --- a/compiler/noirc_frontend/src/elaborator/scope.rs +++ b/compiler/noirc_frontend/src/elaborator/scope.rs @@ -73,7 +73,7 @@ impl<'context> Elaborator<'context> { let resolver = StandardPathResolver::new(module_id); let path_resolution; - if self.interner.track_references { + if self.interner.lsp_mode { let last_segment = path.last_ident(); let location = Location::new(last_segment.span(), self.file); let is_self_type_name = last_segment.is_self_type_name(); diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 60489660762..864cbef56c1 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -306,7 +306,7 @@ 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; - let resolved_import = if context.def_interner.track_references { + let resolved_import = if context.def_interner.lsp_mode { let mut references: Vec> = Vec::new(); let resolved_import = resolve_import( crate_id, diff --git a/compiler/noirc_frontend/src/hir/mod.rs b/compiler/noirc_frontend/src/hir/mod.rs index 87c4133d68e..6e91f2fdb61 100644 --- a/compiler/noirc_frontend/src/hir/mod.rs +++ b/compiler/noirc_frontend/src/hir/mod.rs @@ -291,8 +291,8 @@ impl Context<'_, '_> { }) } - // Enables reference tracking (useful for tools like LSP). - pub fn track_references(&mut self) { - self.def_interner.track_references = true; + /// Activates LSP mode, which will track references for all definitions. + pub fn activate_lsp_mode(&mut self) { + self.def_interner.lsp_mode = true; } } diff --git a/compiler/noirc_frontend/src/locations.rs b/compiler/noirc_frontend/src/locations.rs index 0ba74e22781..c437676b605 100644 --- a/compiler/noirc_frontend/src/locations.rs +++ b/compiler/noirc_frontend/src/locations.rs @@ -147,7 +147,7 @@ impl NodeInterner { location: Location, is_self_type: bool, ) { - if !self.track_references { + if !self.lsp_mode { return; } @@ -166,7 +166,7 @@ impl NodeInterner { referenced: ReferenceId, module_id: Option, ) { - if !self.track_references { + if !self.lsp_mode { return; } diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 87ff45f8f1a..d5996e6a1f3 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -200,8 +200,8 @@ pub struct NodeInterner { /// the actual type since types do not implement Send or Sync. quoted_types: noirc_arena::Arena, - /// Whether to track references. In regular compilations this is false, but tools set it to true. - pub(crate) track_references: bool, + /// Determins whether to run in LSP mode. In LSP mode references are tracked. + pub(crate) lsp_mode: bool, /// Store the location of the references in the graph. /// Edges are directed from reference nodes to referenced nodes. @@ -589,7 +589,7 @@ impl Default for NodeInterner { type_alias_ref: Vec::new(), type_ref_locations: Vec::new(), quoted_types: Default::default(), - track_references: false, + lsp_mode: false, location_indices: LocationIndices::default(), reference_graph: petgraph::graph::DiGraph::new(), reference_graph_indices: HashMap::new(), @@ -1969,6 +1969,10 @@ impl NodeInterner { let env = Box::new(Type::Unit); (Type::Function(args, Box::new(ret.clone()), env), ret) } + + pub fn is_in_lsp_mode(&self) -> bool { + self.lsp_mode + } } impl Methods { diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 2268fbccb46..04af2855084 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -289,7 +289,7 @@ pub(crate) fn prepare_package<'file_manager, 'parsed_files>( package: &Package, ) -> (Context<'file_manager, 'parsed_files>, CrateId) { let (mut context, crate_id) = nargo::prepare_package(file_manager, parsed_files, package); - context.track_references(); + context.activate_lsp_mode(); (context, crate_id) } @@ -310,7 +310,7 @@ fn prepare_source(source: String, state: &mut LspState) -> (Context<'static, 'st let parsed_files = parse_diff(&file_manager, state); let mut context = Context::new(file_manager, parsed_files); - context.track_references(); + context.activate_lsp_mode(); let root_crate_id = prepare_crate(&mut context, file_name); diff --git a/tooling/lsp/src/requests/inlay_hint.rs b/tooling/lsp/src/requests/inlay_hint.rs index a2ce8b46c8b..35ee36e11fa 100644 --- a/tooling/lsp/src/requests/inlay_hint.rs +++ b/tooling/lsp/src/requests/inlay_hint.rs @@ -104,11 +104,7 @@ impl<'a> InlayHintCollector<'a> { } ItemKind::Global(let_statement) => self.collect_in_let_statement(let_statement), ItemKind::Submodules(parsed_submodule) => { - // Inlay hints inside a contract might show up incorrectly because contracts can - // have generated code whose location overlaps with real code. - if !parsed_submodule.is_contract { - self.collect_in_parsed_module(&parsed_submodule.contents); - } + self.collect_in_parsed_module(&parsed_submodule.contents); } ItemKind::ModuleDecl(_) => (), ItemKind::Import(_) => (),