From 860b73f1644ecd6548ae403ec483625fb7b625ea Mon Sep 17 00:00:00 2001 From: Minijackson Date: Sat, 23 Nov 2019 19:27:21 +0100 Subject: entities rework, allow "inline" documentation, merge config with cli --- src/config.rs | 54 ++++++++++++-- src/entities.rs | 142 ++++++++++++++++++++++++++++-------- src/generator.rs | 146 +++++++++++++++++++------------------ src/main.rs | 16 +++-- src/pandoc.rs | 204 ++++++++++++++++------------------------------------ src/pandoc/types.rs | 39 ---------- src/parsing.rs | 55 ++++++++++---- 7 files changed, 353 insertions(+), 303 deletions(-) delete mode 100644 src/pandoc/types.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 4463479..b448469 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,5 @@ +use crate::cli::Cli; + use anyhow::{anyhow, Context, Result}; use codemap::CodeMap; use codemap_diagnostic::Diagnostic; @@ -15,19 +17,61 @@ pub(super) const DEFAULT_PROJECT_CONFIGURATION_FILE_NAME: &str = "poseidoc.toml" #[serde(rename_all = "kebab-case", default)] pub(crate) struct Config { #[structopt(skip)] - pub(crate) name: String, - #[structopt(long, default_value = ".")] - pub(crate) compile_commands_location: PathBuf, + pub(crate) name: Option, + #[structopt(long)] + pub(crate) compile_commands_location: Option, #[structopt(skip = vec![])] pub(crate) extra_clang_args: Vec, + #[structopt(flatten)] + pub(crate) class: ClassConfig, +} + +impl Config { + pub(crate) fn merge_cli(self, cli: Cli) -> Self { + Config { + name: cli.common_options.name.or(self.name), + compile_commands_location: cli + .common_options + .compile_commands_location + .or(self.compile_commands_location), + extra_clang_args: cli + .extra_arg + .into_iter() + .flatten() + .chain(self.extra_clang_args) + .collect(), + class: self.class.merge_cli(cli.common_options.class), + } + } } impl Default for Config { fn default() -> Self { Config { - name: "My Project".into(), - compile_commands_location: PathBuf::from(r"."), + name: Some(String::from("My Project")), + compile_commands_location: Some(PathBuf::from(r".")), extra_clang_args: Vec::new(), + class: ClassConfig::default(), + } + } +} + +#[derive(Debug, Clone, StructOpt, Deserialize, Serialize)] +#[structopt(rename_all = "kebab-case")] +#[serde(rename_all = "kebab-case", default)] +pub(crate) struct ClassConfig { +} + +impl ClassConfig { + fn merge_cli(self, _cli: ClassConfig) -> Self { + ClassConfig { + } + } +} + +impl Default for ClassConfig { + fn default() -> Self { + ClassConfig { } } } diff --git a/src/entities.rs b/src/entities.rs index b7368df..89905c6 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -1,16 +1,17 @@ use std::collections::HashMap; +pub(crate) type DynEntity = dyn Entity + Sync + Send; + #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub(crate) struct Usr(pub(crate) String); -#[derive(Debug, Clone)] pub(crate) struct EntitiesManager { - toplevel_entities: HashMap, + toplevel_entities: HashMap>, descriptions: HashMap, } pub(crate) struct EntitiesManagerComponents { - pub(crate) toplevel_entities: HashMap, + pub(crate) toplevel_entities: HashMap>, pub(crate) descriptions: HashMap, } @@ -27,7 +28,7 @@ impl EntitiesManager { self.descriptions.insert(usr, description); } - pub fn insert_toplevel(&mut self, usr: Usr, entity: Entity) { + pub fn insert_toplevel(&mut self, usr: Usr, entity: Box) { self.toplevel_entities.insert(usr, entity); } @@ -61,33 +62,88 @@ pub(crate) struct Described { pub(crate) entity: T, } +pub(crate) struct ChildGroup<'a> { + pub(crate) name: &'static str, + pub(crate) children: Vec<(&'a Usr, &'a DynEntity)>, +} + +pub(crate) trait Entity { + fn kind_name(&self) -> &'static str; + fn embeddable_children(&self) -> Vec { + Vec::new() + } + fn separate_children(&self) -> Vec { + Vec::new() + } +} + #[derive(Debug, Clone)] -pub(crate) enum Entity { +pub(crate) struct NameSpace { + // TODO: replace with Vec to keep order + pub(crate) members: HashMap, +} + +#[derive(Debug, Clone)] +pub(crate) enum NameSpaceChild { NameSpace(NameSpace), + Class(Class), Variable(Variable), Function(Function), - Class(Class), } -impl Entity { +impl Entity for NameSpace { fn kind_name(&self) -> &'static str { - match self { - Entity::NameSpace(_) => "namespace", - Entity::Variable(_) => "variable", - Entity::Function(_) => "function", - Entity::Class(_) => "class", + "namespace" + } + + fn embeddable_children(&self) -> Vec { + let mut variables = Vec::new(); + let mut functions = Vec::new(); + for (usr, member) in &self.members { + match member { + NameSpaceChild::NameSpace(_) => {} + NameSpaceChild::Class(_) => {} + NameSpaceChild::Variable(variable) => variables.push((usr, variable as &DynEntity)), + NameSpaceChild::Function(function) => functions.push((usr, function as &DynEntity)), + } } + + vec![ + ChildGroup { + name: "Variables", + children: variables, + }, + ChildGroup { + name: "Functions", + children: functions, + }, + ] } -} -#[derive(Debug, Clone)] -pub(crate) struct NameSpace { - pub(crate) members: HashMap, -} + fn separate_children(&self) -> Vec { + let mut namespaces = Vec::new(); + let mut classes = Vec::new(); + for (usr, member) in &self.members { + match member { + NameSpaceChild::NameSpace(namespace) => { + namespaces.push((usr, namespace as &DynEntity)) + } + NameSpaceChild::Class(class) => classes.push((usr, class as &DynEntity)), + NameSpaceChild::Variable(_) => {} + NameSpaceChild::Function(_) => {} + } + } -impl From for Entity { - fn from(ns: NameSpace) -> Self { - Entity::NameSpace(ns) + vec![ + ChildGroup { + name: "Namespaces", + children: namespaces, + }, + ChildGroup { + name: "Classes", + children: classes, + }, + ] } } @@ -96,9 +152,9 @@ pub(crate) struct Variable { pub(crate) r#type: String, } -impl From for Entity { - fn from(var: Variable) -> Self { - Entity::Variable(var) +impl Entity for Variable { + fn kind_name(&self) -> &'static str { + "variable" } } @@ -108,9 +164,9 @@ pub(crate) struct Function { pub(crate) return_type: String, } -impl From for Entity { - fn from(func: Function) -> Self { - Entity::Function(func) +impl Entity for Function { + fn kind_name(&self) -> &'static str { + "function" } } @@ -122,13 +178,39 @@ pub(crate) struct FunctionArgument { #[derive(Debug, Clone)] pub(crate) struct Class { - pub(crate) member_types: Vec, + //pub(crate) member_types: Vec, + // TODO: replace with Vec to keep order pub(crate) member_functions: HashMap, pub(crate) member_variables: HashMap, } -impl From for Entity { - fn from(class: Class) -> Self { - Entity::Class(class) +impl Entity for Class { + fn kind_name(&self) -> &'static str { + "class" + } + + fn embeddable_children(&self) -> Vec { + vec![ + ChildGroup { + name: "Functions", + children: self + .member_functions + .iter() + .map(|(usr, func)| (usr, func as &DynEntity)) + .collect(), + }, + ChildGroup { + name: "Variables", + children: self + .member_variables + .iter() + .map(|(usr, var)| (usr, var as &DynEntity)) + .collect(), + }, + ] + } + + fn separate_children(&self) -> Vec { + Vec::new() } } diff --git a/src/generator.rs b/src/generator.rs index 0ab4511..0fa5a94 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -1,16 +1,20 @@ +use crate::config::Config; use crate::entities::{ - Described, Description, EntitiesManager, EntitiesManagerComponents, Entity, Usr, + Description, DynEntity, EntitiesManager, EntitiesManagerComponents, Usr, }; +use crate::pandoc::into_pandoc; -use anyhow::{Context, Result}; +use anyhow::{ensure, Context, Result}; +use rayon::Scope; use thiserror::Error; -use threadpool::ThreadPool; use std::collections::HashMap; +use std::io::Write; use std::path::Path; -use std::sync::{mpsc::channel, Arc}; -pub(crate) fn generate(base_dir: &Path, manager: EntitiesManager) -> Result<()> { +const DEFAULT_CSS: &[u8] = include_bytes!("../res/style.css"); + +pub(crate) fn generate(base_dir: &Path, manager: EntitiesManager, config: &Config) -> Result<()> { let EntitiesManagerComponents { toplevel_entities, descriptions, @@ -24,87 +28,78 @@ pub(crate) fn generate(base_dir: &Path, manager: EntitiesManager) -> Result<()> std::fs::create_dir_all(&html_output_dir) .context("Failed to create the HTML output directory")?; - let pool = ThreadPool::new(num_cpus::get()); - - let descriptions = Arc::new(descriptions); - - let (tx, rx) = channel::<()>(); - - for (usr, entity) in toplevel_entities { - generate_recursively( - usr, - entity, - pool.clone(), - tx.clone(), - descriptions.clone(), - &md_output_dir, - &html_output_dir, - ); - } + let mut css_tempfile = tempfile::Builder::new() + .prefix("style") + .suffix(".css") + .tempfile()?; + css_tempfile.write_all(DEFAULT_CSS)?; - drop(tx); + let css_path = css_tempfile.path(); + debug!("Generated temporary file with CSS at: {:?}", css_path); - // This is not really idiomatic, but iter returns None when every Sender is destroyed, so just - // by passing around Senders in generate_recursively, we wait for every job. - rx.iter().for_each(drop); + rayon::scope(|scope| { + for (usr, entity) in &toplevel_entities { + generate_recursively( + &usr, + entity.as_ref(), + scope, + &descriptions, + &md_output_dir, + &html_output_dir, + css_path, + ); + } + }); Ok(()) } -fn generate_recursively( - usr: Usr, - entity: Entity, - pool: ThreadPool, - tx: std::sync::mpsc::Sender<()>, - descriptions: Arc>, - md_output_dir: impl AsRef, - html_output_dir: impl AsRef, +fn generate_recursively<'a>( + usr: &'a Usr, + entity: &'a DynEntity, + pool: &Scope<'a>, + descriptions: &'a HashMap, + md_output_dir: &'a Path, + html_output_dir: &'a Path, + css_path: &'a Path, ) { - let descriptions = descriptions.clone(); - let md_output_dir = md_output_dir.as_ref().to_owned(); - let html_output_dir = html_output_dir.as_ref().to_owned(); - - let pool2 = pool.clone(); - pool.execute(move || { + pool.spawn(move |pool| { trace!("Trying to generate {}", usr.0); - let entity = Described:: { - entity, - description: descriptions.get(&usr).unwrap().clone(), - }; - let leftovers = generate_single( &usr, entity, + descriptions.get(&usr).unwrap(), &descriptions, &md_output_dir, &html_output_dir, + &css_path, ) .unwrap(); for (usr, entity) in leftovers { - let pool = pool2.clone(); - let tx = tx.clone(); generate_recursively( usr, entity, pool, - tx, - descriptions.clone(), - md_output_dir.clone(), - html_output_dir.clone(), + descriptions, + md_output_dir, + html_output_dir, + css_path, ); } }); } -fn generate_single( +fn generate_single<'e>( usr: &Usr, - entity: Described, + entity: &'e DynEntity, + description: &Description, descriptions: &HashMap, md_output_dir: impl AsRef, html_output_dir: impl AsRef, -) -> Result> { + css_path: impl AsRef, +) -> Result> { use std::io::prelude::*; use std::process::{Command, Stdio}; @@ -132,7 +127,7 @@ fn generate_single( .spawn() .context("Failed to execute Pandoc command")?; - let (pandoc_ast, leftovers) = entity.into_pandoc(&descriptions); + let (pandoc_ast, leftovers) = into_pandoc(entity, description, descriptions); if log_enabled!(log::Level::Trace) { let json = @@ -152,17 +147,20 @@ fn generate_single( .context("Failed to convert Pandoc AST to JSON")?; } + let command_str = format!("{:?}", pandoc); + let output = pandoc .wait_with_output() .expect("Pandoc command wasn't running"); - if !output.status.success() { - Err(CommandError { + ensure!( + output.status.success(), + CommandError { + command: format!("{:?}", command_str), status: output.status, stderr: String::from_utf8(output.stderr).expect("Pandoc outputted invalid UTF-8"), - }) - .context("Pandoc command failed")?; - } + } + ); let mut command = Command::new("pandoc"); command @@ -172,7 +170,11 @@ fn generate_single( .args(&[ "--from=markdown", "--to=html", - "--css=res/style.css", + "--css", + css_path + .as_ref() + .to_str() + .context("CSS path is not valid UTF-8")?, "--standalone", "--self-contained", md_output_file @@ -184,26 +186,34 @@ fn generate_single( .context("Entity name is not valid UTF-8")?, ]); - debug!("Launching command: {:?}", command); + let command_str = format!("{:?}", command); + debug!("Launching command: {}", command_str); let output = command .output() .context("Failed to execute Pandoc command")?; - if !output.status.success() { - Err(CommandError { + ensure!( + output.status.success(), + CommandError { + command: command_str, status: output.status, stderr: String::from_utf8(output.stderr).expect("Pandoc outputted invalid UTF-8"), - }) - .context("Pandoc command failed")?; - } + } + ); Ok(leftovers) } #[derive(Debug, Clone, Error)] -#[error("Command returned status {:?} and stderr {:?}", status, stderr)] +#[error( + "Command {} returned status {:?} and stderr {:?}", + command, + status, + stderr +)] struct CommandError { + command: String, status: std::process::ExitStatus, stderr: String, } diff --git a/src/main.rs b/src/main.rs index 503688e..e6e36d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![warn(clippy::all)] + //mod doxygen; mod cli; mod config; @@ -83,13 +85,15 @@ fn start(codemap: &mut CodeMap) -> Result<()> { std::env::set_current_dir(&cli.directory) .with_context(|| format!("Cannot change current directory to: {:?}", cli.directory))?; - match cli.command { + match &cli.command { Command::Generate { file } => { - let extra_args = cli.extra_arg.iter().flatten().map(AsRef::as_ref).collect(); - let manager = parse_file(file, extra_args); + let file = file.clone(); + let config = load_effective_config(cli, codemap)?; + + let manager = parse_file(file, &config.extra_clang_args); let base_output_dir = std::path::Path::new("doc"); - generate(&base_output_dir, manager)?; + generate(&base_output_dir, manager, &config)?; } Command::Config { command: ConfigCommand::Default, @@ -108,3 +112,7 @@ fn start(codemap: &mut CodeMap) -> Result<()> { Ok(()) } + +fn load_effective_config(cli: cli::Cli, codemap: &mut CodeMap) -> Result { + Ok(config::load_config(".", codemap)?.merge_cli(cli)) +} diff --git a/src/pandoc.rs b/src/pandoc.rs index 5ca84e7..8477f28 100644 --- a/src/pandoc.rs +++ b/src/pandoc.rs @@ -1,186 +1,106 @@ -//mod types; - use crate::entities::*; use pandoc_types::definition::{Attr, Block, Inline, Meta, MetaValue, Pandoc}; use std::collections::HashMap; -impl Described { - pub fn into_pandoc( - self, - descriptions: &HashMap, - ) -> (Pandoc, HashMap) { - let mut meta = Meta::null(); - - let title = self.title(); - let mut content_before = self.content_before(&descriptions); - let mut content_after = self.content_after(&descriptions); - let leftovers = self.leftovers(); - - meta.0.insert( - "title".to_string(), - MetaValue::MetaString(self.description.name), - ); - - let mut content = Vec::new(); - - content.push(Block::Header(1, Attr::null(), title)); - - content.append(&mut content_before); - - if !self.description.detailed.is_empty() { - content.push(Block::Header( - 2, - Attr::null(), - vec![Inline::Str(String::from("Description"))], - )); - - content.push(Block::Div( - Attr(String::new(), vec![String::from("doc")], vec![]), - vec![raw_markdown(self.description.detailed)], - )); - } - - content.append(&mut content_after); - - (Pandoc(meta, content), leftovers) - } -} - -// TODO: replace with single function so we can move out, and remove all of those clones -trait PandocDisplay { - fn content_before(&self, _descriptions: &HashMap) -> Vec { - vec![] - } - - fn content_after(&self, _descriptions: &HashMap) -> Vec { - vec![] - } - - fn leftovers(&self) -> HashMap { - HashMap::new() - } -} - -impl Described { - fn title(&self) -> Vec { - match &self.entity { - Entity::Variable(variable) => vec![Inline::Code( - Attr(String::new(), vec![String::from("cpp")], vec![]), - variable.r#type.clone() + " " + &self.description.name, - )], - _ => vec![Inline::Code(Attr::null(), self.description.name.clone())], - } - } -} +pub(crate) fn into_pandoc<'e>( + entity: &'e dyn Entity, + description: &Description, + descriptions: &HashMap, +) -> (Pandoc, HashMap<&'e Usr, &'e DynEntity>) { + let mut meta = Meta::null(); -impl PandocDisplay for Described { - fn content_before(&self, descriptions: &HashMap) -> Vec { - match &self.entity { - Entity::NameSpace(ns) => ns.content_before(descriptions), - Entity::Variable(var) => var.content_before(descriptions), - Entity::Function(func) => func.content_before(descriptions), - Entity::Class(class) => class.content_before(descriptions), - } - } + let title = vec![Inline::Code(Attr::null(), description.name.clone())]; - fn content_after(&self, descriptions: &HashMap) -> Vec { - match &self.entity { - Entity::NameSpace(ns) => ns.content_after(descriptions), - Entity::Variable(var) => var.content_after(descriptions), - Entity::Function(func) => func.content_after(descriptions), - Entity::Class(class) => class.content_after(descriptions), - } - } + meta.0.insert( + "title".to_string(), + MetaValue::MetaString(description.name.clone()), + ); - fn leftovers(&self) -> HashMap { - match &self.entity { - Entity::NameSpace(ns) => ns.leftovers(), - Entity::Variable(var) => var.leftovers(), - Entity::Function(func) => func.leftovers(), - Entity::Class(class) => class.leftovers(), - } - } -} + let mut content = Vec::new(); -impl PandocDisplay for NameSpace { - fn content_after(&self, descriptions: &HashMap) -> Vec { - let mut content = Vec::new(); + content.push(Block::Header(1, Attr::null(), title)); + if !description.detailed.is_empty() { content.push(Block::Header( 2, Attr::null(), - vec![Inline::Str("Members".to_string())], + vec![Inline::Str(String::from("Description"))], )); - if let Some(member_list) = member_list(self.members.keys(), descriptions) { - content.push(member_list); - } else { - content.push(str_block(String::from("None"))); - } - - content - } - - fn leftovers(&self) -> HashMap { - self.members.clone() + content.push(Block::Div( + Attr(String::new(), vec![String::from("doc")], vec![]), + vec![raw_markdown(description.detailed.clone())], + )); } -} -impl PandocDisplay for Class { - fn content_after(&self, descriptions: &HashMap) -> Vec { - let mut content = Vec::new(); + let separate_children = entity.separate_children(); + let embeddable_children = entity.embeddable_children(); - if let Some(member_types) = member_list(&self.member_types, descriptions) { + for section in &separate_children { + if let Some(members_list) = member_list( + section.children.iter().map(|&(usr, _child)| usr), + descriptions, + ) { content.push(Block::Header( 2, Attr::null(), - vec![Inline::Str("Member Types".to_string())], + vec![Inline::Str(String::from(section.name))], )); - content.push(member_types); + content.push(members_list); } + } + + let mut embedded_documentation = Vec::new(); - if let Some(member_functions) = member_list(self.member_functions.keys(), descriptions) { + for section in &embeddable_children { + if let Some(members_list) = member_list( + section.children.iter().map(|&(usr, _child)| usr), + descriptions, + ) { content.push(Block::Header( 2, Attr::null(), - vec![Inline::Str("Member Functions".to_string())], + vec![Inline::Str(String::from(section.name))], )); - content.push(member_functions); - } + content.push(members_list); - if let Some(member_variables) = member_list(self.member_variables.keys(), descriptions) { - content.push(Block::Header( + embedded_documentation.push(Block::Header( 2, Attr::null(), - vec![Inline::Str("Member Variables".to_string())], + vec![Inline::Str(String::from(section.name) + " Documentation")], )); - content.push(member_variables); - } + for (usr, _child) in §ion.children { + let child_doc = descriptions.get(usr).unwrap(); - content - } + embedded_documentation.push(Block::Header( + 3, + Attr::null(), + vec![Inline::Code(Attr::null(), String::from(&child_doc.name))], + )); - fn leftovers(&self) -> HashMap { - self.member_functions - .iter() - .map(|(usr, func)| (usr.clone(), Entity::from(func.clone()))) - .chain( - self.member_variables - .iter() - .map(|(usr, var)| (usr.clone(), Entity::from(var.clone()))), - ) - .collect() + embedded_documentation.push(Block::Div( + Attr(String::new(), vec![String::from("doc")], vec![]), + vec![raw_markdown(child_doc.detailed.clone())], + )); + } + } } -} -impl PandocDisplay for Variable {} + content.append(&mut embedded_documentation); -impl PandocDisplay for Function {} + let leftovers = separate_children + .iter() + .map(|section| section.children.clone()) + .flatten() + .collect(); + + (Pandoc(meta, content), leftovers) +} fn str_block(content: String) -> Block { Block::Plain(vec![Inline::Str(content)]) diff --git a/src/pandoc/types.rs b/src/pandoc/types.rs deleted file mode 100644 index dc5be64..0000000 --- a/src/pandoc/types.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::pandoc::{Block, Inline}; - -#[derive(Debug, Clone)] -pub(super) struct Class { - inners: Vec, -} - -#[derive(Debug, Clone)] -struct Inner { - kind: InnerKind, - name: String, - //refid: String -} - -#[derive(Debug, Clone)] -enum InnerKind { - Class, - Enum, -} - -impl std::fmt::Display for InnerKind { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - InnerKind::Class => write!(f, "class"), - InnerKind::Enum => write!(f, "enum"), - } - } -} - -impl From for (Vec, Vec>) { - fn from(inner: Inner) -> (Vec, Vec>) { - ( - vec![Inline::Str(inner.name)], - vec![vec![Block::Plain(vec![Inline::Str( - inner.kind.to_string(), - )])]], - ) - } -} diff --git a/src/parsing.rs b/src/parsing.rs index 137b89d..d7aaa49 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -6,11 +6,13 @@ use codemap::CodeMap; use std::collections::HashMap; use std::path::{Path, PathBuf}; -pub(crate) fn parse_file(path: T, mut extra_args: Vec<&str>) -> EntitiesManager +pub(crate) fn parse_file(path: T, extra_args: &[S]) -> EntitiesManager where T: Into, T: AsRef, T: ToString, + S: AsRef, + S: std::fmt::Debug, { let mut codemap = CodeMap::new(); let file_map = codemap.add_file(path.to_string(), std::fs::read_to_string(&path).unwrap()); @@ -21,7 +23,6 @@ where let mut parser = index.parser(path); parser.skip_function_bodies(true); - extra_args.push("-Werror=documentation"); parser.arguments(&extra_args); if log_enabled!(log::Level::Debug) { @@ -70,7 +71,7 @@ where let mut emitter = Emitter::stderr(ColorConfig::Auto, Some(&codemap)); for diagnostic in trans_unit.get_diagnostics().iter() { - let main_diag = match clang_diag_to_codemap_diag(&diagnostic, &file_span) { + let main_diag = match clang_diag_to_codemap_diag(&diagnostic, file_span) { Some(diag) => diag, None => continue, }; @@ -78,12 +79,12 @@ where let sub_diags = diagnostic .get_children() .into_iter() - .filter_map(|diagnostic| clang_diag_to_codemap_diag(&diagnostic, &file_span)); + .filter_map(|diagnostic| clang_diag_to_codemap_diag(&diagnostic, file_span)); let fix_it_diags = diagnostic .get_fix_its() .into_iter() - .map(|fix_it| clang_fix_it_to_codemap_diag(&fix_it, &file_span)); + .map(|fix_it| clang_fix_it_to_codemap_diag(&fix_it, file_span)); emitter.emit( &std::iter::once(main_diag) @@ -98,7 +99,7 @@ where fn clang_diag_to_codemap_diag( diagnostic: &clang::diagnostic::Diagnostic, - file_span: &codemap::Span, + file_span: codemap::Span, ) -> Option { use codemap_diagnostic::{Diagnostic, Level, SpanLabel, SpanStyle}; @@ -146,7 +147,7 @@ fn clang_diag_to_codemap_diag( fn clang_fix_it_to_codemap_diag( fix_it: &clang::diagnostic::FixIt, - file_span: &codemap::Span, + file_span: codemap::Span, ) -> codemap_diagnostic::Diagnostic { use clang::diagnostic::FixIt; use codemap_diagnostic::{Diagnostic, Level, SpanLabel, SpanStyle}; @@ -195,6 +196,7 @@ fn clang_fix_it_to_codemap_diag( pub(crate) struct Comment(String); impl Comment { + // TODO: weirdness with emojis and line returns? pub fn from_raw(raw: String) -> Self { #[derive(Debug)] enum CommentStyle { @@ -237,7 +239,7 @@ impl Comment { break; } Some(position) => { - result.push_str(&rest[..position + 1]); + result.push_str(&rest[..=position]); chars.nth(position); } } @@ -318,20 +320,20 @@ fn get_description(entity: &clang::Entity) -> Description { } } -impl FromClangEntity for Entity { +impl FromClangEntity for Box { fn from_clang_entity(entity: clang::Entity, manager: &mut EntitiesManager) -> Self { use clang::EntityKind; match entity.get_kind() { - EntityKind::Namespace => Self::NameSpace(entity.into_poseidoc_entity(manager)), + EntityKind::Namespace => Box::new(NameSpace::from_clang_entity(entity, manager)), EntityKind::FieldDecl | EntityKind::VarDecl => { - Self::Variable(entity.into_poseidoc_entity(manager)) + Box::new(Variable::from_clang_entity(entity, manager)) } EntityKind::FunctionDecl | EntityKind::Method | EntityKind::FunctionTemplate => { - Self::Function(entity.into_poseidoc_entity(manager)) + Box::new(Function::from_clang_entity(entity, manager)) } EntityKind::ClassDecl | EntityKind::StructDecl | EntityKind::ClassTemplate => { - Self::Class(entity.into_poseidoc_entity(manager)) + Box::new(Class::from_clang_entity(entity, manager)) } _ => panic!("Unsupported entity: {:?}", entity), } @@ -362,6 +364,28 @@ impl FromClangEntity for NameSpace { } } +impl FromClangEntity for NameSpaceChild { + fn from_clang_entity(entity: clang::Entity, manager: &mut EntitiesManager) -> Self { + use clang::EntityKind; + + match entity.get_kind() { + EntityKind::Namespace => { + NameSpaceChild::NameSpace(NameSpace::from_clang_entity(entity, manager)) + } + EntityKind::FieldDecl | EntityKind::VarDecl => { + NameSpaceChild::Variable(Variable::from_clang_entity(entity, manager)) + } + EntityKind::FunctionDecl | EntityKind::Method | EntityKind::FunctionTemplate => { + NameSpaceChild::Function(Function::from_clang_entity(entity, manager)) + } + EntityKind::ClassDecl | EntityKind::StructDecl | EntityKind::ClassTemplate => { + NameSpaceChild::Class(Class::from_clang_entity(entity, manager)) + } + _ => panic!("Unsupported entity: {:?}", entity), + } + } +} + impl FromClangEntity for Variable { fn from_clang_entity(entity: clang::Entity, manager: &mut EntitiesManager) -> Self { match entity.get_kind() { @@ -383,6 +407,7 @@ impl FromClangEntity for Function { fn from_clang_entity(entity: clang::Entity, manager: &mut EntitiesManager) -> Self { match entity.get_kind() { clang::EntityKind::Method + | clang::EntityKind::Constructor | clang::EntityKind::FunctionDecl | clang::EntityKind::FunctionTemplate => {} _ => panic!("Trying to parse a non-function into a function"), @@ -436,7 +461,7 @@ impl FromClangEntity for Class { EntityKind::ClassDecl | EntityKind::StructDecl | EntityKind::TypeAliasDecl => { member_types.push(child_usr); } - EntityKind::Method => { + EntityKind::Method | EntityKind::Constructor | EntityKind::FunctionDecl => { member_functions.insert(child_usr, child.into_poseidoc_entity(manager)); } EntityKind::FieldDecl => { @@ -449,7 +474,7 @@ impl FromClangEntity for Class { manager.insert(entity.get_usr().unwrap().into(), get_description(&entity)); Class { - member_types, + //member_types, member_functions, member_variables, } -- cgit v1.2.3