From 775ab30eb39ffd1a6cc84a67a3b8b6c6f4ed3748 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Fri, 6 Sep 2024 17:24:47 -0300 Subject: [PATCH 01/20] feat: show doc comments in LSP --- aztec_macros/src/transforms/storage.rs | 1 + aztec_macros/src/utils/parse_utils.rs | 10 +++++- compiler/noirc_frontend/src/ast/expression.rs | 4 +++ compiler/noirc_frontend/src/ast/structure.rs | 1 + compiler/noirc_frontend/src/ast/traits.rs | 11 ++++++- compiler/noirc_frontend/src/ast/visitor.rs | 10 +++++- compiler/noirc_frontend/src/elaborator/mod.rs | 7 ++++ .../noirc_frontend/src/elaborator/traits.rs | 4 +++ .../src/hir/def_collector/dc_mod.rs | 13 +++++++- compiler/noirc_frontend/src/lexer/lexer.rs | 4 +-- compiler/noirc_frontend/src/lexer/token.rs | 4 +++ compiler/noirc_frontend/src/node_interner.rs | 8 +++++ compiler/noirc_frontend/src/parser/parser.rs | 1 + .../src/parser/parser/doc_comments.rs | 22 +++++++++++++ .../src/parser/parser/function.rs | 10 ++++-- .../src/parser/parser/structs.rs | 15 +++++++-- .../src/parser/parser/traits.rs | 25 ++++++++++++--- .../requests/completion/completion_items.rs | 32 +++++++++++++++---- tooling/lsp/src/requests/hover.rs | 18 ++++++++++- 19 files changed, 176 insertions(+), 24 deletions(-) create mode 100644 compiler/noirc_frontend/src/parser/parser/doc_comments.rs diff --git a/aztec_macros/src/transforms/storage.rs b/aztec_macros/src/transforms/storage.rs index 7dd21f1a8ac..ce5c4ded550 100644 --- a/aztec_macros/src/transforms/storage.rs +++ b/aztec_macros/src/transforms/storage.rs @@ -236,6 +236,7 @@ pub fn generate_storage_implementation( &BlockExpression { statements: vec![storage_constructor_statement] }, &[], &return_type(chained_path!("Self")), + Vec::new(), )); let ordered_args = vec![generic_context_type.clone()]; diff --git a/aztec_macros/src/utils/parse_utils.rs b/aztec_macros/src/utils/parse_utils.rs index e7b3e347a96..8c6be14544f 100644 --- a/aztec_macros/src/utils/parse_utils.rs +++ b/aztec_macros/src/utils/parse_utils.rs @@ -108,7 +108,15 @@ fn empty_noir_function(noir_function: &mut NoirFunction) { fn empty_trait_item(trait_item: &mut TraitItem) { match trait_item { - TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => { + TraitItem::Function { + name, + generics, + parameters, + return_type, + where_clause, + body, + doc_comments: _, + } => { empty_ident(name); empty_unresolved_generics(generics); for (name, typ) in parameters.iter_mut() { diff --git a/compiler/noirc_frontend/src/ast/expression.rs b/compiler/noirc_frontend/src/ast/expression.rs index f242180134d..ebc9fba76f4 100644 --- a/compiler/noirc_frontend/src/ast/expression.rs +++ b/compiler/noirc_frontend/src/ast/expression.rs @@ -479,6 +479,8 @@ pub struct FunctionDefinition { pub where_clause: Vec, pub return_type: FunctionReturnType, pub return_visibility: Visibility, + + pub doc_comments: Vec, } impl FunctionDefinition { @@ -788,6 +790,7 @@ impl FunctionDefinition { body: &BlockExpression, where_clause: &[UnresolvedTraitConstraint], return_type: &FunctionReturnType, + doc_comments: Vec, ) -> FunctionDefinition { let p = parameters .iter() @@ -812,6 +815,7 @@ impl FunctionDefinition { where_clause: where_clause.to_vec(), return_type: return_type.clone(), return_visibility: Visibility::Private, + doc_comments, } } diff --git a/compiler/noirc_frontend/src/ast/structure.rs b/compiler/noirc_frontend/src/ast/structure.rs index 732cbee9232..7f5dfe6225f 100644 --- a/compiler/noirc_frontend/src/ast/structure.rs +++ b/compiler/noirc_frontend/src/ast/structure.rs @@ -13,6 +13,7 @@ pub struct NoirStruct { pub attributes: Vec, pub generics: UnresolvedGenerics, pub fields: Vec<(Ident, UnresolvedType)>, + pub doc_comments: Vec, pub span: Span, } diff --git a/compiler/noirc_frontend/src/ast/traits.rs b/compiler/noirc_frontend/src/ast/traits.rs index e3221f287d3..e588d2189eb 100644 --- a/compiler/noirc_frontend/src/ast/traits.rs +++ b/compiler/noirc_frontend/src/ast/traits.rs @@ -35,6 +35,7 @@ pub enum TraitItem { return_type: FunctionReturnType, where_clause: Vec, body: Option, + doc_comments: Vec, }, Constant { name: Ident, @@ -140,7 +141,15 @@ impl Display for NoirTrait { impl Display for TraitItem { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => { + TraitItem::Function { + name, + generics, + parameters, + return_type, + where_clause, + body, + doc_comments: _, + } => { let generics = vecmap(generics, |generic| generic.to_string()); let parameters = vecmap(parameters, |(name, typ)| format!("{name}: {typ}")); let where_clause = vecmap(where_clause, ToString::to_string); diff --git a/compiler/noirc_frontend/src/ast/visitor.rs b/compiler/noirc_frontend/src/ast/visitor.rs index 64b479b5fd6..30a818b5452 100644 --- a/compiler/noirc_frontend/src/ast/visitor.rs +++ b/compiler/noirc_frontend/src/ast/visitor.rs @@ -630,7 +630,15 @@ impl TraitItem { pub fn accept_children(&self, visitor: &mut impl Visitor) { match self { - TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => { + TraitItem::Function { + name, + generics, + parameters, + return_type, + where_clause, + body, + doc_comments: _, + } => { if visitor.visit_trait_item_function( name, generics, diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs index d321d04bef9..b57b8a8e599 100644 --- a/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -792,6 +792,13 @@ impl<'context> Elaborator<'context> { None }; + // For now we only collect docs in LSP mode, until we have a doc generator + if self.interner.is_in_lsp_mode() && !func.def.doc_comments.is_empty() { + self.interner + .doc_comments + .insert(ModuleDefId::FunctionId(func_id), func.def.doc_comments.clone()); + } + let attributes = func.secondary_attributes().iter(); let attributes = attributes.filter_map(|secondary_attribute| secondary_attribute.as_custom()); diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs index f651630baa2..d7dee63d490 100644 --- a/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -74,6 +74,7 @@ impl<'context> Elaborator<'context> { return_type, where_clause, body: _, + doc_comments, } = item { self.recover_generics(|this| { @@ -104,6 +105,7 @@ impl<'context> Elaborator<'context> { parameters, return_type, where_clause, + doc_comments.clone(), func_id, ); @@ -157,6 +159,7 @@ impl<'context> Elaborator<'context> { parameters: &[(Ident, UnresolvedType)], return_type: &FunctionReturnType, where_clause: &[UnresolvedTraitConstraint], + doc_comments: Vec, func_id: FuncId, ) { let old_generic_count = self.generics.len(); @@ -182,6 +185,7 @@ impl<'context> Elaborator<'context> { where_clause: where_clause.to_vec(), return_type: return_type.clone(), return_visibility: Visibility::Private, + doc_comments, }; let mut function = NoirFunction { kind, def }; diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 6c1b7632a2e..265d4f1dbf6 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -15,7 +15,9 @@ use crate::ast::{ TypeImpl, }; use crate::hir::resolution::errors::ResolverError; -use crate::macros_api::{Expression, NodeInterner, StructId, UnresolvedType, UnresolvedTypeData}; +use crate::macros_api::{ + Expression, ModuleDefId, NodeInterner, StructId, UnresolvedType, UnresolvedTypeData, +}; use crate::node_interner::ModuleAttributes; use crate::token::SecondaryAttribute; use crate::usage_tracker::UnusedItem; @@ -414,6 +416,7 @@ impl<'a> ModCollector<'a> { return_type, where_clause, body, + doc_comments, } => { let func_id = context.def_interner.push_empty_fn(); method_ids.insert(name.to_string(), func_id); @@ -447,6 +450,7 @@ impl<'a> ModCollector<'a> { body, where_clause, return_type, + doc_comments.clone(), )); unresolved_functions.push_fn( self.module_id, @@ -915,6 +919,13 @@ pub fn collect_struct( } }; + // For now we only collect docs in LSP mode, until we have a doc generator + if interner.is_in_lsp_mode() && !unresolved.struct_def.doc_comments.is_empty() { + interner + .doc_comments + .insert(ModuleDefId::TypeId(id), unresolved.struct_def.doc_comments.clone()); + } + // Add the struct to scope so its path can be looked up later let result = def_map.modules[module_id.0].declare_struct(name.clone(), id); diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index b7492396c90..58c0c5736ee 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -623,7 +623,7 @@ impl<'a> Lexer<'a> { }; let comment = self.eat_while(None, |ch| ch != '\n'); - if self.skip_comments { + if doc_style.is_none() && self.skip_comments { return self.next_token(); } @@ -668,7 +668,7 @@ impl<'a> Lexer<'a> { } if depth == 0 { - if self.skip_comments { + if doc_style.is_none() && self.skip_comments { return self.next_token(); } Ok(Token::BlockComment(content, doc_style).into_span(start, self.position)) diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index 7b805b5fd8d..d3bbbc7acf2 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -440,6 +440,7 @@ pub enum TokenKind { InternedLValue, InternedUnresolvedTypeData, UnquoteMarker, + OuterDocComment, } impl fmt::Display for TokenKind { @@ -458,6 +459,7 @@ impl fmt::Display for TokenKind { TokenKind::InternedLValue => write!(f, "interned lvalue"), TokenKind::InternedUnresolvedTypeData => write!(f, "interned unresolved type"), TokenKind::UnquoteMarker => write!(f, "macro result"), + TokenKind::OuterDocComment => write!(f, "doc comment"), } } } @@ -481,6 +483,8 @@ impl Token { Token::InternedStatement(_) => TokenKind::InternedStatement, Token::InternedLValue(_) => TokenKind::InternedLValue, Token::InternedUnresolvedTypeData(_) => TokenKind::InternedUnresolvedTypeData, + Token::LineComment(_, Some(DocStyle::Outer)) + | Token::BlockComment(_, Some(DocStyle::Outer)) => TokenKind::OuterDocComment, tok => TokenKind::Token(tok.clone()), } } diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index aa51779d24b..e0849ffe21e 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -269,6 +269,9 @@ pub struct NodeInterner { pub(crate) comptime_scopes: Vec>, pub(crate) usage_tracker: UsageTracker, + + /// Captures the documentation comments for each module, struct, trait, function, etc. + pub(crate) doc_comments: HashMap>, } /// A dependency in the dependency graph may be a type or a definition. @@ -656,6 +659,7 @@ impl Default for NodeInterner { comptime_scopes: vec![HashMap::default()], trait_impl_associated_types: HashMap::default(), usage_tracker: UsageTracker::new(), + doc_comments: HashMap::default(), } } } @@ -2196,6 +2200,10 @@ impl NodeInterner { bindings } + + pub fn doc_comments(&self, id: ModuleDefId) -> Option<&Vec> { + self.doc_comments.get(&id) + } } impl Methods { diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 48d25e7a1d8..74da7d4c234 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -59,6 +59,7 @@ use noirc_errors::{Span, Spanned}; mod assertion; mod attributes; +mod doc_comments; mod function; mod lambdas; mod literals; diff --git a/compiler/noirc_frontend/src/parser/parser/doc_comments.rs b/compiler/noirc_frontend/src/parser/parser/doc_comments.rs new file mode 100644 index 00000000000..3ac434e0802 --- /dev/null +++ b/compiler/noirc_frontend/src/parser/parser/doc_comments.rs @@ -0,0 +1,22 @@ +use chumsky::Parser; + +use crate::{ + parser::NoirParser, + token::{DocStyle, Token, TokenKind}, +}; + +use super::primitives::token_kind; + +fn outer_doc_comment() -> impl NoirParser { + token_kind(TokenKind::OuterDocComment).map(|token| match token { + Token::LineComment(comment, Some(DocStyle::Outer)) => comment, + Token::BlockComment(comment, Some(DocStyle::Outer)) => comment, + _ => unreachable!( + "Parser should have already errored due to token not being an outer doc comment" + ), + }) +} + +pub(super) fn outer_doc_comments() -> impl NoirParser> { + outer_doc_comment().repeated() +} diff --git a/compiler/noirc_frontend/src/parser/parser/function.rs b/compiler/noirc_frontend/src/parser/parser/function.rs index 05138bfffd9..2b788636356 100644 --- a/compiler/noirc_frontend/src/parser/parser/function.rs +++ b/compiler/noirc_frontend/src/parser/parser/function.rs @@ -1,6 +1,8 @@ use super::{ attributes::{attributes, validate_attributes}, - block, fresh_statement, ident, keyword, maybe_comp_time, nothing, parameter_name_recovery, + block, + doc_comments::outer_doc_comments, + fresh_statement, ident, keyword, maybe_comp_time, nothing, parameter_name_recovery, parameter_recovery, parenthesized, parse_type, pattern, primitives::token_kind, self_parameter, @@ -43,7 +45,8 @@ pub(super) fn function_definition(allow_self: bool) -> impl NoirParser impl NoirParser impl NoirParser impl NoirParser { )) .or(just(Semicolon).to(Vec::new())); - attributes() + outer_doc_comments() + .then(attributes()) .then_ignore(keyword(Struct)) .then(ident()) .then(function::generics()) .then(fields) - .validate(|(((attributes, name), generics), fields), span, emit| { + .validate(|((((doc_comments, attributes), name), generics), fields), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); - TopLevelStatement::Struct(NoirStruct { name, attributes, generics, fields, span }) + TopLevelStatement::Struct(NoirStruct { + name, + attributes, + generics, + fields, + doc_comments, + span, + }) }) } diff --git a/compiler/noirc_frontend/src/parser/parser/traits.rs b/compiler/noirc_frontend/src/parser/parser/traits.rs index bf5a4b4d0b4..bc9a4a19773 100644 --- a/compiler/noirc_frontend/src/parser/parser/traits.rs +++ b/compiler/noirc_frontend/src/parser/parser/traits.rs @@ -1,6 +1,7 @@ use chumsky::prelude::*; use super::attributes::{attributes, validate_secondary_attributes}; +use super::doc_comments::outer_doc_comments; use super::function::function_return_type; use super::path::path_no_turbofish; use super::{ @@ -97,16 +98,30 @@ fn trait_function_declaration() -> impl NoirParser { } }); - keyword(Keyword::Fn) - .ignore_then(ident()) + outer_doc_comments() + .then_ignore(keyword(Keyword::Fn)) + .then(ident()) .then(function::generics()) .then(parenthesized(function_declaration_parameters())) .then(function_return_type().map(|(_, typ)| typ)) .then(where_clause()) .then(trait_function_body_or_semicolon_or_error) - .map(|(((((name, generics), parameters), return_type), where_clause), body)| { - TraitItem::Function { name, generics, parameters, return_type, where_clause, body } - }) + .map( + |( + (((((doc_comments, name), generics), parameters), return_type), where_clause), + body, + )| { + TraitItem::Function { + name, + generics, + parameters, + return_type, + where_clause, + body, + doc_comments, + } + }, + ) } /// trait_type_declaration: 'type' ident generics diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs index c3afc225f52..a9d91fdf85c 100644 --- a/tooling/lsp/src/requests/completion/completion_items.rs +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -1,10 +1,11 @@ use lsp_types::{ - Command, CompletionItem, CompletionItemKind, CompletionItemLabelDetails, InsertTextFormat, + Command, CompletionItem, CompletionItemKind, CompletionItemLabelDetails, Documentation, + InsertTextFormat, MarkupContent, MarkupKind, }; use noirc_frontend::{ ast::AttributeTarget, hir_def::{function::FuncMeta, stmt::HirPattern}, - macros_api::ModuleDefId, + macros_api::{ModuleDefId, StructId}, node_interner::{FuncId, GlobalId}, QuotedType, Type, }; @@ -63,15 +64,26 @@ impl<'a> NodeFinder<'a> { attribute_first_type.as_ref(), false, // self_prefix ), - ModuleDefId::TypeId(..) => Some(self.struct_completion_item(name)), + ModuleDefId::TypeId(struct_id) => Some(self.struct_completion_item(name, struct_id)), ModuleDefId::TypeAliasId(..) => Some(self.type_alias_completion_item(name)), ModuleDefId::TraitId(..) => Some(self.trait_completion_item(name)), ModuleDefId::GlobalId(global_id) => Some(self.global_completion_item(name, global_id)), } } - fn struct_completion_item(&self, name: String) -> CompletionItem { - simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)) + fn struct_completion_item(&self, name: String, struct_id: StructId) -> CompletionItem { + let mut completion_item = + simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)); + + if let Some(doc_comments) = self.interner.doc_comments(ModuleDefId::TypeId(struct_id)) { + let docs = doc_comments.join("\n"); + completion_item.documentation = Some(Documentation::MarkupContent(MarkupContent { + kind: MarkupKind::Markdown, + value: docs, + })); + } + + completion_item } fn type_alias_completion_item(&self, name: String) -> CompletionItem { @@ -204,13 +216,21 @@ impl<'a> NodeFinder<'a> { completion_item }; - let completion_item = match function_completion_kind { + let mut completion_item = match function_completion_kind { FunctionCompletionKind::Name => completion_item, FunctionCompletionKind::NameAndParameters => { completion_item_with_trigger_parameter_hints_command(completion_item) } }; + if let Some(doc_comments) = self.interner.doc_comments(ModuleDefId::FunctionId(func_id)) { + let docs = doc_comments.join("\n"); + completion_item.documentation = Some(Documentation::MarkupContent(MarkupContent { + kind: MarkupKind::Markdown, + value: docs, + })); + } + Some(completion_item) } diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index ae1e57f5ecc..75a3748e43d 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -8,7 +8,7 @@ use noirc_frontend::{ graph::CrateId, hir::def_map::ModuleId, hir_def::{stmt::HirPattern, traits::Trait}, - macros_api::{NodeInterner, StructId}, + macros_api::{ModuleDefId, NodeInterner, StructId}, node_interner::{ DefinitionId, DefinitionKind, FuncId, GlobalId, ReferenceId, TraitId, TypeAliasId, }, @@ -108,6 +108,9 @@ fn format_struct(id: StructId, args: &ProcessRequestCallbackArgs) -> String { string.push_str(",\n"); } string.push_str(" }"); + + append_doc_comments(args.interner, ModuleDefId::TypeId(id), &mut string); + string } @@ -220,6 +223,8 @@ fn format_function(id: FuncId, args: &ProcessRequestCallbackArgs) -> String { string.push_str(&go_to_type_links(return_type, args.interner, args.files)); + append_doc_comments(args.interner, ModuleDefId::FunctionId(id), &mut string); + string } @@ -270,6 +275,7 @@ fn format_local(id: DefinitionId, args: &ProcessRequestCallbackArgs) -> String { string } +/// Some doc comments fn format_generics(generics: &Generics, string: &mut String) { if generics.is_empty() { return; @@ -513,6 +519,16 @@ fn format_link(name: String, location: lsp_types::Location) -> String { ) } +fn append_doc_comments(interner: &NodeInterner, id: ModuleDefId, string: &mut String) { + if let Some(doc_comments) = interner.doc_comments(id) { + string.push_str("\n\n---\n\n"); + for comment in doc_comments { + string.push_str(comment); + string.push('\n'); + } + } +} + #[cfg(test)] mod hover_tests { use crate::test_utils; From f18e68bfab9f899c8b29b18344db7ad56bd6378b Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Fri, 6 Sep 2024 21:33:31 -0300 Subject: [PATCH 02/20] Always track doc comments --- compiler/noirc_frontend/src/elaborator/mod.rs | 3 +-- compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs index b57b8a8e599..e8225d8b0b0 100644 --- a/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -792,8 +792,7 @@ impl<'context> Elaborator<'context> { None }; - // For now we only collect docs in LSP mode, until we have a doc generator - if self.interner.is_in_lsp_mode() && !func.def.doc_comments.is_empty() { + if !func.def.doc_comments.is_empty() { self.interner .doc_comments .insert(ModuleDefId::FunctionId(func_id), func.def.doc_comments.clone()); diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 265d4f1dbf6..af2160dd789 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -919,8 +919,7 @@ pub fn collect_struct( } }; - // For now we only collect docs in LSP mode, until we have a doc generator - if interner.is_in_lsp_mode() && !unresolved.struct_def.doc_comments.is_empty() { + if !unresolved.struct_def.doc_comments.is_empty() { interner .doc_comments .insert(ModuleDefId::TypeId(id), unresolved.struct_def.doc_comments.clone()); From 6e9873909dc6828bd2c066ebaab1b455a698a0cc Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Fri, 6 Sep 2024 21:48:34 -0300 Subject: [PATCH 03/20] Doc comments for globals --- aztec_macros/src/transforms/note_interface.rs | 2 +- aztec_macros/src/utils/parse_utils.rs | 2 +- compiler/noirc_frontend/src/ast/visitor.rs | 2 +- .../noirc_frontend/src/elaborator/comptime.rs | 3 +- .../src/hir/def_collector/dc_mod.rs | 10 +++- compiler/noirc_frontend/src/parser/mod.rs | 18 +++---- compiler/noirc_frontend/src/parser/parser.rs | 24 +++++++-- .../requests/completion/completion_items.rs | 49 ++++++++++--------- tooling/lsp/src/requests/hover.rs | 3 ++ tooling/nargo_fmt/src/visitor/item.rs | 2 +- 10 files changed, 73 insertions(+), 42 deletions(-) diff --git a/aztec_macros/src/transforms/note_interface.rs b/aztec_macros/src/transforms/note_interface.rs index df237926486..a2f553ed3c1 100644 --- a/aztec_macros/src/transforms/note_interface.rs +++ b/aztec_macros/src/transforms/note_interface.rs @@ -579,7 +579,7 @@ fn generate_note_exports_global( } let mut global_ast = global_ast.into_sorted(); - Ok(global_ast.globals.pop().unwrap()) + Ok(global_ast.globals.pop().unwrap().0) } // Source code generator functions. These utility methods produce Noir code as strings, that are then parsed and added to the AST. diff --git a/aztec_macros/src/utils/parse_utils.rs b/aztec_macros/src/utils/parse_utils.rs index 8c6be14544f..39744cb04e0 100644 --- a/aztec_macros/src/utils/parse_utils.rs +++ b/aztec_macros/src/utils/parse_utils.rs @@ -45,7 +45,7 @@ fn empty_item(item: &mut Item) { ItemKind::Impl(type_impl) => { empty_type_impl(type_impl); } - ItemKind::Global(let_statement) => empty_let_statement(let_statement), + ItemKind::Global(let_statement, _) => empty_let_statement(let_statement), ItemKind::Submodules(parsed_submodule) => { empty_parsed_submodule(parsed_submodule); } diff --git a/compiler/noirc_frontend/src/ast/visitor.rs b/compiler/noirc_frontend/src/ast/visitor.rs index 30a818b5452..5b85893028b 100644 --- a/compiler/noirc_frontend/src/ast/visitor.rs +++ b/compiler/noirc_frontend/src/ast/visitor.rs @@ -482,7 +482,7 @@ impl Item { noir_trait_impl.accept(self.span, visitor); } ItemKind::Impl(type_impl) => type_impl.accept(self.span, visitor), - ItemKind::Global(let_statement) => { + ItemKind::Global(let_statement, _doc_comments) => { if visitor.visit_global(let_statement, self.span) { let_statement.accept(visitor); } diff --git a/compiler/noirc_frontend/src/elaborator/comptime.rs b/compiler/noirc_frontend/src/elaborator/comptime.rs index 0cd0824b6d9..87eb3a3481f 100644 --- a/compiler/noirc_frontend/src/elaborator/comptime.rs +++ b/compiler/noirc_frontend/src/elaborator/comptime.rs @@ -432,11 +432,12 @@ impl<'context> Elaborator<'context> { resolved_trait_generics: Vec::new(), }); } - TopLevelStatement::Global(global) => { + TopLevelStatement::Global(global, doc_comments) => { let (global, error) = dc_mod::collect_global( self.interner, self.def_maps.get_mut(&self.crate_id).unwrap(), global, + doc_comments, self.file, self.local_module, self.crate_id, diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index af2160dd789..28dd16f62af 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -148,15 +148,16 @@ impl<'a> ModCollector<'a> { fn collect_globals( &mut self, context: &mut Context, - globals: Vec, + globals: Vec<(LetStatement, Vec)>, crate_id: CrateId, ) -> Vec<(CompilationError, fm::FileId)> { let mut errors = vec![]; - for global in globals { + for (global, doc_comments) in globals { let (global, error) = collect_global( &mut context.def_interner, &mut self.def_collector.def_map, global, + doc_comments, self.file_id, self.module_id, crate_id, @@ -1097,6 +1098,7 @@ pub(crate) fn collect_global( interner: &mut NodeInterner, def_map: &mut CrateDefMap, global: LetStatement, + doc_comments: Vec, file_id: FileId, module_id: LocalModuleId, crate_id: CrateId, @@ -1122,6 +1124,10 @@ pub(crate) fn collect_global( (err.into(), file_id) }); + if !doc_comments.is_empty() { + interner.doc_comments.insert(ModuleDefId::GlobalId(global_id), doc_comments); + } + let global = UnresolvedGlobal { file_id, module_id, global_id, stmt_def: global }; (global, error) } diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index 66be0fdced5..65e21463dd5 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -41,7 +41,7 @@ pub enum TopLevelStatement { Impl(TypeImpl), TypeAlias(NoirTypeAlias), SubModule(ParsedSubModule), - Global(LetStatement), + Global(LetStatement, Vec /* doc comments */), InnerAttribute(SecondaryAttribute), Error, } @@ -58,7 +58,7 @@ impl TopLevelStatement { TopLevelStatement::Impl(i) => Some(ItemKind::Impl(i)), TopLevelStatement::TypeAlias(t) => Some(ItemKind::TypeAlias(t)), TopLevelStatement::SubModule(s) => Some(ItemKind::Submodules(s)), - TopLevelStatement::Global(c) => Some(ItemKind::Global(c)), + TopLevelStatement::Global(c, doc_comments) => Some(ItemKind::Global(c, doc_comments)), TopLevelStatement::InnerAttribute(a) => Some(ItemKind::InnerAttribute(a)), TopLevelStatement::Error => None, } @@ -243,7 +243,7 @@ pub struct SortedModule { pub trait_impls: Vec, pub impls: Vec, pub type_aliases: Vec, - pub globals: Vec, + pub globals: Vec<(LetStatement, Vec /* doc comments */)>, /// Module declarations like `mod foo;` pub module_decls: Vec, @@ -264,7 +264,7 @@ impl std::fmt::Display for SortedModule { write!(f, "{import}")?; } - for global_const in &self.globals { + for (global_const, _) in &self.globals { write!(f, "{global_const}")?; } @@ -311,7 +311,7 @@ impl ParsedModule { ItemKind::TraitImpl(trait_impl) => module.push_trait_impl(trait_impl), ItemKind::Impl(r#impl) => module.push_impl(r#impl), ItemKind::TypeAlias(type_alias) => module.push_type_alias(type_alias), - ItemKind::Global(global) => module.push_global(global), + ItemKind::Global(global, doc_comments) => module.push_global(global, doc_comments), ItemKind::ModuleDecl(mod_name) => module.push_module_decl(mod_name), ItemKind::Submodules(submodule) => module.push_submodule(submodule.into_sorted()), ItemKind::InnerAttribute(attribute) => module.inner_attributes.push(attribute), @@ -337,7 +337,7 @@ pub enum ItemKind { TraitImpl(NoirTraitImpl), Impl(TypeImpl), TypeAlias(NoirTypeAlias), - Global(LetStatement), + Global(LetStatement, Vec /* doc comments */), ModuleDecl(ModuleDeclaration), Submodules(ParsedSubModule), InnerAttribute(SecondaryAttribute), @@ -421,8 +421,8 @@ impl SortedModule { self.submodules.push(submodule); } - fn push_global(&mut self, global: LetStatement) { - self.globals.push(global); + fn push_global(&mut self, global: LetStatement, doc_comments: Vec) { + self.globals.push((global, doc_comments)); } } @@ -521,7 +521,7 @@ impl std::fmt::Display for TopLevelStatement { TopLevelStatement::Impl(i) => i.fmt(f), TopLevelStatement::TypeAlias(t) => t.fmt(f), TopLevelStatement::SubModule(s) => s.fmt(f), - TopLevelStatement::Global(c) => c.fmt(f), + TopLevelStatement::Global(c, _) => c.fmt(f), TopLevelStatement::InnerAttribute(a) => write!(f, "#![{}]", a), TopLevelStatement::Error => write!(f, "error"), } diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 74da7d4c234..4c4941d4f96 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -27,6 +27,7 @@ use self::path::as_trait_path; use self::primitives::{keyword, macro_quote_marker, mutable_reference, variable}; use self::types::{generic_type_args, maybe_comp_time}; use attributes::{attributes, inner_attribute, validate_secondary_attributes}; +use doc_comments::outer_doc_comments; pub use types::parse_type; use visibility::item_visibility; pub use visibility::visibility; @@ -263,7 +264,8 @@ fn implementation() -> impl NoirParser { /// global_declaration: 'global' ident global_type_annotation '=' literal fn global_declaration() -> impl NoirParser { - let p = attributes::attributes() + let p = outer_doc_comments() + .then(attributes::attributes()) .then(maybe_comp_time()) .then(spanned(keyword(Keyword::Mut)).or_not()) .then_ignore(keyword(Keyword::Global).labelled(ParsingRuleLabel::Global)) @@ -273,7 +275,12 @@ fn global_declaration() -> impl NoirParser { let p = then_commit_ignore(p, just(Token::Assign)); let p = then_commit(p, expression()); p.validate( - |(((((attributes, comptime), mutable), mut pattern), r#type), expression), span, emit| { + |( + (((((doc_comments, attributes), comptime), mutable), mut pattern), r#type), + expression, + ), + span, + emit| { let global_attributes = attributes::validate_secondary_attributes(attributes, span, emit); @@ -283,10 +290,19 @@ fn global_declaration() -> impl NoirParser { let span = mut_span.merge(pattern.span()); pattern = Pattern::Mutable(Box::new(pattern), span, false); } - LetStatement { pattern, r#type, comptime, expression, attributes: global_attributes } + ( + LetStatement { + pattern, + r#type, + comptime, + expression, + attributes: global_attributes, + }, + doc_comments, + ) }, ) - .map(TopLevelStatement::Global) + .map(|(let_statement, doc_comments)| TopLevelStatement::Global(let_statement, doc_comments)) } /// submodule: 'mod' ident '{' module '}' diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs index a9d91fdf85c..bf09030f939 100644 --- a/tooling/lsp/src/requests/completion/completion_items.rs +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -72,18 +72,9 @@ impl<'a> NodeFinder<'a> { } fn struct_completion_item(&self, name: String, struct_id: StructId) -> CompletionItem { - let mut completion_item = + let completion_item = simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)); - - if let Some(doc_comments) = self.interner.doc_comments(ModuleDefId::TypeId(struct_id)) { - let docs = doc_comments.join("\n"); - completion_item.documentation = Some(Documentation::MarkupContent(MarkupContent { - kind: MarkupKind::Markdown, - value: docs, - })); - } - - completion_item + self.completion_item_with_doc_comments(ModuleDefId::TypeId(struct_id), completion_item) } fn type_alias_completion_item(&self, name: String) -> CompletionItem { @@ -99,7 +90,9 @@ impl<'a> NodeFinder<'a> { let typ = self.interner.definition_type(global.definition_id); let description = typ.to_string(); - simple_completion_item(name, CompletionItemKind::CONSTANT, Some(description)) + let completion_item = + simple_completion_item(name, CompletionItemKind::CONSTANT, Some(description)); + self.completion_item_with_doc_comments(ModuleDefId::GlobalId(global_id), completion_item) } pub(super) fn function_completion_item( @@ -216,21 +209,14 @@ impl<'a> NodeFinder<'a> { completion_item }; - let mut completion_item = match function_completion_kind { + let completion_item = match function_completion_kind { FunctionCompletionKind::Name => completion_item, FunctionCompletionKind::NameAndParameters => { completion_item_with_trigger_parameter_hints_command(completion_item) } }; - - if let Some(doc_comments) = self.interner.doc_comments(ModuleDefId::FunctionId(func_id)) { - let docs = doc_comments.join("\n"); - completion_item.documentation = Some(Documentation::MarkupContent(MarkupContent { - kind: MarkupKind::Markdown, - value: docs, - })); - } - + let completion_item = self + .completion_item_with_doc_comments(ModuleDefId::FunctionId(func_id), completion_item); Some(completion_item) } @@ -279,6 +265,25 @@ impl<'a> NodeFinder<'a> { text } + fn completion_item_with_doc_comments( + &self, + id: ModuleDefId, + completion_item: CompletionItem, + ) -> CompletionItem { + if let Some(doc_comments) = self.interner.doc_comments(id) { + let docs = doc_comments.join("\n"); + CompletionItem { + documentation: Some(Documentation::MarkupContent(MarkupContent { + kind: MarkupKind::Markdown, + value: docs, + })), + ..completion_item + } + } else { + completion_item + } + } + fn hir_pattern_to_argument(&self, pattern: &HirPattern, text: &mut String) { match pattern { HirPattern::Identifier(hir_ident) => { diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index 75a3748e43d..1662c2b4e9c 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -166,6 +166,9 @@ fn format_global(id: GlobalId, args: &ProcessRequestCallbackArgs) -> String { string.push_str(": "); string.push_str(&format!("{}", typ)); string.push_str(&go_to_type_links(&typ, args.interner, args.files)); + + append_doc_comments(args.interner, ModuleDefId::GlobalId(id), &mut string); + string } diff --git a/tooling/nargo_fmt/src/visitor/item.rs b/tooling/nargo_fmt/src/visitor/item.rs index 9e556e0fcbe..b3a21c2f6b5 100644 --- a/tooling/nargo_fmt/src/visitor/item.rs +++ b/tooling/nargo_fmt/src/visitor/item.rs @@ -231,7 +231,7 @@ impl super::FmtVisitor<'_> { | ItemKind::Trait(_) | ItemKind::TraitImpl(_) | ItemKind::TypeAlias(_) - | ItemKind::Global(_) + | ItemKind::Global(_, _) | ItemKind::ModuleDecl(_) | ItemKind::InnerAttribute(_) => { self.push_rewrite(self.slice(span).to_string(), span); From 1e2750440a38e7a0c5916f15b27d2950c7ab1b4f Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Fri, 6 Sep 2024 22:12:13 -0300 Subject: [PATCH 04/20] Doc comments for modules --- compiler/noirc_frontend/src/ast/statement.rs | 1 + .../src/hir/def_collector/dc_mod.rs | 19 +++++++ compiler/noirc_frontend/src/lexer/token.rs | 6 ++- compiler/noirc_frontend/src/parser/mod.rs | 7 +++ compiler/noirc_frontend/src/parser/parser.rs | 51 ++++++++++++------- .../src/parser/parser/doc_comments.rs | 14 +++++ .../requests/completion/completion_items.rs | 12 ++++- tooling/lsp/src/requests/hover.rs | 3 ++ tooling/nargo_fmt/src/visitor/item.rs | 5 ++ 9 files changed, 99 insertions(+), 19 deletions(-) diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs index 30db8ad63fd..3bfa4ad9af6 100644 --- a/compiler/noirc_frontend/src/ast/statement.rs +++ b/compiler/noirc_frontend/src/ast/statement.rs @@ -293,6 +293,7 @@ pub trait Recoverable { pub struct ModuleDeclaration { pub ident: Ident, pub outer_attributes: Vec, + pub outer_doc_comments: Vec, } impl std::fmt::Display for ModuleDeclaration { diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 28dd16f62af..d76277e0edc 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -589,6 +589,18 @@ impl<'a> ModCollector<'a> { false, ); + if !submodule.outer_doc_comments.is_empty() + || !submodule.contents.inner_doc_comments.is_empty() + { + let mut doc_comments = submodule.outer_doc_comments; + doc_comments.extend(submodule.contents.inner_doc_comments.clone()); + + context + .def_interner + .doc_comments + .insert(ModuleDefId::ModuleId(child), doc_comments); + } + errors.extend(collect_defs( self.def_collector, submodule.contents, @@ -696,6 +708,13 @@ impl<'a> ModCollector<'a> { // Track that the "foo" in `mod foo;` points to the module "foo" context.def_interner.add_module_reference(child_mod_id, location); + if !mod_decl.outer_doc_comments.is_empty() { + context + .def_interner + .doc_comments + .insert(ModuleDefId::ModuleId(child_mod_id), mod_decl.outer_doc_comments); + } + errors.extend(collect_defs( self.def_collector, ast, diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index d3bbbc7acf2..5a932de83f4 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -441,6 +441,7 @@ pub enum TokenKind { InternedUnresolvedTypeData, UnquoteMarker, OuterDocComment, + InnerDocComment, } impl fmt::Display for TokenKind { @@ -459,7 +460,8 @@ impl fmt::Display for TokenKind { TokenKind::InternedLValue => write!(f, "interned lvalue"), TokenKind::InternedUnresolvedTypeData => write!(f, "interned unresolved type"), TokenKind::UnquoteMarker => write!(f, "macro result"), - TokenKind::OuterDocComment => write!(f, "doc comment"), + TokenKind::OuterDocComment => write!(f, "outer doc comment"), + TokenKind::InnerDocComment => write!(f, "inner doc comment"), } } } @@ -485,6 +487,8 @@ impl Token { Token::InternedUnresolvedTypeData(_) => TokenKind::InternedUnresolvedTypeData, Token::LineComment(_, Some(DocStyle::Outer)) | Token::BlockComment(_, Some(DocStyle::Outer)) => TokenKind::OuterDocComment, + Token::LineComment(_, Some(DocStyle::Inner)) + | Token::BlockComment(_, Some(DocStyle::Inner)) => TokenKind::InnerDocComment, tok => TokenKind::Token(tok.clone()), } } diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index 65e21463dd5..c2f430a997c 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -252,6 +252,7 @@ pub struct SortedModule { pub submodules: Vec, pub inner_attributes: Vec, + pub inner_doc_comments: Vec, } impl std::fmt::Display for SortedModule { @@ -296,6 +297,7 @@ impl std::fmt::Display for SortedModule { #[derive(Clone, Debug, Default)] pub struct ParsedModule { pub items: Vec, + pub inner_doc_comments: Vec, } impl ParsedModule { @@ -318,6 +320,8 @@ impl ParsedModule { } } + module.inner_doc_comments = self.inner_doc_comments; + module } } @@ -350,6 +354,7 @@ pub struct ParsedSubModule { pub name: Ident, pub contents: ParsedModule, pub outer_attributes: Vec, + pub outer_doc_comments: Vec, pub is_contract: bool, } @@ -359,6 +364,7 @@ impl ParsedSubModule { name: self.name, contents: self.contents.into_sorted(), outer_attributes: self.outer_attributes, + outer_doc_comments: self.outer_doc_comments, is_contract: self.is_contract, } } @@ -381,6 +387,7 @@ pub struct SortedSubModule { pub name: Ident, pub contents: SortedModule, pub outer_attributes: Vec, + pub outer_doc_comments: Vec, pub is_contract: bool, } diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 4c4941d4f96..626f160993e 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -27,7 +27,7 @@ use self::path::as_trait_path; use self::primitives::{keyword, macro_quote_marker, mutable_reference, variable}; use self::types::{generic_type_args, maybe_comp_time}; use attributes::{attributes, inner_attribute, validate_secondary_attributes}; -use doc_comments::outer_doc_comments; +use doc_comments::{inner_doc_comments, outer_doc_comments}; pub use types::parse_type; use visibility::item_visibility; pub use visibility::visibility; @@ -179,13 +179,20 @@ fn program() -> impl NoirParser { /// | %empty pub fn module() -> impl NoirParser { recursive(|module_parser| { - empty() - .to(ParsedModule::default()) - .then(spanned(top_level_statement(module_parser)).repeated()) - .foldl(|mut program, (statement, span)| { - if let Some(kind) = statement.into_item_kind() { - program.items.push(Item { kind, span }); - } + inner_doc_comments() + .then( + empty() + .to(ParsedModule::default()) + .then(spanned(top_level_statement(module_parser)).repeated()) + .foldl(|mut program, (statement, span)| { + if let Some(kind) = statement.into_item_kind() { + program.items.push(Item { kind, span }); + } + program + }), + ) + .map(|(doc_comments, mut program)| { + program.inner_doc_comments = doc_comments; program }) }) @@ -307,18 +314,20 @@ fn global_declaration() -> impl NoirParser { /// submodule: 'mod' ident '{' module '}' fn submodule(module_parser: impl NoirParser) -> impl NoirParser { - attributes() + outer_doc_comments() + .then(attributes()) .then_ignore(keyword(Keyword::Mod)) .then(ident()) .then_ignore(just(Token::LeftBrace)) .then(module_parser) .then_ignore(just(Token::RightBrace)) - .validate(|((attributes, name), contents), span, emit| { + .validate(|(((doc_comments, attributes), name), contents), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); TopLevelStatement::SubModule(ParsedSubModule { name, contents, outer_attributes: attributes, + outer_doc_comments: doc_comments, is_contract: false, }) }) @@ -326,18 +335,20 @@ fn submodule(module_parser: impl NoirParser) -> impl NoirParser) -> impl NoirParser { - attributes() + outer_doc_comments() + .then(attributes()) .then_ignore(keyword(Keyword::Contract)) .then(ident()) .then_ignore(just(Token::LeftBrace)) .then(module_parser) .then_ignore(just(Token::RightBrace)) - .validate(|((attributes, name), contents), span, emit| { + .validate(|(((doc_comments, attributes), name), contents), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); TopLevelStatement::SubModule(ParsedSubModule { name, contents, outer_attributes: attributes, + outer_doc_comments: doc_comments, is_contract: true, }) }) @@ -468,12 +479,18 @@ fn optional_type_annotation<'a>() -> impl NoirParser + 'a { } fn module_declaration() -> impl NoirParser { - attributes().then_ignore(keyword(Keyword::Mod)).then(ident()).validate( - |(attributes, ident), span, emit| { + outer_doc_comments() + .then(attributes()) + .then_ignore(keyword(Keyword::Mod)) + .then(ident()) + .validate(|((doc_comments, attributes), ident), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); - TopLevelStatement::Module(ModuleDeclaration { ident, outer_attributes: attributes }) - }, - ) + TopLevelStatement::Module(ModuleDeclaration { + ident, + outer_attributes: attributes, + outer_doc_comments: doc_comments, + }) + }) } fn use_statement() -> impl NoirParser { diff --git a/compiler/noirc_frontend/src/parser/parser/doc_comments.rs b/compiler/noirc_frontend/src/parser/parser/doc_comments.rs index 3ac434e0802..151ff21017f 100644 --- a/compiler/noirc_frontend/src/parser/parser/doc_comments.rs +++ b/compiler/noirc_frontend/src/parser/parser/doc_comments.rs @@ -20,3 +20,17 @@ fn outer_doc_comment() -> impl NoirParser { pub(super) fn outer_doc_comments() -> impl NoirParser> { outer_doc_comment().repeated() } + +fn inner_doc_comment() -> impl NoirParser { + token_kind(TokenKind::InnerDocComment).map(|token| match token { + Token::LineComment(comment, Some(DocStyle::Inner)) => comment, + Token::BlockComment(comment, Some(DocStyle::Inner)) => comment, + _ => unreachable!( + "Parser should have already errored due to token not being an inner doc comment" + ), + }) +} + +pub(super) fn inner_doc_comments() -> impl NoirParser> { + inner_doc_comment().repeated() +} diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs index bf09030f939..bec380e7aa7 100644 --- a/tooling/lsp/src/requests/completion/completion_items.rs +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -4,6 +4,7 @@ use lsp_types::{ }; use noirc_frontend::{ ast::AttributeTarget, + hir::def_map::ModuleId, hir_def::{function::FuncMeta, stmt::HirPattern}, macros_api::{ModuleDefId, StructId}, node_interner::{FuncId, GlobalId}, @@ -55,7 +56,7 @@ impl<'a> NodeFinder<'a> { }; match module_def_id { - ModuleDefId::ModuleId(_) => Some(module_completion_item(name)), + ModuleDefId::ModuleId(id) => Some(self.module_completion_item(name, id)), ModuleDefId::FunctionId(func_id) => self.function_completion_item( &name, func_id, @@ -71,6 +72,15 @@ impl<'a> NodeFinder<'a> { } } + pub(super) fn module_completion_item( + &self, + name: impl Into, + id: ModuleId, + ) -> CompletionItem { + let completion_item = module_completion_item(name); + self.completion_item_with_doc_comments(ModuleDefId::ModuleId(id), completion_item) + } + fn struct_completion_item(&self, name: String, struct_id: StructId) -> CompletionItem { let completion_item = simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)); diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index 1662c2b4e9c..352bee37e98 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -84,6 +84,9 @@ fn format_module(id: ModuleId, args: &ProcessRequestCallbackArgs) -> Option { continue; } + for doc_comment in module.outer_doc_comments { + self.push_str(&format!("///{doc_comment}\n")); + self.push_str(&self.indent.to_string()); + } + for attribute in module.outer_attributes { self.push_str(&format!("#[{}]\n", attribute.as_ref())); self.push_str(&self.indent.to_string()); From 71f149ca432f576330df6f8699fe28c524716299 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Fri, 6 Sep 2024 22:26:05 -0300 Subject: [PATCH 05/20] Remove the Lalrpop parser --- Cargo.lock | 103 +------------- compiler/noirc_frontend/Cargo.toml | 4 - compiler/noirc_frontend/build.rs | 28 ---- .../noirc_frontend/src/elaborator/comptime.rs | 32 ++--- .../noirc_frontend/src/hir/comptime/value.rs | 4 +- compiler/noirc_frontend/src/lexer/lexer.rs | 32 +++-- .../noirc_frontend/src/noir_parser.lalrpop | 6 +- compiler/noirc_frontend/src/parser/mod.rs | 66 +++++---- compiler/noirc_frontend/src/parser/parser.rs | 127 ++++-------------- .../src/parser/parser/structs.rs | 6 +- .../src/parser/parser/traits.rs | 14 +- 11 files changed, 118 insertions(+), 304 deletions(-) delete mode 100644 compiler/noirc_frontend/build.rs diff --git a/Cargo.lock b/Cargo.lock index 3f56f5b6965..796ac50ca9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -274,7 +274,7 @@ dependencies = [ "ark-std", "derivative", "hashbrown 0.13.2", - "itertools 0.10.5", + "itertools", "num-traits", "zeroize", ] @@ -291,7 +291,7 @@ dependencies = [ "ark-std", "derivative", "digest", - "itertools 0.10.5", + "itertools", "num-bigint", "num-traits", "paste", @@ -380,15 +380,6 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" -[[package]] -name = "ascii-canvas" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" -dependencies = [ - "term", -] - [[package]] name = "assert_cmd" version = "2.0.12" @@ -1069,7 +1060,7 @@ dependencies = [ "clap", "criterion-plot", "is-terminal", - "itertools 0.10.5", + "itertools", "num-traits", "once_cell", "oorandom", @@ -1090,7 +1081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools 0.10.5", + "itertools", ] [[package]] @@ -1410,15 +1401,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ena" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" -dependencies = [ - "log", -] - [[package]] name = "encode_unicode" version = "0.3.6" @@ -2207,15 +2189,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.9" @@ -2400,37 +2373,6 @@ dependencies = [ "libc", ] -[[package]] -name = "lalrpop" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" -dependencies = [ - "ascii-canvas", - "bit-set", - "ena", - "itertools 0.11.0", - "lalrpop-util", - "petgraph", - "pico-args", - "regex", - "regex-syntax 0.8.2", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", - "walkdir", -] - -[[package]] -name = "lalrpop-util" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" -dependencies = [ - "regex-automata 0.4.7", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -2731,12 +2673,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - [[package]] name = "nibble_vec" version = "0.1.0" @@ -3034,8 +2970,6 @@ dependencies = [ "fm", "im", "iter-extended", - "lalrpop", - "lalrpop-util", "noirc_arena", "noirc_errors", "noirc_printable_type", @@ -3377,12 +3311,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pico-args" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" - [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3489,12 +3417,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - [[package]] name = "predicates" version = "2.1.5" @@ -3503,7 +3425,7 @@ checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" dependencies = [ "difflib", "float-cmp", - "itertools 0.10.5", + "itertools", "normalize-line-endings", "predicates-core", "regex", @@ -3517,7 +3439,7 @@ checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" dependencies = [ "anstyle", "difflib", - "itertools 0.10.5", + "itertools", "predicates-core", ] @@ -4396,19 +4318,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" -[[package]] -name = "string_cache" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot 0.12.1", - "phf_shared", - "precomputed-hash", -] - [[package]] name = "strsim" version = "0.10.0" diff --git a/compiler/noirc_frontend/Cargo.toml b/compiler/noirc_frontend/Cargo.toml index c0f6c8965fb..510cff08dec 100644 --- a/compiler/noirc_frontend/Cargo.toml +++ b/compiler/noirc_frontend/Cargo.toml @@ -31,7 +31,6 @@ cfg-if.workspace = true tracing.workspace = true petgraph = "0.6" rangemap = "1.4.0" -lalrpop-util = { version = "0.20.2", features = ["lexer"] } strum = "0.24" strum_macros = "0.24" @@ -39,9 +38,6 @@ strum_macros = "0.24" [dev-dependencies] base64.workspace = true -[build-dependencies] -lalrpop = "0.20.2" - [features] experimental_parser = [] bn254 = [] diff --git a/compiler/noirc_frontend/build.rs b/compiler/noirc_frontend/build.rs deleted file mode 100644 index eb896a377ae..00000000000 --- a/compiler/noirc_frontend/build.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::fs::{read_to_string, File}; -use std::io::Write; - -fn main() { - lalrpop::Configuration::new() - .emit_rerun_directives(true) - .use_cargo_dir_conventions() - .process() - .unwrap(); - - // here, we get a lint error from "extern crate core" so patching that until lalrpop does - // (adding cfg directives appears to be unsupported by lalrpop) - let out_dir = std::env::var("OUT_DIR").unwrap(); - let parser_path = std::path::Path::new(&out_dir).join("noir_parser.rs"); - let content_str = read_to_string(parser_path.clone()).unwrap(); - let mut parser_file = File::create(parser_path).unwrap(); - for line in content_str.lines() { - if line.contains("extern crate core") { - parser_file - .write_all( - format!("{}\n", line.replace("extern crate core", "use core")).as_bytes(), - ) - .unwrap(); - } else { - parser_file.write_all(format!("{}\n", line).as_bytes()).unwrap(); - } - } -} diff --git a/compiler/noirc_frontend/src/elaborator/comptime.rs b/compiler/noirc_frontend/src/elaborator/comptime.rs index 87eb3a3481f..feb9932ecc5 100644 --- a/compiler/noirc_frontend/src/elaborator/comptime.rs +++ b/compiler/noirc_frontend/src/elaborator/comptime.rs @@ -24,7 +24,7 @@ use crate::{ Expression, ExpressionKind, HirExpression, NodeInterner, SecondaryAttribute, StructId, }, node_interner::{DefinitionKind, DependencyId, FuncId, TraitId}, - parser::{self, TopLevelStatement}, + parser::{self, TopLevelStatementKind}, Type, TypeBindings, UnificationError, }; @@ -366,7 +366,7 @@ impl<'context> Elaborator<'context> { fn add_items( &mut self, - items: Vec, + items: Vec, generated_items: &mut CollectedItems, location: Location, ) { @@ -377,12 +377,12 @@ impl<'context> Elaborator<'context> { pub(crate) fn add_item( &mut self, - item: TopLevelStatement, + item: TopLevelStatementKind, generated_items: &mut CollectedItems, location: Location, ) { match item { - TopLevelStatement::Function(function) => { + TopLevelStatementKind::Function(function) => { let module_id = self.module_id(); if let Some(id) = dc_mod::collect_function( @@ -402,7 +402,7 @@ impl<'context> Elaborator<'context> { }); } } - TopLevelStatement::TraitImpl(mut trait_impl) => { + TopLevelStatementKind::TraitImpl(mut trait_impl) => { let (methods, associated_types, associated_constants) = dc_mod::collect_trait_impl_items( self.interner, @@ -432,7 +432,7 @@ impl<'context> Elaborator<'context> { resolved_trait_generics: Vec::new(), }); } - TopLevelStatement::Global(global, doc_comments) => { + TopLevelStatementKind::Global(global, doc_comments) => { let (global, error) = dc_mod::collect_global( self.interner, self.def_maps.get_mut(&self.crate_id).unwrap(), @@ -448,7 +448,7 @@ impl<'context> Elaborator<'context> { self.errors.push(error); } } - TopLevelStatement::Struct(struct_def) => { + TopLevelStatementKind::Struct(struct_def) => { if let Some((type_id, the_struct)) = dc_mod::collect_struct( self.interner, self.def_maps.get_mut(&self.crate_id).unwrap(), @@ -461,20 +461,20 @@ impl<'context> Elaborator<'context> { generated_items.types.insert(type_id, the_struct); } } - TopLevelStatement::Impl(r#impl) => { + TopLevelStatementKind::Impl(r#impl) => { let module = self.module_id(); dc_mod::collect_impl(self.interner, generated_items, r#impl, self.file, module); } // Assume that an error has already been issued - TopLevelStatement::Error => (), - - TopLevelStatement::Module(_) - | TopLevelStatement::Import(..) - | TopLevelStatement::Trait(_) - | TopLevelStatement::TypeAlias(_) - | TopLevelStatement::SubModule(_) - | TopLevelStatement::InnerAttribute(_) => { + TopLevelStatementKind::Error => (), + + TopLevelStatementKind::Module(_) + | TopLevelStatementKind::Import(..) + | TopLevelStatementKind::Trait(_) + | TopLevelStatementKind::TypeAlias(_) + | TopLevelStatementKind::SubModule(_) + | TopLevelStatementKind::InnerAttribute(_) => { let item = item.to_string(); let error = InterpreterError::UnsupportedTopLevelItemUnquote { item, location }; self.errors.push(error.into_compilation_error_pair()); diff --git a/compiler/noirc_frontend/src/hir/comptime/value.rs b/compiler/noirc_frontend/src/hir/comptime/value.rs index 04c557552bd..51145d1b8ff 100644 --- a/compiler/noirc_frontend/src/hir/comptime/value.rs +++ b/compiler/noirc_frontend/src/hir/comptime/value.rs @@ -25,7 +25,7 @@ use crate::{ StructId, }, node_interner::{ExprId, FuncId, StmtId, TraitId, TraitImplId}, - parser::{self, NoirParser, TopLevelStatement}, + parser::{self, NoirParser, TopLevelStatementKind}, token::{SpannedToken, Token, Tokens}, QuotedType, Shared, Type, TypeBindings, }; @@ -506,7 +506,7 @@ impl Value { self, location: Location, interner: &NodeInterner, - ) -> IResult> { + ) -> IResult> { match self { Value::Quoted(tokens) => parse_tokens(tokens, parser::top_level_items(), location), _ => { diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index 58c0c5736ee..9fccdd6a4c3 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -2,9 +2,7 @@ use crate::token::{Attribute, DocStyle}; use super::{ errors::LexerErrorKind, - token::{ - token_to_borrowed_token, BorrowedToken, IntType, Keyword, SpannedToken, Token, Tokens, - }, + token::{IntType, Keyword, SpannedToken, Token, Tokens}, }; use acvm::{AcirField, FieldElement}; use noirc_errors::{Position, Span}; @@ -26,20 +24,20 @@ pub struct Lexer<'a> { pub type SpannedTokenResult = Result; -pub(crate) fn from_spanned_token_result( - token_result: &SpannedTokenResult, -) -> Result<(usize, BorrowedToken<'_>, usize), LexerErrorKind> { - token_result - .as_ref() - .map(|spanned_token| { - ( - spanned_token.to_span().start() as usize, - token_to_borrowed_token(spanned_token.into()), - spanned_token.to_span().end() as usize, - ) - }) - .map_err(Clone::clone) -} +// pub(crate) fn from_spanned_token_result( +// token_result: &SpannedTokenResult, +// ) -> Result<(usize, BorrowedToken<'_>, usize), LexerErrorKind> { +// token_result +// .as_ref() +// .map(|spanned_token| { +// ( +// spanned_token.to_span().start() as usize, +// token_to_borrowed_token(spanned_token.into()), +// spanned_token.to_span().end() as usize, +// ) +// }) +// .map_err(Clone::clone) +// } impl<'a> Lexer<'a> { /// Given a source file of noir code, return all the tokens in the file diff --git a/compiler/noirc_frontend/src/noir_parser.lalrpop b/compiler/noirc_frontend/src/noir_parser.lalrpop index 01b8be8f721..11c345f0af5 100644 --- a/compiler/noirc_frontend/src/noir_parser.lalrpop +++ b/compiler/noirc_frontend/src/noir_parser.lalrpop @@ -3,7 +3,7 @@ use noirc_errors::Span; use crate::lexer::token::BorrowedToken; use crate::lexer::token as noir_token; use crate::lexer::errors::LexerErrorKind; -use crate::parser::TopLevelStatement; +use crate::parser::TopLevelStatementKind; use crate::ast::{Ident, Path, PathKind, PathSegment, UseTree, UseTreeKind}; use lalrpop_util::ErrorRecovery; @@ -101,9 +101,9 @@ extern { } } -pub(crate) TopLevelStatement: TopLevelStatement = { +pub(crate) TopLevelStatementKind: TopLevelStatementKind = { "use" r"[\t\r\n ]+" ";" EOF => { - TopLevelStatement::Import(use_tree, crate::ast::ItemVisibility::Private) + TopLevelStatementKind::Import(use_tree, crate::ast::ItemVisibility::Private) } } diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index c2f430a997c..94d55011e50 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -31,7 +31,13 @@ pub use parser::{ }; #[derive(Debug, Clone)] -pub enum TopLevelStatement { +pub struct TopLevelStatement { + pub kind: TopLevelStatementKind, + pub doc_comments: Vec, +} + +#[derive(Debug, Clone)] +pub enum TopLevelStatementKind { Function(NoirFunction), Module(ModuleDeclaration), Import(UseTree, ItemVisibility), @@ -46,21 +52,23 @@ pub enum TopLevelStatement { Error, } -impl TopLevelStatement { +impl TopLevelStatementKind { pub fn into_item_kind(self) -> Option { match self { - TopLevelStatement::Function(f) => Some(ItemKind::Function(f)), - TopLevelStatement::Module(m) => Some(ItemKind::ModuleDecl(m)), - TopLevelStatement::Import(i, visibility) => Some(ItemKind::Import(i, visibility)), - TopLevelStatement::Struct(s) => Some(ItemKind::Struct(s)), - TopLevelStatement::Trait(t) => Some(ItemKind::Trait(t)), - TopLevelStatement::TraitImpl(t) => Some(ItemKind::TraitImpl(t)), - TopLevelStatement::Impl(i) => Some(ItemKind::Impl(i)), - TopLevelStatement::TypeAlias(t) => Some(ItemKind::TypeAlias(t)), - TopLevelStatement::SubModule(s) => Some(ItemKind::Submodules(s)), - TopLevelStatement::Global(c, doc_comments) => Some(ItemKind::Global(c, doc_comments)), - TopLevelStatement::InnerAttribute(a) => Some(ItemKind::InnerAttribute(a)), - TopLevelStatement::Error => None, + TopLevelStatementKind::Function(f) => Some(ItemKind::Function(f)), + TopLevelStatementKind::Module(m) => Some(ItemKind::ModuleDecl(m)), + TopLevelStatementKind::Import(i, visibility) => Some(ItemKind::Import(i, visibility)), + TopLevelStatementKind::Struct(s) => Some(ItemKind::Struct(s)), + TopLevelStatementKind::Trait(t) => Some(ItemKind::Trait(t)), + TopLevelStatementKind::TraitImpl(t) => Some(ItemKind::TraitImpl(t)), + TopLevelStatementKind::Impl(i) => Some(ItemKind::Impl(i)), + TopLevelStatementKind::TypeAlias(t) => Some(ItemKind::TypeAlias(t)), + TopLevelStatementKind::SubModule(s) => Some(ItemKind::Submodules(s)), + TopLevelStatementKind::Global(c, doc_comments) => { + Some(ItemKind::Global(c, doc_comments)) + } + TopLevelStatementKind::InnerAttribute(a) => Some(ItemKind::InnerAttribute(a)), + TopLevelStatementKind::Error => None, } } } @@ -222,11 +230,11 @@ fn parameter_name_recovery() -> impl NoirParser { try_skip_until([Colon, RightParen, Comma], [RightParen, Comma]) } -fn top_level_statement_recovery() -> impl NoirParser { +fn top_level_statement_recovery() -> impl NoirParser { none_of([Token::RightBrace, Token::EOF]) .repeated() .ignore_then(one_of([Token::Semicolon])) - .map(|_| TopLevelStatement::Error) + .map(|_| TopLevelStatementKind::Error) } /// Force the given parser to succeed, logging any errors it had @@ -510,27 +518,27 @@ impl Precedence { } } -impl std::fmt::Display for TopLevelStatement { +impl std::fmt::Display for TopLevelStatementKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - TopLevelStatement::Function(fun) => fun.fmt(f), - TopLevelStatement::Module(m) => m.fmt(f), - TopLevelStatement::Import(tree, visibility) => { + TopLevelStatementKind::Function(fun) => fun.fmt(f), + TopLevelStatementKind::Module(m) => m.fmt(f), + TopLevelStatementKind::Import(tree, visibility) => { if visibility == &ItemVisibility::Private { write!(f, "use {tree}") } else { write!(f, "{visibility} use {tree}") } } - TopLevelStatement::Trait(t) => t.fmt(f), - TopLevelStatement::TraitImpl(i) => i.fmt(f), - TopLevelStatement::Struct(s) => s.fmt(f), - TopLevelStatement::Impl(i) => i.fmt(f), - TopLevelStatement::TypeAlias(t) => t.fmt(f), - TopLevelStatement::SubModule(s) => s.fmt(f), - TopLevelStatement::Global(c, _) => c.fmt(f), - TopLevelStatement::InnerAttribute(a) => write!(f, "#![{}]", a), - TopLevelStatement::Error => write!(f, "error"), + TopLevelStatementKind::Trait(t) => t.fmt(f), + TopLevelStatementKind::TraitImpl(i) => i.fmt(f), + TopLevelStatementKind::Struct(s) => s.fmt(f), + TopLevelStatementKind::Impl(i) => i.fmt(f), + TopLevelStatementKind::TypeAlias(t) => t.fmt(f), + TopLevelStatementKind::SubModule(s) => s.fmt(f), + TopLevelStatementKind::Global(c, _) => c.fmt(f), + TopLevelStatementKind::InnerAttribute(a) => write!(f, "#![{}]", a), + TopLevelStatementKind::Error => write!(f, "error"), } } } diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 626f160993e..339b411a040 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -36,9 +36,9 @@ use super::{ foldl_with_span, labels::ParsingRuleLabel, parameter_name_recovery, parameter_recovery, parenthesized, then_commit, then_commit_ignore, top_level_statement_recovery, ExprParser, NoirParser, ParsedModule, ParsedSubModule, ParserError, ParserErrorReason, Precedence, - TopLevelStatement, + TopLevelStatementKind, }; -use super::{spanned, Item, ItemKind}; +use super::{spanned, Item}; use crate::ast::{ BinaryOp, BinaryOpKind, BlockExpression, ForLoopStatement, ForRange, GenericTypeArgs, Ident, IfExpression, InfixExpression, LValue, Literal, ModuleDeclaration, NoirTypeAlias, Param, Path, @@ -48,14 +48,13 @@ use crate::ast::{ use crate::ast::{ Expression, ExpressionKind, LetStatement, StatementKind, UnresolvedType, UnresolvedTypeData, }; -use crate::lexer::{lexer::from_spanned_token_result, Lexer}; +use crate::lexer::Lexer; use crate::parser::{force, ignore_then_commit, statement_recovery}; use crate::token::{Keyword, Token, TokenKind}; use acvm::AcirField; use chumsky::prelude::*; use iter_extended::vecmap; -use lalrpop_util::lalrpop_mod; use noirc_errors::{Span, Spanned}; mod assertion; @@ -72,7 +71,7 @@ mod types; mod visibility; // synthesized by LALRPOP -lalrpop_mod!(pub noir_parser); +// lalrpop_mod!(pub noir_parser); #[cfg(test)] mod test_helpers; @@ -97,79 +96,9 @@ pub fn parse_program(source_program: &str) -> (ParsedModule, Vec) { parsing_errors.extend(lexing_errors.into_iter().map(Into::into)); let parsed_module = module.unwrap_or_default(); - if cfg!(feature = "experimental_parser") { - for parsed_item in &parsed_module.items { - if lalrpop_parser_supports_kind(&parsed_item.kind) { - match &parsed_item.kind { - ItemKind::Import(parsed_use_tree, _visibility) => { - prototype_parse_use_tree(Some(parsed_use_tree), source_program); - } - // other kinds prevented by lalrpop_parser_supports_kind - _ => unreachable!(), - } - } - } - } (parsed_module, parsing_errors) } -fn prototype_parse_use_tree(expected_use_tree_opt: Option<&UseTree>, input: &str) { - // TODO(https://github.com/noir-lang/noir/issues/4777): currently skipping - // recursive use trees, e.g. "use std::{foo, bar}" - if input.contains('{') { - return; - } - - let mut lexer = Lexer::new(input); - lexer = lexer.skip_whitespaces(false); - let mut errors = Vec::new(); - - // NOTE: this is a hack to get the references working - // => this likely means that we'll want to propagate the <'input> lifetime further into Token - let lexer_result = lexer.collect::>(); - let referenced_lexer_result = lexer_result.iter().map(from_spanned_token_result); - - let calculated = noir_parser::TopLevelStatementParser::new().parse( - input, - &mut errors, - referenced_lexer_result, - ); - - if let Some(expected_use_tree) = expected_use_tree_opt { - assert!( - calculated.is_ok(), - "calculated not Ok(_): {:?}\n\nlexer: {:?}\n\ninput: {:?}", - calculated, - lexer_result, - input - ); - - match calculated.unwrap() { - TopLevelStatement::Import(parsed_use_tree, _visibility) => { - assert_eq!(expected_use_tree, &parsed_use_tree); - } - unexpected_calculated => { - panic!( - "expected a TopLevelStatement::Import, but found: {:?}", - unexpected_calculated - ) - } - } - } else { - assert!( - calculated.is_err(), - "calculated not Err(_): {:?}\n\nlexer: {:?}\n\ninput: {:?}", - calculated, - lexer_result, - input - ); - } -} - -fn lalrpop_parser_supports_kind(kind: &ItemKind) -> bool { - matches!(kind, ItemKind::Import(..)) -} - /// program: module EOF fn program() -> impl NoirParser { module().then_ignore(just(Token::EOF)) @@ -199,7 +128,7 @@ pub fn module() -> impl NoirParser { } /// This parser is used for parsing top level statements in macros -pub fn top_level_items() -> impl NoirParser> { +pub fn top_level_items() -> impl NoirParser> { top_level_statement(module()).repeated() } @@ -213,9 +142,9 @@ pub fn top_level_items() -> impl NoirParser> { /// | global_declaration pub fn top_level_statement<'a>( module_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { +) -> impl NoirParser + 'a { choice(( - function::function_definition(false).map(TopLevelStatement::Function), + function::function_definition(false).map(TopLevelStatementKind::Function), structs::struct_definition(), traits::trait_definition(), traits::trait_implementation(), @@ -226,7 +155,7 @@ pub fn top_level_statement<'a>( module_declaration().then_ignore(force(just(Token::Semicolon))), use_statement().then_ignore(force(just(Token::Semicolon))), global_declaration().then_ignore(force(just(Token::Semicolon))), - inner_attribute().map(TopLevelStatement::InnerAttribute), + inner_attribute().map(TopLevelStatementKind::InnerAttribute), )) .recover_via(top_level_statement_recovery()) } @@ -234,7 +163,7 @@ pub fn top_level_statement<'a>( /// Parses a non-trait implementation, adding a set of methods to a type. /// /// implementation: 'impl' generics type '{' function_definition ... '}' -fn implementation() -> impl NoirParser { +fn implementation() -> impl NoirParser { let methods_or_error = just(Token::LeftBrace) .ignore_then(spanned(function::function_definition(true)).repeated()) .then_ignore(just(Token::RightBrace)) @@ -259,7 +188,7 @@ fn implementation() -> impl NoirParser { .map(|args| { let ((other_args, where_clause), methods) = args; let (generics, (object_type, type_span)) = other_args; - TopLevelStatement::Impl(TypeImpl { + TopLevelStatementKind::Impl(TypeImpl { generics, object_type, type_span, @@ -270,7 +199,7 @@ fn implementation() -> impl NoirParser { } /// global_declaration: 'global' ident global_type_annotation '=' literal -fn global_declaration() -> impl NoirParser { +fn global_declaration() -> impl NoirParser { let p = outer_doc_comments() .then(attributes::attributes()) .then(maybe_comp_time()) @@ -309,11 +238,13 @@ fn global_declaration() -> impl NoirParser { ) }, ) - .map(|(let_statement, doc_comments)| TopLevelStatement::Global(let_statement, doc_comments)) + .map(|(let_statement, doc_comments)| TopLevelStatementKind::Global(let_statement, doc_comments)) } /// submodule: 'mod' ident '{' module '}' -fn submodule(module_parser: impl NoirParser) -> impl NoirParser { +fn submodule( + module_parser: impl NoirParser, +) -> impl NoirParser { outer_doc_comments() .then(attributes()) .then_ignore(keyword(Keyword::Mod)) @@ -323,7 +254,7 @@ fn submodule(module_parser: impl NoirParser) -> impl NoirParser) -> impl NoirParser) -> impl NoirParser { +fn contract( + module_parser: impl NoirParser, +) -> impl NoirParser { outer_doc_comments() .then(attributes()) .then_ignore(keyword(Keyword::Contract)) @@ -344,7 +277,7 @@ fn contract(module_parser: impl NoirParser) -> impl NoirParser) -> impl NoirParser impl NoirParser { +fn type_alias_definition() -> impl NoirParser { use self::Keyword::Type; let p = ignore_then_commit(keyword(Type), ident()); @@ -363,7 +296,7 @@ fn type_alias_definition() -> impl NoirParser { let p = then_commit(p, parse_type()); p.map_with_span(|((name, generics), typ), span| { - TopLevelStatement::TypeAlias(NoirTypeAlias { name, generics, typ, span }) + TopLevelStatementKind::TypeAlias(NoirTypeAlias { name, generics, typ, span }) }) } @@ -478,14 +411,14 @@ fn optional_type_annotation<'a>() -> impl NoirParser + 'a { }) } -fn module_declaration() -> impl NoirParser { +fn module_declaration() -> impl NoirParser { outer_doc_comments() .then(attributes()) .then_ignore(keyword(Keyword::Mod)) .then(ident()) .validate(|((doc_comments, attributes), ident), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); - TopLevelStatement::Module(ModuleDeclaration { + TopLevelStatementKind::Module(ModuleDeclaration { ident, outer_attributes: attributes, outer_doc_comments: doc_comments, @@ -493,11 +426,11 @@ fn module_declaration() -> impl NoirParser { }) } -fn use_statement() -> impl NoirParser { +fn use_statement() -> impl NoirParser { item_visibility() .then_ignore(keyword(Keyword::Use)) .then(use_tree()) - .map(|(visibility, use_tree)| TopLevelStatement::Import(use_tree, visibility)) + .map(|(visibility, use_tree)| TopLevelStatementKind::Import(use_tree, visibility)) } fn rename() -> impl NoirParser> { @@ -1614,12 +1547,12 @@ mod test { for (use_statement_str, expect_valid) in use_statements { let mut use_statement_str = use_statement_str.to_string(); - let expected_use_statement = if expect_valid { + if expect_valid { let (result_opt, _diagnostics) = parse_recover(&use_statement(), &use_statement_str); use_statement_str.push(';'); match result_opt.unwrap() { - TopLevelStatement::Import(expected_use_statement, _visibility) => { + TopLevelStatementKind::Import(expected_use_statement, _visibility) => { Some(expected_use_statement) } _ => unreachable!(), @@ -1629,8 +1562,6 @@ mod test { assert!(result.is_err()); None }; - - prototype_parse_use_tree(expected_use_statement.as_ref(), &use_statement_str); } } @@ -1876,7 +1807,7 @@ mod test { assert_eq!(errors[0].message, "expected <, where or { after impl type"); let top_level_statement = top_level_statement.unwrap(); - let TopLevelStatement::Impl(impl_) = top_level_statement else { + let TopLevelStatementKind::Impl(impl_) = top_level_statement else { panic!("Expected to parse an impl"); }; diff --git a/compiler/noirc_frontend/src/parser/parser/structs.rs b/compiler/noirc_frontend/src/parser/parser/structs.rs index 3a42dfdf897..ea63b51059d 100644 --- a/compiler/noirc_frontend/src/parser/parser/structs.rs +++ b/compiler/noirc_frontend/src/parser/parser/structs.rs @@ -9,12 +9,12 @@ use crate::{ function, parse_type, primitives::{ident, keyword}, }, - NoirParser, TopLevelStatement, + NoirParser, TopLevelStatementKind, }, token::{Keyword, Token}, }; -pub(super) fn struct_definition() -> impl NoirParser { +pub(super) fn struct_definition() -> impl NoirParser { use self::Keyword::Struct; use Token::*; @@ -36,7 +36,7 @@ pub(super) fn struct_definition() -> impl NoirParser { .then(fields) .validate(|((((doc_comments, attributes), name), generics), fields), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); - TopLevelStatement::Struct(NoirStruct { + TopLevelStatementKind::Struct(NoirStruct { name, attributes, generics, diff --git a/compiler/noirc_frontend/src/parser/parser/traits.rs b/compiler/noirc_frontend/src/parser/parser/traits.rs index bc9a4a19773..a821705144b 100644 --- a/compiler/noirc_frontend/src/parser/parser/traits.rs +++ b/compiler/noirc_frontend/src/parser/parser/traits.rs @@ -16,14 +16,14 @@ use crate::macros_api::Pattern; use crate::{ parser::{ ignore_then_commit, parenthesized, parser::primitives::keyword, NoirParser, ParserError, - ParserErrorReason, TopLevelStatement, + ParserErrorReason, TopLevelStatementKind, }, token::{Keyword, Token}, }; use super::{generic_type_args, parse_type, primitives::ident}; -pub(super) fn trait_definition() -> impl NoirParser { +pub(super) fn trait_definition() -> impl NoirParser { let trait_body_or_error = just(Token::LeftBrace) .ignore_then(trait_body()) .then_ignore(just(Token::RightBrace)) @@ -48,7 +48,7 @@ pub(super) fn trait_definition() -> impl NoirParser { .then(trait_body_or_error) .validate(|((((attributes, name), generics), where_clause), items), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); - TopLevelStatement::Trait(NoirTrait { + TopLevelStatementKind::Trait(NoirTrait { name, generics, where_clause, @@ -137,7 +137,7 @@ fn trait_type_declaration() -> impl NoirParser { /// and an optional `where` clause is also useable. /// /// trait_implementation: 'impl' generics ident generic_args for type '{' trait_implementation_body '}' -pub(super) fn trait_implementation() -> impl NoirParser { +pub(super) fn trait_implementation() -> impl NoirParser { let body_or_error = just(Token::LeftBrace) .ignore_then(trait_implementation_body()) @@ -167,7 +167,7 @@ pub(super) fn trait_implementation() -> impl NoirParser { .map(|args| { let (((other_args, object_type), where_clause), items) = args; let ((impl_generics, trait_name), trait_generics) = other_args; - TopLevelStatement::TraitImpl(NoirTraitImpl { + TopLevelStatementKind::TraitImpl(NoirTraitImpl { impl_generics, trait_name, trait_generics, @@ -306,7 +306,7 @@ mod test { assert_eq!(errors[0].message, "expected <, where or { after trait name"); let top_level_statement = top_level_statement.unwrap(); - let TopLevelStatement::Trait(trait_) = top_level_statement else { + let TopLevelStatementKind::Trait(trait_) = top_level_statement else { panic!("Expected to parse a trait"); }; @@ -323,7 +323,7 @@ mod test { assert_eq!(errors[0].message, "expected <, where or { after trait impl for type"); let top_level_statement = top_level_statement.unwrap(); - let TopLevelStatement::TraitImpl(trait_impl) = top_level_statement else { + let TopLevelStatementKind::TraitImpl(trait_impl) = top_level_statement else { panic!("Expected to parse a trait impl"); }; From 37703fedd8871ee11b6f7fd8d807327b23d66146 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 07:33:43 -0300 Subject: [PATCH 06/20] Parse doc comments for top level items --- aztec_macros/src/lib.rs | 10 ++- ...te_note_hash_and_optionally_a_nullifier.rs | 2 +- .../src/transforms/contract_interface.rs | 9 +- aztec_macros/src/transforms/events.rs | 49 ++++++---- aztec_macros/src/transforms/functions.rs | 4 +- aztec_macros/src/transforms/note_interface.rs | 71 +++++++++------ aztec_macros/src/transforms/storage.rs | 11 ++- aztec_macros/src/utils/ast_utils.rs | 2 +- aztec_macros/src/utils/parse_utils.rs | 18 ++-- compiler/noirc_frontend/src/ast/docs.rs | 23 +++++ compiler/noirc_frontend/src/ast/expression.rs | 4 - compiler/noirc_frontend/src/ast/mod.rs | 2 + compiler/noirc_frontend/src/ast/statement.rs | 1 - compiler/noirc_frontend/src/ast/structure.rs | 1 - compiler/noirc_frontend/src/ast/traits.rs | 19 ++-- compiler/noirc_frontend/src/ast/visitor.rs | 18 ++-- .../noirc_frontend/src/elaborator/comptime.rs | 16 ++-- compiler/noirc_frontend/src/elaborator/mod.rs | 6 -- .../noirc_frontend/src/elaborator/traits.rs | 14 +-- .../noirc_frontend/src/hir/comptime/value.rs | 4 +- .../src/hir/def_collector/dc_mod.rs | 76 ++++++++++------ compiler/noirc_frontend/src/lib.rs | 2 +- compiler/noirc_frontend/src/parser/mod.rs | 64 ++++++------- compiler/noirc_frontend/src/parser/parser.rs | 89 +++++++++---------- .../src/parser/parser/function.rs | 10 +-- .../src/parser/parser/structs.rs | 15 +--- .../src/parser/parser/traits.rs | 46 ++++------ compiler/noirc_frontend/src/tests.rs | 2 +- tooling/lsp/src/requests/completion.rs | 4 +- tooling/lsp/src/requests/document_symbol.rs | 6 +- tooling/nargo_fmt/src/visitor/item.rs | 8 +- 31 files changed, 316 insertions(+), 290 deletions(-) create mode 100644 compiler/noirc_frontend/src/ast/docs.rs diff --git a/aztec_macros/src/lib.rs b/aztec_macros/src/lib.rs index ec1d395725d..4ba8951c2f9 100644 --- a/aztec_macros/src/lib.rs +++ b/aztec_macros/src/lib.rs @@ -66,7 +66,9 @@ fn transform( // 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) { + for submodule in + ast.submodules.iter_mut().map(|m| &mut m.item).filter(|submodule| submodule.is_contract) + { if transform_module( &file_id, &mut submodule.contents, @@ -111,7 +113,8 @@ fn transform_module( } let has_initializer = module.functions.iter().any(|func| { - func.def + func.item + .def .attributes .secondary .iter() @@ -121,6 +124,7 @@ fn transform_module( let mut stubs: Vec<_> = vec![]; for func in module.functions.iter_mut() { + let func = &mut func.item; let mut is_private = false; let mut is_public = false; let mut is_initializer = false; @@ -175,6 +179,7 @@ fn transform_module( let private_functions: Vec<_> = module .functions .iter() + .map(|t| &t.item) .filter(|func| { func.def .attributes @@ -187,6 +192,7 @@ fn transform_module( let public_functions: Vec<_> = module .functions .iter() + .map(|func| &func.item) .filter(|func| { func.def .attributes 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 8983266dab9..4d5dcc6f1af 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 @@ -166,7 +166,7 @@ fn generate_compute_note_hash_and_optionally_a_nullifier( assert_eq!(errors.len(), 0, "Failed to parse Noir macro code. This is either a bug in the compiler or the Noir macro code"); let mut function_ast = function_ast.into_sorted(); - function_ast.functions.remove(0) + function_ast.functions.remove(0).item } fn generate_compute_note_hash_and_optionally_a_nullifier_source( diff --git a/aztec_macros/src/transforms/contract_interface.rs b/aztec_macros/src/transforms/contract_interface.rs index 7a8a7187857..e2de30d6d93 100644 --- a/aztec_macros/src/transforms/contract_interface.rs +++ b/aztec_macros/src/transforms/contract_interface.rs @@ -1,7 +1,7 @@ use acvm::acir::AcirField; use noirc_errors::Location; -use noirc_frontend::ast::{Ident, NoirFunction, UnresolvedTypeData}; +use noirc_frontend::ast::{Documented, Ident, NoirFunction, UnresolvedTypeData}; use noirc_frontend::{ graph::CrateId, macros_api::{FieldElement, FileId, HirContext, HirExpression, HirLiteral, HirStatement}, @@ -267,15 +267,16 @@ pub fn generate_contract_interface( .methods .iter() .enumerate() - .map(|(i, (method, orig_span))| { + .map(|(i, (documented_method, orig_span))| { + let method = &documented_method.item; if method.name() == "at" || method.name() == "interface" || method.name() == "storage" { - (method.clone(), *orig_span) + (documented_method.clone(), *orig_span) } else { let (_, new_location) = stubs[i]; let mut modified_method = method.clone(); modified_method.def.name = Ident::new(modified_method.name().to_string(), new_location.span); - (modified_method, *orig_span) + (Documented::not_documented(modified_method), *orig_span) } }) .collect(); diff --git a/aztec_macros/src/transforms/events.rs b/aztec_macros/src/transforms/events.rs index ede8a350bf2..5ced863d454 100644 --- a/aztec_macros/src/transforms/events.rs +++ b/aztec_macros/src/transforms/events.rs @@ -1,4 +1,4 @@ -use noirc_frontend::ast::{ItemVisibility, NoirFunction, NoirTraitImpl, TraitImplItem}; +use noirc_frontend::ast::{Documented, ItemVisibility, NoirFunction, NoirTraitImpl, TraitImplItem}; use noirc_frontend::macros_api::{NodeInterner, StructId}; use noirc_frontend::token::SecondaryAttribute; use noirc_frontend::{ @@ -34,10 +34,11 @@ pub fn generate_event_impls( // print!("\ngenerate_event_interface_impl COUNT: {}\n", event_struct.name.0.contents); // } - for submodule in module.submodules.iter_mut() { - let annotated_event_structs = submodule.contents.types.iter_mut().filter(|typ| { - typ.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)")) - }); + for submodule in module.submodules.iter_mut().map(|m| &mut m.item) { + let annotated_event_structs = + submodule.contents.types.iter_mut().map(|typ| &mut typ.item).filter(|typ| { + typ.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)")) + }); for event_struct in annotated_event_structs { // event_struct.attributes.push(SecondaryAttribute::Abi("events".to_string())); @@ -64,18 +65,30 @@ pub fn generate_event_impls( 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, empty_spans)?, + event_interface_trait_impl.items.push(Documented::not_documented( + TraitImplItem::Function(generate_fn_get_event_type_id( + event_type.as_str(), + event_len, + empty_spans, + )?), + )); + event_interface_trait_impl.items.push(Documented::not_documented( + TraitImplItem::Function(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_private_to_be_bytes(event_type.as_str(), event_byte_len, empty_spans)?, + event_interface_trait_impl.items.push(Documented::not_documented( + TraitImplItem::Function(generate_fn_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, empty_spans)?, + event_interface_trait_impl.items.push(Documented::not_documented( + TraitImplItem::Function(generate_fn_emit(event_type.as_str(), empty_spans)?), )); - event_interface_trait_impl - .items - .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( @@ -245,7 +258,7 @@ fn generate_fn_get_event_type_id( } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -292,7 +305,7 @@ fn generate_fn_private_to_be_bytes( } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -337,7 +350,7 @@ fn generate_fn_to_be_bytes( } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) } @@ -361,7 +374,7 @@ fn generate_fn_emit(event_type: &str, empty_spans: bool) -> Result, + types: &mut Vec>, func: &NoirFunction, empty_spans: bool, ) -> Result<(), AztecMacroError> { diff --git a/aztec_macros/src/transforms/note_interface.rs b/aztec_macros/src/transforms/note_interface.rs index a2f553ed3c1..7639c9799ba 100644 --- a/aztec_macros/src/transforms/note_interface.rs +++ b/aztec_macros/src/transforms/note_interface.rs @@ -1,7 +1,7 @@ use noirc_errors::Span; use noirc_frontend::ast::{ - ItemVisibility, LetStatement, NoirFunction, NoirStruct, PathKind, TraitImplItem, TypeImpl, - UnresolvedTypeData, UnresolvedTypeExpression, + Documented, ItemVisibility, LetStatement, NoirFunction, NoirStruct, PathKind, TraitImplItem, + TypeImpl, UnresolvedTypeData, UnresolvedTypeExpression, }; use noirc_frontend::{ graph::CrateId, @@ -35,10 +35,10 @@ pub fn generate_note_interface_impl( empty_spans: bool, ) -> Result<(), AztecMacroError> { // Find structs annotated with #[aztec(note)] - let annotated_note_structs = module - .types - .iter_mut() - .filter(|typ| typ.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(note)"))); + let annotated_note_structs = + module.types.iter_mut().map(|t| &mut t.item).filter(|typ| { + typ.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(note)")) + }); let mut structs_to_inject = vec![]; @@ -138,7 +138,10 @@ pub fn generate_note_interface_impl( if !check_trait_method_implemented(trait_impl, "serialize_content") && !check_trait_method_implemented(trait_impl, "deserialize_content") - && !note_impl.methods.iter().any(|(func, _)| func.def.name.0.contents == "properties") + && !note_impl + .methods + .iter() + .any(|(func, _)| func.item.def.name.0.contents == "properties") { let note_serialize_content_fn = generate_note_serialize_content( ¬e_type, @@ -148,7 +151,9 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl.items.push(TraitImplItem::Function(note_serialize_content_fn)); + trait_impl.items.push(Documented::not_documented(TraitImplItem::Function( + note_serialize_content_fn, + ))); let note_deserialize_content_fn = generate_note_deserialize_content( ¬e_type, @@ -158,7 +163,9 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl.items.push(TraitImplItem::Function(note_deserialize_content_fn)); + trait_impl.items.push(Documented::not_documented(TraitImplItem::Function( + note_deserialize_content_fn, + ))); let note_properties_struct = generate_note_properties_struct( ¬e_type, @@ -167,7 +174,7 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - structs_to_inject.push(note_properties_struct); + structs_to_inject.push(Documented::not_documented(note_properties_struct)); let note_properties_fn = generate_note_properties_fn( ¬e_type, ¬e_fields, @@ -175,7 +182,9 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - note_impl.methods.push((note_properties_fn, note_impl.type_span)); + note_impl + .methods + .push((Documented::not_documented(note_properties_fn), note_impl.type_span)); } if !check_trait_method_implemented(trait_impl, "get_header") { @@ -185,7 +194,9 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl.items.push(TraitImplItem::Function(get_header_fn)); + trait_impl + .items + .push(Documented::not_documented(TraitImplItem::Function(get_header_fn))); } if !check_trait_method_implemented(trait_impl, "set_header") { let set_header_fn = generate_note_set_header( @@ -194,14 +205,18 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl.items.push(TraitImplItem::Function(set_header_fn)); + trait_impl + .items + .push(Documented::not_documented(TraitImplItem::Function(set_header_fn))); } 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, empty_spans)?; - trait_impl.items.push(TraitImplItem::Function(get_note_type_id_fn)); + trait_impl + .items + .push(Documented::not_documented(TraitImplItem::Function(get_note_type_id_fn))); } if !check_trait_method_implemented(trait_impl, "compute_note_hiding_point") { @@ -210,7 +225,9 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl.items.push(TraitImplItem::Function(compute_note_hiding_point_fn)); + trait_impl.items.push(Documented::not_documented(TraitImplItem::Function( + compute_note_hiding_point_fn, + ))); } if !check_trait_method_implemented(trait_impl, "to_be_bytes") { @@ -221,7 +238,9 @@ pub fn generate_note_interface_impl( note_interface_impl_span, empty_spans, )?; - trait_impl.items.push(TraitImplItem::Function(to_be_bytes_fn)); + trait_impl + .items + .push(Documented::not_documented(TraitImplItem::Function(to_be_bytes_fn))); } } @@ -275,7 +294,7 @@ fn generate_note_to_be_bytes( } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.span = impl_span; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) @@ -307,7 +326,7 @@ fn generate_note_get_header( } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.span = impl_span; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) @@ -338,7 +357,7 @@ fn generate_note_set_header( } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.span = impl_span; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) @@ -372,7 +391,7 @@ fn generate_get_note_type_id( } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.span = impl_span; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) @@ -407,7 +426,7 @@ fn generate_note_properties_struct( } let mut struct_ast = struct_ast.into_sorted(); - Ok(struct_ast.types.remove(0)) + Ok(struct_ast.types.remove(0).item) } // Generate the deserialize_content method as @@ -445,7 +464,7 @@ fn generate_note_deserialize_content( } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.span = impl_span; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) @@ -483,7 +502,7 @@ fn generate_note_serialize_content( } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.span = impl_span; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) @@ -508,7 +527,7 @@ fn generate_note_properties_fn( }); } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.span = impl_span; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) @@ -547,7 +566,7 @@ fn generate_compute_note_hiding_point( }); } let mut function_ast = function_ast.into_sorted(); - let mut noir_fn = function_ast.functions.remove(0); + let mut noir_fn = function_ast.functions.remove(0).item; noir_fn.def.span = impl_span; noir_fn.def.visibility = ItemVisibility::Public; Ok(noir_fn) @@ -579,7 +598,7 @@ fn generate_note_exports_global( } let mut global_ast = global_ast.into_sorted(); - Ok(global_ast.globals.pop().unwrap().0) + Ok(global_ast.globals.pop().unwrap().item) } // Source code generator functions. These utility methods produce Noir code as strings, that are then parsed and added to the AST. diff --git a/aztec_macros/src/transforms/storage.rs b/aztec_macros/src/transforms/storage.rs index ce5c4ded550..4a25c2d091e 100644 --- a/aztec_macros/src/transforms/storage.rs +++ b/aztec_macros/src/transforms/storage.rs @@ -1,8 +1,8 @@ use acvm::acir::AcirField; use noirc_errors::Span; use noirc_frontend::ast::{ - BlockExpression, Expression, ExpressionKind, FunctionDefinition, GenericTypeArgs, Ident, - Literal, NoirFunction, NoirStruct, Pattern, StatementKind, TypeImpl, UnresolvedType, + BlockExpression, Documented, Expression, ExpressionKind, FunctionDefinition, GenericTypeArgs, + Ident, Literal, NoirFunction, NoirStruct, Pattern, StatementKind, TypeImpl, UnresolvedType, UnresolvedTypeData, }; use noirc_frontend::{ @@ -38,6 +38,7 @@ pub fn check_for_storage_definition( let result: Vec<&NoirStruct> = module .types .iter() + .map(|t| &t.item) .filter(|r#struct| { r#struct.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(storage)")) }) @@ -88,6 +89,7 @@ pub fn inject_context_in_storage(module: &mut SortedModule) -> Result<(), AztecM let storage_struct = module .types .iter_mut() + .map(|t| &mut t.item) .find(|r#struct| { r#struct.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(storage)")) }) @@ -200,6 +202,7 @@ pub fn generate_storage_implementation( let definition = module .types .iter() + .map(|t| &t.item) .find(|r#struct| r#struct.name.0.contents == *storage_struct_name) .unwrap(); @@ -236,7 +239,6 @@ pub fn generate_storage_implementation( &BlockExpression { statements: vec![storage_constructor_statement] }, &[], &return_type(chained_path!("Self")), - Vec::new(), )); let ordered_args = vec![generic_context_type.clone()]; @@ -250,7 +252,7 @@ pub fn generate_storage_implementation( type_span: Span::default(), generics: vec![generic_context_ident.into()], - methods: vec![(init, Span::default())], + methods: vec![(Documented::not_documented(init), Span::default())], where_clause: vec![], }; @@ -510,6 +512,7 @@ pub fn generate_storage_layout( let definition = module .types .iter() + .map(|t| &t.item) .find(|r#struct| r#struct.name.0.contents == *storage_struct_name) .unwrap(); diff --git a/aztec_macros/src/utils/ast_utils.rs b/aztec_macros/src/utils/ast_utils.rs index 316aa60da62..b68946ec020 100644 --- a/aztec_macros/src/utils/ast_utils.rs +++ b/aztec_macros/src/utils/ast_utils.rs @@ -179,7 +179,7 @@ pub fn index_array(array: Ident, index: &str) -> Expression { } pub fn check_trait_method_implemented(trait_impl: &NoirTraitImpl, method_name: &str) -> bool { - trait_impl.items.iter().any(|item| match item { + trait_impl.items.iter().any(|item| match &item.item { TraitImplItem::Function(func) => func.def.name.0.contents == method_name, _ => false, }) diff --git a/aztec_macros/src/utils/parse_utils.rs b/aztec_macros/src/utils/parse_utils.rs index 39744cb04e0..5a94d7fd1f5 100644 --- a/aztec_macros/src/utils/parse_utils.rs +++ b/aztec_macros/src/utils/parse_utils.rs @@ -45,7 +45,7 @@ fn empty_item(item: &mut Item) { ItemKind::Impl(type_impl) => { empty_type_impl(type_impl); } - ItemKind::Global(let_statement, _) => empty_let_statement(let_statement), + ItemKind::Global(let_statement) => empty_let_statement(let_statement), ItemKind::Submodules(parsed_submodule) => { empty_parsed_submodule(parsed_submodule); } @@ -64,7 +64,7 @@ fn empty_noir_trait(noir_trait: &mut NoirTrait) { 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); + empty_trait_item(&mut item.item); } } @@ -74,7 +74,7 @@ fn empty_noir_trait_impl(noir_trait_impl: &mut NoirTraitImpl) { 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); + empty_trait_impl_item(&mut item.item); } } @@ -84,7 +84,7 @@ fn empty_type_impl(type_impl: &mut TypeImpl) { 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); + empty_noir_function(&mut noir_function.item); } } @@ -108,15 +108,7 @@ fn empty_noir_function(noir_function: &mut NoirFunction) { fn empty_trait_item(trait_item: &mut TraitItem) { match trait_item { - TraitItem::Function { - name, - generics, - parameters, - return_type, - where_clause, - body, - doc_comments: _, - } => { + TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => { empty_ident(name); empty_unresolved_generics(generics); for (name, typ) in parameters.iter_mut() { diff --git a/compiler/noirc_frontend/src/ast/docs.rs b/compiler/noirc_frontend/src/ast/docs.rs new file mode 100644 index 00000000000..f00f15c215d --- /dev/null +++ b/compiler/noirc_frontend/src/ast/docs.rs @@ -0,0 +1,23 @@ +use std::fmt::Display; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Documented { + pub item: T, + pub doc_comments: Vec, +} + +impl Documented { + pub fn new(item: T, doc_comments: Vec) -> Self { + Self { item, doc_comments } + } + + pub fn not_documented(item: T) -> Self { + Self { item, doc_comments: Vec::new() } + } +} + +impl Display for Documented { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.item) + } +} diff --git a/compiler/noirc_frontend/src/ast/expression.rs b/compiler/noirc_frontend/src/ast/expression.rs index ebc9fba76f4..f242180134d 100644 --- a/compiler/noirc_frontend/src/ast/expression.rs +++ b/compiler/noirc_frontend/src/ast/expression.rs @@ -479,8 +479,6 @@ pub struct FunctionDefinition { pub where_clause: Vec, pub return_type: FunctionReturnType, pub return_visibility: Visibility, - - pub doc_comments: Vec, } impl FunctionDefinition { @@ -790,7 +788,6 @@ impl FunctionDefinition { body: &BlockExpression, where_clause: &[UnresolvedTraitConstraint], return_type: &FunctionReturnType, - doc_comments: Vec, ) -> FunctionDefinition { let p = parameters .iter() @@ -815,7 +812,6 @@ impl FunctionDefinition { where_clause: where_clause.to_vec(), return_type: return_type.clone(), return_visibility: Visibility::Private, - doc_comments, } } diff --git a/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs index 1ed88115fa0..12a8aec05eb 100644 --- a/compiler/noirc_frontend/src/ast/mod.rs +++ b/compiler/noirc_frontend/src/ast/mod.rs @@ -4,6 +4,7 @@ //! //! Noir's Ast is produced by the parser and taken as input to name resolution, //! where it is converted into the Hir (defined in the hir_def module). +mod docs; mod expression; mod function; mod statement; @@ -18,6 +19,7 @@ pub use visitor::Visitor; pub use expression::*; pub use function::*; +pub use docs::*; use noirc_errors::Span; use serde::{Deserialize, Serialize}; pub use statement::*; diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs index 3bfa4ad9af6..30db8ad63fd 100644 --- a/compiler/noirc_frontend/src/ast/statement.rs +++ b/compiler/noirc_frontend/src/ast/statement.rs @@ -293,7 +293,6 @@ pub trait Recoverable { pub struct ModuleDeclaration { pub ident: Ident, pub outer_attributes: Vec, - pub outer_doc_comments: Vec, } impl std::fmt::Display for ModuleDeclaration { diff --git a/compiler/noirc_frontend/src/ast/structure.rs b/compiler/noirc_frontend/src/ast/structure.rs index 7f5dfe6225f..732cbee9232 100644 --- a/compiler/noirc_frontend/src/ast/structure.rs +++ b/compiler/noirc_frontend/src/ast/structure.rs @@ -13,7 +13,6 @@ pub struct NoirStruct { pub attributes: Vec, pub generics: UnresolvedGenerics, pub fields: Vec<(Ident, UnresolvedType)>, - pub doc_comments: Vec, pub span: Span, } diff --git a/compiler/noirc_frontend/src/ast/traits.rs b/compiler/noirc_frontend/src/ast/traits.rs index e588d2189eb..0463a5b8392 100644 --- a/compiler/noirc_frontend/src/ast/traits.rs +++ b/compiler/noirc_frontend/src/ast/traits.rs @@ -10,7 +10,7 @@ use crate::ast::{ use crate::macros_api::SecondaryAttribute; use crate::node_interner::TraitId; -use super::GenericTypeArgs; +use super::{Documented, GenericTypeArgs}; /// AST node for trait definitions: /// `trait name { ... items ... }` @@ -20,7 +20,7 @@ pub struct NoirTrait { pub generics: UnresolvedGenerics, pub where_clause: Vec, pub span: Span, - pub items: Vec, + pub items: Vec>, pub attributes: Vec, } @@ -35,7 +35,6 @@ pub enum TraitItem { return_type: FunctionReturnType, where_clause: Vec, body: Option, - doc_comments: Vec, }, Constant { name: Ident, @@ -55,7 +54,7 @@ pub struct TypeImpl { pub type_span: Span, pub generics: UnresolvedGenerics, pub where_clause: Vec, - pub methods: Vec<(NoirFunction, Span)>, + pub methods: Vec<(Documented, Span)>, } /// Ast node for an implementation of a trait for a particular type @@ -72,7 +71,7 @@ pub struct NoirTraitImpl { pub where_clause: Vec, - pub items: Vec, + pub items: Vec>, } /// Represents a simple trait constraint such as `where Foo: TraitY` @@ -141,15 +140,7 @@ impl Display for NoirTrait { impl Display for TraitItem { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - TraitItem::Function { - name, - generics, - parameters, - return_type, - where_clause, - body, - doc_comments: _, - } => { + TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => { let generics = vecmap(generics, |generic| generic.to_string()); let parameters = vecmap(parameters, |(name, typ)| format!("{name}: {typ}")); let where_clause = vecmap(where_clause, ToString::to_string); diff --git a/compiler/noirc_frontend/src/ast/visitor.rs b/compiler/noirc_frontend/src/ast/visitor.rs index 5b85893028b..6bcf0899efd 100644 --- a/compiler/noirc_frontend/src/ast/visitor.rs +++ b/compiler/noirc_frontend/src/ast/visitor.rs @@ -482,7 +482,7 @@ impl Item { noir_trait_impl.accept(self.span, visitor); } ItemKind::Impl(type_impl) => type_impl.accept(self.span, visitor), - ItemKind::Global(let_statement, _doc_comments) => { + ItemKind::Global(let_statement) => { if visitor.visit_global(let_statement, self.span) { let_statement.accept(visitor); } @@ -553,7 +553,7 @@ impl NoirTraitImpl { self.object_type.accept(visitor); for item in &self.items { - item.accept(visitor); + item.item.accept(visitor); } } } @@ -602,7 +602,7 @@ impl TypeImpl { self.object_type.accept(visitor); for (method, span) in &self.methods { - method.accept(*span, visitor); + method.item.accept(*span, visitor); } } } @@ -616,7 +616,7 @@ impl NoirTrait { pub fn accept_children(&self, visitor: &mut impl Visitor) { for item in &self.items { - item.accept(visitor); + item.item.accept(visitor); } } } @@ -630,15 +630,7 @@ impl TraitItem { pub fn accept_children(&self, visitor: &mut impl Visitor) { match self { - TraitItem::Function { - name, - generics, - parameters, - return_type, - where_clause, - body, - doc_comments: _, - } => { + TraitItem::Function { name, generics, parameters, return_type, where_clause, body } => { if visitor.visit_trait_item_function( name, generics, diff --git a/compiler/noirc_frontend/src/elaborator/comptime.rs b/compiler/noirc_frontend/src/elaborator/comptime.rs index feb9932ecc5..a956fa97644 100644 --- a/compiler/noirc_frontend/src/elaborator/comptime.rs +++ b/compiler/noirc_frontend/src/elaborator/comptime.rs @@ -24,7 +24,7 @@ use crate::{ Expression, ExpressionKind, HirExpression, NodeInterner, SecondaryAttribute, StructId, }, node_interner::{DefinitionKind, DependencyId, FuncId, TraitId}, - parser::{self, TopLevelStatementKind}, + parser::{self, TopLevelStatement, TopLevelStatementKind}, Type, TypeBindings, UnificationError, }; @@ -366,7 +366,7 @@ impl<'context> Elaborator<'context> { fn add_items( &mut self, - items: Vec, + items: Vec, generated_items: &mut CollectedItems, location: Location, ) { @@ -377,11 +377,11 @@ impl<'context> Elaborator<'context> { pub(crate) fn add_item( &mut self, - item: TopLevelStatementKind, + item: TopLevelStatement, generated_items: &mut CollectedItems, location: Location, ) { - match item { + match item.kind { TopLevelStatementKind::Function(function) => { let module_id = self.module_id(); @@ -391,6 +391,7 @@ impl<'context> Elaborator<'context> { &function, module_id, self.file, + item.doc_comments, &mut self.errors, ) { let functions = vec![(self.local_module, id, function)]; @@ -432,12 +433,12 @@ impl<'context> Elaborator<'context> { resolved_trait_generics: Vec::new(), }); } - TopLevelStatementKind::Global(global, doc_comments) => { + TopLevelStatementKind::Global(global) => { let (global, error) = dc_mod::collect_global( self.interner, self.def_maps.get_mut(&self.crate_id).unwrap(), global, - doc_comments, + item.doc_comments, self.file, self.local_module, self.crate_id, @@ -456,6 +457,7 @@ impl<'context> Elaborator<'context> { self.file, self.local_module, self.crate_id, + item.doc_comments, &mut self.errors, ) { generated_items.types.insert(type_id, the_struct); @@ -475,7 +477,7 @@ impl<'context> Elaborator<'context> { | TopLevelStatementKind::TypeAlias(_) | TopLevelStatementKind::SubModule(_) | TopLevelStatementKind::InnerAttribute(_) => { - let item = item.to_string(); + let item = item.kind.to_string(); let error = InterpreterError::UnsupportedTopLevelItemUnquote { item, location }; self.errors.push(error.into_compilation_error_pair()); } diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs index e8225d8b0b0..d321d04bef9 100644 --- a/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -792,12 +792,6 @@ impl<'context> Elaborator<'context> { None }; - if !func.def.doc_comments.is_empty() { - self.interner - .doc_comments - .insert(ModuleDefId::FunctionId(func_id), func.def.doc_comments.clone()); - } - let attributes = func.secondary_attributes().iter(); let attributes = attributes.filter_map(|secondary_attribute| secondary_attribute.as_custom()); diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs index d7dee63d490..4262f85b2fe 100644 --- a/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -11,7 +11,7 @@ use crate::{ hir_def::{function::Parameters, traits::TraitFunction}, macros_api::{ BlockExpression, FunctionDefinition, FunctionReturnType, Ident, ItemVisibility, - NodeInterner, NoirFunction, Param, Pattern, UnresolvedType, Visibility, + ModuleDefId, NodeInterner, NoirFunction, Param, Pattern, UnresolvedType, Visibility, }, node_interner::{FuncId, TraitId}, token::Attributes, @@ -74,8 +74,7 @@ impl<'context> Elaborator<'context> { return_type, where_clause, body: _, - doc_comments, - } = item + } = &item.item { self.recover_generics(|this| { let the_trait = this.interner.get_trait(trait_id); @@ -105,10 +104,15 @@ impl<'context> Elaborator<'context> { parameters, return_type, where_clause, - doc_comments.clone(), func_id, ); + if !item.doc_comments.is_empty() { + this.interner + .doc_comments + .insert(ModuleDefId::FunctionId(func_id), item.doc_comments.clone()); + } + let func_meta = this.interner.function_meta(&func_id); let arguments = vecmap(&func_meta.parameters.0, |(_, typ, _)| typ.clone()); @@ -159,7 +163,6 @@ impl<'context> Elaborator<'context> { parameters: &[(Ident, UnresolvedType)], return_type: &FunctionReturnType, where_clause: &[UnresolvedTraitConstraint], - doc_comments: Vec, func_id: FuncId, ) { let old_generic_count = self.generics.len(); @@ -185,7 +188,6 @@ impl<'context> Elaborator<'context> { where_clause: where_clause.to_vec(), return_type: return_type.clone(), return_visibility: Visibility::Private, - doc_comments, }; let mut function = NoirFunction { kind, def }; diff --git a/compiler/noirc_frontend/src/hir/comptime/value.rs b/compiler/noirc_frontend/src/hir/comptime/value.rs index 51145d1b8ff..04c557552bd 100644 --- a/compiler/noirc_frontend/src/hir/comptime/value.rs +++ b/compiler/noirc_frontend/src/hir/comptime/value.rs @@ -25,7 +25,7 @@ use crate::{ StructId, }, node_interner::{ExprId, FuncId, StmtId, TraitId, TraitImplId}, - parser::{self, NoirParser, TopLevelStatementKind}, + parser::{self, NoirParser, TopLevelStatement}, token::{SpannedToken, Token, Tokens}, QuotedType, Shared, Type, TypeBindings, }; @@ -506,7 +506,7 @@ impl Value { self, location: Location, interner: &NodeInterner, - ) -> IResult> { + ) -> IResult> { match self { Value::Quoted(tokens) => parse_tokens(tokens, parser::top_level_items(), location), _ => { diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index d76277e0edc..e2b590677c4 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -10,9 +10,9 @@ use num_traits::Num; use rustc_hash::FxHashMap as HashMap; use crate::ast::{ - FunctionDefinition, Ident, ItemVisibility, LetStatement, ModuleDeclaration, NoirFunction, - NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Pattern, TraitImplItem, TraitItem, - TypeImpl, + Documented, FunctionDefinition, Ident, ItemVisibility, LetStatement, ModuleDeclaration, + NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Pattern, TraitImplItem, + TraitItem, TypeImpl, }; use crate::hir::resolution::errors::ResolverError; use crate::macros_api::{ @@ -69,10 +69,11 @@ pub fn collect_defs( for decl in ast.module_decls { errors.extend(collector.parse_module_declaration( context, - decl, + decl.item, crate_id, file_id, module_id, + decl.doc_comments, macro_processors, )); } @@ -148,16 +149,16 @@ impl<'a> ModCollector<'a> { fn collect_globals( &mut self, context: &mut Context, - globals: Vec<(LetStatement, Vec)>, + globals: Vec>, crate_id: CrateId, ) -> Vec<(CompilationError, fm::FileId)> { let mut errors = vec![]; - for (global, doc_comments) in globals { + for global in globals { let (global, error) = collect_global( &mut context.def_interner, &mut self.def_collector.def_map, - global, - doc_comments, + global.item, + global.doc_comments, self.file_id, self.module_id, crate_id, @@ -238,7 +239,7 @@ impl<'a> ModCollector<'a> { fn collect_functions( &mut self, context: &mut Context, - functions: Vec, + functions: Vec>, krate: CrateId, ) -> Vec<(CompilationError, FileId)> { let mut unresolved_functions = UnresolvedFunctions { @@ -255,9 +256,10 @@ impl<'a> ModCollector<'a> { let Some(func_id) = collect_function( &mut context.def_interner, &mut self.def_collector.def_map, - &function, + &function.item, module, self.file_id, + function.doc_comments, &mut errors, ) else { continue; @@ -269,7 +271,7 @@ impl<'a> ModCollector<'a> { // and replace it // With this method we iterate each function in the Crate and not each module // This may not be great because we have to pull the module_data for each function - unresolved_functions.push_fn(self.module_id, func_id, function); + unresolved_functions.push_fn(self.module_id, func_id, function.item); } self.def_collector.items.functions.push(unresolved_functions); @@ -282,7 +284,7 @@ impl<'a> ModCollector<'a> { fn collect_structs( &mut self, context: &mut Context, - types: Vec, + types: Vec>, krate: CrateId, ) -> Vec<(CompilationError, FileId)> { let mut definition_errors = vec![]; @@ -290,10 +292,11 @@ impl<'a> ModCollector<'a> { if let Some((id, the_struct)) = collect_struct( &mut context.def_interner, &mut self.def_collector.def_map, - struct_definition, + struct_definition.item, self.file_id, self.module_id, krate, + struct_definition.doc_comments, &mut definition_errors, ) { self.def_collector.items.types.insert(id, the_struct); @@ -409,7 +412,7 @@ impl<'a> ModCollector<'a> { let mut associated_types = Generics::new(); for trait_item in &trait_definition.items { - match trait_item { + match &trait_item.item { TraitItem::Function { name, generics, @@ -417,7 +420,6 @@ impl<'a> ModCollector<'a> { return_type, where_clause, body, - doc_comments, } => { let func_id = context.def_interner.push_empty_fn(); method_ids.insert(name.to_string(), func_id); @@ -438,6 +440,13 @@ impl<'a> ModCollector<'a> { .def_interner .push_function_definition(func_id, modifiers, trait_id.0, location); + if !trait_item.doc_comments.is_empty() { + context.def_interner.doc_comments.insert( + ModuleDefId::FunctionId(func_id), + trait_item.doc_comments.clone(), + ); + } + match self.def_collector.def_map.modules[trait_id.0.local_id.0] .declare_function(name.clone(), ItemVisibility::Public, func_id) { @@ -451,7 +460,6 @@ impl<'a> ModCollector<'a> { body, where_clause, return_type, - doc_comments.clone(), )); unresolved_functions.push_fn( self.module_id, @@ -564,12 +572,15 @@ impl<'a> ModCollector<'a> { context: &mut Context, crate_id: CrateId, parent_module_id: LocalModuleId, - submodules: Vec, + submodules: Vec>, file_id: FileId, macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; for submodule in submodules { + let mut doc_comments = submodule.doc_comments; + let submodule = submodule.item; + match self.push_child_module( context, &submodule.name, @@ -589,10 +600,8 @@ impl<'a> ModCollector<'a> { false, ); - if !submodule.outer_doc_comments.is_empty() - || !submodule.contents.inner_doc_comments.is_empty() + if !doc_comments.is_empty() || !submodule.contents.inner_doc_comments.is_empty() { - let mut doc_comments = submodule.outer_doc_comments; doc_comments.extend(submodule.contents.inner_doc_comments.clone()); context @@ -629,6 +638,7 @@ impl<'a> ModCollector<'a> { crate_id: CrateId, parent_file_id: FileId, parent_module_id: LocalModuleId, + doc_comments: Vec, macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; @@ -708,11 +718,11 @@ impl<'a> ModCollector<'a> { // Track that the "foo" in `mod foo;` points to the module "foo" context.def_interner.add_module_reference(child_mod_id, location); - if !mod_decl.outer_doc_comments.is_empty() { + if !doc_comments.is_empty() { context .def_interner .doc_comments - .insert(ModuleDefId::ModuleId(child_mod_id), mod_decl.outer_doc_comments); + .insert(ModuleDefId::ModuleId(child_mod_id), doc_comments); } errors.extend(collect_defs( @@ -851,6 +861,7 @@ pub fn collect_function( function: &NoirFunction, module: ModuleId, file: FileId, + doc_comments: Vec, errors: &mut Vec<(CompilationError, FileId)>, ) -> Option { if let Some(field) = function.attributes().get_field_attribute() { @@ -882,6 +893,10 @@ pub fn collect_function( interner.usage_tracker.add_unused_item(module, name.clone(), item, visibility); } + if !doc_comments.is_empty() { + interner.doc_comments.insert(ModuleDefId::FunctionId(func_id), doc_comments); + } + // Add function to scope/ns of the module let result = def_map.modules[module.local_id.0].declare_function(name, visibility, func_id); if let Err((first_def, second_def)) = result { @@ -902,6 +917,7 @@ pub fn collect_struct( file_id: FileId, module_id: LocalModuleId, krate: CrateId, + doc_comments: Vec, definition_errors: &mut Vec<(CompilationError, FileId)>, ) -> Option<(StructId, UnresolvedStruct)> { check_duplicate_field_names(&struct_definition, file_id, definition_errors); @@ -939,10 +955,8 @@ pub fn collect_struct( } }; - if !unresolved.struct_def.doc_comments.is_empty() { - interner - .doc_comments - .insert(ModuleDefId::TypeId(id), unresolved.struct_def.doc_comments.clone()); + if !doc_comments.is_empty() { + interner.doc_comments.insert(ModuleDefId::TypeId(id), doc_comments.clone()); } // Add the struct to scope so its path can be looked up later @@ -975,12 +989,18 @@ pub fn collect_impl( let mut unresolved_functions = UnresolvedFunctions { file_id, functions: Vec::new(), trait_id: None, self_type: None }; - for (mut method, _) in r#impl.methods { + for (method, _) in r#impl.methods { + let doc_comments = method.doc_comments; + let mut method = method.item; let func_id = interner.push_empty_fn(); method.def.where_clause.extend(r#impl.where_clause.clone()); let location = Location::new(method.span(), file_id); interner.push_function(func_id, &method.def, module_id, location); unresolved_functions.push_fn(module_id.local_id, func_id, method); + + if !doc_comments.is_empty() { + interner.doc_comments.insert(ModuleDefId::FunctionId(func_id), doc_comments); + } } let key = (r#impl.object_type, module_id.local_id); @@ -1094,7 +1114,7 @@ pub(crate) fn collect_trait_impl_items( let module = ModuleId { krate, local_id }; for item in std::mem::take(&mut trait_impl.items) { - match item { + match item.item { TraitImplItem::Function(impl_method) => { let func_id = interner.push_empty_fn(); let location = Location::new(impl_method.span(), file_id); diff --git a/compiler/noirc_frontend/src/lib.rs b/compiler/noirc_frontend/src/lib.rs index ec09f680bc2..9f7a0564789 100644 --- a/compiler/noirc_frontend/src/lib.rs +++ b/compiler/noirc_frontend/src/lib.rs @@ -53,7 +53,7 @@ pub mod macros_api { pub use crate::token::SecondaryAttribute; pub use crate::ast::{ - BlockExpression, CallExpression, CastExpression, Expression, ExpressionKind, + BlockExpression, CallExpression, CastExpression, Documented, Expression, ExpressionKind, FunctionReturnType, Ident, IndexExpression, ItemVisibility, LetStatement, Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, Path, PathKind, Pattern, Statement, UnresolvedType, UnresolvedTypeData, Visibility, diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index 94d55011e50..e617fce17ad 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -12,9 +12,9 @@ mod labels; mod parser; use crate::ast::{ - Expression, Ident, ImportStatement, ItemVisibility, LetStatement, ModuleDeclaration, - NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Recoverable, StatementKind, - TypeImpl, UseTree, + Documented, Expression, Ident, ImportStatement, ItemVisibility, LetStatement, + ModuleDeclaration, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, + Recoverable, StatementKind, TypeImpl, UseTree, }; use crate::token::{Keyword, SecondaryAttribute, Token}; @@ -47,7 +47,7 @@ pub enum TopLevelStatementKind { Impl(TypeImpl), TypeAlias(NoirTypeAlias), SubModule(ParsedSubModule), - Global(LetStatement, Vec /* doc comments */), + Global(LetStatement), InnerAttribute(SecondaryAttribute), Error, } @@ -64,9 +64,7 @@ impl TopLevelStatementKind { TopLevelStatementKind::Impl(i) => Some(ItemKind::Impl(i)), TopLevelStatementKind::TypeAlias(t) => Some(ItemKind::TypeAlias(t)), TopLevelStatementKind::SubModule(s) => Some(ItemKind::Submodules(s)), - TopLevelStatementKind::Global(c, doc_comments) => { - Some(ItemKind::Global(c, doc_comments)) - } + TopLevelStatementKind::Global(c) => Some(ItemKind::Global(c)), TopLevelStatementKind::InnerAttribute(a) => Some(ItemKind::InnerAttribute(a)), TopLevelStatementKind::Error => None, } @@ -245,19 +243,19 @@ fn force<'a, T: 'a>(parser: impl NoirParser + 'a) -> impl NoirParser, - pub functions: Vec, - pub types: Vec, + pub functions: Vec>, + pub types: Vec>, pub traits: Vec, pub trait_impls: Vec, pub impls: Vec, pub type_aliases: Vec, - pub globals: Vec<(LetStatement, Vec /* doc comments */)>, + pub globals: Vec>, /// Module declarations like `mod foo;` - pub module_decls: Vec, + pub module_decls: Vec>, /// Full submodules as in `mod foo { ... definitions ... }` - pub submodules: Vec, + pub submodules: Vec>, pub inner_attributes: Vec, pub inner_doc_comments: Vec, @@ -273,7 +271,7 @@ impl std::fmt::Display for SortedModule { write!(f, "{import}")?; } - for (global_const, _) in &self.globals { + for global_const in &self.globals { write!(f, "{global_const}")?; } @@ -315,15 +313,19 @@ impl ParsedModule { for item in self.items { match item.kind { ItemKind::Import(import, visibility) => module.push_import(import, visibility), - ItemKind::Function(func) => module.push_function(func), - ItemKind::Struct(typ) => module.push_type(typ), + ItemKind::Function(func) => module.push_function(func, item.doc_comments), + ItemKind::Struct(typ) => module.push_type(typ, item.doc_comments), ItemKind::Trait(noir_trait) => module.push_trait(noir_trait), ItemKind::TraitImpl(trait_impl) => module.push_trait_impl(trait_impl), ItemKind::Impl(r#impl) => module.push_impl(r#impl), ItemKind::TypeAlias(type_alias) => module.push_type_alias(type_alias), - ItemKind::Global(global, doc_comments) => module.push_global(global, doc_comments), - ItemKind::ModuleDecl(mod_name) => module.push_module_decl(mod_name), - ItemKind::Submodules(submodule) => module.push_submodule(submodule.into_sorted()), + ItemKind::Global(global) => module.push_global(global, item.doc_comments), + ItemKind::ModuleDecl(mod_name) => { + module.push_module_decl(mod_name, item.doc_comments) + } + ItemKind::Submodules(submodule) => { + module.push_submodule(submodule.into_sorted(), item.doc_comments) + } ItemKind::InnerAttribute(attribute) => module.inner_attributes.push(attribute), } } @@ -338,6 +340,7 @@ impl ParsedModule { pub struct Item { pub kind: ItemKind, pub span: Span, + pub doc_comments: Vec, } #[derive(Clone, Debug)] @@ -349,7 +352,7 @@ pub enum ItemKind { TraitImpl(NoirTraitImpl), Impl(TypeImpl), TypeAlias(NoirTypeAlias), - Global(LetStatement, Vec /* doc comments */), + Global(LetStatement), ModuleDecl(ModuleDeclaration), Submodules(ParsedSubModule), InnerAttribute(SecondaryAttribute), @@ -362,7 +365,6 @@ pub struct ParsedSubModule { pub name: Ident, pub contents: ParsedModule, pub outer_attributes: Vec, - pub outer_doc_comments: Vec, pub is_contract: bool, } @@ -372,7 +374,6 @@ impl ParsedSubModule { name: self.name, contents: self.contents.into_sorted(), outer_attributes: self.outer_attributes, - outer_doc_comments: self.outer_doc_comments, is_contract: self.is_contract, } } @@ -395,17 +396,16 @@ pub struct SortedSubModule { pub name: Ident, pub contents: SortedModule, pub outer_attributes: Vec, - pub outer_doc_comments: Vec, pub is_contract: bool, } impl SortedModule { - fn push_function(&mut self, func: NoirFunction) { - self.functions.push(func); + fn push_function(&mut self, func: NoirFunction, doc_comments: Vec) { + self.functions.push(Documented::new(func, doc_comments)); } - fn push_type(&mut self, typ: NoirStruct) { - self.types.push(typ); + fn push_type(&mut self, typ: NoirStruct, doc_comments: Vec) { + self.types.push(Documented::new(typ, doc_comments)); } fn push_trait(&mut self, noir_trait: NoirTrait) { @@ -428,16 +428,16 @@ impl SortedModule { self.imports.extend(import_stmt.desugar(None, visibility)); } - fn push_module_decl(&mut self, mod_decl: ModuleDeclaration) { - self.module_decls.push(mod_decl); + fn push_module_decl(&mut self, mod_decl: ModuleDeclaration, doc_comments: Vec) { + self.module_decls.push(Documented::new(mod_decl, doc_comments)); } - fn push_submodule(&mut self, submodule: SortedSubModule) { - self.submodules.push(submodule); + fn push_submodule(&mut self, submodule: SortedSubModule, doc_comments: Vec) { + self.submodules.push(Documented::new(submodule, doc_comments)); } fn push_global(&mut self, global: LetStatement, doc_comments: Vec) { - self.globals.push((global, doc_comments)); + self.globals.push(Documented::new(global, doc_comments)); } } @@ -536,7 +536,7 @@ impl std::fmt::Display for TopLevelStatementKind { TopLevelStatementKind::Impl(i) => i.fmt(f), TopLevelStatementKind::TypeAlias(t) => t.fmt(f), TopLevelStatementKind::SubModule(s) => s.fmt(f), - TopLevelStatementKind::Global(c, _) => c.fmt(f), + TopLevelStatementKind::Global(c) => c.fmt(f), TopLevelStatementKind::InnerAttribute(a) => write!(f, "#![{}]", a), TopLevelStatementKind::Error => write!(f, "error"), } diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 339b411a040..70f8ba05437 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -38,12 +38,12 @@ use super::{ NoirParser, ParsedModule, ParsedSubModule, ParserError, ParserErrorReason, Precedence, TopLevelStatementKind, }; -use super::{spanned, Item}; +use super::{spanned, Item, TopLevelStatement}; use crate::ast::{ - BinaryOp, BinaryOpKind, BlockExpression, ForLoopStatement, ForRange, GenericTypeArgs, Ident, - IfExpression, InfixExpression, LValue, Literal, ModuleDeclaration, NoirTypeAlias, Param, Path, - Pattern, Recoverable, Statement, TypeImpl, UnaryRhsMemberAccess, UnaryRhsMethodCall, UseTree, - UseTreeKind, Visibility, + BinaryOp, BinaryOpKind, BlockExpression, Documented, ForLoopStatement, ForRange, + GenericTypeArgs, Ident, IfExpression, InfixExpression, LValue, Literal, ModuleDeclaration, + NoirTypeAlias, Param, Path, Pattern, Recoverable, Statement, TypeImpl, UnaryRhsMemberAccess, + UnaryRhsMethodCall, UseTree, UseTreeKind, Visibility, }; use crate::ast::{ Expression, ExpressionKind, LetStatement, StatementKind, UnresolvedType, UnresolvedTypeData, @@ -114,8 +114,12 @@ pub fn module() -> impl NoirParser { .to(ParsedModule::default()) .then(spanned(top_level_statement(module_parser)).repeated()) .foldl(|mut program, (statement, span)| { - if let Some(kind) = statement.into_item_kind() { - program.items.push(Item { kind, span }); + if let Some(kind) = statement.kind.into_item_kind() { + program.items.push(Item { + kind, + span, + doc_comments: statement.doc_comments, + }); } program }), @@ -128,10 +132,18 @@ pub fn module() -> impl NoirParser { } /// This parser is used for parsing top level statements in macros -pub fn top_level_items() -> impl NoirParser> { +pub fn top_level_items() -> impl NoirParser> { top_level_statement(module()).repeated() } +pub fn top_level_statement<'a>( + module_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { + outer_doc_comments() + .then(top_level_statement_kind(module_parser)) + .map(|(doc_comments, kind)| TopLevelStatement { kind, doc_comments }) +} + /// top_level_statement: function_definition /// | struct_definition /// | trait_definition @@ -140,7 +152,7 @@ pub fn top_level_items() -> impl NoirParser> { /// | module_declaration /// | use_statement /// | global_declaration -pub fn top_level_statement<'a>( +fn top_level_statement_kind<'a>( module_parser: impl NoirParser + 'a, ) -> impl NoirParser + 'a { choice(( @@ -164,8 +176,14 @@ pub fn top_level_statement<'a>( /// /// implementation: 'impl' generics type '{' function_definition ... '}' fn implementation() -> impl NoirParser { + let method = spanned(function::function_definition(true)); + let methods = outer_doc_comments() + .then(method) + .map(|(doc_comments, (method, span))| (Documented::new(method, doc_comments), span)) + .repeated(); + let methods_or_error = just(Token::LeftBrace) - .ignore_then(spanned(function::function_definition(true)).repeated()) + .ignore_then(methods) .then_ignore(just(Token::RightBrace)) .or_not() .validate(|methods, span, emit| { @@ -200,8 +218,7 @@ fn implementation() -> impl NoirParser { /// global_declaration: 'global' ident global_type_annotation '=' literal fn global_declaration() -> impl NoirParser { - let p = outer_doc_comments() - .then(attributes::attributes()) + let p = attributes::attributes() .then(maybe_comp_time()) .then(spanned(keyword(Keyword::Mut)).or_not()) .then_ignore(keyword(Keyword::Global).labelled(ParsingRuleLabel::Global)) @@ -211,12 +228,7 @@ fn global_declaration() -> impl NoirParser { let p = then_commit_ignore(p, just(Token::Assign)); let p = then_commit(p, expression()); p.validate( - |( - (((((doc_comments, attributes), comptime), mutable), mut pattern), r#type), - expression, - ), - span, - emit| { + |(((((attributes, comptime), mutable), mut pattern), r#type), expression), span, emit| { let global_attributes = attributes::validate_secondary_attributes(attributes, span, emit); @@ -226,39 +238,28 @@ fn global_declaration() -> impl NoirParser { let span = mut_span.merge(pattern.span()); pattern = Pattern::Mutable(Box::new(pattern), span, false); } - ( - LetStatement { - pattern, - r#type, - comptime, - expression, - attributes: global_attributes, - }, - doc_comments, - ) + LetStatement { pattern, r#type, comptime, expression, attributes: global_attributes } }, ) - .map(|(let_statement, doc_comments)| TopLevelStatementKind::Global(let_statement, doc_comments)) + .map(TopLevelStatementKind::Global) } /// submodule: 'mod' ident '{' module '}' fn submodule( module_parser: impl NoirParser, ) -> impl NoirParser { - outer_doc_comments() - .then(attributes()) + attributes() .then_ignore(keyword(Keyword::Mod)) .then(ident()) .then_ignore(just(Token::LeftBrace)) .then(module_parser) .then_ignore(just(Token::RightBrace)) - .validate(|(((doc_comments, attributes), name), contents), span, emit| { + .validate(|((attributes, name), contents), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); TopLevelStatementKind::SubModule(ParsedSubModule { name, contents, outer_attributes: attributes, - outer_doc_comments: doc_comments, is_contract: false, }) }) @@ -268,20 +269,18 @@ fn submodule( fn contract( module_parser: impl NoirParser, ) -> impl NoirParser { - outer_doc_comments() - .then(attributes()) + attributes() .then_ignore(keyword(Keyword::Contract)) .then(ident()) .then_ignore(just(Token::LeftBrace)) .then(module_parser) .then_ignore(just(Token::RightBrace)) - .validate(|(((doc_comments, attributes), name), contents), span, emit| { + .validate(|((attributes, name), contents), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); TopLevelStatementKind::SubModule(ParsedSubModule { name, contents, outer_attributes: attributes, - outer_doc_comments: doc_comments, is_contract: true, }) }) @@ -412,18 +411,12 @@ fn optional_type_annotation<'a>() -> impl NoirParser + 'a { } fn module_declaration() -> impl NoirParser { - outer_doc_comments() - .then(attributes()) - .then_ignore(keyword(Keyword::Mod)) - .then(ident()) - .validate(|((doc_comments, attributes), ident), span, emit| { + attributes().then_ignore(keyword(Keyword::Mod)).then(ident()).validate( + |(attributes, ident), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); - TopLevelStatementKind::Module(ModuleDeclaration { - ident, - outer_attributes: attributes, - outer_doc_comments: doc_comments, - }) - }) + TopLevelStatementKind::Module(ModuleDeclaration { ident, outer_attributes: attributes }) + }, + ) } fn use_statement() -> impl NoirParser { diff --git a/compiler/noirc_frontend/src/parser/parser/function.rs b/compiler/noirc_frontend/src/parser/parser/function.rs index 2b788636356..05138bfffd9 100644 --- a/compiler/noirc_frontend/src/parser/parser/function.rs +++ b/compiler/noirc_frontend/src/parser/parser/function.rs @@ -1,8 +1,6 @@ use super::{ attributes::{attributes, validate_attributes}, - block, - doc_comments::outer_doc_comments, - fresh_statement, ident, keyword, maybe_comp_time, nothing, parameter_name_recovery, + block, fresh_statement, ident, keyword, maybe_comp_time, nothing, parameter_name_recovery, parameter_recovery, parenthesized, parse_type, pattern, primitives::token_kind, self_parameter, @@ -45,8 +43,7 @@ pub(super) fn function_definition(allow_self: bool) -> impl NoirParser impl NoirParser impl NoirParser impl NoirParser { )) .or(just(Semicolon).to(Vec::new())); - outer_doc_comments() - .then(attributes()) + attributes() .then_ignore(keyword(Struct)) .then(ident()) .then(function::generics()) .then(fields) - .validate(|((((doc_comments, attributes), name), generics), fields), span, emit| { + .validate(|(((attributes, name), generics), fields), span, emit| { let attributes = validate_secondary_attributes(attributes, span, emit); - TopLevelStatementKind::Struct(NoirStruct { - name, - attributes, - generics, - fields, - doc_comments, - span, - }) + TopLevelStatementKind::Struct(NoirStruct { name, attributes, generics, fields, span }) }) } diff --git a/compiler/noirc_frontend/src/parser/parser/traits.rs b/compiler/noirc_frontend/src/parser/parser/traits.rs index a821705144b..cb17bf2caf7 100644 --- a/compiler/noirc_frontend/src/parser/parser/traits.rs +++ b/compiler/noirc_frontend/src/parser/parser/traits.rs @@ -9,8 +9,8 @@ use super::{ }; use crate::ast::{ - Expression, ItemVisibility, NoirTrait, NoirTraitImpl, TraitBound, TraitImplItem, TraitItem, - UnresolvedTraitConstraint, UnresolvedType, + Documented, Expression, ItemVisibility, NoirTrait, NoirTraitImpl, TraitBound, TraitImplItem, + TraitItem, UnresolvedTraitConstraint, UnresolvedType, }; use crate::macros_api::Pattern; use crate::{ @@ -59,10 +59,12 @@ pub(super) fn trait_definition() -> impl NoirParser { }) } -fn trait_body() -> impl NoirParser> { - trait_function_declaration() - .or(trait_type_declaration()) - .or(trait_constant_declaration()) +fn trait_body() -> impl NoirParser>> { + let item = + trait_function_declaration().or(trait_type_declaration()).or(trait_constant_declaration()); + outer_doc_comments() + .then(item) + .map(|(doc_comments, item)| Documented::new(item, doc_comments)) .repeated() } @@ -98,30 +100,16 @@ fn trait_function_declaration() -> impl NoirParser { } }); - outer_doc_comments() - .then_ignore(keyword(Keyword::Fn)) - .then(ident()) + keyword(Keyword::Fn) + .ignore_then(ident()) .then(function::generics()) .then(parenthesized(function_declaration_parameters())) .then(function_return_type().map(|(_, typ)| typ)) .then(where_clause()) .then(trait_function_body_or_semicolon_or_error) - .map( - |( - (((((doc_comments, name), generics), parameters), return_type), where_clause), - body, - )| { - TraitItem::Function { - name, - generics, - parameters, - return_type, - where_clause, - body, - doc_comments, - } - }, - ) + .map(|(((((name, generics), parameters), return_type), where_clause), body)| { + TraitItem::Function { name, generics, parameters, return_type, where_clause, body } + }) } /// trait_type_declaration: 'type' ident generics @@ -178,7 +166,7 @@ pub(super) fn trait_implementation() -> impl NoirParser { }) } -fn trait_implementation_body() -> impl NoirParser> { +fn trait_implementation_body() -> impl NoirParser>> { let function = function::function_definition(true).validate(|mut f, span, emit| { if f.def().is_unconstrained || f.def().visibility != ItemVisibility::Private { emit(ParserError::with_reason(ParserErrorReason::TraitImplFunctionModifiers, span)); @@ -205,7 +193,11 @@ fn trait_implementation_body() -> impl NoirParser> { }, ); - choice((function, alias, let_statement)).repeated() + let item = choice((function, alias, let_statement)); + outer_doc_comments() + .then(item) + .map(|(doc_comments, item)| Documented::new(item, doc_comments)) + .repeated() } pub(super) fn where_clause() -> impl NoirParser> { diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 3e01c370154..1a0f086b484 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -857,7 +857,7 @@ fn get_program_captures(src: &str) -> Vec> { let interner = context.def_interner; let mut all_captures: Vec> = Vec::new(); for func in program.into_sorted().functions { - let func_id = interner.find_function(func.name()).unwrap(); + let func_id = interner.find_function(func.item.name()).unwrap(); let hir_func = interner.function(&func_id); // Iterate over function statements and apply filtering function find_lambda_captures(hir_func.block(&interner).statements(), &interner, &mut all_captures); diff --git a/tooling/lsp/src/requests/completion.rs b/tooling/lsp/src/requests/completion.rs index dad0d37aba7..f5552604018 100644 --- a/tooling/lsp/src/requests/completion.rs +++ b/tooling/lsp/src/requests/completion.rs @@ -937,7 +937,7 @@ impl<'a> Visitor for NodeFinder<'a> { self.collect_type_parameters_in_generics(&noir_trait_impl.impl_generics); for item in &noir_trait_impl.items { - item.accept(self); + item.item.accept(self); } self.type_parameters.clear(); @@ -952,7 +952,7 @@ impl<'a> Visitor for NodeFinder<'a> { self.collect_type_parameters_in_generics(&type_impl.generics); for (method, span) in &type_impl.methods { - method.accept(*span, self); + method.item.accept(*span, self); // Optimization: stop looking in functions past the completion cursor if span.end() as usize > self.byte_index { diff --git a/tooling/lsp/src/requests/document_symbol.rs b/tooling/lsp/src/requests/document_symbol.rs index e06a3451681..a78cf8950a8 100644 --- a/tooling/lsp/src/requests/document_symbol.rs +++ b/tooling/lsp/src/requests/document_symbol.rs @@ -223,7 +223,7 @@ impl<'a> Visitor for DocumentSymbolCollector<'a> { self.symbols = Vec::new(); for item in &noir_trait.items { - item.accept(self); + item.item.accept(self); } let children = std::mem::take(&mut self.symbols); @@ -350,7 +350,7 @@ impl<'a> Visitor for DocumentSymbolCollector<'a> { self.symbols = Vec::new(); for trait_impl_item in &noir_trait_impl.items { - trait_impl_item.accept(self); + trait_impl_item.item.accept(self); } let children = std::mem::take(&mut self.symbols); @@ -405,7 +405,7 @@ impl<'a> Visitor for DocumentSymbolCollector<'a> { self.symbols = Vec::new(); for (noir_function, noir_function_span) in &type_impl.methods { - noir_function.accept(*noir_function_span, self); + noir_function.item.accept(*noir_function_span, self); } let children = std::mem::take(&mut self.symbols); diff --git a/tooling/nargo_fmt/src/visitor/item.rs b/tooling/nargo_fmt/src/visitor/item.rs index 2e3e532d5ab..ba9a8214702 100644 --- a/tooling/nargo_fmt/src/visitor/item.rs +++ b/tooling/nargo_fmt/src/visitor/item.rs @@ -151,7 +151,7 @@ impl super::FmtVisitor<'_> { } fn visit_module(&mut self, module: ParsedModule) { - for Item { kind, span } in module.items { + for Item { kind, span, doc_comments } in module.items { match kind { ItemKind::Function(func) => { self.visit_function(span, func); @@ -165,7 +165,7 @@ impl super::FmtVisitor<'_> { continue; } - for doc_comment in module.outer_doc_comments { + for doc_comment in doc_comments { self.push_str(&format!("///{doc_comment}\n")); self.push_str(&self.indent.to_string()); } @@ -219,7 +219,7 @@ impl super::FmtVisitor<'_> { self.indent.block_indent(self.config); for (method, span) in impl_.methods { - self.visit_function(span, method); + self.visit_function(span, method.item); } self.close_block((self.last_position..span.end() - 1).into()); @@ -236,7 +236,7 @@ impl super::FmtVisitor<'_> { | ItemKind::Trait(_) | ItemKind::TraitImpl(_) | ItemKind::TypeAlias(_) - | ItemKind::Global(_, _) + | ItemKind::Global(_) | ItemKind::ModuleDecl(_) | ItemKind::InnerAttribute(_) => { self.push_rewrite(self.slice(span).to_string(), span); From b6aefe3ba1db0118d21eaee765b8328d1d04fb8f Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 07:50:25 -0300 Subject: [PATCH 07/20] Doc comments for traits --- .../noirc_frontend/src/hir/def_collector/dc_mod.rs | 11 ++++++++++- compiler/noirc_frontend/src/parser/mod.rs | 8 ++++---- .../lsp/src/requests/completion/completion_items.rs | 10 ++++++---- tooling/lsp/src/requests/hover.rs | 3 +++ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index e2b590677c4..5276850d1b0 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -363,11 +363,13 @@ impl<'a> ModCollector<'a> { fn collect_traits( &mut self, context: &mut Context, - traits: Vec, + traits: Vec>, krate: CrateId, ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; for trait_definition in traits { + let doc_comments = trait_definition.doc_comments; + let trait_definition = trait_definition.item; let name = trait_definition.name.clone(); // Create the corresponding module for the trait namespace @@ -387,6 +389,13 @@ impl<'a> ModCollector<'a> { } }; + if !doc_comments.is_empty() { + context + .def_interner + .doc_comments + .insert(ModuleDefId::TraitId(trait_id), doc_comments); + } + // Add the trait to scope so its path can be looked up later let result = self.def_collector.def_map.modules[self.module_id.0] .declare_trait(name.clone(), trait_id); diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index e617fce17ad..47e8f660c25 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -245,7 +245,7 @@ pub struct SortedModule { pub imports: Vec, pub functions: Vec>, pub types: Vec>, - pub traits: Vec, + pub traits: Vec>, pub trait_impls: Vec, pub impls: Vec, pub type_aliases: Vec, @@ -315,7 +315,7 @@ impl ParsedModule { ItemKind::Import(import, visibility) => module.push_import(import, visibility), ItemKind::Function(func) => module.push_function(func, item.doc_comments), ItemKind::Struct(typ) => module.push_type(typ, item.doc_comments), - ItemKind::Trait(noir_trait) => module.push_trait(noir_trait), + ItemKind::Trait(noir_trait) => module.push_trait(noir_trait, item.doc_comments), ItemKind::TraitImpl(trait_impl) => module.push_trait_impl(trait_impl), ItemKind::Impl(r#impl) => module.push_impl(r#impl), ItemKind::TypeAlias(type_alias) => module.push_type_alias(type_alias), @@ -408,8 +408,8 @@ impl SortedModule { self.types.push(Documented::new(typ, doc_comments)); } - fn push_trait(&mut self, noir_trait: NoirTrait) { - self.traits.push(noir_trait); + fn push_trait(&mut self, noir_trait: NoirTrait, doc_comments: Vec) { + self.traits.push(Documented::new(noir_trait, doc_comments)); } fn push_trait_impl(&mut self, trait_impl: NoirTraitImpl) { diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs index bec380e7aa7..3bc48c3feb5 100644 --- a/tooling/lsp/src/requests/completion/completion_items.rs +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -7,7 +7,7 @@ use noirc_frontend::{ hir::def_map::ModuleId, hir_def::{function::FuncMeta, stmt::HirPattern}, macros_api::{ModuleDefId, StructId}, - node_interner::{FuncId, GlobalId}, + node_interner::{FuncId, GlobalId, TraitId}, QuotedType, Type, }; @@ -67,7 +67,7 @@ impl<'a> NodeFinder<'a> { ), ModuleDefId::TypeId(struct_id) => Some(self.struct_completion_item(name, struct_id)), ModuleDefId::TypeAliasId(..) => Some(self.type_alias_completion_item(name)), - ModuleDefId::TraitId(..) => Some(self.trait_completion_item(name)), + ModuleDefId::TraitId(trait_id) => Some(self.trait_completion_item(name, trait_id)), ModuleDefId::GlobalId(global_id) => Some(self.global_completion_item(name, global_id)), } } @@ -91,8 +91,10 @@ impl<'a> NodeFinder<'a> { simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)) } - fn trait_completion_item(&self, name: String) -> CompletionItem { - simple_completion_item(name.clone(), CompletionItemKind::INTERFACE, Some(name)) + fn trait_completion_item(&self, name: String, trait_id: TraitId) -> CompletionItem { + let completion_item = + simple_completion_item(name.clone(), CompletionItemKind::INTERFACE, Some(name)); + self.completion_item_with_doc_comments(ModuleDefId::TraitId(trait_id), completion_item) } fn global_completion_item(&self, name: String, global_id: GlobalId) -> CompletionItem { diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index 352bee37e98..b28cc4edda4 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -151,6 +151,9 @@ fn format_trait(id: TraitId, args: &ProcessRequestCallbackArgs) -> String { string.push_str("trait "); string.push_str(&a_trait.name.0.contents); format_generics(&a_trait.generics, &mut string); + + append_doc_comments(args.interner, ModuleDefId::TraitId(id), &mut string); + string } From 3d82628cc72b34524c2c11ccaab5a1b9707573a6 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 07:54:39 -0300 Subject: [PATCH 08/20] Doc comments for aliases --- .../noirc_frontend/src/hir/def_collector/dc_mod.rs | 11 ++++++++++- compiler/noirc_frontend/src/parser/mod.rs | 10 ++++++---- .../lsp/src/requests/completion/completion_items.rs | 10 ++++++---- tooling/lsp/src/requests/hover.rs | 3 +++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 5276850d1b0..d4f28d0031d 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -310,11 +310,13 @@ impl<'a> ModCollector<'a> { fn collect_type_aliases( &mut self, context: &mut Context, - type_aliases: Vec, + type_aliases: Vec>, krate: CrateId, ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; for type_alias in type_aliases { + let doc_comments = type_alias.doc_comments; + let type_alias = type_alias.item; let name = type_alias.name.clone(); // And store the TypeId -> TypeAlias mapping somewhere it is reachable @@ -334,6 +336,13 @@ impl<'a> ModCollector<'a> { let type_alias_id = context.def_interner.push_type_alias(&unresolved, resolved_generics); + if !doc_comments.is_empty() { + context + .def_interner + .doc_comments + .insert(ModuleDefId::TypeAliasId(type_alias_id), doc_comments); + } + // Add the type alias to scope so its path can be looked up later let result = self.def_collector.def_map.modules[self.module_id.0] .declare_type_alias(name.clone(), type_alias_id); diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index 47e8f660c25..74f73d538ba 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -248,7 +248,7 @@ pub struct SortedModule { pub traits: Vec>, pub trait_impls: Vec, pub impls: Vec, - pub type_aliases: Vec, + pub type_aliases: Vec>, pub globals: Vec>, /// Module declarations like `mod foo;` @@ -318,7 +318,9 @@ impl ParsedModule { ItemKind::Trait(noir_trait) => module.push_trait(noir_trait, item.doc_comments), ItemKind::TraitImpl(trait_impl) => module.push_trait_impl(trait_impl), ItemKind::Impl(r#impl) => module.push_impl(r#impl), - ItemKind::TypeAlias(type_alias) => module.push_type_alias(type_alias), + ItemKind::TypeAlias(type_alias) => { + module.push_type_alias(type_alias, item.doc_comments) + } ItemKind::Global(global) => module.push_global(global, item.doc_comments), ItemKind::ModuleDecl(mod_name) => { module.push_module_decl(mod_name, item.doc_comments) @@ -420,8 +422,8 @@ impl SortedModule { self.impls.push(r#impl); } - fn push_type_alias(&mut self, type_alias: NoirTypeAlias) { - self.type_aliases.push(type_alias); + fn push_type_alias(&mut self, type_alias: NoirTypeAlias, doc_comments: Vec) { + self.type_aliases.push(Documented::new(type_alias, doc_comments)); } fn push_import(&mut self, import_stmt: UseTree, visibility: ItemVisibility) { diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs index 3bc48c3feb5..8c90358a13b 100644 --- a/tooling/lsp/src/requests/completion/completion_items.rs +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -7,7 +7,7 @@ use noirc_frontend::{ hir::def_map::ModuleId, hir_def::{function::FuncMeta, stmt::HirPattern}, macros_api::{ModuleDefId, StructId}, - node_interner::{FuncId, GlobalId, TraitId}, + node_interner::{FuncId, GlobalId, TraitId, TypeAliasId}, QuotedType, Type, }; @@ -66,7 +66,7 @@ impl<'a> NodeFinder<'a> { false, // self_prefix ), ModuleDefId::TypeId(struct_id) => Some(self.struct_completion_item(name, struct_id)), - ModuleDefId::TypeAliasId(..) => Some(self.type_alias_completion_item(name)), + ModuleDefId::TypeAliasId(id) => Some(self.type_alias_completion_item(name, id)), ModuleDefId::TraitId(trait_id) => Some(self.trait_completion_item(name, trait_id)), ModuleDefId::GlobalId(global_id) => Some(self.global_completion_item(name, global_id)), } @@ -87,8 +87,10 @@ impl<'a> NodeFinder<'a> { self.completion_item_with_doc_comments(ModuleDefId::TypeId(struct_id), completion_item) } - fn type_alias_completion_item(&self, name: String) -> CompletionItem { - simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)) + fn type_alias_completion_item(&self, name: String, id: TypeAliasId) -> CompletionItem { + let completion_item = + simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)); + self.completion_item_with_doc_comments(ModuleDefId::TypeAliasId(id), completion_item) } fn trait_completion_item(&self, name: String, trait_id: TraitId) -> CompletionItem { diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index b28cc4edda4..f88139e3f7e 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -249,6 +249,9 @@ fn format_alias(id: TypeAliasId, args: &ProcessRequestCallbackArgs) -> String { string.push_str(&type_alias.name.0.contents); string.push_str(" = "); string.push_str(&format!("{}", &type_alias.typ)); + + append_doc_comments(args.interner, ModuleDefId::TypeAliasId(id), &mut string); + string } From b38422f4f04096292494086827430b6853878909 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 08:01:27 -0300 Subject: [PATCH 09/20] Use ReferenceId --- .../noirc_frontend/src/elaborator/traits.rs | 6 ++--- .../src/hir/def_collector/dc_mod.rs | 24 +++++++++---------- compiler/noirc_frontend/src/node_interner.rs | 4 ++-- .../requests/completion/completion_items.rs | 18 +++++++------- tooling/lsp/src/requests/hover.rs | 16 ++++++------- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs index 4262f85b2fe..1e00861904a 100644 --- a/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -11,9 +11,9 @@ use crate::{ hir_def::{function::Parameters, traits::TraitFunction}, macros_api::{ BlockExpression, FunctionDefinition, FunctionReturnType, Ident, ItemVisibility, - ModuleDefId, NodeInterner, NoirFunction, Param, Pattern, UnresolvedType, Visibility, + NodeInterner, NoirFunction, Param, Pattern, UnresolvedType, Visibility, }, - node_interner::{FuncId, TraitId}, + node_interner::{FuncId, ReferenceId, TraitId}, token::Attributes, Kind, ResolvedGeneric, Type, TypeBindings, TypeVariableKind, }; @@ -110,7 +110,7 @@ impl<'context> Elaborator<'context> { if !item.doc_comments.is_empty() { this.interner .doc_comments - .insert(ModuleDefId::FunctionId(func_id), item.doc_comments.clone()); + .insert(ReferenceId::Function(func_id), item.doc_comments.clone()); } let func_meta = this.interner.function_meta(&func_id); diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index d4f28d0031d..caefdb4acf7 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -15,10 +15,8 @@ use crate::ast::{ TraitItem, TypeImpl, }; use crate::hir::resolution::errors::ResolverError; -use crate::macros_api::{ - Expression, ModuleDefId, NodeInterner, StructId, UnresolvedType, UnresolvedTypeData, -}; -use crate::node_interner::ModuleAttributes; +use crate::macros_api::{Expression, NodeInterner, StructId, UnresolvedType, UnresolvedTypeData}; +use crate::node_interner::{ModuleAttributes, ReferenceId}; use crate::token::SecondaryAttribute; use crate::usage_tracker::UnusedItem; use crate::{ @@ -340,7 +338,7 @@ impl<'a> ModCollector<'a> { context .def_interner .doc_comments - .insert(ModuleDefId::TypeAliasId(type_alias_id), doc_comments); + .insert(ReferenceId::Alias(type_alias_id), doc_comments); } // Add the type alias to scope so its path can be looked up later @@ -402,7 +400,7 @@ impl<'a> ModCollector<'a> { context .def_interner .doc_comments - .insert(ModuleDefId::TraitId(trait_id), doc_comments); + .insert(ReferenceId::Trait(trait_id), doc_comments); } // Add the trait to scope so its path can be looked up later @@ -460,7 +458,7 @@ impl<'a> ModCollector<'a> { if !trait_item.doc_comments.is_empty() { context.def_interner.doc_comments.insert( - ModuleDefId::FunctionId(func_id), + ReferenceId::Function(func_id), trait_item.doc_comments.clone(), ); } @@ -625,7 +623,7 @@ impl<'a> ModCollector<'a> { context .def_interner .doc_comments - .insert(ModuleDefId::ModuleId(child), doc_comments); + .insert(ReferenceId::Module(child), doc_comments); } errors.extend(collect_defs( @@ -740,7 +738,7 @@ impl<'a> ModCollector<'a> { context .def_interner .doc_comments - .insert(ModuleDefId::ModuleId(child_mod_id), doc_comments); + .insert(ReferenceId::Module(child_mod_id), doc_comments); } errors.extend(collect_defs( @@ -912,7 +910,7 @@ pub fn collect_function( } if !doc_comments.is_empty() { - interner.doc_comments.insert(ModuleDefId::FunctionId(func_id), doc_comments); + interner.doc_comments.insert(ReferenceId::Function(func_id), doc_comments); } // Add function to scope/ns of the module @@ -974,7 +972,7 @@ pub fn collect_struct( }; if !doc_comments.is_empty() { - interner.doc_comments.insert(ModuleDefId::TypeId(id), doc_comments.clone()); + interner.doc_comments.insert(ReferenceId::Struct(id), doc_comments.clone()); } // Add the struct to scope so its path can be looked up later @@ -1017,7 +1015,7 @@ pub fn collect_impl( unresolved_functions.push_fn(module_id.local_id, func_id, method); if !doc_comments.is_empty() { - interner.doc_comments.insert(ModuleDefId::FunctionId(func_id), doc_comments); + interner.doc_comments.insert(ReferenceId::Function(func_id), doc_comments); } } @@ -1182,7 +1180,7 @@ pub(crate) fn collect_global( }); if !doc_comments.is_empty() { - interner.doc_comments.insert(ModuleDefId::GlobalId(global_id), doc_comments); + interner.doc_comments.insert(ReferenceId::Global(global_id), doc_comments); } let global = UnresolvedGlobal { file_id, module_id, global_id, stmt_def: global }; diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index e0849ffe21e..0d5c10fd930 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -271,7 +271,7 @@ pub struct NodeInterner { pub(crate) usage_tracker: UsageTracker, /// Captures the documentation comments for each module, struct, trait, function, etc. - pub(crate) doc_comments: HashMap>, + pub(crate) doc_comments: HashMap>, } /// A dependency in the dependency graph may be a type or a definition. @@ -2201,7 +2201,7 @@ impl NodeInterner { bindings } - pub fn doc_comments(&self, id: ModuleDefId) -> Option<&Vec> { + pub fn doc_comments(&self, id: ReferenceId) -> Option<&Vec> { self.doc_comments.get(&id) } } diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs index 8c90358a13b..63f981617a8 100644 --- a/tooling/lsp/src/requests/completion/completion_items.rs +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -7,7 +7,7 @@ use noirc_frontend::{ hir::def_map::ModuleId, hir_def::{function::FuncMeta, stmt::HirPattern}, macros_api::{ModuleDefId, StructId}, - node_interner::{FuncId, GlobalId, TraitId, TypeAliasId}, + node_interner::{FuncId, GlobalId, ReferenceId, TraitId, TypeAliasId}, QuotedType, Type, }; @@ -78,25 +78,25 @@ impl<'a> NodeFinder<'a> { id: ModuleId, ) -> CompletionItem { let completion_item = module_completion_item(name); - self.completion_item_with_doc_comments(ModuleDefId::ModuleId(id), completion_item) + self.completion_item_with_doc_comments(ReferenceId::Module(id), completion_item) } fn struct_completion_item(&self, name: String, struct_id: StructId) -> CompletionItem { let completion_item = simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)); - self.completion_item_with_doc_comments(ModuleDefId::TypeId(struct_id), completion_item) + self.completion_item_with_doc_comments(ReferenceId::Struct(struct_id), completion_item) } fn type_alias_completion_item(&self, name: String, id: TypeAliasId) -> CompletionItem { let completion_item = simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)); - self.completion_item_with_doc_comments(ModuleDefId::TypeAliasId(id), completion_item) + self.completion_item_with_doc_comments(ReferenceId::Alias(id), completion_item) } fn trait_completion_item(&self, name: String, trait_id: TraitId) -> CompletionItem { let completion_item = simple_completion_item(name.clone(), CompletionItemKind::INTERFACE, Some(name)); - self.completion_item_with_doc_comments(ModuleDefId::TraitId(trait_id), completion_item) + self.completion_item_with_doc_comments(ReferenceId::Trait(trait_id), completion_item) } fn global_completion_item(&self, name: String, global_id: GlobalId) -> CompletionItem { @@ -106,7 +106,7 @@ impl<'a> NodeFinder<'a> { let completion_item = simple_completion_item(name, CompletionItemKind::CONSTANT, Some(description)); - self.completion_item_with_doc_comments(ModuleDefId::GlobalId(global_id), completion_item) + self.completion_item_with_doc_comments(ReferenceId::Global(global_id), completion_item) } pub(super) fn function_completion_item( @@ -229,8 +229,8 @@ impl<'a> NodeFinder<'a> { completion_item_with_trigger_parameter_hints_command(completion_item) } }; - let completion_item = self - .completion_item_with_doc_comments(ModuleDefId::FunctionId(func_id), completion_item); + let completion_item = + self.completion_item_with_doc_comments(ReferenceId::Function(func_id), completion_item); Some(completion_item) } @@ -281,7 +281,7 @@ impl<'a> NodeFinder<'a> { fn completion_item_with_doc_comments( &self, - id: ModuleDefId, + id: ReferenceId, completion_item: CompletionItem, ) -> CompletionItem { if let Some(doc_comments) = self.interner.doc_comments(id) { diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index f88139e3f7e..eead366098e 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -8,7 +8,7 @@ use noirc_frontend::{ graph::CrateId, hir::def_map::ModuleId, hir_def::{stmt::HirPattern, traits::Trait}, - macros_api::{ModuleDefId, NodeInterner, StructId}, + macros_api::{NodeInterner, StructId}, node_interner::{ DefinitionId, DefinitionKind, FuncId, GlobalId, ReferenceId, TraitId, TypeAliasId, }, @@ -85,7 +85,7 @@ fn format_module(id: ModuleId, args: &ProcessRequestCallbackArgs) -> Option String { } string.push_str(" }"); - append_doc_comments(args.interner, ModuleDefId::TypeId(id), &mut string); + append_doc_comments(args.interner, ReferenceId::Struct(id), &mut string); string } @@ -152,7 +152,7 @@ fn format_trait(id: TraitId, args: &ProcessRequestCallbackArgs) -> String { string.push_str(&a_trait.name.0.contents); format_generics(&a_trait.generics, &mut string); - append_doc_comments(args.interner, ModuleDefId::TraitId(id), &mut string); + append_doc_comments(args.interner, ReferenceId::Trait(id), &mut string); string } @@ -173,7 +173,7 @@ fn format_global(id: GlobalId, args: &ProcessRequestCallbackArgs) -> String { string.push_str(&format!("{}", typ)); string.push_str(&go_to_type_links(&typ, args.interner, args.files)); - append_doc_comments(args.interner, ModuleDefId::GlobalId(id), &mut string); + append_doc_comments(args.interner, ReferenceId::Global(id), &mut string); string } @@ -232,7 +232,7 @@ fn format_function(id: FuncId, args: &ProcessRequestCallbackArgs) -> String { string.push_str(&go_to_type_links(return_type, args.interner, args.files)); - append_doc_comments(args.interner, ModuleDefId::FunctionId(id), &mut string); + append_doc_comments(args.interner, ReferenceId::Function(id), &mut string); string } @@ -250,7 +250,7 @@ fn format_alias(id: TypeAliasId, args: &ProcessRequestCallbackArgs) -> String { string.push_str(" = "); string.push_str(&format!("{}", &type_alias.typ)); - append_doc_comments(args.interner, ModuleDefId::TypeAliasId(id), &mut string); + append_doc_comments(args.interner, ReferenceId::Alias(id), &mut string); string } @@ -531,7 +531,7 @@ fn format_link(name: String, location: lsp_types::Location) -> String { ) } -fn append_doc_comments(interner: &NodeInterner, id: ModuleDefId, string: &mut String) { +fn append_doc_comments(interner: &NodeInterner, id: ReferenceId, string: &mut String) { if let Some(doc_comments) = interner.doc_comments(id) { string.push_str("\n\n---\n\n"); for comment in doc_comments { From 114c5476e4c0b8faa69e72b9dd88353825396929 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 08:35:26 -0300 Subject: [PATCH 10/20] Doc comments for struct fields --- aztec_macros/src/transforms/events.rs | 4 ++- aztec_macros/src/transforms/note_interface.rs | 26 +++++++------- aztec_macros/src/transforms/storage.rs | 11 +++--- aztec_macros/src/utils/parse_utils.rs | 6 ++-- compiler/noirc_frontend/src/ast/structure.rs | 14 ++++++-- compiler/noirc_frontend/src/ast/visitor.rs | 4 +-- compiler/noirc_frontend/src/elaborator/mod.rs | 4 ++- .../src/hir/def_collector/dc_mod.rs | 12 ++++++- .../src/parser/parser/structs.rs | 16 +++++---- tooling/lsp/src/requests/completion.rs | 36 +++++++++++-------- .../requests/completion/completion_items.rs | 15 ++++++++ tooling/lsp/src/requests/document_symbol.rs | 4 ++- tooling/lsp/src/requests/hover.rs | 3 ++ 13 files changed, 106 insertions(+), 49 deletions(-) diff --git a/aztec_macros/src/transforms/events.rs b/aztec_macros/src/transforms/events.rs index 5ced863d454..d753bb43471 100644 --- a/aztec_macros/src/transforms/events.rs +++ b/aztec_macros/src/transforms/events.rs @@ -53,7 +53,9 @@ pub fn generate_event_impls( let mut event_fields = vec![]; - for (field_ident, field_type) in event_struct.fields.iter() { + for field in event_struct.fields.iter() { + let field_ident = &field.item.name; + let field_type = &field.item.typ; event_fields.push(( field_ident.0.contents.to_string(), field_type.typ.to_string().replace("plain::", ""), diff --git a/aztec_macros/src/transforms/note_interface.rs b/aztec_macros/src/transforms/note_interface.rs index 7639c9799ba..6e95efa637c 100644 --- a/aztec_macros/src/transforms/note_interface.rs +++ b/aztec_macros/src/transforms/note_interface.rs @@ -1,7 +1,7 @@ use noirc_errors::Span; use noirc_frontend::ast::{ - Documented, ItemVisibility, LetStatement, NoirFunction, NoirStruct, PathKind, TraitImplItem, - TypeImpl, UnresolvedTypeData, UnresolvedTypeExpression, + Documented, ItemVisibility, LetStatement, NoirFunction, NoirStruct, PathKind, StructField, + TraitImplItem, TypeImpl, UnresolvedTypeData, UnresolvedTypeExpression, }; use noirc_frontend::{ graph::CrateId, @@ -110,26 +110,28 @@ pub fn generate_note_interface_impl( ); // Automatically inject the header field if it's not present - let (header_field_name, _) = if let Some(existing_header) = - note_struct.fields.iter().find(|(_, field_type)| match &field_type.typ { + let header_field_name = if let Some(existing_header) = + note_struct.fields.iter().find(|field| match &field.item.typ.typ { UnresolvedTypeData::Named(path, _, _) => path.last_name() == "NoteHeader", _ => false, }) { - existing_header.clone() + existing_header.clone().item.name } else { - let generated_header = ( - ident("header"), - make_type(UnresolvedTypeData::Named( + let generated_header = StructField { + name: ident("header"), + typ: make_type(UnresolvedTypeData::Named( chained_dep!("aztec", "note", "note_header", "NoteHeader"), Default::default(), false, )), - ); - note_struct.fields.push(generated_header.clone()); - generated_header + }; + note_struct.fields.push(Documented::not_documented(generated_header.clone())); + generated_header.name }; - for (field_ident, field_type) in note_struct.fields.iter() { + for field in note_struct.fields.iter() { + let field_ident = &field.item.name; + let field_type = &field.item.typ; note_fields.push(( field_ident.0.contents.to_string(), field_type.typ.to_string().replace("plain::", ""), diff --git a/aztec_macros/src/transforms/storage.rs b/aztec_macros/src/transforms/storage.rs index 4a25c2d091e..a6bf2e14fb3 100644 --- a/aztec_macros/src/transforms/storage.rs +++ b/aztec_macros/src/transforms/storage.rs @@ -98,7 +98,7 @@ pub fn inject_context_in_storage(module: &mut SortedModule) -> Result<(), AztecM storage_struct .fields .iter_mut() - .map(|(_, field)| inject_context_in_storage_field(field)) + .map(|field| inject_context_in_storage_field(&mut field.item.typ)) .collect::, _>>()?; Ok(()) } @@ -215,8 +215,10 @@ pub fn generate_storage_implementation( .fields .iter() .flat_map(|field| { - generate_storage_field_constructor(field, slot_zero.clone()) - .map(|expression| (field.0.clone(), expression)) + let ident = &field.item.name; + let typ = &field.item.typ; + generate_storage_field_constructor(&(ident.clone(), typ.clone()), slot_zero.clone()) + .map(|expression| (field.item.name.clone(), expression)) }) .collect(); @@ -519,7 +521,8 @@ pub fn generate_storage_layout( let mut storable_fields = vec![]; let mut storable_fields_impl = vec![]; - definition.fields.iter().for_each(|(field_ident, _)| { + definition.fields.iter().for_each(|field| { + let field_ident = &field.item.name; storable_fields.push(format!("{}: dep::aztec::prelude::Storable", field_ident)); storable_fields_impl .push(format!("{}: dep::aztec::prelude::Storable {{ slot: 0 }}", field_ident,)); diff --git a/aztec_macros/src/utils/parse_utils.rs b/aztec_macros/src/utils/parse_utils.rs index 5a94d7fd1f5..018307bfb86 100644 --- a/aztec_macros/src/utils/parse_utils.rs +++ b/aztec_macros/src/utils/parse_utils.rs @@ -187,9 +187,9 @@ fn empty_use_tree(use_tree: &mut UseTree) { 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); + for field in noir_struct.fields.iter_mut() { + empty_ident(&mut field.item.name); + empty_unresolved_type(&mut field.item.typ); } empty_unresolved_generics(&mut noir_struct.generics); } diff --git a/compiler/noirc_frontend/src/ast/structure.rs b/compiler/noirc_frontend/src/ast/structure.rs index 732cbee9232..cd42abb29c7 100644 --- a/compiler/noirc_frontend/src/ast/structure.rs +++ b/compiler/noirc_frontend/src/ast/structure.rs @@ -6,16 +6,24 @@ use crate::token::SecondaryAttribute; use iter_extended::vecmap; use noirc_errors::Span; +use super::Documented; + /// Ast node for a struct #[derive(Clone, Debug, PartialEq, Eq)] pub struct NoirStruct { pub name: Ident, pub attributes: Vec, pub generics: UnresolvedGenerics, - pub fields: Vec<(Ident, UnresolvedType)>, + pub fields: Vec>, pub span: Span, } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct StructField { + pub name: Ident, + pub typ: UnresolvedType, +} + impl Display for NoirStruct { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let generics = vecmap(&self.generics, |generic| generic.to_string()); @@ -23,8 +31,8 @@ impl Display for NoirStruct { writeln!(f, "struct {}{} {{", self.name, generics)?; - for (name, typ) in self.fields.iter() { - writeln!(f, " {name}: {typ},")?; + for field in self.fields.iter() { + writeln!(f, " {}: {},", field.item.name, field.item.typ)?; } write!(f, "}}") diff --git a/compiler/noirc_frontend/src/ast/visitor.rs b/compiler/noirc_frontend/src/ast/visitor.rs index 6bcf0899efd..6f54ad2e3b9 100644 --- a/compiler/noirc_frontend/src/ast/visitor.rs +++ b/compiler/noirc_frontend/src/ast/visitor.rs @@ -701,8 +701,8 @@ impl NoirStruct { attribute.accept(AttributeTarget::Struct, visitor); } - for (_name, unresolved_type) in &self.fields { - unresolved_type.accept(visitor); + for field in &self.fields { + field.item.typ.accept(visitor); } } } diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs index d321d04bef9..dd8e985d3a2 100644 --- a/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -1248,7 +1248,9 @@ impl<'context> Elaborator<'context> { let struct_def = this.interner.get_struct(struct_id); this.add_existing_generics(&unresolved.generics, &struct_def.borrow().generics); - let fields = vecmap(&unresolved.fields, |(ident, typ)| { + let fields = vecmap(&unresolved.fields, |field| { + let ident = &field.item.name; + let typ = &field.item.typ; (ident.clone(), this.resolve_type(typ.clone())) }); diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index caefdb4acf7..ccf6cf65d44 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -975,6 +975,14 @@ pub fn collect_struct( interner.doc_comments.insert(ReferenceId::Struct(id), doc_comments.clone()); } + for (index, field) in unresolved.struct_def.fields.iter().enumerate() { + if !field.doc_comments.is_empty() { + interner + .doc_comments + .insert(ReferenceId::StructMember(id, index), field.doc_comments.clone()); + } + } + // Add the struct to scope so its path can be looked up later let result = def_map.modules[module_id.0].declare_struct(name.clone(), id); @@ -1193,7 +1201,9 @@ fn check_duplicate_field_names( definition_errors: &mut Vec<(CompilationError, FileId)>, ) { let mut seen_field_names = std::collections::HashSet::new(); - for (field_name, _) in &struct_definition.fields { + for field in &struct_definition.fields { + let field_name = &field.item.name; + if seen_field_names.insert(field_name) { continue; } diff --git a/compiler/noirc_frontend/src/parser/parser/structs.rs b/compiler/noirc_frontend/src/parser/parser/structs.rs index d0c363268ee..66d30a6f407 100644 --- a/compiler/noirc_frontend/src/parser/parser/structs.rs +++ b/compiler/noirc_frontend/src/parser/parser/structs.rs @@ -1,6 +1,6 @@ use chumsky::prelude::*; -use crate::ast::{Ident, NoirStruct, UnresolvedType}; +use crate::ast::{Documented, NoirStruct, StructField}; use crate::{ parser::{ parser::{ @@ -13,6 +13,8 @@ use crate::{ token::{Keyword, Token}, }; +use super::doc_comments::outer_doc_comments; + pub(super) fn struct_definition() -> impl NoirParser { use self::Keyword::Struct; use Token::*; @@ -38,12 +40,12 @@ pub(super) fn struct_definition() -> impl NoirParser { }) } -fn struct_fields() -> impl NoirParser> { - ident() - .then_ignore(just(Token::Colon)) - .then(parse_type()) - .separated_by(just(Token::Comma)) - .allow_trailing() +fn struct_fields() -> impl NoirParser>> { + let field = ident().then_ignore(just(Token::Colon)).then(parse_type()); + let field = outer_doc_comments().then(field).map(|(doc_comments, (name, typ))| { + Documented::new(StructField { name, typ }, doc_comments) + }); + field.separated_by(just(Token::Comma)).allow_trailing() } #[cfg(test)] diff --git a/tooling/lsp/src/requests/completion.rs b/tooling/lsp/src/requests/completion.rs index f5552604018..980e3d16f8d 100644 --- a/tooling/lsp/src/requests/completion.rs +++ b/tooling/lsp/src/requests/completion.rs @@ -6,7 +6,6 @@ use std::{ use async_lsp::ResponseError; use completion_items::{ crate_completion_item, field_completion_item, simple_completion_item, snippet_completion_item, - struct_field_completion_item, }; use convert_case::{Case, Casing}; use fm::{FileId, FileMap, PathString}; @@ -183,20 +182,23 @@ impl<'a> NodeFinder<'a> { let struct_type = struct_type.borrow(); // First get all of the struct's fields - let mut fields = HashMap::new(); - let fields_as_written = struct_type.get_fields_as_written(); - for (field, typ) in &fields_as_written { - fields.insert(field, typ); - } + let mut fields: Vec<_> = + struct_type.get_fields_as_written().into_iter().enumerate().collect(); // Remove the ones that already exists in the constructor - for (field, _) in &constructor_expression.fields { - fields.remove(&field.0.contents); + for (used_name, _) in &constructor_expression.fields { + fields.retain(|(_, (name, _))| name != &used_name.0.contents); } let self_prefix = false; - for (field, typ) in fields { - self.completion_items.push(struct_field_completion_item(field, typ, self_prefix)); + for (field_index, (field, typ)) in &fields { + self.completion_items.push(self.struct_field_completion_item( + field, + typ, + struct_type.id, + *field_index, + self_prefix, + )); } } @@ -652,9 +654,15 @@ impl<'a> NodeFinder<'a> { prefix: &str, self_prefix: bool, ) { - for (name, typ) in &struct_type.get_fields(generics) { + for (field_index, (name, typ)) in struct_type.get_fields(generics).iter().enumerate() { if name_matches(name, prefix) { - self.completion_items.push(struct_field_completion_item(name, typ, self_prefix)); + self.completion_items.push(self.struct_field_completion_item( + name, + typ, + struct_type.id, + field_index, + self_prefix, + )); } } } @@ -973,8 +981,8 @@ impl<'a> Visitor for NodeFinder<'a> { self.type_parameters.clear(); self.collect_type_parameters_in_generics(&noir_struct.generics); - for (_name, unresolved_type) in &noir_struct.fields { - unresolved_type.accept(self); + for field in &noir_struct.fields { + field.item.typ.accept(self); } self.type_parameters.clear(); diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs index 63f981617a8..a135969bbf8 100644 --- a/tooling/lsp/src/requests/completion/completion_items.rs +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -87,6 +87,21 @@ impl<'a> NodeFinder<'a> { self.completion_item_with_doc_comments(ReferenceId::Struct(struct_id), completion_item) } + pub(super) fn struct_field_completion_item( + &self, + field: &str, + typ: &Type, + struct_id: StructId, + field_index: usize, + self_type: bool, + ) -> CompletionItem { + let completion_item = struct_field_completion_item(field, typ, self_type); + self.completion_item_with_doc_comments( + ReferenceId::StructMember(struct_id, field_index), + completion_item, + ) + } + fn type_alias_completion_item(&self, name: String, id: TypeAliasId) -> CompletionItem { let completion_item = simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)); diff --git a/tooling/lsp/src/requests/document_symbol.rs b/tooling/lsp/src/requests/document_symbol.rs index a78cf8950a8..6f120496e58 100644 --- a/tooling/lsp/src/requests/document_symbol.rs +++ b/tooling/lsp/src/requests/document_symbol.rs @@ -171,7 +171,9 @@ impl<'a> Visitor for DocumentSymbolCollector<'a> { }; let mut children = Vec::new(); - for (field_name, typ) in &noir_struct.fields { + for field in &noir_struct.fields { + let field_name = &field.item.name; + let typ = &field.item.typ; let span = Span::from(field_name.span().start()..typ.span.end()); let Some(field_location) = self.to_lsp_location(span) else { diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index eead366098e..b697e837309 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -137,6 +137,9 @@ fn format_struct_member( string.push_str(": "); string.push_str(&format!("{}", field_type)); string.push_str(&go_to_type_links(field_type, args.interner, args.files)); + + append_doc_comments(args.interner, ReferenceId::StructMember(id, field_index), &mut string); + string } From 084420c6dcb5fbc0676b106b8d76350fea1cf92d Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 08:41:41 -0300 Subject: [PATCH 11/20] Clippy and refactors --- .../noirc_frontend/src/elaborator/comptime.rs | 7 ++--- .../src/hir/def_collector/dc_mod.rs | 29 +++++++++++-------- compiler/noirc_frontend/src/parser/mod.rs | 6 ++-- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/compiler/noirc_frontend/src/elaborator/comptime.rs b/compiler/noirc_frontend/src/elaborator/comptime.rs index a956fa97644..240c48fd260 100644 --- a/compiler/noirc_frontend/src/elaborator/comptime.rs +++ b/compiler/noirc_frontend/src/elaborator/comptime.rs @@ -6,6 +6,7 @@ use iter_extended::vecmap; use noirc_errors::{Location, Span}; use crate::{ + ast::Documented, hir::{ comptime::{Interpreter, InterpreterError, Value}, def_collector::{ @@ -437,8 +438,7 @@ impl<'context> Elaborator<'context> { let (global, error) = dc_mod::collect_global( self.interner, self.def_maps.get_mut(&self.crate_id).unwrap(), - global, - item.doc_comments, + Documented::new(global, item.doc_comments), self.file, self.local_module, self.crate_id, @@ -453,11 +453,10 @@ impl<'context> Elaborator<'context> { if let Some((type_id, the_struct)) = dc_mod::collect_struct( self.interner, self.def_maps.get_mut(&self.crate_id).unwrap(), - struct_def, + Documented::new(struct_def, item.doc_comments), self.file, self.local_module, self.crate_id, - item.doc_comments, &mut self.errors, ) { generated_items.types.insert(type_id, the_struct); diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index ccf6cf65d44..95bd3480a5c 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -1,3 +1,4 @@ +use core::str; use std::path::Path; use std::rc::Rc; use std::vec; @@ -67,11 +68,10 @@ pub fn collect_defs( for decl in ast.module_decls { errors.extend(collector.parse_module_declaration( context, - decl.item, + decl, crate_id, file_id, module_id, - decl.doc_comments, macro_processors, )); } @@ -155,8 +155,7 @@ impl<'a> ModCollector<'a> { let (global, error) = collect_global( &mut context.def_interner, &mut self.def_collector.def_map, - global.item, - global.doc_comments, + global, self.file_id, self.module_id, crate_id, @@ -290,11 +289,10 @@ impl<'a> ModCollector<'a> { if let Some((id, the_struct)) = collect_struct( &mut context.def_interner, &mut self.def_collector.def_map, - struct_definition.item, + struct_definition, self.file_id, self.module_id, krate, - struct_definition.doc_comments, &mut definition_errors, ) { self.def_collector.items.types.insert(id, the_struct); @@ -647,16 +645,19 @@ impl<'a> ModCollector<'a> { /// Search for a module named `mod_name` /// Parse it, add it as a child to the parent module in which it was declared /// and then collect all definitions of the child module + #[allow(clippy::too_many_arguments)] fn parse_module_declaration( &mut self, context: &mut Context, - mod_decl: ModuleDeclaration, + mod_decl: Documented, crate_id: CrateId, parent_file_id: FileId, parent_module_id: LocalModuleId, - doc_comments: Vec, macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { + let doc_comments = mod_decl.doc_comments; + let mod_decl = mod_decl.item; + let mut errors: Vec<(CompilationError, FileId)> = vec![]; let child_file_id = match find_module(&context.file_manager, self.file_id, &mod_decl.ident) { @@ -929,13 +930,15 @@ pub fn collect_function( pub fn collect_struct( interner: &mut NodeInterner, def_map: &mut CrateDefMap, - struct_definition: NoirStruct, + struct_definition: Documented, file_id: FileId, module_id: LocalModuleId, krate: CrateId, - doc_comments: Vec, definition_errors: &mut Vec<(CompilationError, FileId)>, ) -> Option<(StructId, UnresolvedStruct)> { + let doc_comments = struct_definition.doc_comments; + let struct_definition = struct_definition.item; + check_duplicate_field_names(&struct_definition, file_id, definition_errors); let name = struct_definition.name.clone(); @@ -1160,12 +1163,14 @@ pub(crate) fn collect_trait_impl_items( pub(crate) fn collect_global( interner: &mut NodeInterner, def_map: &mut CrateDefMap, - global: LetStatement, - doc_comments: Vec, + global: Documented, file_id: FileId, module_id: LocalModuleId, crate_id: CrateId, ) -> (UnresolvedGlobal, Option<(CompilationError, FileId)>) { + let doc_comments = global.doc_comments; + let global = global.item; + let name = global.pattern.name_ident().clone(); let global_id = interner.push_empty_global( diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index 74f73d538ba..968af82a8b3 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -319,14 +319,14 @@ impl ParsedModule { ItemKind::TraitImpl(trait_impl) => module.push_trait_impl(trait_impl), ItemKind::Impl(r#impl) => module.push_impl(r#impl), ItemKind::TypeAlias(type_alias) => { - module.push_type_alias(type_alias, item.doc_comments) + module.push_type_alias(type_alias, item.doc_comments); } ItemKind::Global(global) => module.push_global(global, item.doc_comments), ItemKind::ModuleDecl(mod_name) => { - module.push_module_decl(mod_name, item.doc_comments) + module.push_module_decl(mod_name, item.doc_comments); } ItemKind::Submodules(submodule) => { - module.push_submodule(submodule.into_sorted(), item.doc_comments) + module.push_submodule(submodule.into_sorted(), item.doc_comments); } ItemKind::InnerAttribute(attribute) => module.inner_attributes.push(attribute), } From 00eea7e5f99881e0cb89fda2f1b0f5166412bf67 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 09:42:34 -0300 Subject: [PATCH 12/20] Add `NodeInterner::set_doc_comments` --- .../noirc_frontend/src/elaborator/traits.rs | 5 +-- .../src/hir/def_collector/dc_mod.rs | 42 +++++-------------- compiler/noirc_frontend/src/node_interner.rs | 6 +++ tooling/lsp/src/requests/hover.rs | 2 + 4 files changed, 20 insertions(+), 35 deletions(-) diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs index 1e00861904a..d6bfd3aa647 100644 --- a/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -108,9 +108,8 @@ impl<'context> Elaborator<'context> { ); if !item.doc_comments.is_empty() { - this.interner - .doc_comments - .insert(ReferenceId::Function(func_id), item.doc_comments.clone()); + let id = ReferenceId::Function(func_id); + this.interner.set_doc_comments(id, item.doc_comments.clone()); } let func_meta = this.interner.function_meta(&func_id); diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 95bd3480a5c..87c1ebae661 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -332,12 +332,7 @@ impl<'a> ModCollector<'a> { let type_alias_id = context.def_interner.push_type_alias(&unresolved, resolved_generics); - if !doc_comments.is_empty() { - context - .def_interner - .doc_comments - .insert(ReferenceId::Alias(type_alias_id), doc_comments); - } + context.def_interner.set_doc_comments(ReferenceId::Alias(type_alias_id), doc_comments); // Add the type alias to scope so its path can be looked up later let result = self.def_collector.def_map.modules[self.module_id.0] @@ -394,12 +389,7 @@ impl<'a> ModCollector<'a> { } }; - if !doc_comments.is_empty() { - context - .def_interner - .doc_comments - .insert(ReferenceId::Trait(trait_id), doc_comments); - } + context.def_interner.set_doc_comments(ReferenceId::Trait(trait_id), doc_comments); // Add the trait to scope so its path can be looked up later let result = self.def_collector.def_map.modules[self.module_id.0] @@ -455,7 +445,7 @@ impl<'a> ModCollector<'a> { .push_function_definition(func_id, modifiers, trait_id.0, location); if !trait_item.doc_comments.is_empty() { - context.def_interner.doc_comments.insert( + context.def_interner.set_doc_comments( ReferenceId::Function(func_id), trait_item.doc_comments.clone(), ); @@ -620,8 +610,7 @@ impl<'a> ModCollector<'a> { context .def_interner - .doc_comments - .insert(ReferenceId::Module(child), doc_comments); + .set_doc_comments(ReferenceId::Module(child), doc_comments); } errors.extend(collect_defs( @@ -738,8 +727,7 @@ impl<'a> ModCollector<'a> { if !doc_comments.is_empty() { context .def_interner - .doc_comments - .insert(ReferenceId::Module(child_mod_id), doc_comments); + .set_doc_comments(ReferenceId::Module(child_mod_id), doc_comments); } errors.extend(collect_defs( @@ -910,9 +898,7 @@ pub fn collect_function( interner.usage_tracker.add_unused_item(module, name.clone(), item, visibility); } - if !doc_comments.is_empty() { - interner.doc_comments.insert(ReferenceId::Function(func_id), doc_comments); - } + interner.set_doc_comments(ReferenceId::Function(func_id), doc_comments); // Add function to scope/ns of the module let result = def_map.modules[module.local_id.0].declare_function(name, visibility, func_id); @@ -974,15 +960,12 @@ pub fn collect_struct( } }; - if !doc_comments.is_empty() { - interner.doc_comments.insert(ReferenceId::Struct(id), doc_comments.clone()); - } + interner.set_doc_comments(ReferenceId::Struct(id), doc_comments); for (index, field) in unresolved.struct_def.fields.iter().enumerate() { if !field.doc_comments.is_empty() { interner - .doc_comments - .insert(ReferenceId::StructMember(id, index), field.doc_comments.clone()); + .set_doc_comments(ReferenceId::StructMember(id, index), field.doc_comments.clone()); } } @@ -1024,10 +1007,7 @@ pub fn collect_impl( let location = Location::new(method.span(), file_id); interner.push_function(func_id, &method.def, module_id, location); unresolved_functions.push_fn(module_id.local_id, func_id, method); - - if !doc_comments.is_empty() { - interner.doc_comments.insert(ReferenceId::Function(func_id), doc_comments); - } + interner.set_doc_comments(ReferenceId::Function(func_id), doc_comments); } let key = (r#impl.object_type, module_id.local_id); @@ -1192,9 +1172,7 @@ pub(crate) fn collect_global( (err.into(), file_id) }); - if !doc_comments.is_empty() { - interner.doc_comments.insert(ReferenceId::Global(global_id), doc_comments); - } + interner.set_doc_comments(ReferenceId::Global(global_id), doc_comments); let global = UnresolvedGlobal { file_id, module_id, global_id, stmt_def: global }; (global, error) diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 0d5c10fd930..881c5e6251a 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -2201,6 +2201,12 @@ impl NodeInterner { bindings } + pub fn set_doc_comments(&mut self, id: ReferenceId, doc_comments: Vec) { + if !doc_comments.is_empty() { + self.doc_comments.insert(id, doc_comments); + } + } + pub fn doc_comments(&self, id: ReferenceId) -> Option<&Vec> { self.doc_comments.get(&id) } diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index b697e837309..de4a944edd5 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -235,6 +235,8 @@ fn format_function(id: FuncId, args: &ProcessRequestCallbackArgs) -> String { string.push_str(&go_to_type_links(return_type, args.interner, args.files)); + eprintln!("Function id: {:?}", id); + append_doc_comments(args.interner, ReferenceId::Function(id), &mut string); string From 8493aae8d7122d8fc630eafaea3dd8dc7bcca3c7 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 09:45:57 -0300 Subject: [PATCH 13/20] Make it work for trait impl methods --- compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 87c1ebae661..6012609586d 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -1126,6 +1126,7 @@ pub(crate) fn collect_trait_impl_items( let func_id = interner.push_empty_fn(); let location = Location::new(impl_method.span(), file_id); interner.push_function(func_id, &impl_method.def, module, location); + interner.set_doc_comments(ReferenceId::Function(func_id), item.doc_comments); unresolved_functions.push_fn(local_id, func_id, impl_method); } TraitImplItem::Constant(name, typ, expr) => { From fab1d66ef3b0eed10583908267d1a4677172069d Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 16:01:34 -0300 Subject: [PATCH 14/20] Collect inner doc comments from module in another file --- compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 6012609586d..b0000502ac2 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -644,7 +644,7 @@ impl<'a> ModCollector<'a> { parent_module_id: LocalModuleId, macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { - let doc_comments = mod_decl.doc_comments; + let mut doc_comments = mod_decl.doc_comments; let mod_decl = mod_decl.item; let mut errors: Vec<(CompilationError, FileId)> = vec![]; @@ -724,7 +724,9 @@ impl<'a> ModCollector<'a> { // Track that the "foo" in `mod foo;` points to the module "foo" context.def_interner.add_module_reference(child_mod_id, location); - if !doc_comments.is_empty() { + if !doc_comments.is_empty() || !ast.inner_doc_comments.is_empty() { + doc_comments.extend(ast.inner_doc_comments.clone()); + context .def_interner .set_doc_comments(ReferenceId::Module(child_mod_id), doc_comments); From a4dc6b965efa2743d2b1c0361f924ddc658d365d Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 16:01:46 -0300 Subject: [PATCH 15/20] Remove eprintln --- tooling/lsp/src/requests/hover.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index de4a944edd5..b697e837309 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -235,8 +235,6 @@ fn format_function(id: FuncId, args: &ProcessRequestCallbackArgs) -> String { string.push_str(&go_to_type_links(return_type, args.interner, args.files)); - eprintln!("Function id: {:?}", id); - append_doc_comments(args.interner, ReferenceId::Function(id), &mut string); string From 85e647526c920fdc5945826ee3370bd3fc2e2d0e Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 16:13:36 -0300 Subject: [PATCH 16/20] Make it work for the crate root module too --- .../src/hir/def_collector/dc_crate.rs | 5 ++ tooling/lsp/src/requests/completion.rs | 9 ++-- .../requests/completion/completion_items.rs | 15 +++--- tooling/lsp/src/requests/completion/tests.rs | 8 ++-- tooling/lsp/src/requests/hover.rs | 48 +++++++++++-------- 5 files changed, 49 insertions(+), 36 deletions(-) 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 7ee1840690a..6265d0e65f2 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -313,6 +313,11 @@ impl DefCollector { let crate_root = def_map.root; let mut def_collector = DefCollector::new(def_map); + let module_id = ModuleId { krate: crate_id, local_id: crate_root }; + context + .def_interner + .set_doc_comments(ReferenceId::Module(module_id), ast.inner_doc_comments.clone()); + // Collecting module declarations with ModCollector // and lowering the functions // i.e. Use a mod collector to collect the nodes at the root module diff --git a/tooling/lsp/src/requests/completion.rs b/tooling/lsp/src/requests/completion.rs index 980e3d16f8d..f861c8113df 100644 --- a/tooling/lsp/src/requests/completion.rs +++ b/tooling/lsp/src/requests/completion.rs @@ -4,9 +4,7 @@ use std::{ }; use async_lsp::ResponseError; -use completion_items::{ - crate_completion_item, field_completion_item, simple_completion_item, snippet_completion_item, -}; +use completion_items::{field_completion_item, simple_completion_item, snippet_completion_item}; use convert_case::{Case, Casing}; use fm::{FileId, FileMap, PathString}; use kinds::{FunctionCompletionKind, FunctionKind, RequestedItems}; @@ -754,7 +752,10 @@ impl<'a> NodeFinder<'a> { for dependency in self.dependencies { let dependency_name = dependency.as_name(); if name_matches(&dependency_name, prefix) { - self.completion_items.push(crate_completion_item(dependency_name)); + let root_id = self.def_maps[&dependency.crate_id].root(); + let module_id = ModuleId { krate: dependency.crate_id, local_id: root_id }; + self.completion_items + .push(self.crate_completion_item(dependency_name, module_id)); } } diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs index a135969bbf8..aa959b226b0 100644 --- a/tooling/lsp/src/requests/completion/completion_items.rs +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -72,6 +72,14 @@ impl<'a> NodeFinder<'a> { } } + pub(super) fn crate_completion_item( + &self, + name: impl Into, + id: ModuleId, + ) -> CompletionItem { + self.module_completion_item(name, id) + } + pub(super) fn module_completion_item( &self, name: impl Into, @@ -342,13 +350,6 @@ pub(super) fn module_completion_item(name: impl Into) -> CompletionItem ) } -pub(super) fn crate_completion_item(name: impl Into) -> CompletionItem { - completion_item_with_sort_text( - simple_completion_item(name, CompletionItemKind::MODULE, None), - crate_or_module_sort_text(), - ) -} - fn func_meta_type_to_string(func_meta: &FuncMeta, has_self_type: bool) -> String { let mut typ = &func_meta.typ; if let Type::Forall(_, typ_) = typ { diff --git a/tooling/lsp/src/requests/completion/tests.rs b/tooling/lsp/src/requests/completion/tests.rs index e6a732e9142..c449466fc5c 100644 --- a/tooling/lsp/src/requests/completion/tests.rs +++ b/tooling/lsp/src/requests/completion/tests.rs @@ -6,8 +6,8 @@ mod completion_tests { completion::{ completion_items::{ completion_item_with_sort_text, - completion_item_with_trigger_parameter_hints_command, crate_completion_item, - module_completion_item, simple_completion_item, snippet_completion_item, + completion_item_with_trigger_parameter_hints_command, module_completion_item, + simple_completion_item, snippet_completion_item, }, sort_text::{auto_import_sort_text, self_mismatch_sort_text}, }, @@ -208,7 +208,7 @@ mod completion_tests { let src = r#" use s>|< "#; - assert_completion(src, vec![crate_completion_item("std")]).await; + assert_completion(src, vec![module_completion_item("std")]).await; // "std" doesn't show up anymore because of the "crate::" prefix let src = r#" @@ -284,7 +284,7 @@ mod completion_tests { src, vec![ module_completion_item("something"), - crate_completion_item("std"), + module_completion_item("std"), simple_completion_item("super::", CompletionItemKind::KEYWORD, None), ], ) diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index b697e837309..0c056e6800a 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -60,30 +60,36 @@ fn format_reference(reference: ReferenceId, args: &ProcessRequestCallbackArgs) - fn format_module(id: ModuleId, args: &ProcessRequestCallbackArgs) -> Option { let crate_root = args.def_maps[&id.krate].root(); - if id.local_id == crate_root { - let dep = args.dependencies.iter().find(|dep| dep.crate_id == id.krate); - return dep.map(|dep| format!(" crate {}", dep.name)); - } - - // Note: it's not clear why `try_module_attributes` might return None here, but it happens. - // This is a workaround to avoid panicking in that case (which brings the LSP server down). - // Cases where this happens are related to generated code, so once that stops happening - // this won't be an issue anymore. - let module_attributes = args.interner.try_module_attributes(&id)?; - let mut string = String::new(); - if let Some(parent_local_id) = module_attributes.parent { - if format_parent_module_from_module_id( - &ModuleId { krate: id.krate, local_id: parent_local_id }, - args, - &mut string, - ) { - string.push('\n'); + + if id.local_id == crate_root { + let Some(dep) = args.dependencies.iter().find(|dep| dep.crate_id == id.krate) else { + return None; + }; + string.push_str(" crate "); + string.push_str(&dep.name.to_string()); + } else { + // Note: it's not clear why `try_module_attributes` might return None here, but it happens. + // This is a workaround to avoid panicking in that case (which brings the LSP server down). + // Cases where this happens are related to generated code, so once that stops happening + // this won't be an issue anymore. + let module_attributes = args.interner.try_module_attributes(&id)?; + + if let Some(parent_local_id) = module_attributes.parent { + if format_parent_module_from_module_id( + &ModuleId { krate: id.krate, local_id: parent_local_id }, + args, + &mut string, + ) { + string.push('\n'); + } } + string.push_str(" "); + string.push_str("mod "); + string.push_str(&module_attributes.name); } - string.push_str(" "); - string.push_str("mod "); - string.push_str(&module_attributes.name); + + eprintln!("Module ID: {:?}", id); append_doc_comments(args.interner, ReferenceId::Module(id), &mut string); From c34ad71b759d88505b04f277b32dc981b2c6b097 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sat, 7 Sep 2024 16:58:51 -0300 Subject: [PATCH 17/20] Remove some comments and eprintln --- compiler/noirc_frontend/src/lexer/lexer.rs | 15 --------------- compiler/noirc_frontend/src/parser/parser.rs | 3 --- tooling/lsp/src/requests/hover.rs | 2 -- 3 files changed, 20 deletions(-) diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index 9fccdd6a4c3..7fbbb4fccef 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -24,21 +24,6 @@ pub struct Lexer<'a> { pub type SpannedTokenResult = Result; -// pub(crate) fn from_spanned_token_result( -// token_result: &SpannedTokenResult, -// ) -> Result<(usize, BorrowedToken<'_>, usize), LexerErrorKind> { -// token_result -// .as_ref() -// .map(|spanned_token| { -// ( -// spanned_token.to_span().start() as usize, -// token_to_borrowed_token(spanned_token.into()), -// spanned_token.to_span().end() as usize, -// ) -// }) -// .map_err(Clone::clone) -// } - impl<'a> Lexer<'a> { /// Given a source file of noir code, return all the tokens in the file /// in order, along with any lexing errors that occurred. diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 70f8ba05437..317eb01f21e 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -70,9 +70,6 @@ pub(super) mod traits; mod types; mod visibility; -// synthesized by LALRPOP -// lalrpop_mod!(pub noir_parser); - #[cfg(test)] mod test_helpers; diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs index 0c056e6800a..20333e8b728 100644 --- a/tooling/lsp/src/requests/hover.rs +++ b/tooling/lsp/src/requests/hover.rs @@ -89,8 +89,6 @@ fn format_module(id: ModuleId, args: &ProcessRequestCallbackArgs) -> Option Date: Mon, 9 Sep 2024 09:59:34 -0300 Subject: [PATCH 18/20] Apply suggestions from code review Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index b0000502ac2..f86e2235b1e 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -604,7 +604,7 @@ impl<'a> ModCollector<'a> { false, ); - if !doc_comments.is_empty() || !submodule.contents.inner_doc_comments.is_empty() + if !(doc_comments.is_empty() && submodule.contents.inner_doc_comments.is_empty()) { doc_comments.extend(submodule.contents.inner_doc_comments.clone()); @@ -724,7 +724,7 @@ impl<'a> ModCollector<'a> { // Track that the "foo" in `mod foo;` points to the module "foo" context.def_interner.add_module_reference(child_mod_id, location); - if !doc_comments.is_empty() || !ast.inner_doc_comments.is_empty() { + if !(doc_comments.is_empty() && ast.inner_doc_comments.is_empty()) { doc_comments.extend(ast.inner_doc_comments.clone()); context From 4099f75d89ba74bfa97341e7115df6eedba742a5 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Mon, 9 Sep 2024 09:59:57 -0300 Subject: [PATCH 19/20] Remove lalrpop file --- .../noirc_frontend/src/noir_parser.lalrpop | 170 ------------------ 1 file changed, 170 deletions(-) delete mode 100644 compiler/noirc_frontend/src/noir_parser.lalrpop diff --git a/compiler/noirc_frontend/src/noir_parser.lalrpop b/compiler/noirc_frontend/src/noir_parser.lalrpop deleted file mode 100644 index 11c345f0af5..00000000000 --- a/compiler/noirc_frontend/src/noir_parser.lalrpop +++ /dev/null @@ -1,170 +0,0 @@ -use noirc_errors::Span; - -use crate::lexer::token::BorrowedToken; -use crate::lexer::token as noir_token; -use crate::lexer::errors::LexerErrorKind; -use crate::parser::TopLevelStatementKind; -use crate::ast::{Ident, Path, PathKind, PathSegment, UseTree, UseTreeKind}; - -use lalrpop_util::ErrorRecovery; - -grammar<'input, 'err>(input: &'input str, errors: &'err mut [ErrorRecovery, &'static str>]); - -extern { - type Location = usize; - - type Error = LexerErrorKind; - - // NOTE: each token needs a terminal defined - enum BorrowedToken<'input> { - string => BorrowedToken::Str(<&'input str>), - ident => BorrowedToken::Ident(<&'input str>), - - // symbols - "<" => BorrowedToken::Less, - "<=" => BorrowedToken::LessEqual, - ">" => BorrowedToken::Greater, - ">=" => BorrowedToken::GreaterEqual, - "==" => BorrowedToken::Equal, - "!=" => BorrowedToken::NotEqual, - "+" => BorrowedToken::Plus, - "-" => BorrowedToken::Minus, - "*" => BorrowedToken::Star, - "/" => BorrowedToken::Slash, - "%" => BorrowedToken::Percent, - "&" => BorrowedToken::Ampersand, - "^" => BorrowedToken::Caret, - "<<" => BorrowedToken::ShiftLeft, - ">>" => BorrowedToken::ShiftRight, - "." => BorrowedToken::Dot, - ".." => BorrowedToken::DoubleDot, - "(" => BorrowedToken::LeftParen, - ")" => BorrowedToken::RightParen, - "{" => BorrowedToken::LeftBrace, - "}" => BorrowedToken::RightBrace, - "[" => BorrowedToken::LeftBracket, - "]" => BorrowedToken::RightBracket, - "->" => BorrowedToken::Arrow, - "|" => BorrowedToken::Pipe, - "#" => BorrowedToken::Pound, - "," => BorrowedToken::Comma, - ":" => BorrowedToken::Colon, - "::" => BorrowedToken::DoubleColon, - ";" => BorrowedToken::Semicolon, - "!" => BorrowedToken::Bang, - "=" => BorrowedToken::Assign, - // keywords - "as" => BorrowedToken::Keyword(noir_token::Keyword::As), - "assert" => BorrowedToken::Keyword(noir_token::Keyword::Assert), - "assert_eq" => BorrowedToken::Keyword(noir_token::Keyword::AssertEq), - "bool" => BorrowedToken::Keyword(noir_token::Keyword::Bool), - "break" => BorrowedToken::Keyword(noir_token::Keyword::Break), - "call_data" => BorrowedToken::Keyword(noir_token::Keyword::CallData), - "char" => BorrowedToken::Keyword(noir_token::Keyword::Char), - "comptime" => BorrowedToken::Keyword(noir_token::Keyword::Comptime), - "constrain" => BorrowedToken::Keyword(noir_token::Keyword::Constrain), - "continue" => BorrowedToken::Keyword(noir_token::Keyword::Continue), - "contract" => BorrowedToken::Keyword(noir_token::Keyword::Contract), - "crate" => BorrowedToken::Keyword(noir_token::Keyword::Crate), - "dep" => BorrowedToken::Keyword(noir_token::Keyword::Dep), - "else" => BorrowedToken::Keyword(noir_token::Keyword::Else), - "Field" => BorrowedToken::Keyword(noir_token::Keyword::Field), - "fn" => BorrowedToken::Keyword(noir_token::Keyword::Fn), - "for" => BorrowedToken::Keyword(noir_token::Keyword::For), - "fmtstr" => BorrowedToken::Keyword(noir_token::Keyword::FormatString), - "global" => BorrowedToken::Keyword(noir_token::Keyword::Global), - "if" => BorrowedToken::Keyword(noir_token::Keyword::If), - "impl" => BorrowedToken::Keyword(noir_token::Keyword::Impl), - "in" => BorrowedToken::Keyword(noir_token::Keyword::In), - "let" => BorrowedToken::Keyword(noir_token::Keyword::Let), - "mod" => BorrowedToken::Keyword(noir_token::Keyword::Mod), - "mut" => BorrowedToken::Keyword(noir_token::Keyword::Mut), - "pub" => BorrowedToken::Keyword(noir_token::Keyword::Pub), - "return" => BorrowedToken::Keyword(noir_token::Keyword::Return), - "return_data" => BorrowedToken::Keyword(noir_token::Keyword::ReturnData), - "str" => BorrowedToken::Keyword(noir_token::Keyword::String), - "struct" => BorrowedToken::Keyword(noir_token::Keyword::Struct), - "trait" => BorrowedToken::Keyword(noir_token::Keyword::Trait), - "type" => BorrowedToken::Keyword(noir_token::Keyword::Type), - "unchecked" => BorrowedToken::Keyword(noir_token::Keyword::Unchecked), - "unconstrained" => BorrowedToken::Keyword(noir_token::Keyword::Unconstrained), - "use" => BorrowedToken::Keyword(noir_token::Keyword::Use), - "where" => BorrowedToken::Keyword(noir_token::Keyword::Where), - "while" => BorrowedToken::Keyword(noir_token::Keyword::While), - // bool - "true" => BorrowedToken::Bool(true), - "false" => BorrowedToken::Bool(false), - - r"[\t\r\n ]+" => BorrowedToken::Whitespace(_), - - EOF => BorrowedToken::EOF, - } -} - -pub(crate) TopLevelStatementKind: TopLevelStatementKind = { - "use" r"[\t\r\n ]+" ";" EOF => { - TopLevelStatementKind::Import(use_tree, crate::ast::ItemVisibility::Private) - } -} - -UseTree: UseTree = { - // path::to::ident as SomeAlias - => { - let ident = prefix.pop().ident; - let kind = UseTreeKind::Path(ident, alias); - UseTree { prefix, kind } - }, -} - -pub(crate) Path: Path = { - "crate" "::" => { - let kind = PathKind::Crate; - let span = Span::from(lo as u32..hi as u32); - Path { segments, kind, span } - }, - - "dep" "::" => { - let kind = PathKind::Plain; - let span = Span::from(lo as u32..hi as u32); - Path { segments, kind, span } - }, - - => { - segments.insert(0, id); - let kind = PathKind::Plain; - let span = Span::from(lo as u32..hi as u32); - Path { segments, kind, span } - }, -} - -PathSegments: Vec = { - )*> => { - segments - } -} - -PathSegment: PathSegment = { - => { - let token = noir_token::Token::Ident(i.to_string()); - let span = Span::from(lo as u32..hi as u32); - PathSegment::from(Ident::from_token(token, span)) - }, -} - -Alias: Ident = { - r"[\t\r\n ]+" "as" r"[\t\r\n ]+" => <>, -} - -Ident: Ident = { - => { - let token = noir_token::Token::Ident(i.to_string()); - let span = Span::from(lo as u32..hi as u32); - Ident::from_token(token, span) - }, -} - -Bool: BorrowedToken<'input> = { - "true" => BorrowedToken::Bool(true), - "false" => BorrowedToken::Bool(false), -}; - From 8636d574556707f046dca002da8131631c676f33 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Mon, 9 Sep 2024 10:07:06 -0300 Subject: [PATCH 20/20] cargo fmt --- compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index f86e2235b1e..d93b708c91d 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -604,7 +604,8 @@ impl<'a> ModCollector<'a> { false, ); - if !(doc_comments.is_empty() && submodule.contents.inner_doc_comments.is_empty()) + if !(doc_comments.is_empty() + && submodule.contents.inner_doc_comments.is_empty()) { doc_comments.extend(submodule.contents.inner_doc_comments.clone());