From de896baff7e97fac4dde79078c9a2fa1c652576b Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 18 Dec 2019 20:56:53 +0100 Subject: Big refactoring - entities should be more coherent when parsing multiple files - well defined, language agnostic entity tree - each module has its own configuration - less dead code --- src/parsing/clang/entities.rs | 369 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100644 src/parsing/clang/entities.rs (limited to 'src/parsing/clang/entities.rs') diff --git a/src/parsing/clang/entities.rs b/src/parsing/clang/entities.rs new file mode 100644 index 0000000..a8062bb --- /dev/null +++ b/src/parsing/clang/entities.rs @@ -0,0 +1,369 @@ +use crate::types::Entity; + +use clang::{EntityKind, Usr}; +use thiserror::Error; + +use std::collections::BTreeMap; +use std::convert::TryFrom; + +// TODO: factor out hardcoded strings + +#[derive(Debug)] +pub(super) struct Children { + namespaces: Option>>, + variables: Option>>, + structs: Option>>, + functions: Option>>, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(super) enum ClangEntityKind { + Namespace, + Variable(VariableKind), + Struct(StructKind), + Function(FunctionKind), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(super) enum VariableKind { + Variable, + Field, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(super) enum StructKind { + Struct, + Class, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(super) enum FunctionKind { + Function, + Method, +} + +#[derive(Debug, Error)] +#[error("Unsupported Clang entity kind: {:?}", _0)] +pub(super) struct TryFromEntityKindError(String); + +impl TryFrom for ClangEntityKind { + type Error = TryFromEntityKindError; + + fn try_from(kind: EntityKind) -> Result { + Ok(match kind { + EntityKind::Namespace => ClangEntityKind::Namespace, + EntityKind::VarDecl => ClangEntityKind::Variable(VariableKind::Variable), + EntityKind::FieldDecl => ClangEntityKind::Variable(VariableKind::Field), + EntityKind::FunctionDecl => ClangEntityKind::Function(FunctionKind::Function), + EntityKind::Method | EntityKind::Constructor => { + ClangEntityKind::Function(FunctionKind::Method) + } + EntityKind::StructDecl => ClangEntityKind::Struct(StructKind::Struct), + EntityKind::ClassDecl => ClangEntityKind::Struct(StructKind::Class), + kind => return Err(TryFromEntityKindError(format!("{:?}", kind))), + }) + } +} + +pub(super) trait ClangEntity { + fn kind(&self) -> &'static str; + + fn get_member_namespaces(&mut self) -> Option<&mut BTreeMap>> { + None + } + fn get_member_variables(&mut self) -> Option<&mut BTreeMap>> { + None + } + fn get_member_structs(&mut self) -> Option<&mut BTreeMap>> { + None + } + fn get_member_functions(&mut self) -> Option<&mut BTreeMap>> { + None + } + + fn into_children(self) -> Children + where + Self: Sized, + { + Children { + namespaces: None, + variables: None, + structs: None, + functions: None, + } + } +} + +/* +pub(super) trait FromNamespaceParent: ClangEntity + Sized { + fn from_namespace_parent<'a>( + parent: &'a mut Described, + name: &Usr, + ) -> Option<&'a mut Described>; +} +*/ + +pub(super) trait NamespaceParentManipulation { + fn get_members_mut(&mut self) -> Option<&mut BTreeMap>>; +} + +impl NamespaceParentManipulation for U +where + U: ClangEntity, +{ + fn get_members_mut(&mut self) -> Option<&mut BTreeMap>> { + self.get_member_namespaces() + } +} + +impl NamespaceParentManipulation for U +where + U: ClangEntity, +{ + fn get_members_mut(&mut self) -> Option<&mut BTreeMap>> { + self.get_member_variables() + } +} + +impl NamespaceParentManipulation for U +where + U: ClangEntity, +{ + fn get_members_mut(&mut self) -> Option<&mut BTreeMap>> { + self.get_member_functions() + } +} + +impl NamespaceParentManipulation for U +where + U: ClangEntity, +{ + fn get_members_mut(&mut self) -> Option<&mut BTreeMap>> { + self.get_member_structs() + } +} + +impl From> for Entity { + fn from(entity: Described) -> Self { + let mut children = BTreeMap::new(); + + let kind = String::from(entity.entity.kind()); + let clang_children = entity.entity.into_children(); + + if let Some(namespaces) = clang_children.namespaces { + children.insert( + String::from("namespace"), + namespaces + .into_iter() + .map(|(usr, namespace)| (usr.0, namespace.into())) + .collect(), + ); + } + + if let Some(variables) = clang_children.variables { + children.insert( + String::from("variable"), + variables + .into_iter() + .map(|(usr, variable)| (usr.0, variable.into())) + .collect(), + ); + } + + if let Some(structs) = clang_children.structs { + children.insert( + String::from("struct"), + structs + .into_iter() + .map(|(usr, the_struct)| (usr.0, the_struct.into())) + .collect(), + ); + } + + if let Some(functions) = clang_children.functions { + children.insert( + String::from("function"), + functions + .into_iter() + .map(|(usr, function)| (usr.0, function.into())) + .collect(), + ); + } + + Entity { + name: entity.description.name, + language: String::from("clang"), + kind, + brief_description: entity.description.brief, + documentation: entity.description.detailed, + children, + } + } +} + +#[derive(Debug, Clone, Default)] +pub(super) struct Description { + pub(super) name: String, + pub(super) brief: String, + pub(super) detailed: String, +} + +#[derive(Debug, Clone)] +pub(super) struct Described { + pub(super) description: Description, + pub(super) entity: T, +} + +#[derive(Debug, Clone)] +pub(super) struct Namespace { + pub(super) member_namespaces: BTreeMap>, + pub(super) member_variables: BTreeMap>, + pub(super) member_structs: BTreeMap>, + pub(super) member_functions: BTreeMap>, +} + +impl ClangEntity for Namespace { + fn kind(&self) -> &'static str { + "namespace" + } + + fn get_member_namespaces(&mut self) -> Option<&mut BTreeMap>> { + Some(&mut self.member_namespaces) + } + fn get_member_variables(&mut self) -> Option<&mut BTreeMap>> { + Some(&mut self.member_variables) + } + fn get_member_structs(&mut self) -> Option<&mut BTreeMap>> { + Some(&mut self.member_structs) + } + fn get_member_functions(&mut self) -> Option<&mut BTreeMap>> { + Some(&mut self.member_functions) + } + + fn into_children(self) -> Children { + Children { + namespaces: Some(self.member_namespaces), + variables: Some(self.member_variables), + structs: Some(self.member_structs), + functions: Some(self.member_functions), + } + } +} + +/* +impl FromNamespaceParent for Namespace { + fn from_namespace_parent<'a>( + parent: &'a mut Described, + name: &Usr, + ) -> Option<&'a mut Described> { + parent.entity.member_namespaces.get_mut(name) + } +} +*/ + +#[derive(Debug, Clone)] +pub(super) struct Variable { + pub(super) kind: VariableKind, + pub(super) r#type: String, +} + +impl ClangEntity for Variable { + fn kind(&self) -> &'static str { + match self.kind { + VariableKind::Variable => "variable", + VariableKind::Field => "field", + } + } +} + +/* +impl FromNamespaceParent for Variable { + fn from_namespace_parent<'a>( + parent: &'a mut Described, + name: &Usr, + ) -> Option<&'a mut Described> { + parent.entity.member_variables.get_mut(name) + } +} +*/ + +#[derive(Debug, Clone)] +pub(super) struct Struct { + //pub(super) member_types: Vec, + pub(super) kind: StructKind, + pub(super) member_variables: BTreeMap>, + pub(super) member_structs: BTreeMap>, + pub(super) member_functions: BTreeMap>, +} + +impl ClangEntity for Struct { + fn kind(&self) -> &'static str { + match self.kind { + StructKind::Struct => "struct", + StructKind::Class => "class", + } + } + + fn get_member_variables(&mut self) -> Option<&mut BTreeMap>> { + Some(&mut self.member_variables) + } + fn get_member_structs(&mut self) -> Option<&mut BTreeMap>> { + Some(&mut self.member_structs) + } + fn get_member_functions(&mut self) -> Option<&mut BTreeMap>> { + Some(&mut self.member_functions) + } + + fn into_children(self) -> Children { + Children { + namespaces: None, + variables: Some(self.member_variables), + structs: Some(self.member_structs), + functions: Some(self.member_functions), + } + } +} + +/* +impl FromNamespaceParent for Struct { + fn from_namespace_parent<'a>( + parent: &'a mut Described, + name: &Usr, + ) -> Option<&'a mut Described> { + parent.entity.member_structs.get_mut(name) + } +} +*/ + +#[derive(Debug, Clone)] +pub(super) struct Function { + pub(super) kind: FunctionKind, + pub(super) arguments: Vec, + pub(super) return_type: String, +} + +impl ClangEntity for Function { + fn kind(&self) -> &'static str { + match self.kind { + FunctionKind::Function => "function", + FunctionKind::Method => "method", + } + } +} + +/* +impl FromNamespaceParent for Function { + fn from_namespace_parent<'a>( + parent: &'a mut Described, + name: &Usr, + ) -> Option<&'a mut Described> { + parent.entity.member_functions.get_mut(name) + } +} +*/ + +#[derive(Debug, Clone)] +pub(super) struct FunctionArgument { + pub(super) name: String, + pub(super) r#type: String, +} -- cgit v1.2.3