diff --git a/Cargo.lock b/Cargo.lock index 22175bc283..c952c253be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -614,6 +614,7 @@ dependencies = [ name = "docs" version = "0.1.0" dependencies = [ + "bumpalo", "fs_extra", "handlebars", "pulldown-cmark", diff --git a/compiler/load/src/docs.rs b/compiler/load/src/docs.rs index 3d034f5306..28ad23926c 100644 --- a/compiler/load/src/docs.rs +++ b/compiler/load/src/docs.rs @@ -1574,7 +1574,7 @@ pub struct DocEntry { pub docs: Option, } -fn generate_module_docs<'a>( +pub fn generate_module_docs<'a>( module_name: ModuleName, exposed_ident_ids: &'a IdentIds, parsed_defs: &'a bumpalo::collections::Vec<'a, Located>>, diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index 5318e5296b..7d6f5d9692 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -1,3 +1,4 @@ +use crate::docs::ModuleDocumentation; use bumpalo::Bump; use crossbeam::channel::{bounded, Sender}; use crossbeam::deque::{Injector, Stealer, Worker}; @@ -202,6 +203,7 @@ struct ModuleCache<'a> { typechecked: MutMap>, found_specializations: MutMap>, external_specializations_requested: MutMap, + documentation: MutMap, } fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) -> BuildTask<'a> { @@ -378,6 +380,7 @@ pub struct LoadedModule { pub exposed_to_host: MutMap, pub src: Box, pub timings: MutMap, + pub documentation: MutMap, } #[derive(Debug)] @@ -458,6 +461,7 @@ enum Msg<'a> { problems: Vec, var_store: VarStore, module_timing: ModuleTiming, + module_docs: ModuleDocumentation, }, SolvedTypes { src: &'a str, @@ -471,6 +475,7 @@ enum Msg<'a> { FinishedAllTypeChecking { solved_subs: Solved, exposed_vars_by_symbol: Vec<(Symbol, Variable)>, + documentation: MutMap, src: &'a str, }, FoundSpecializations { @@ -1096,6 +1101,7 @@ where Msg::FinishedAllTypeChecking { solved_subs, exposed_vars_by_symbol, + documentation, src, } => { // We're done! There should be no more messages pending. @@ -1112,6 +1118,7 @@ where state, solved_subs, exposed_vars_by_symbol, + documentation, src, ))); } @@ -1228,11 +1235,17 @@ fn update<'a>( problems, var_store, module_timing, + module_docs, } => { log!("generated constraints for {:?}", module.module_id); let module_id = module.module_id; state.can_problems.extend(problems); + state + .module_cache + .documentation + .insert(module_id, module_docs); + let constrained_module = ConstrainedModule { module, constraint, @@ -1243,6 +1256,7 @@ fn update<'a>( var_store, imported_modules, }; + state .module_cache .constrained @@ -1288,10 +1302,18 @@ fn update<'a>( state.timings.insert(module_id, module_timing); + let documentation = { + let mut empty = MutMap::default(); + std::mem::swap(&mut empty, &mut state.module_cache.documentation); + + empty + }; + msg_tx .send(Msg::FinishedAllTypeChecking { solved_subs, exposed_vars_by_symbol: solved_module.exposed_vars_by_symbol, + documentation, src, }) .map_err(|_| LoadingProblem::MsgChannelDied)?; @@ -1514,6 +1536,7 @@ fn finish<'a>( state: State<'a>, solved: Solved, exposed_vars_by_symbol: Vec<(Symbol, Variable)>, + documentation: MutMap, src: &'a str, ) -> LoadedModule { let module_ids = Arc::try_unwrap(state.arc_modules) @@ -1535,6 +1558,7 @@ fn finish<'a>( exposed_to_host: exposed_vars_by_symbol.into_iter().collect(), src: src.into(), timings: state.timings, + documentation, } } @@ -1994,6 +2018,15 @@ fn parse_and_constrain<'a>( // immediately afterward (for the beginning of canonicalization). let parse_end = SystemTime::now(); let module_id = header.module_id; + + // Generate documentation information + // TODO: store timing information? + let module_docs = crate::docs::generate_module_docs( + header.module_name, + &header.exposed_ident_ids, + &parsed_defs, + ); + let mut var_store = VarStore::default(); let canonicalized = canonicalize_module_defs( &arena, @@ -2070,6 +2103,7 @@ fn parse_and_constrain<'a>( problems, var_store, module_timing, + module_docs, }) } diff --git a/docs/Cargo.toml b/docs/Cargo.toml index 22014d6153..7deb6bd0ec 100644 --- a/docs/Cargo.toml +++ b/docs/Cargo.toml @@ -16,3 +16,4 @@ pulldown-cmark = { version = "0.8", default-features = false } roc_load = { path = "../compiler/load" } roc_builtins = { path = "../compiler/builtins" } roc_collections = { path = "../compiler/collections" } +bumpalo = { version = "3.2", features = ["collections"] } diff --git a/docs/src/main.rs b/docs/src/main.rs index c825e4f8aa..101c28c6f5 100644 --- a/docs/src/main.rs +++ b/docs/src/main.rs @@ -8,6 +8,7 @@ extern crate serde_json; use std::error::Error; use std::fs; extern crate roc_load; +use bumpalo::Bump; use roc_collections::all::MutMap; use std::path::{Path, PathBuf}; @@ -43,6 +44,8 @@ pub struct TemplateLinkEntry { fn main() -> Result<(), Box> { let std_lib = roc_builtins::std::standard_stdlib(); let subs_by_module = MutMap::default(); + let arena = Bump::new(); + let src_dir = Path::new("../compiler/builtins/docs"); let files = vec![ PathBuf::from(r"../compiler/builtins/docs/Bool.roc"), @@ -59,9 +62,15 @@ fn main() -> Result<(), Box> { // Load each file is files vector for filename in files { - let loaded = roc_load::docs::load(filename, &std_lib, src_dir, subs_by_module.clone()) - .expect("TODO gracefully handle load failing"); - modules_docs.push(loaded.module_docs); + let mut loaded = roc_load::file::load_and_typecheck( + &arena, + filename, + std_lib.clone(), + src_dir, + subs_by_module.clone(), + ) + .expect("TODO gracefully handle load failing"); + modules_docs.extend(loaded.documentation.drain().map(|x| x.1)); } let package = roc_load::docs::Documentation {