From 3171a15ed0261303624b74ac37f0304d92f99731 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Dec 2022 23:15:22 -0500 Subject: [PATCH] Parse header_docs --- crates/compiler/load_internal/src/docs.rs | 17 ++++++- crates/compiler/load_internal/src/file.rs | 16 +++++- crates/compiler/parse/src/ast.rs | 59 +++++++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) diff --git a/crates/compiler/load_internal/src/docs.rs b/crates/compiler/load_internal/src/docs.rs index 574011823a..e4ce7a910c 100644 --- a/crates/compiler/load_internal/src/docs.rs +++ b/crates/compiler/load_internal/src/docs.rs @@ -98,6 +98,7 @@ pub fn generate_module_docs( parsed_defs: &roc_parse::ast::Defs, exposed_module_ids: &[ModuleId], exposed_symbols: VecSet, + header_docs: &[&str], ) -> ModuleDocumentation { let entries = generate_entry_docs( home, @@ -105,6 +106,7 @@ pub fn generate_module_docs( module_ids, parsed_defs, exposed_module_ids, + header_docs, ); ModuleDocumentation { @@ -148,10 +150,23 @@ fn generate_entry_docs( module_ids: &ModuleIds, defs: &roc_parse::ast::Defs<'_>, exposed_module_ids: &[ModuleId], + header_docs: &[&str], ) -> Vec { use roc_parse::ast::Pattern; - let mut acc = Vec::with_capacity(defs.tags.len()); + let mut acc = Vec::with_capacity(defs.tags.len() + 1); + + if !header_docs.is_empty() { + let mut buf = String::with_capacity(128); + + for line in header_docs { + buf.push_str(line); + buf.push('\n'); + } + + acc.push(DetachedDoc(buf)); + } + let mut before_comments_or_new_lines: Option<&[CommentOrNewline]> = None; let mut scratchpad = Vec::new(); diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 00a0b2e1f6..3154a88e5a 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -683,6 +683,7 @@ struct ModuleHeader<'a> { exposed_imports: MutMap, parse_state: roc_parse::state::State<'a>, header_type: HeaderType<'a>, + header_docs: &'a [&'a str], symbols_from_requires: Vec<(Loc, Loc>)>, module_timing: ModuleTiming, } @@ -824,6 +825,7 @@ struct ParsedModule<'a> { parsed_defs: Defs<'a>, symbols_from_requires: Vec<(Loc, Loc>)>, header_type: HeaderType<'a>, + header_docs: &'a [&'a str], } type LocExpects = VecMap>; @@ -3623,6 +3625,7 @@ fn load_builtin_module_help<'a>( exposes: unspace(arena, header.exposes.item.items), generates_with: &[], }, + header_docs: header.docs(arena), }; (info, parse_state) @@ -3914,7 +3917,6 @@ fn parse_header<'a>( verify_interface_matches_file_path(header.name, &filename, &parse_state)?; let header_name_region = header.name.region; - let info = HeaderInfo { filename, is_root_module, @@ -3925,6 +3927,7 @@ fn parse_header<'a>( name: header.name.value, exposes: unspace(arena, header.exposes.item.items), }, + header_docs: header.docs(arena), }; let (module_id, module_name, header) = build_header( @@ -3978,6 +3981,7 @@ fn parse_header<'a>( generates: header.generates.item, generates_with: unspace(arena, header.generates_with.item.items), }, + header_docs: header.docs(arena), }; let (module_id, _, header) = build_header( @@ -4001,6 +4005,7 @@ fn parse_header<'a>( }, parse_state, )) => { + let header_docs = header.docs(arena); let mut app_file_dir = filename.clone(); app_file_dir.pop(); @@ -4038,6 +4043,7 @@ fn parse_header<'a>( output_name: header.name.value, to_platform: header.provides.to.value, }, + header_docs, }; let (module_id, _, resolved_header) = build_header( @@ -4302,6 +4308,7 @@ struct HeaderInfo<'a> { packages: &'a [Loc>], imports: &'a [Loc>], header_type: HeaderType<'a>, + header_docs: &'a [&'a str], } fn build_header<'a>( @@ -4318,6 +4325,7 @@ fn build_header<'a>( packages, imports, header_type, + header_docs, } = info; let mut imported_modules: MutMap = MutMap::default(); @@ -4633,6 +4641,7 @@ fn build_header<'a>( exposed_imports: scope, symbols_from_requires, header_type, + header_docs, module_timing, }, ) @@ -5187,6 +5196,7 @@ fn build_package_header<'a>( packages, imports: &[], header_type, + header_docs: header.docs(arena), }; build_header( @@ -5250,6 +5260,7 @@ fn build_platform_header<'a>( packages: &[], imports, header_type, + header_docs: header.docs(arena), }; build_header( @@ -5349,6 +5360,7 @@ fn canonicalize_and_constrain<'a>( &parsed_defs_for_docs, exposed_module_ids, module_output.exposed_symbols.clone(), + parsed.header_docs, ); Some(docs) @@ -5487,6 +5499,7 @@ fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result, Loadi module_path, header_type, symbols_from_requires, + header_docs, .. } = header; @@ -5502,6 +5515,7 @@ fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result, Loadi parsed_defs, symbols_from_requires, header_type, + header_docs, }; Ok(Msg::Parsed(parsed)) diff --git a/crates/compiler/parse/src/ast.rs b/crates/compiler/parse/src/ast.rs index a092cca177..d9a7329d58 100644 --- a/crates/compiler/parse/src/ast.rs +++ b/crates/compiler/parse/src/ast.rs @@ -95,6 +95,65 @@ pub enum Header<'a> { Hosted(HostedHeader<'a>), } +impl<'a> HostedHeader<'a> { + pub fn docs(&self, arena: &'a Bump) -> &'a [&'a str] { + bumpalo::collections::Vec::from_iter_in( + doc_comments(self.before_name.iter().copied()), + arena, + ) + .into_bump_slice() + } +} + +impl<'a> PackageHeader<'a> { + pub fn docs(&self, arena: &'a Bump) -> &'a [&'a str] { + bumpalo::collections::Vec::from_iter_in( + doc_comments(self.before_name.iter().copied()), + arena, + ) + .into_bump_slice() + } +} + +impl<'a> PlatformHeader<'a> { + pub fn docs(&self, arena: &'a Bump) -> &'a [&'a str] { + bumpalo::collections::Vec::from_iter_in( + doc_comments(self.before_name.iter().copied()), + arena, + ) + .into_bump_slice() + } +} + +impl<'a> AppHeader<'a> { + pub fn docs(&self, arena: &'a Bump) -> &'a [&'a str] { + bumpalo::collections::Vec::from_iter_in( + doc_comments(self.before_name.iter().copied()), + arena, + ) + .into_bump_slice() + } +} + +impl<'a> InterfaceHeader<'a> { + pub fn docs(&self, arena: &'a Bump) -> &'a [&'a str] { + bumpalo::collections::Vec::from_iter_in( + doc_comments(self.before_name.iter().copied()), + arena, + ) + .into_bump_slice() + } +} + +fn doc_comments<'a>( + before_name: impl IntoIterator>, +) -> impl Iterator { + before_name.into_iter().filter_map(|doc| match doc { + CommentOrNewline::Newline | CommentOrNewline::LineComment(_) => None, + CommentOrNewline::DocComment(line) => Some(line), + }) +} + #[derive(Clone, Copy, Debug, PartialEq)] pub struct WhenBranch<'a> { pub patterns: &'a [Loc>],