From 48ebdf2a757c1d83c11854e1f977f2df1f34f1ca Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Sat, 26 Jun 2021 13:42:41 -0500 Subject: [PATCH 01/21] Added go folder and updated mod.rs --- src/lang/go/mod.rs | 12 ++++++++++++ src/lang/mod.rs | 1 + 2 files changed, 13 insertions(+) create mode 100644 src/lang/go/mod.rs diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs new file mode 100644 index 0000000..4b9f317 --- /dev/null +++ b/src/lang/go/mod.rs @@ -0,0 +1,12 @@ +use crate::parse::AST; +use crate::prophet::*; + +/* +pub fn find_components(ast: AST, path: &str) -> Vec { + find_components_internal(ast, String::new(), path) +} + +pub fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec { + +} +*/ diff --git a/src/lang/mod.rs b/src/lang/mod.rs index e72ee8e..8c9064e 100644 --- a/src/lang/mod.rs +++ b/src/lang/mod.rs @@ -1,2 +1,3 @@ pub mod cpp; pub mod java; +pub mod go; From bf81d01ddedf654ad3f1b6b47d5df93984f674b4 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Wed, 30 Jun 2021 13:24:18 -0500 Subject: [PATCH 02/21] initial commit --- .idea/.gitignore | 3 +++ .idea/modules.xml | 8 ++++++ .idea/source-code-parser.iml | 13 +++++++++ .idea/vcs.xml | 6 +++++ src/lang/go/class_def.rs | 52 ++++++++++++++++++++++++++++++++++++ src/lang/go/mod.rs | 46 ++++++++++++++++++++++++++++--- src/parse.rs | 2 +- 7 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/modules.xml create mode 100644 .idea/source-code-parser.iml create mode 100644 .idea/vcs.xml create mode 100644 src/lang/go/class_def.rs diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..f5f3c9a --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/source-code-parser.iml b/.idea/source-code-parser.iml new file mode 100644 index 0000000..495c100 --- /dev/null +++ b/.idea/source-code-parser.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs new file mode 100644 index 0000000..bf2bcbf --- /dev/null +++ b/src/lang/go/class_def.rs @@ -0,0 +1,52 @@ +use crate::parse::AST; +use crate::prophet::*; + + +pub(crate)fn parse_struct( + ast: &AST, + package: &str, + path: &str +) -> Option { + + let instance_type = match ast.find_child_by_type(&["struct"]) { + Some(r#type) => match &*r#type.value { + "interface" => InstanceType::InterfaceComponent, + _ => InstanceType::ClassComponent, + }, + None => InstanceType::ClassComponent, + }; + + + let instance_name = match ast.find_child_by_type(&["type_identifier"]) { + Some(identifier) => identifier.value.clone(), + None => "Fail".into(), + }; + + //let instance_name = ast.find_child_by_type(&["type_identifier"]).map_or_else(|| "fail".into(), |t| t.value.clone()); + println!("{}", instance_name.to_string()); + + + let component = ComponentInfo { + path: path.into(), + package_name: package.into(), + instance_name: format!("{}", instance_name), + instance_type: instance_type, + }; + + Some(ClassOrInterfaceComponent { + component: ContainerComponent { + component, + accessor: AccessorType::Private, + stereotype: ContainerStereotype::Fabricated, + methods: vec![], + container_name: instance_name, + line_count: 0 + }, + declaration_type: ContainerType::Class, + annotations: vec![], + constructors: vec![], + field_components: vec![] + }) + + +} \ No newline at end of file diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 4b9f317..3d65ba6 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -1,12 +1,52 @@ +use std::collections::HashMap; + use crate::parse::AST; use crate::prophet::*; -/* +mod class_def; +use class_def::*; + pub fn find_components(ast: AST, path: &str) -> Vec { find_components_internal(ast, String::new(), path) } -pub fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec { +fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec { + let mut components = vec![]; + + for node in ast + .find_all_children_by_type(&[ + "type_declaration", + "func_declaration", + ]) + .get_or_insert(vec![]) + .iter() + { + match &*node.r#type { + //"function_declaration" => match transform_into_method() + "type_declaration" => { + for decl in node.find_all_children_by_type(&["type_spec"]).get_or_insert(vec![]).iter() { + match &*decl.r#type { + "type_spec" => { + parse_struct(&ast, &package, path); + }, + _ => { + println!("{}", &decl.r#type); + }, + } + } + } + tag => todo!("Cannot identify provided tag {:#?}", tag), + }; + } + components } -*/ + +/* +pub fn transform_into_method(ast: AST, module_name: &str, path: &str) -> Option { + let decl = match ast.find_child_by_type(&[ + "" + ]) +} + */ + diff --git a/src/parse.rs b/src/parse.rs index 47b4189..7843a24 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -88,7 +88,7 @@ impl AST { LANG::Cpp => (cpp::find_components(self, path, path), lang.into()), LANG::Java => (java::find_components(self, path), lang.into()), LANG::Python => (vec![], Language::Python), - LANG::Go => (vec![], Language::Go), + LANG::Go => (go::find_components(self, path), lang.into()), lang => { println!("unsupported lang: {:?}", lang); (vec![], Language::Unknown) From 86d3c280c7fa42bd71e0f2f7481d48f7096281ca Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Wed, 30 Jun 2021 13:51:23 -0500 Subject: [PATCH 03/21] fixed calling of parse_struct --- src/lang/go/class_def.rs | 3 +-- src/lang/go/mod.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index bf2bcbf..7f3091d 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -15,8 +15,7 @@ pub(crate)fn parse_struct( }, None => InstanceType::ClassComponent, }; - - + let instance_name = match ast.find_child_by_type(&["type_identifier"]) { Some(identifier) => identifier.value.clone(), None => "Fail".into(), diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 3d65ba6..8aa9cb6 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -27,7 +27,7 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec { - parse_struct(&ast, &package, path); + parse_struct(decl, &package, path); }, _ => { println!("{}", &decl.r#type); From 5a9401f4a60538f6c7d2387a6405ae668fe898a2 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Wed, 30 Jun 2021 14:47:37 -0500 Subject: [PATCH 04/21] added parse_types method --- src/lang/go/class_def.rs | 25 ++++++++++++++++++++++--- src/lang/go/mod.rs | 13 ++++--------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index 7f3091d..6a632b6 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -1,8 +1,27 @@ use crate::parse::AST; use crate::prophet::*; +pub(crate) fn parse_types( + ast: &AST, + package: &str, + path: &str +) -> Vec{ + let mut vec = vec![]; -pub(crate)fn parse_struct( + for node in ast.find_all_children_by_type(&["type_spec"]).get_or_insert(vec![]).iter() { + match &*node.r#type { + "type_spec" => match parse_struct(node, &package, path) { + Some(struct_type) => vec.push(ComponentType::ClassOrInterfaceComponent(struct_type)), + None => {} + }, + tag => todo!("Cannot identify provided tag {:#?}", tag), + }; + } + + vec +} + +pub(crate) fn parse_struct( ast: &AST, package: &str, path: &str @@ -15,14 +34,14 @@ pub(crate)fn parse_struct( }, None => InstanceType::ClassComponent, }; - + let instance_name = match ast.find_child_by_type(&["type_identifier"]) { Some(identifier) => identifier.value.clone(), None => "Fail".into(), }; //let instance_name = ast.find_child_by_type(&["type_identifier"]).map_or_else(|| "fail".into(), |t| t.value.clone()); - println!("{}", instance_name.to_string()); + //println!("{}", instance_name.to_string()); let component = ComponentInfo { diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 8aa9cb6..8cfa629 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -24,15 +24,10 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec match transform_into_method() "type_declaration" => { - for decl in node.find_all_children_by_type(&["type_spec"]).get_or_insert(vec![]).iter() { - match &*decl.r#type { - "type_spec" => { - parse_struct(decl, &package, path); - }, - _ => { - println!("{}", &decl.r#type); - }, - } + let types = parse_types(node, &package, path); + + for component in types { + components.push(component); } } tag => todo!("Cannot identify provided tag {:#?}", tag), From 0040fbdd7adaf693046e4bd76aa9335f194069fa Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Fri, 2 Jul 2021 13:20:03 -0500 Subject: [PATCH 05/21] added variable and type detection --- src/lang/go/class_def.rs | 118 +++++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 16 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index 6a632b6..bc8ced7 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -10,7 +10,7 @@ pub(crate) fn parse_types( for node in ast.find_all_children_by_type(&["type_spec"]).get_or_insert(vec![]).iter() { match &*node.r#type { - "type_spec" => match parse_struct(node, &package, path) { + "type_spec" => match parse_type(node, &package, path) { Some(struct_type) => vec.push(ComponentType::ClassOrInterfaceComponent(struct_type)), None => {} }, @@ -21,13 +21,13 @@ pub(crate) fn parse_types( vec } -pub(crate) fn parse_struct( +pub(crate) fn parse_type( ast: &AST, package: &str, path: &str ) -> Option { - - let instance_type = match ast.find_child_by_type(&["struct"]) { + //determine the type of the instance + let instance_type = match ast.find_child_by_type(&["struct_type"]) { Some(r#type) => match &*r#type.value { "interface" => InstanceType::InterfaceComponent, _ => InstanceType::ClassComponent, @@ -35,36 +35,122 @@ pub(crate) fn parse_struct( None => InstanceType::ClassComponent, }; + //find the name of the type let instance_name = match ast.find_child_by_type(&["type_identifier"]) { Some(identifier) => identifier.value.clone(), - None => "Fail".into(), + None => "".into(), }; - //let instance_name = ast.find_child_by_type(&["type_identifier"]).map_or_else(|| "fail".into(), |t| t.value.clone()); - //println!("{}", instance_name.to_string()); - + //determine what type the instance is + let declaration_type = match instance_type { + InstanceType::InterfaceComponent => ContainerType::Interface, + _ => ContainerType::Class, + }; + //get the component information using the path, package, instance name, and instance type let component = ComponentInfo { path: path.into(), package_name: package.into(), - instance_name: format!("{}", instance_name), + instance_name: format!( + "{}::{}", + instance_name, + match instance_type { + InstanceType::InterfaceComponent => "InterfaceComponent", + _ => "ClassComponent", + } + ), instance_type: instance_type, }; + // Find bounds + let (start, end) = match ast.span { + Some(span) => (span.0 as i32, span.1 as i32), + None => (0, 0), + }; + + // Define default values + let stereotype = ContainerStereotype::Entity; // TODO determine properly + let mut fields = vec![]; + let mut constructors = vec![]; + let mut methods = vec![]; + //let mut modifier = Modifier::new(); + + for child in ast.children.iter() { + match &*child.r#type { + "struct_type" => { + parse_type_body(child, &component, &mut methods, &mut fields); + }, + _ => {}, + } + } + + Some(ClassOrInterfaceComponent { component: ContainerComponent { - component, + component: component, accessor: AccessorType::Private, - stereotype: ContainerStereotype::Fabricated, - methods: vec![], + stereotype: stereotype, + methods: methods, container_name: instance_name, - line_count: 0 + line_count: end - start + 1, }, - declaration_type: ContainerType::Class, + declaration_type: declaration_type, annotations: vec![], - constructors: vec![], - field_components: vec![] + constructors: constructors, + field_components: fields }) +} + +fn parse_type_body( + ast: &AST, + component: &ComponentInfo, + methods: &mut Vec, + fields: &mut Vec, +) { + for node in ast.children.iter() { + match &*node.r#type { + "field_declaration_list" => fields.append(&mut parse_fields(node, component)), + _ => {}, + } + } +} + +fn parse_fields(ast: &AST, component: &ComponentInfo) -> Vec { + let mut fields = vec![]; + for node in ast.children.iter() { + match &*node.r#type { + "field_declaration" => { + let field_identifier = match node.find_child_by_type(&["field_identifier"]) { + Some(field_id) => field_id.value.clone(), + None => "".into(), + }; + let type_identifier = match node.find_child_by_type(&["type_identifier"]) { + Some(r#type) => r#type.value.to_string(), + None => "".into(), + }; + + fields.push(FieldComponent { + component: ComponentInfo { + path: component.path.clone(), + package_name: component.package_name.clone(), + instance_name: field_identifier.clone(), + instance_type: InstanceType::FieldComponent, + }, + annotations: vec![], + variables: vec![], + field_name: field_identifier, + accessor: AccessorType::Private, + is_static: false, + is_final: false, + default_value: String::new(), + r#type: type_identifier, + }) + + }, + _ => {}, + } + } + fields } \ No newline at end of file From 015d7933ed47ff5ee478ff6ed62398d22b62ea63 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Fri, 2 Jul 2021 13:46:47 -0500 Subject: [PATCH 06/21] added initial package detection --- src/lang/go/mod.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 8cfa629..5e79a5a 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -17,19 +17,24 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec match transform_into_method() + "package_clause" => { + package = parse_package(node); + } "type_declaration" => { - let types = parse_types(node, &package, path); + let types = parse_types(node, &*package, path); for component in types { components.push(component); } } + tag => todo!("Cannot identify provided tag {:#?}", tag), }; } @@ -45,3 +50,10 @@ pub fn transform_into_method(ast: AST, module_name: &str, path: &str) -> Option< } */ +fn parse_package(ast: &AST) -> String { + match ast.find_child_by_type(&["package_identifier"]) { + Some(pkg) => pkg.value.to_string(), + None => "".into(), + } +} + From dced4e6b1177729e8cb6ace09a361f4cac9b3e63 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Fri, 2 Jul 2021 14:23:52 -0500 Subject: [PATCH 07/21] made fields appear properly as public --- src/lang/go/class_def.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index bc8ced7..317ae6a 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -88,7 +88,7 @@ pub(crate) fn parse_type( Some(ClassOrInterfaceComponent { component: ContainerComponent { component: component, - accessor: AccessorType::Private, + accessor: AccessorType::Public, stereotype: stereotype, methods: methods, container_name: instance_name, @@ -141,7 +141,7 @@ fn parse_fields(ast: &AST, component: &ComponentInfo) -> Vec { annotations: vec![], variables: vec![], field_name: field_identifier, - accessor: AccessorType::Private, + accessor: AccessorType::Public, is_static: false, is_final: false, default_value: String::new(), From 8dac6646f78247671f702298241d2da567079107 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Sun, 18 Jul 2021 17:31:49 -0500 Subject: [PATCH 08/21] added function parsing, as well as general refactoring --- src/lang/go/class_def.rs | 28 ++++++----- src/lang/go/function_def.rs | 88 ++++++++++++++++++++++++++++++++++ src/lang/go/mod.rs | 51 +++++++++++++------- src/lang/go/util/identifier.rs | 26 ++++++++++ src/lang/go/util/mod.rs | 22 +++++++++ src/lang/go/util/vartype.rs | 22 +++++++++ 6 files changed, 208 insertions(+), 29 deletions(-) create mode 100644 src/lang/go/function_def.rs create mode 100644 src/lang/go/util/identifier.rs create mode 100644 src/lang/go/util/mod.rs create mode 100644 src/lang/go/util/vartype.rs diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index 317ae6a..af2de18 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -1,7 +1,9 @@ use crate::parse::AST; use crate::prophet::*; +use crate::go::util::vartype::find_type; +use crate::go::util::identifier::parse_identifier; -pub(crate) fn parse_types( +pub(crate) fn parse_struct( ast: &AST, package: &str, path: &str @@ -10,7 +12,7 @@ pub(crate) fn parse_types( for node in ast.find_all_children_by_type(&["type_spec"]).get_or_insert(vec![]).iter() { match &*node.r#type { - "type_spec" => match parse_type(node, &package, path) { + "type_spec" => match parse_struct_internal(node, &package, path) { Some(struct_type) => vec.push(ComponentType::ClassOrInterfaceComponent(struct_type)), None => {} }, @@ -21,7 +23,7 @@ pub(crate) fn parse_types( vec } -pub(crate) fn parse_type( +pub(crate) fn parse_struct_internal( ast: &AST, package: &str, path: &str @@ -64,7 +66,7 @@ pub(crate) fn parse_type( // Find bounds let (start, end) = match ast.span { - Some(span) => (span.0 as i32, span.1 as i32), + Some(span) => (span.0 as i32, span.2 as i32), None => (0, 0), }; @@ -78,7 +80,7 @@ pub(crate) fn parse_type( for child in ast.children.iter() { match &*child.r#type { "struct_type" => { - parse_type_body(child, &component, &mut methods, &mut fields); + parse_struct_body(child, &component, &mut methods, &mut fields); }, _ => {}, } @@ -92,18 +94,16 @@ pub(crate) fn parse_type( stereotype: stereotype, methods: methods, container_name: instance_name, - line_count: end - start + 1, + line_count: (end - start) + 1, }, declaration_type: declaration_type, annotations: vec![], constructors: constructors, - field_components: fields + field_components: fields, }) - - } -fn parse_type_body( +fn parse_struct_body( ast: &AST, component: &ComponentInfo, methods: &mut Vec, @@ -122,15 +122,21 @@ fn parse_fields(ast: &AST, component: &ComponentInfo) -> Vec { for node in ast.children.iter() { match &*node.r#type { "field_declaration" => { + let field_identifier = parse_identifier(node); + /* let field_identifier = match node.find_child_by_type(&["field_identifier"]) { Some(field_id) => field_id.value.clone(), None => "".into(), }; + */ + + let type_identifier = find_type(node); + /* let type_identifier = match node.find_child_by_type(&["type_identifier"]) { Some(r#type) => r#type.value.to_string(), None => "".into(), }; - + */ fields.push(FieldComponent { component: ComponentInfo { path: component.path.clone(), diff --git a/src/lang/go/function_def.rs b/src/lang/go/function_def.rs new file mode 100644 index 0000000..ef6fd0a --- /dev/null +++ b/src/lang/go/function_def.rs @@ -0,0 +1,88 @@ +use crate::parse::AST; +use crate::prophet::*; +use crate::go::util::vartype::find_type; +use crate::go::util::identifier::parse_identifier; +use crate::msd::NodeType::MethodParam; + +pub(crate) fn parse_function( + ast: &AST, + module_name: &str, + path: &str +) -> Option { + //find the function name + let fn_identifier = parse_identifier(ast); + //get return type + let return_type = find_type(ast); + let component = ComponentInfo { + path: path.to_string(), + package_name: module_name.to_string(), + instance_name: fn_identifier.clone(), + instance_type: InstanceType::MethodComponent, + }; + + let span = ast.span.expect("No span for a method! AST malformed!"); + let line_begin = span.0 as i32; + let line_end = span.2 as i32; + + //parse parameter list + let mut parameters = vec![]; + let param_list = match ast.find_child_by_type(&["parameter_list"]) { + Some(list) => { + //iterate through the list, pushing each parameter to parameters + for node in list.children.iter() { + match &*node.r#type { + "parameter_declaration" => parameters.push(parse_parameter(node, &component)), + _ => {}, + } + } + }, + None => {} + }; + + + + + let func = MethodComponent { + component: ComponentInfo { + path: path.into(), + package_name: module_name.to_string(), + instance_name: fn_identifier.clone(), + instance_type: InstanceType::MethodComponent + }, + accessor: AccessorType::Private, + method_name: fn_identifier, + return_type: return_type, + parameters: parameters, + is_static: false, + is_abstract: false, + is_final: false, + sub_methods: vec![], + annotations: vec![], + line_count: line_end - line_begin + 1, + line_begin, + line_end, + body: None + }; + Some(func) + +} + +fn parse_parameter(ast: &AST, component: &ComponentInfo) -> MethodParamComponent { + let mut name = parse_identifier(ast); + //let mut modifier = Modifier::new(); + let param_type = find_type(ast); + + + MethodParamComponent { + component: ComponentInfo { + path: component.path.clone(), + package_name: component.package_name.clone(), + instance_name: component.instance_name.clone(), + instance_type: InstanceType::MethodParamComponent, + }, + annotation: None, + r#type: param_type.into(), + parameter_name: name.into(), + } + +} \ No newline at end of file diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 5e79a5a..8ada4d2 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -4,7 +4,12 @@ use crate::parse::AST; use crate::prophet::*; mod class_def; +mod function_def; +mod util; + use class_def::*; +use function_def::*; +use crate::go::util::identifier::parse_identifier; pub fn find_components(ast: AST, path: &str) -> Vec { find_components_internal(ast, String::new(), path) @@ -16,25 +21,29 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec match transform_into_method() + "function_declaration" => match parse_function(node, &*package, path) { + Some(function) => components.push(ComponentType::MethodComponent(function.clone())), + None => {}, + }, "package_clause" => { package = parse_package(node); - } + }, "type_declaration" => { - let types = parse_types(node, &*package, path); + let types = parse_struct(node, &*package, path); for component in types { components.push(component); } - } - + }, + "import_declaration" => println!("{}", parse_import(node)), tag => todo!("Cannot identify provided tag {:#?}", tag), }; } @@ -42,18 +51,24 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec Option { - let decl = match ast.find_child_by_type(&[ - "" - ]) +fn parse_package(ast: &AST) -> String { + parse_identifier(ast) } - */ -fn parse_package(ast: &AST) -> String { - match ast.find_child_by_type(&["package_identifier"]) { - Some(pkg) => pkg.value.to_string(), - None => "".into(), - } +fn parse_import(ast: &AST) -> String { + let mut buffer = String::new(); + for node in ast.children.iter() { + match &*node.r#type { + "import_spec" => { + match node.find_child_by_type(&["interpreted_string_literal"]) { + Some(import) => buffer.push_str(&*import.value), + None => {} + } + }, + _ => buffer.push_str(&*parse_import(node)) + } + } + + buffer } diff --git a/src/lang/go/util/identifier.rs b/src/lang/go/util/identifier.rs new file mode 100644 index 0000000..09b3503 --- /dev/null +++ b/src/lang/go/util/identifier.rs @@ -0,0 +1,26 @@ +use crate::go::util::stringify_tree_children; +use crate::AST; + +/// Indicates when no type is found +pub const NO_NAME: &str = "N/A"; + +pub(crate) fn parse_identifier(ast: &AST) -> String { + let name_node = match ast.find_child_by_type(&[ + "package_identifier", + "field_identifier", + "identifier"]) { + Some(node) => node, + None => ast, + }; + + let name_str = match &*name_node.r#type { + "package_identifier" + | "field_identifier" + | "identifier" => name_node.value.clone(), + + _ => NO_NAME.into(), + }; + + name_str +} + diff --git a/src/lang/go/util/mod.rs b/src/lang/go/util/mod.rs new file mode 100644 index 0000000..e167462 --- /dev/null +++ b/src/lang/go/util/mod.rs @@ -0,0 +1,22 @@ +use crate::AST; + +pub(crate) mod identifier; +pub(crate) mod vartype; + +/// Convert a vector into an Option. If the vector is empty, swaps it out for None; otherwise is Some(vector) +pub(crate) fn fold_vec(vector: Vec) -> Option> { + if !vector.is_empty() { + Some(vector) + } else { + None + } +} + +/// Convert the children of a provided tree into a single, consecutive string +pub(crate) fn stringify_tree_children(ast: &AST) -> String { + let mut buffer = String::new(); + for member in ast.children.iter() { + buffer.push_str(&*member.value); + } + buffer +} \ No newline at end of file diff --git a/src/lang/go/util/vartype.rs b/src/lang/go/util/vartype.rs new file mode 100644 index 0000000..52189f5 --- /dev/null +++ b/src/lang/go/util/vartype.rs @@ -0,0 +1,22 @@ +use crate::go::util::stringify_tree_children; +use crate::AST; + +/// Indicates when no type is found +pub const NO_TYPE: &str = "N/A"; + + +pub(crate) fn find_type(ast: &AST) -> String { + let id_node = match ast.find_child_by_type(&["type_identifier"]) { + Some(node) => node, + None => ast, + }; + let r#type = parse_type(id_node); + r#type +} + +fn parse_type(ast: &AST) -> String { + match &*ast.r#type { + "type_identifier" => ast.value.clone(), + _ => NO_TYPE.into() + } +} \ No newline at end of file From 63547bcfaf76952ee022cc014526e3f482f87eb9 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Mon, 19 Jul 2021 12:27:16 -0500 Subject: [PATCH 09/21] made functions default as public --- src/lang/go/function_def.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lang/go/function_def.rs b/src/lang/go/function_def.rs index ef6fd0a..1956666 100644 --- a/src/lang/go/function_def.rs +++ b/src/lang/go/function_def.rs @@ -13,6 +13,7 @@ pub(crate) fn parse_function( let fn_identifier = parse_identifier(ast); //get return type let return_type = find_type(ast); + let component = ComponentInfo { path: path.to_string(), package_name: module_name.to_string(), @@ -49,7 +50,7 @@ pub(crate) fn parse_function( instance_name: fn_identifier.clone(), instance_type: InstanceType::MethodComponent }, - accessor: AccessorType::Private, + accessor: AccessorType::Public, method_name: fn_identifier, return_type: return_type, parameters: parameters, From a70eb38f6538b22aa277fdc07c9eb86a978f0e75 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Mon, 19 Jul 2021 18:57:05 -0500 Subject: [PATCH 10/21] added initial implementation for member functions --- src/lang/go/class_def.rs | 24 ++++-------- src/lang/go/function_def.rs | 78 +++++++++++++++++++++++++++++++++++-- src/lang/go/mod.rs | 55 ++++++++++++++++++++++++-- 3 files changed, 132 insertions(+), 25 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index af2de18..36054f7 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -3,26 +3,16 @@ use crate::prophet::*; use crate::go::util::vartype::find_type; use crate::go::util::identifier::parse_identifier; -pub(crate) fn parse_struct( - ast: &AST, - package: &str, - path: &str -) -> Vec{ - let mut vec = vec![]; - - for node in ast.find_all_children_by_type(&["type_spec"]).get_or_insert(vec![]).iter() { - match &*node.r#type { - "type_spec" => match parse_struct_internal(node, &package, path) { - Some(struct_type) => vec.push(ComponentType::ClassOrInterfaceComponent(struct_type)), - None => {} - }, - tag => todo!("Cannot identify provided tag {:#?}", tag), - }; - } +pub(crate) fn parse_struct(ast: &AST, package: &str, path: &str) -> Option { + let node = match ast.find_child_by_type(&["type_spec"]) { + Some(type_node) => type_node, + None => ast + }; - vec + parse_struct_internal(node, &package, path) } + pub(crate) fn parse_struct_internal( ast: &AST, package: &str, diff --git a/src/lang/go/function_def.rs b/src/lang/go/function_def.rs index 1956666..7dd19a9 100644 --- a/src/lang/go/function_def.rs +++ b/src/lang/go/function_def.rs @@ -40,9 +40,6 @@ pub(crate) fn parse_function( None => {} }; - - - let func = MethodComponent { component: ComponentInfo { path: path.into(), @@ -65,15 +62,88 @@ pub(crate) fn parse_function( body: None }; Some(func) +} + +pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) + -> (String, MethodComponent) { + let method_identifier = parse_identifier(ast); + let return_type = find_type(ast); + + let component = ComponentInfo { + path: path.to_string(), + package_name: module_name.to_string(), + instance_name: method_identifier.clone(), + instance_type: InstanceType::MethodComponent, + }; + + let span = ast.span.expect("No span for a method! AST malformed!"); + let line_begin = span.0 as i32; + let line_end = span.2 as i32; + + //parse first parameter list, which ideally is where the actual parent struct is + let mut parent_struct_type_name = String::new(); + match ast.find_child_by_type(&["parameter_list"]) { + Some(parameter_list) => { + match parameter_list.find_child_by_type(&["parameter_declaration"]) { + Some(parameter_node) => { + parent_struct_type_name = parse_parameter(parameter_node, &component).r#type.clone() + }, + None => {}, + } + }, + None => {}, + }; + + let mut i = 0; + let mut parameters = vec![]; + for node in ast.find_all_children_by_type(&["parameter_list"]).get_or_insert(vec![]).iter() { + if i == 0 { + i = 1; + } + else { + for param_node in node.children.iter() { + match &*param_node.r#type { + "parameter_declaration" => parameters.push(parse_parameter(param_node, &component)), + _ => {}, + } + } + } + }; + + let func = MethodComponent { + component: ComponentInfo { + path: path.into(), + package_name: module_name.to_string(), + instance_name: method_identifier.clone(), + instance_type: InstanceType::MethodComponent + }, + accessor: AccessorType::Public, + method_name: method_identifier, + return_type: return_type, + parameters: parameters, + is_static: false, + is_abstract: false, + is_final: false, + sub_methods: vec![], + annotations: vec![], + line_count: line_end - line_begin + 1, + line_begin, + line_end, + body: None + }; + (parent_struct_type_name, func) } + + + + fn parse_parameter(ast: &AST, component: &ComponentInfo) -> MethodParamComponent { let mut name = parse_identifier(ast); //let mut modifier = Modifier::new(); let param_type = find_type(ast); - MethodParamComponent { component: ComponentInfo { path: component.path.clone(), diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 8ada4d2..82792c2 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -10,6 +10,7 @@ mod util; use class_def::*; use function_def::*; use crate::go::util::identifier::parse_identifier; +use std::borrow::Borrow; pub fn find_components(ast: AST, path: &str) -> Vec { find_components_internal(ast, String::new(), path) @@ -17,7 +18,9 @@ pub fn find_components(ast: AST, path: &str) -> Vec { fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec { let mut components = vec![]; + let mut types = HashMap::new(); + //first parse for all nodes EXCEPT for "method_declaration" for node in ast .find_all_children_by_type(&[ "type_declaration", @@ -37,10 +40,12 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec { - let types = parse_struct(node, &*package, path); - - for component in types { - components.push(component); + match parse_struct(node, &*package, path) { + Some(struct_type) => { + let struct_name = struct_type.component.container_name.clone(); + types.insert(struct_name, struct_type); + }, + None => {} } }, "import_declaration" => println!("{}", parse_import(node)), @@ -48,6 +53,48 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec { + //create a copy of the instance of the original struct and add the method to it + let mut new_methods = parent_struct.component.methods.clone(); + new_methods.push(tuple.1.clone()); + + let parent_component = parent_struct.component.clone(); + let new_parent_struct = ClassOrInterfaceComponent { + component: ContainerComponent { + component: parent_component.component.clone(), + accessor: parent_component.accessor.clone(), + stereotype: parent_component.stereotype.clone(), + methods: new_methods, + container_name: parent_component.container_name.clone(), + line_count: parent_component.line_count.clone(), + }, + declaration_type: ContainerType::Class, + annotations: parent_struct.annotations.clone(), + constructors: parent_struct.constructors.clone(), + field_components: parent_struct.field_components.clone(), + }; + + types.insert(tuple.0, new_parent_struct); + }, + None => {}, + } + + } + + //push types onto the components vector + for (k, v) in types { + components.push(ComponentType::ClassOrInterfaceComponent(v)); + } + components } From d3a5f9f80d85c7480031aaad5a78be2f99965be5 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Tue, 20 Jul 2021 10:05:15 -0500 Subject: [PATCH 11/21] edits to improve readability --- src/lang/go/class_def.rs | 15 +-------------- src/lang/go/function_def.rs | 1 - src/lang/go/mod.rs | 2 +- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index 36054f7..baf2d73 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -12,7 +12,6 @@ pub(crate) fn parse_struct(ast: &AST, package: &str, path: &str) -> Option Vec { match &*node.r#type { "field_declaration" => { let field_identifier = parse_identifier(node); - /* - let field_identifier = match node.find_child_by_type(&["field_identifier"]) { - Some(field_id) => field_id.value.clone(), - None => "".into(), - }; - */ - let type_identifier = find_type(node); - /* - let type_identifier = match node.find_child_by_type(&["type_identifier"]) { - Some(r#type) => r#type.value.to_string(), - None => "".into(), - }; - */ + fields.push(FieldComponent { component: ComponentInfo { path: component.path.clone(), diff --git a/src/lang/go/function_def.rs b/src/lang/go/function_def.rs index 7dd19a9..70d579f 100644 --- a/src/lang/go/function_def.rs +++ b/src/lang/go/function_def.rs @@ -110,7 +110,6 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) } }; - let func = MethodComponent { component: ComponentInfo { path: path.into(), diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 82792c2..9ac7fdc 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -90,7 +90,7 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec Date: Tue, 20 Jul 2021 10:33:32 -0500 Subject: [PATCH 12/21] improvement to parsing imports to allow for import lists --- src/lang/go/mod.rs | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 9ac7fdc..9b1f6fe 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -108,14 +108,49 @@ fn parse_import(ast: &AST) -> String { match &*node.r#type { "import_spec" => { match node.find_child_by_type(&["interpreted_string_literal"]) { - Some(import) => buffer.push_str(&*import.value), + Some(import) => buffer.push_str(&*trim_import((&*import.value).to_string())), None => {} } }, + "import_spec_list" => { + for import_node in node.children.iter() { + match &*import_node.r#type { + "import_spec" => { + match import_node.find_child_by_type(&["interpreted_string_literal"]) { + Some(import) => { + buffer.push_str(&*trim_import((&*import.value).to_string())); + buffer.push_str("\n"); + }, + None => {} + } + }, + _ => {} + } + } + } _ => buffer.push_str(&*parse_import(node)) } } + //to remove the last newline for multiple imports + if buffer.ends_with('\n') { + buffer.pop(); + } + buffer } +/// removes the quotations surrounding the values of the "interpreted_string_literal" nodes +fn trim_import(import_str: String) -> String { + let mut str = import_str.clone(); + + /// additional checks to see if the string actually begins and ends with quotation marks + if str.starts_with('\"') { + str.remove(0); + } + if str.ends_with('\"') { + str.pop(); + } + + str +} \ No newline at end of file From 2b0bbac6b7686ab6048bbc723775b80614ee2d46 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Fri, 30 Jul 2021 10:04:30 -0600 Subject: [PATCH 13/21] general fixes and updates --- src/lang/go/class_def.rs | 20 +++++++++++++------- src/lang/go/mod.rs | 12 ++++++------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index baf2d73..2b1eaf4 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -3,29 +3,35 @@ use crate::prophet::*; use crate::go::util::vartype::find_type; use crate::go::util::identifier::parse_identifier; -pub(crate) fn parse_struct(ast: &AST, package: &str, path: &str) -> Option { +pub(crate) fn parse_type(ast: &AST, package: &str, path: &str) -> Option { let node = match ast.find_child_by_type(&["type_spec"]) { Some(type_node) => type_node, None => ast }; - parse_struct_internal(node, &package, path) + parse_type_internal(node, &package, path) } -pub(crate) fn parse_struct_internal( +pub(crate) fn parse_type_internal( ast: &AST, package: &str, path: &str ) -> Option { //determine the type of the instance - let instance_type = match ast.find_child_by_type(&["struct_type"]) { - Some(r#type) => match &*r#type.value { - "interface" => InstanceType::InterfaceComponent, + + let instance_type = match ast.find_child_by_type(&["struct_type", "interface_type"]) { + Some(node) => match &*node.r#type { + "interface_type" => InstanceType::InterfaceComponent, _ => InstanceType::ClassComponent, }, None => InstanceType::ClassComponent, }; - + /* + let instance_type = match ast.find_child_by_type(&["struct_type"]) { + Some(child) => InstanceType::ClassComponent, + None => InstanceType::InterfaceComponent, + }; + */ //find the name of the type let instance_name = match ast.find_child_by_type(&["type_identifier"]) { Some(identifier) => identifier.value.clone(), diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 9b1f6fe..aa6378e 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -40,11 +40,11 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec { - match parse_struct(node, &*package, path) { - Some(struct_type) => { - let struct_name = struct_type.component.container_name.clone(); - types.insert(struct_name, struct_type); - }, + match parse_type(node, &*package, path) { + Some(type_decl) => { + let type_name = type_decl.component.container_name.clone(); + types.insert(type_name, type_decl); + } None => {} } }, @@ -77,7 +77,7 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec Date: Tue, 24 Aug 2021 14:06:35 -0500 Subject: [PATCH 14/21] Updated to add function body parsing --- src/lang/go/function_body/expr.rs | 68 +++++++++++++++++++++++++++++++ src/lang/go/function_body/mod.rs | 36 ++++++++++++++++ src/lang/go/function_body/node.rs | 34 ++++++++++++++++ src/lang/go/function_body/stmt.rs | 63 ++++++++++++++++++++++++++++ src/lang/go/function_def.rs | 26 +++++++++++- src/lang/go/mod.rs | 2 + 6 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 src/lang/go/function_body/expr.rs create mode 100644 src/lang/go/function_body/mod.rs create mode 100644 src/lang/go/function_body/node.rs create mode 100644 src/lang/go/function_body/stmt.rs diff --git a/src/lang/go/function_body/expr.rs b/src/lang/go/function_body/expr.rs new file mode 100644 index 0000000..c670d71 --- /dev/null +++ b/src/lang/go/function_body/expr.rs @@ -0,0 +1,68 @@ +use crate::go::function_body::node::{parse_child_nodes, parse_node}; +use crate::go::function_body::parse_block; +use crate::go::util::vartype::find_type; + +use crate::ast::*; +use crate::ComponentInfo; +use crate::AST; + +pub(crate) fn parse_expr(ast: &AST, component: &ComponentInfo) -> Option { + match &*ast.r#type { + // Variables an initialization + "var_declaration" => parse_assignment(ast, component), + "identifier" => parse_ident(ast, component), + + unknown => None + } +} + + +fn parse_ident(ast: &AST, component: &ComponentInfo) -> Option { + let ident: Expr = Ident::new(ast.value.clone()).into(); + Some(ident.into()) +} + +/// Parse an assignment expression. May contain a variable declaration +pub(crate) fn parse_assignment(ast: &AST, component: &ComponentInfo) -> Option { + // Define attributes + let mut lhs = None; + let mut rhs = None; + + // Find values + for node in ast.children.iter() { + let unknown = &*node.r#type; + if unknown == "=" { + continue; + } + + let result = parse_expr(node, component); + if result.is_some() { + if lhs.is_none() { + lhs = result; + } else if rhs.is_none() { + rhs = result; + } else { + eprintln!( + "Extra parsable tag {} encountered while parsing assignment", + unknown + ); + } + } else { + //log_unknown_tag(unknown, "parse_assignment"); + } + } + + // Assemble + if let Some(lhs) = lhs { + if let Some(rhs) = rhs { + let bin: Expr = BinaryExpr::new(Box::new(lhs.into()), "=".into(), Box::new(rhs)).into(); + Some(bin.into()) + } else { + Some(lhs.into()) + } + } else { + eprintln!("Assignment with no lefthand side!"); + None + } +} + diff --git a/src/lang/go/function_body/mod.rs b/src/lang/go/function_body/mod.rs new file mode 100644 index 0000000..e7045f3 --- /dev/null +++ b/src/lang/go/function_body/mod.rs @@ -0,0 +1,36 @@ +use crate::{ast::Block, ComponentInfo, AST}; + +use self::node::parse_child_nodes; + +mod node; +mod stmt; +mod expr; + + +/// Parse the body of a method, static block, constructor, etc. +pub(crate) fn parse_block(ast: &AST, component: &ComponentInfo) -> Block { + Block::new(parse_child_nodes(ast, component)) +} + + + +/// Logs an unknown tag was encountered. You better not think too much about that. +/// It does not, however, log well-known "filler tags", to keep from cluttering output. +pub(crate) fn log_unknown_tag(tag: &str, parent: &str) { + if !is_common_junk_tag(tag) { + eprintln!("Unknown tag {} encountered while parsing {}!", tag, parent); + } +} + +/// Catch all for standard-issue junk tags from treesitter, to allow easy blanket-silencing of +/// false alarms, to focus on the tags that are actually important +pub(crate) fn is_common_junk_tag(tag: &str) -> bool { + // TECHNICALLY should just be 2 match arms. I split it up by the class of tag, so its easy to + // if a case is handled already. The compiler's gotta be smart enough to figure it out. + match tag { + "if" | "else" | "for" | "while" | "do" | "switch" | "try" | "catch" | "finally" => true, + "class" | "interface" | "enum" => true, + "(" | ")" | "{" | "}" | "->" | ";" | "," | "." | "..." => true, + _ => false, + } +} diff --git a/src/lang/go/function_body/node.rs b/src/lang/go/function_body/node.rs new file mode 100644 index 0000000..0fdd64c --- /dev/null +++ b/src/lang/go/function_body/node.rs @@ -0,0 +1,34 @@ +use crate::ast::*; +use crate::ComponentInfo; +use crate::AST; + +use crate::go::function_body::stmt::parse_decl; + +use super::{ + parse_block, + //stmt::{parse_do_while, parse_if, parse_labeled, parse_return, parse_throw, parse_while}, +}; +use crate::go::function_body::expr::parse_expr; + + +pub(crate) fn parse_child_nodes(ast: &AST, component: &ComponentInfo) -> Vec { + ast.children + .iter() + .map(|member| parse_node(member, component)) + .flat_map(|some| some) + .collect() +} + +pub(crate) fn parse_node(ast: &AST, component: &ComponentInfo) -> Option { + match &*ast.r#type { + "var_declaration" => { + let decl = Some(Node::Stmt(parse_decl(ast, component).into())); + + decl + } + _ => { + let expr: Stmt = parse_expr(ast, component)?.into(); + Some(expr.into()) + } + } +} \ No newline at end of file diff --git a/src/lang/go/function_body/stmt.rs b/src/lang/go/function_body/stmt.rs new file mode 100644 index 0000000..dab5091 --- /dev/null +++ b/src/lang/go/function_body/stmt.rs @@ -0,0 +1,63 @@ +use crate::ast::*; +use crate::ComponentInfo; +use crate::AST; + +use crate::go::util::vartype::find_type; + + +//use super::{expr::parse_expr, is_common_junk_tag, node::parse_node}; +use super::node::parse_node; +use crate::go::function_body::node::parse_child_nodes; + +/// Parse an AST section containing a variable declaration +pub(crate) fn parse_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt { + // Extract informtion about the variable + let ast = match ast.find_child_by_type(&["var_spec"]) { + Some(var) => var, + None => ast + }; + let r#type = find_type(ast); + + + + // Determine the value it was set to + let rhs = parse_child_nodes(ast, component); + + let mut decl = DeclStmt::new(vec![], vec![]); + for var in rhs.iter() { + // Extract expression from the hierarchy + let base = match var { + Node::Stmt(Stmt::ExprStmt(ExprStmt { expr, .. })) | Node::Expr(expr) => expr, + _ => { + eprintln!("Unable to interpret as variable: {:#?}", var); + continue; + } + }; + + // Parse variable + match base { + Expr::BinaryExpr(expr) => match expr.lhs.as_ref() { + Expr::Ident(lhs) => { + decl.variables + .push(VarDecl::new(Some(r#type.clone()), lhs.clone())); + decl.expressions.push(Some(expr.rhs.as_ref().clone())); + } + unknown => eprintln!("Expected Ident got {:#?}", unknown), + }, + Expr::Ident(id) => { + decl.variables + .push(VarDecl::new(Some(r#type.clone()), id.clone())); + decl.expressions.push(None); + } + unknown => { + eprintln!("Expected BinaryExpr or Ident, got {:#?}", unknown); + } + } + } + + + for var_decl in decl.variables.iter_mut() { + var_decl.var_type = Some(r#type.clone()); + } + decl.into() +} \ No newline at end of file diff --git a/src/lang/go/function_def.rs b/src/lang/go/function_def.rs index 70d579f..84194ea 100644 --- a/src/lang/go/function_def.rs +++ b/src/lang/go/function_def.rs @@ -3,6 +3,7 @@ use crate::prophet::*; use crate::go::util::vartype::find_type; use crate::go::util::identifier::parse_identifier; use crate::msd::NodeType::MethodParam; +use crate::go::function_body::parse_block; pub(crate) fn parse_function( ast: &AST, @@ -21,6 +22,7 @@ pub(crate) fn parse_function( instance_type: InstanceType::MethodComponent, }; + let mut body = None; let span = ast.span.expect("No span for a method! AST malformed!"); let line_begin = span.0 as i32; let line_end = span.2 as i32; @@ -40,6 +42,15 @@ pub(crate) fn parse_function( None => {} }; + for member in ast.children.iter() { + match &*member.r#type { + "block" => { + body = Some(parse_block(member, &component)); + } + _ => {} + } + } + let func = MethodComponent { component: ComponentInfo { path: path.into(), @@ -59,7 +70,7 @@ pub(crate) fn parse_function( line_count: line_end - line_begin + 1, line_begin, line_end, - body: None + body }; Some(func) } @@ -76,6 +87,8 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) instance_type: InstanceType::MethodComponent, }; + //Define fields + let mut body = None; let span = ast.span.expect("No span for a method! AST malformed!"); let line_begin = span.0 as i32; let line_end = span.2 as i32; @@ -110,6 +123,15 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) } }; + for member in ast.children.iter() { + match &*member.r#type { + "block" => { + body = Some(parse_block(member, &component)); + } + _ => {} + } + } + let func = MethodComponent { component: ComponentInfo { path: path.into(), @@ -129,7 +151,7 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) line_count: line_end - line_begin + 1, line_begin, line_end, - body: None + body }; (parent_struct_type_name, func) } diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index aa6378e..54a5314 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -6,11 +6,13 @@ use crate::prophet::*; mod class_def; mod function_def; mod util; +mod function_body; use class_def::*; use function_def::*; use crate::go::util::identifier::parse_identifier; use std::borrow::Borrow; +use crate::lang::go::function_body::parse_block; pub fn find_components(ast: AST, path: &str) -> Vec { find_components_internal(ast, String::new(), path) From e0eb98f6e9b2ec7bfd52e19ad271ccac185878de Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Sun, 3 Oct 2021 17:03:46 -0500 Subject: [PATCH 15/21] added elementary parsing of function bodies --- src/lang/go/class_def.rs | 30 +++-- src/lang/go/function_body/expr.rs | 134 ++++++++++++++++++- src/lang/go/function_body/mod.rs | 5 +- src/lang/go/function_body/node.rs | 28 ++-- src/lang/go/function_body/stmt.rs | 207 ++++++++++++++++++++++++++++-- src/lang/go/function_def.rs | 80 ++++++------ src/lang/go/mod.rs | 69 +++++----- 7 files changed, 432 insertions(+), 121 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index 2b1eaf4..ae95abc 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -1,12 +1,16 @@ +use crate::go::util::identifier::parse_identifier; +use crate::go::util::vartype::find_type; use crate::parse::AST; use crate::prophet::*; -use crate::go::util::vartype::find_type; -use crate::go::util::identifier::parse_identifier; -pub(crate) fn parse_type(ast: &AST, package: &str, path: &str) -> Option { +pub(crate) fn parse_type( + ast: &AST, + package: &str, + path: &str, +) -> Option { let node = match ast.find_child_by_type(&["type_spec"]) { Some(type_node) => type_node, - None => ast + None => ast, }; parse_type_internal(node, &package, path) @@ -15,7 +19,7 @@ pub(crate) fn parse_type(ast: &AST, package: &str, path: &str) -> Option Option { //determine the type of the instance @@ -76,12 +80,11 @@ pub(crate) fn parse_type_internal( match &*child.r#type { "struct_type" => { parse_struct_body(child, &component, &mut methods, &mut fields); - }, - _ => {}, + } + _ => {} } } - Some(ClassOrInterfaceComponent { component: ContainerComponent { component: component, @@ -107,12 +110,12 @@ fn parse_struct_body( for node in ast.children.iter() { match &*node.r#type { "field_declaration_list" => fields.append(&mut parse_fields(node, component)), - _ => {}, + _ => {} } } } -fn parse_fields(ast: &AST, component: &ComponentInfo) -> Vec { +fn parse_fields(ast: &AST, component: &ComponentInfo) -> Vec { let mut fields = vec![]; for node in ast.children.iter() { match &*node.r#type { @@ -136,10 +139,9 @@ fn parse_fields(ast: &AST, component: &ComponentInfo) -> Vec { default_value: String::new(), r#type: type_identifier, }) - - }, - _ => {}, + } + _ => {} } } fields -} \ No newline at end of file +} diff --git a/src/lang/go/function_body/expr.rs b/src/lang/go/function_body/expr.rs index c670d71..8ec5e40 100644 --- a/src/lang/go/function_body/expr.rs +++ b/src/lang/go/function_body/expr.rs @@ -1,21 +1,44 @@ use crate::go::function_body::node::{parse_child_nodes, parse_node}; use crate::go::function_body::parse_block; use crate::go::util::vartype::find_type; +use crate::go::util::identifier::parse_identifier; use crate::ast::*; use crate::ComponentInfo; use crate::AST; +use super::is_common_junk_tag; + pub(crate) fn parse_expr(ast: &AST, component: &ComponentInfo) -> Option { match &*ast.r#type { - // Variables an initialization - "var_declaration" => parse_assignment(ast, component), + // Variables and initialization "identifier" => parse_ident(ast, component), + "int_literal" | + "interpreted_string_literal" => Some(Expr::Literal(ast.value.clone().into())), + "assignment_statement" => parse_assignment(ast, component), + + //language specific + "binary_expression" => parse_binary(ast, component), + "expression_list" => parse_expr_stmt(ast, component), + "inc_statement" | "dec_statement" => parse_inc_dec(ast, component), + + //function and method calls + "call_expression" => parse_function(ast, component), - unknown => None + unknown => None, } } +pub(crate) fn parse_expr_stmt(ast: &AST, component: &ComponentInfo) -> Option { + let mut expr = None; + for comp in ast.children.iter() { + expr = parse_expr(comp, component); + if expr.is_some() { + break; + } + } + expr +} fn parse_ident(ast: &AST, component: &ComponentInfo) -> Option { let ident: Expr = Ident::new(ast.value.clone()).into(); @@ -30,12 +53,14 @@ pub(crate) fn parse_assignment(ast: &AST, component: &ComponentInfo) -> Option Option { + let mut lhs = None; + let mut op = None; + let mut rhs = None; + for child in ast.children.iter() { + if !is_common_junk_tag(&child.r#type) { + let res = Some(child); + if lhs.is_none() { + lhs = res; + } else if op.is_none() { + op = res; + } else if rhs.is_none() { + rhs = res; + break; + } + } + } + + if let Some(lhs) = lhs { + if let Some(op) = op { + if let Some(rhs) = rhs { + return Some( + BinaryExpr::new( + Box::new(parse_expr(lhs, component)?), + op.value.as_str().into(), + Box::new(parse_expr(rhs, component)?), + ) + .into(), + ); + } + } + } + eprintln!("Malformed binary expression detected!"); + None +} + +fn parse_function(ast: &AST, component: &ComponentInfo) -> Option { + let selector = match ast.find_child_by_type(&["selector_expression"]) { + Some(node) => node, + None => ast + }; + + let argument_list = match ast.find_child_by_type(&["argument_list"]) { + Some(node) => node, + None => ast + }; + + let args: Vec = argument_list + .children + .iter() + .map(|arg| parse_expr(arg, component)) + .flat_map(|arg| arg) + .collect(); + + + //determine the type of function call + if selector.find_child_by_type(&["."]).is_some() { + //member functions + let function_name = parse_dot_expr(selector)?; + + Some(CallExpr::new(Box::new(function_name.into()), args).into()) + } else { + //regular functions + let name = Ident::new(parse_identifier(&selector.children[0])); + Some(CallExpr::new(Box::new(name.into()), args).into()) + } + + + + + + + +} + +fn parse_dot_expr(node: &AST) -> Option{ + //get the name of what called the function + let lhs = Ident::new(parse_identifier(&node.children[0])); + let rhs = Ident::new(parse_identifier(&node.children[2])); + + + Some(DotExpr::new(Box::new(lhs.into()), Box::new(rhs.into()))) +} + diff --git a/src/lang/go/function_body/mod.rs b/src/lang/go/function_body/mod.rs index e7045f3..37d9d36 100644 --- a/src/lang/go/function_body/mod.rs +++ b/src/lang/go/function_body/mod.rs @@ -2,18 +2,15 @@ use crate::{ast::Block, ComponentInfo, AST}; use self::node::parse_child_nodes; +mod expr; mod node; mod stmt; -mod expr; - /// Parse the body of a method, static block, constructor, etc. pub(crate) fn parse_block(ast: &AST, component: &ComponentInfo) -> Block { Block::new(parse_child_nodes(ast, component)) } - - /// Logs an unknown tag was encountered. You better not think too much about that. /// It does not, however, log well-known "filler tags", to keep from cluttering output. pub(crate) fn log_unknown_tag(tag: &str, parent: &str) { diff --git a/src/lang/go/function_body/node.rs b/src/lang/go/function_body/node.rs index 0fdd64c..2498316 100644 --- a/src/lang/go/function_body/node.rs +++ b/src/lang/go/function_body/node.rs @@ -2,14 +2,11 @@ use crate::ast::*; use crate::ComponentInfo; use crate::AST; -use crate::go::function_body::stmt::parse_decl; +use crate::go::function_body::stmt::*; -use super::{ - parse_block, - //stmt::{parse_do_while, parse_if, parse_labeled, parse_return, parse_throw, parse_while}, -}; +use super::parse_block; use crate::go::function_body::expr::parse_expr; - +use crate::go::function_body::expr::parse_expr_stmt; pub(crate) fn parse_child_nodes(ast: &AST, component: &ComponentInfo) -> Vec { ast.children @@ -21,14 +18,19 @@ pub(crate) fn parse_child_nodes(ast: &AST, component: &ComponentInfo) -> Vec Option { match &*ast.r#type { - "var_declaration" => { - let decl = Some(Node::Stmt(parse_decl(ast, component).into())); + "var_declaration" => Some(Node::Stmt(parse_decl(ast, component).into())), + "short_var_declaration" => Some(Node::Stmt(parse_short_decl(ast, component).into())), + "if_statement" => parse_if(ast, component), + "block" => Some(parse_block(ast, component).into()), + + "for_statement" => parse_for(ast, component), - decl - } - _ => { + _ => { let expr: Stmt = parse_expr(ast, component)?.into(); Some(expr.into()) - } + }, + } -} \ No newline at end of file +} + + diff --git a/src/lang/go/function_body/stmt.rs b/src/lang/go/function_body/stmt.rs index dab5091..f19ea22 100644 --- a/src/lang/go/function_body/stmt.rs +++ b/src/lang/go/function_body/stmt.rs @@ -2,22 +2,76 @@ use crate::ast::*; use crate::ComponentInfo; use crate::AST; -use crate::go::util::vartype::find_type; - - -//use super::{expr::parse_expr, is_common_junk_tag, node::parse_node}; -use super::node::parse_node; +use super::{expr::parse_expr, is_common_junk_tag, node::parse_node, parse_block}; use crate::go::function_body::node::parse_child_nodes; +use crate::go::util::vartype::find_type; /// Parse an AST section containing a variable declaration pub(crate) fn parse_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt { // Extract informtion about the variable let ast = match ast.find_child_by_type(&["var_spec"]) { Some(var) => var, - None => ast + None => ast, }; let r#type = find_type(ast); + // Determine the value it was set to + let rhs = parse_child_nodes(ast, component); + + let mut decl = DeclStmt::new(vec![], vec![]); + for var in rhs.iter() { + // Extract expression from the hierarchy + let base = match var { + Node::Stmt(Stmt::ExprStmt(ExprStmt { expr, .. })) | Node::Expr(expr) => expr, + _ => { + eprintln!("Unable to interpret as variable: {:#?}", var); + continue; + } + }; + + // Parse variable + match base { + Expr::BinaryExpr(expr) => match expr.lhs.as_ref() { + Expr::Ident(lhs) => { + decl.variables + .push(VarDecl::new(Some(r#type.clone()), lhs.clone())); + decl.expressions.push(Some(expr.rhs.as_ref().clone())); + } + unknown => eprintln!("Expected Ident got {:#?}", unknown), + }, + Expr::Ident(id) => { + decl.variables + .push(VarDecl::new(Some(r#type.clone()), id.clone())); + decl.expressions.push(None); + } + Expr::Literal(lit) => decl.expressions.push(Some(lit.clone().into())), + unknown => { + eprintln!("Expected BinaryExpr or Ident, got {:#?}", unknown); + } + } + } + + for var_decl in decl.variables.iter_mut() { + var_decl.is_final = None; //Go does not have final variables + var_decl.is_static = None; //Go does not have static variables + var_decl.var_type = Some(r#type.clone()); + } + decl.into() +} + +pub(crate) fn parse_short_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt { + let mut r#type = "N/A".to_string(); + let mut i = 0; + for expr in ast.find_all_children_by_type(&["expression_list"]).get_or_insert(vec![]).iter() { + if i == 0 { + i+= 1; + } + else { + r#type = determine_var_type(expr); + } + } + + // Determine the value it was set to @@ -49,15 +103,152 @@ pub(crate) fn parse_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt { .push(VarDecl::new(Some(r#type.clone()), id.clone())); decl.expressions.push(None); } + Expr::Literal(lit) => decl.expressions.push(Some(lit.clone().into())), unknown => { eprintln!("Expected BinaryExpr or Ident, got {:#?}", unknown); } } } - for var_decl in decl.variables.iter_mut() { + var_decl.is_final = None; //Go does not have final variables + var_decl.is_static = None; //Go does not have static variables var_decl.var_type = Some(r#type.clone()); } decl.into() -} \ No newline at end of file +} + +pub(crate) fn parse_if(ast: &AST, component: &ComponentInfo) -> Option { + let mut guard = None; + let mut if_stmt = None; + let mut else_stmt = None; + + for child in ast.children.iter().filter(|node| node.r#type != "else") { + match &*child.r#type { + "binary_expression" => { + guard = parse_expr(child, component) + }, + + _ => { + if let Some(stmt) = parse_node(child, component) { + let stmt = to_block(stmt); + if if_stmt.is_none() { + if_stmt = Some(stmt); + } else { + else_stmt = Some(stmt); + break; + } + } + } + } + } + let retNode = Some(Node::Stmt(IfStmt::new(guard?, if_stmt?, else_stmt).into())); + retNode +} + + +pub(crate) fn parse_for(ast: &AST, component: &ComponentInfo) -> Option { + let mut for_clauses: Vec> = vec![vec![], vec![], vec![]]; + let mut i = 0; + + //find the node containing the for clauses of the statement + let clause_node = match ast.find_child_by_type(&["for_clause"]) { + Some(node) => node, + None => ast, + }; + + //Coerce an Option to an Expr, if it can be + let to_expr = |parts: &Vec| -> Vec { + parts + .into_iter() + .flat_map(|part| match part.clone() { + Node::Expr(node) => Some(node), + Node::Stmt(Stmt::ExprStmt(ExprStmt { expr, .. })) => Some(expr), + _ => None, + }) + .collect() + }; + + //get all the clauses in the for_clauses vector + for node in clause_node.children.iter() { + if !is_common_junk_tag(&*node.r#type) { + for_clauses[i].push(node); + } + else { + i = i + 1; + } + } + + //prepare clauses for parsing + let parts: Vec>> = for_clauses + .iter() + .map(|c| { + if c.len() > 0 { + Some( + c.iter() + .map(|c| parse_node(c, component)) + .flat_map(|c| c) + .collect(), + ) + } else { + None + } + }) + .collect(); + + + + //parse initialization + let init = parts[0].clone().map_or(vec![], |init_parts| { + init_parts + .into_iter() + .flat_map(|p| match p { + Node::Stmt(node) => Some(node), + Node::Expr(node) => Some(Stmt::ExprStmt(ExprStmt::new(node))), + _ => panic!("Not supported: block in for loop init"), + }) + .collect() + }); + //parse guard condition + let guard = parts[1] + .clone() + .map_or(None, |guard| Some(to_expr(&guard)[0].clone())); + + //parse postcondition + let post = parts[2].clone().map_or(vec![], |post| to_expr(&post)); + + + + //find the node containing the block of the for statement + let block_node = match ast.find_child_by_type(&["block"]) { + Some(node) => parse_block(node, component), + None => parse_block(ast, component), + }; + + //assemble into a for statement + let for_stmt = ForStmt::new( + init, + guard, + post, + block_node, + ); + //return the node + Some(Stmt::ForStmt(for_stmt).into()) +} + + +fn determine_var_type(node: &AST) -> String { + let mut toRet = String::from("N/A"); + + match &*node.children[0].r#type { + "int_literal" => { + toRet = String::from("int"); + }, + _ => { + toRet = String::from("Unknown"); + } + } + + toRet +} + diff --git a/src/lang/go/function_def.rs b/src/lang/go/function_def.rs index 84194ea..33d8063 100644 --- a/src/lang/go/function_def.rs +++ b/src/lang/go/function_def.rs @@ -1,15 +1,11 @@ -use crate::parse::AST; -use crate::prophet::*; -use crate::go::util::vartype::find_type; +use crate::go::function_body::parse_block; use crate::go::util::identifier::parse_identifier; +use crate::go::util::vartype::find_type; use crate::msd::NodeType::MethodParam; -use crate::go::function_body::parse_block; +use crate::parse::AST; +use crate::prophet::*; -pub(crate) fn parse_function( - ast: &AST, - module_name: &str, - path: &str -) -> Option { +pub(crate) fn parse_function(ast: &AST, module_name: &str, path: &str) -> Option { //find the function name let fn_identifier = parse_identifier(ast); //get return type @@ -35,10 +31,10 @@ pub(crate) fn parse_function( for node in list.children.iter() { match &*node.r#type { "parameter_declaration" => parameters.push(parse_parameter(node, &component)), - _ => {}, + _ => {} } } - }, + } None => {} }; @@ -56,7 +52,7 @@ pub(crate) fn parse_function( path: path.into(), package_name: module_name.to_string(), instance_name: fn_identifier.clone(), - instance_type: InstanceType::MethodComponent + instance_type: InstanceType::MethodComponent, }, accessor: AccessorType::Public, method_name: fn_identifier, @@ -70,13 +66,12 @@ pub(crate) fn parse_function( line_count: line_end - line_begin + 1, line_begin, line_end, - body + body, }; Some(func) } -pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) - -> (String, MethodComponent) { +pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) -> (String, MethodComponent) { let method_identifier = parse_identifier(ast); let return_type = find_type(ast); @@ -99,45 +94,51 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) Some(parameter_list) => { match parameter_list.find_child_by_type(&["parameter_declaration"]) { Some(parameter_node) => { - parent_struct_type_name = parse_parameter(parameter_node, &component).r#type.clone() - }, - None => {}, + parent_struct_type_name = + parse_parameter(parameter_node, &component).r#type.clone() + } + None => {} } - }, - None => {}, + } + None => {} }; let mut i = 0; let mut parameters = vec![]; - for node in ast.find_all_children_by_type(&["parameter_list"]).get_or_insert(vec![]).iter() { + for node in ast + .find_all_children_by_type(&["parameter_list"]) + .get_or_insert(vec![]) + .iter() + { if i == 0 { i = 1; - } - else { + } else { for param_node in node.children.iter() { match &*param_node.r#type { - "parameter_declaration" => parameters.push(parse_parameter(param_node, &component)), - _ => {}, + "parameter_declaration" => { + parameters.push(parse_parameter(param_node, &component)) + } + _ => {} } } } - }; + } - for member in ast.children.iter() { - match &*member.r#type { - "block" => { - body = Some(parse_block(member, &component)); - } - _ => {} - } - } + for member in ast.children.iter() { + match &*member.r#type { + "block" => { + body = Some(parse_block(member, &component)); + } + _ => {} + } + } let func = MethodComponent { component: ComponentInfo { path: path.into(), package_name: module_name.to_string(), instance_name: method_identifier.clone(), - instance_type: InstanceType::MethodComponent + instance_type: InstanceType::MethodComponent, }, accessor: AccessorType::Public, method_name: method_identifier, @@ -151,15 +152,11 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) line_count: line_end - line_begin + 1, line_begin, line_end, - body + body, }; (parent_struct_type_name, func) } - - - - fn parse_parameter(ast: &AST, component: &ComponentInfo) -> MethodParamComponent { let mut name = parse_identifier(ast); //let mut modifier = Modifier::new(); @@ -176,5 +173,4 @@ fn parse_parameter(ast: &AST, component: &ComponentInfo) -> MethodParamComponent r#type: param_type.into(), parameter_name: name.into(), } - -} \ No newline at end of file +} diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 54a5314..5410a4c 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -4,15 +4,15 @@ use crate::parse::AST; use crate::prophet::*; mod class_def; +mod function_body; mod function_def; mod util; -mod function_body; +use crate::go::util::identifier::parse_identifier; +use crate::lang::go::function_body::parse_block; use class_def::*; use function_def::*; -use crate::go::util::identifier::parse_identifier; use std::borrow::Borrow; -use crate::lang::go::function_body::parse_block; pub fn find_components(ast: AST, path: &str) -> Vec { find_components_internal(ast, String::new(), path) @@ -36,19 +36,17 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec match parse_function(node, &*package, path) { Some(function) => components.push(ComponentType::MethodComponent(function.clone())), - None => {}, + None => {} }, "package_clause" => { package = parse_package(node); - }, - "type_declaration" => { - match parse_type(node, &*package, path) { - Some(type_decl) => { - let type_name = type_decl.component.container_name.clone(); - types.insert(type_name, type_decl); - } - None => {} + } + "type_declaration" => match parse_type(node, &*package, path) { + Some(type_decl) => { + let type_name = type_decl.component.container_name.clone(); + types.insert(type_name, type_decl); } + None => {} }, "import_declaration" => println!("{}", parse_import(node)), tag => todo!("Cannot identify provided tag {:#?}", tag), @@ -71,25 +69,24 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec {}, + } + None => {} } - } //push the now updated types with their member methods onto the components vector @@ -101,18 +98,16 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec String { - parse_identifier(ast) + parse_identifier(ast) } fn parse_import(ast: &AST) -> String { let mut buffer = String::new(); for node in ast.children.iter() { match &*node.r#type { - "import_spec" => { - match node.find_child_by_type(&["interpreted_string_literal"]) { - Some(import) => buffer.push_str(&*trim_import((&*import.value).to_string())), - None => {} - } + "import_spec" => match node.find_child_by_type(&["interpreted_string_literal"]) { + Some(import) => buffer.push_str(&*trim_import((&*import.value).to_string())), + None => {} }, "import_spec_list" => { for import_node in node.children.iter() { @@ -122,15 +117,15 @@ fn parse_import(ast: &AST) -> String { Some(import) => { buffer.push_str(&*trim_import((&*import.value).to_string())); buffer.push_str("\n"); - }, + } None => {} } - }, + } _ => {} } } } - _ => buffer.push_str(&*parse_import(node)) + _ => buffer.push_str(&*parse_import(node)), } } @@ -155,4 +150,4 @@ fn trim_import(import_str: String) -> String { } str -} \ No newline at end of file +} From 5f91e6ecdc2cec1cdfff7ff96d37f73892fb7d2f Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Sun, 3 Oct 2021 17:08:17 -0500 Subject: [PATCH 16/21] resolved various warnings --- src/lang/go/function_body/expr.rs | 3 --- src/lang/go/function_body/node.rs | 1 - src/lang/go/function_def.rs | 1 - src/lang/go/mod.rs | 4 +--- src/lang/go/util/identifier.rs | 1 - src/lang/go/util/vartype.rs | 1 - 6 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/lang/go/function_body/expr.rs b/src/lang/go/function_body/expr.rs index 8ec5e40..cf83605 100644 --- a/src/lang/go/function_body/expr.rs +++ b/src/lang/go/function_body/expr.rs @@ -1,6 +1,3 @@ -use crate::go::function_body::node::{parse_child_nodes, parse_node}; -use crate::go::function_body::parse_block; -use crate::go::util::vartype::find_type; use crate::go::util::identifier::parse_identifier; use crate::ast::*; diff --git a/src/lang/go/function_body/node.rs b/src/lang/go/function_body/node.rs index 2498316..5709456 100644 --- a/src/lang/go/function_body/node.rs +++ b/src/lang/go/function_body/node.rs @@ -6,7 +6,6 @@ use crate::go::function_body::stmt::*; use super::parse_block; use crate::go::function_body::expr::parse_expr; -use crate::go::function_body::expr::parse_expr_stmt; pub(crate) fn parse_child_nodes(ast: &AST, component: &ComponentInfo) -> Vec { ast.children diff --git a/src/lang/go/function_def.rs b/src/lang/go/function_def.rs index 33d8063..970f407 100644 --- a/src/lang/go/function_def.rs +++ b/src/lang/go/function_def.rs @@ -1,7 +1,6 @@ use crate::go::function_body::parse_block; use crate::go::util::identifier::parse_identifier; use crate::go::util::vartype::find_type; -use crate::msd::NodeType::MethodParam; use crate::parse::AST; use crate::prophet::*; diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 5410a4c..4a56887 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -9,10 +9,8 @@ mod function_def; mod util; use crate::go::util::identifier::parse_identifier; -use crate::lang::go::function_body::parse_block; use class_def::*; use function_def::*; -use std::borrow::Borrow; pub fn find_components(ast: AST, path: &str) -> Vec { find_components_internal(ast, String::new(), path) @@ -141,7 +139,7 @@ fn parse_import(ast: &AST) -> String { fn trim_import(import_str: String) -> String { let mut str = import_str.clone(); - /// additional checks to see if the string actually begins and ends with quotation marks + //additional checks to see if the string actually begins and ends with quotation marks if str.starts_with('\"') { str.remove(0); } diff --git a/src/lang/go/util/identifier.rs b/src/lang/go/util/identifier.rs index 09b3503..b3189f2 100644 --- a/src/lang/go/util/identifier.rs +++ b/src/lang/go/util/identifier.rs @@ -1,4 +1,3 @@ -use crate::go::util::stringify_tree_children; use crate::AST; /// Indicates when no type is found diff --git a/src/lang/go/util/vartype.rs b/src/lang/go/util/vartype.rs index 52189f5..0fe74a1 100644 --- a/src/lang/go/util/vartype.rs +++ b/src/lang/go/util/vartype.rs @@ -1,4 +1,3 @@ -use crate::go::util::stringify_tree_children; use crate::AST; /// Indicates when no type is found From b7b42679749a2ea8ef90d824bb9a7fe807b3afd3 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Thu, 14 Oct 2021 16:57:48 -0500 Subject: [PATCH 17/21] changed .gitignore --- .gitignore | 1 + src/lang/go/class_def.rs | 9 ++------- src/lang/go/function_body/mod.rs | 2 ++ src/lang/go/function_body/stmt.rs | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 96ef6c0..97e6d83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target Cargo.lock +.vscode/ diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index ae95abc..26e56ea 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -21,8 +21,8 @@ pub(crate) fn parse_type_internal( package: &str, path: &str, ) -> Option { + //determine the type of the instance - let instance_type = match ast.find_child_by_type(&["struct_type", "interface_type"]) { Some(node) => match &*node.r#type { "interface_type" => InstanceType::InterfaceComponent, @@ -30,12 +30,7 @@ pub(crate) fn parse_type_internal( }, None => InstanceType::ClassComponent, }; - /* - let instance_type = match ast.find_child_by_type(&["struct_type"]) { - Some(child) => InstanceType::ClassComponent, - None => InstanceType::InterfaceComponent, - }; - */ + //find the name of the type let instance_name = match ast.find_child_by_type(&["type_identifier"]) { Some(identifier) => identifier.value.clone(), diff --git a/src/lang/go/function_body/mod.rs b/src/lang/go/function_body/mod.rs index 37d9d36..1fdf12f 100644 --- a/src/lang/go/function_body/mod.rs +++ b/src/lang/go/function_body/mod.rs @@ -11,6 +11,7 @@ pub(crate) fn parse_block(ast: &AST, component: &ComponentInfo) -> Block { Block::new(parse_child_nodes(ast, component)) } +/* /// Logs an unknown tag was encountered. You better not think too much about that. /// It does not, however, log well-known "filler tags", to keep from cluttering output. pub(crate) fn log_unknown_tag(tag: &str, parent: &str) { @@ -18,6 +19,7 @@ pub(crate) fn log_unknown_tag(tag: &str, parent: &str) { eprintln!("Unknown tag {} encountered while parsing {}!", tag, parent); } } +*/ /// Catch all for standard-issue junk tags from treesitter, to allow easy blanket-silencing of /// false alarms, to focus on the tags that are actually important diff --git a/src/lang/go/function_body/stmt.rs b/src/lang/go/function_body/stmt.rs index f19ea22..02ddaf5 100644 --- a/src/lang/go/function_body/stmt.rs +++ b/src/lang/go/function_body/stmt.rs @@ -1,4 +1,4 @@ -use crate::ast::*; +use crate::ast::{to_block, DeclStmt, Expr, ExprStmt, ForStmt, IfStmt, Node, Stmt, VarDecl}; use crate::ComponentInfo; use crate::AST; From e6b47a07f11f6f491afcf58dfbe28e99d58d81e0 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Tue, 2 Nov 2021 18:36:44 -0500 Subject: [PATCH 18/21] added Language to components --- src/lang/go/class_def.rs | 3 +++ src/lang/go/function_body/expr.rs | 21 ++++++++++++--------- src/lang/go/function_body/mod.rs | 4 ++-- src/lang/go/function_body/stmt.rs | 20 +++++++++++--------- src/lang/go/function_def.rs | 5 +++++ 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index 26e56ea..5335015 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -45,6 +45,7 @@ pub(crate) fn parse_type_internal( //get the component information using the path, package, instance name, and instance type let component = ComponentInfo { + language: Language::Go, path: path.into(), package_name: package.into(), instance_name: format!( @@ -120,6 +121,7 @@ fn parse_fields(ast: &AST, component: &ComponentInfo) -> Vec { fields.push(FieldComponent { component: ComponentInfo { + language: Language::Go, path: component.path.clone(), package_name: component.package_name.clone(), instance_name: field_identifier.clone(), @@ -133,6 +135,7 @@ fn parse_fields(ast: &AST, component: &ComponentInfo) -> Vec { is_final: false, default_value: String::new(), r#type: type_identifier, + expression: None, }) } _ => {} diff --git a/src/lang/go/function_body/expr.rs b/src/lang/go/function_body/expr.rs index cf83605..c595788 100644 --- a/src/lang/go/function_body/expr.rs +++ b/src/lang/go/function_body/expr.rs @@ -1,3 +1,4 @@ +use crate::Language; use crate::go::util::identifier::parse_identifier; use crate::ast::*; @@ -11,7 +12,7 @@ pub(crate) fn parse_expr(ast: &AST, component: &ComponentInfo) -> Option { // Variables and initialization "identifier" => parse_ident(ast, component), "int_literal" | - "interpreted_string_literal" => Some(Expr::Literal(ast.value.clone().into())), + "interpreted_string_literal" => Some(Expr::Literal(Literal::new(ast.value.clone(), Language::Go))), "assignment_statement" => parse_assignment(ast, component), //language specific @@ -38,7 +39,7 @@ pub(crate) fn parse_expr_stmt(ast: &AST, component: &ComponentInfo) -> Option Option { - let ident: Expr = Ident::new(ast.value.clone()).into(); + let ident: Expr = Ident::new(ast.value.clone(), Language::Go).into(); Some(ident.into()) } @@ -77,7 +78,7 @@ pub(crate) fn parse_assignment(ast: &AST, component: &ComponentInfo) -> Option Option { op < name, ast.children[op].r#type == "++", Box::new(parse_expr(&ast.children[name], component)?), + Language::Go, ) .into(), ) @@ -133,6 +135,7 @@ fn parse_binary(ast: &AST, component: &ComponentInfo) -> Option { Box::new(parse_expr(lhs, component)?), op.value.as_str().into(), Box::new(parse_expr(rhs, component)?), + Language::Go ) .into(), ); @@ -167,11 +170,11 @@ fn parse_function(ast: &AST, component: &ComponentInfo) -> Option { //member functions let function_name = parse_dot_expr(selector)?; - Some(CallExpr::new(Box::new(function_name.into()), args).into()) + Some(CallExpr::new(Box::new(function_name.into()), args, Language::Go).into()) } else { //regular functions - let name = Ident::new(parse_identifier(&selector.children[0])); - Some(CallExpr::new(Box::new(name.into()), args).into()) + let name = Ident::new(parse_identifier(&selector.children[0]), Language::Go); + Some(CallExpr::new(Box::new(name.into()), args, Language::Go).into()) } @@ -184,10 +187,10 @@ fn parse_function(ast: &AST, component: &ComponentInfo) -> Option { fn parse_dot_expr(node: &AST) -> Option{ //get the name of what called the function - let lhs = Ident::new(parse_identifier(&node.children[0])); - let rhs = Ident::new(parse_identifier(&node.children[2])); + let lhs = Ident::new(parse_identifier(&node.children[0]), Language::Go); + let rhs = Ident::new(parse_identifier(&node.children[2]), Language::Go); - Some(DotExpr::new(Box::new(lhs.into()), Box::new(rhs.into()))) + Some(DotExpr::new(Box::new(lhs.into()), Box::new(rhs.into()), Language::Go)) } diff --git a/src/lang/go/function_body/mod.rs b/src/lang/go/function_body/mod.rs index 1fdf12f..9841383 100644 --- a/src/lang/go/function_body/mod.rs +++ b/src/lang/go/function_body/mod.rs @@ -1,4 +1,4 @@ -use crate::{ast::Block, ComponentInfo, AST}; +use crate::{AST, ComponentInfo, Language, ast::Block}; use self::node::parse_child_nodes; @@ -8,7 +8,7 @@ mod stmt; /// Parse the body of a method, static block, constructor, etc. pub(crate) fn parse_block(ast: &AST, component: &ComponentInfo) -> Block { - Block::new(parse_child_nodes(ast, component)) + Block::new(parse_child_nodes(ast, component), Language::Go) } /* diff --git a/src/lang/go/function_body/stmt.rs b/src/lang/go/function_body/stmt.rs index 02ddaf5..48f88f8 100644 --- a/src/lang/go/function_body/stmt.rs +++ b/src/lang/go/function_body/stmt.rs @@ -1,6 +1,7 @@ use crate::ast::{to_block, DeclStmt, Expr, ExprStmt, ForStmt, IfStmt, Node, Stmt, VarDecl}; use crate::ComponentInfo; use crate::AST; +use crate::Language; use super::{expr::parse_expr, is_common_junk_tag, node::parse_node, parse_block}; use crate::go::function_body::node::parse_child_nodes; @@ -18,7 +19,7 @@ pub(crate) fn parse_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt { // Determine the value it was set to let rhs = parse_child_nodes(ast, component); - let mut decl = DeclStmt::new(vec![], vec![]); + let mut decl = DeclStmt::new(vec![], vec![], Language::Go); for var in rhs.iter() { // Extract expression from the hierarchy let base = match var { @@ -34,14 +35,14 @@ pub(crate) fn parse_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt { Expr::BinaryExpr(expr) => match expr.lhs.as_ref() { Expr::Ident(lhs) => { decl.variables - .push(VarDecl::new(Some(r#type.clone()), lhs.clone())); + .push(VarDecl::new(Some(r#type.clone()), lhs.clone(), Language::Go)); decl.expressions.push(Some(expr.rhs.as_ref().clone())); } unknown => eprintln!("Expected Ident got {:#?}", unknown), }, Expr::Ident(id) => { decl.variables - .push(VarDecl::new(Some(r#type.clone()), id.clone())); + .push(VarDecl::new(Some(r#type.clone()), id.clone(), Language::Go)); decl.expressions.push(None); } Expr::Literal(lit) => decl.expressions.push(Some(lit.clone().into())), @@ -77,7 +78,7 @@ pub(crate) fn parse_short_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt // Determine the value it was set to let rhs = parse_child_nodes(ast, component); - let mut decl = DeclStmt::new(vec![], vec![]); + let mut decl = DeclStmt::new(vec![], vec![], Language::Go); for var in rhs.iter() { // Extract expression from the hierarchy let base = match var { @@ -93,14 +94,14 @@ pub(crate) fn parse_short_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt Expr::BinaryExpr(expr) => match expr.lhs.as_ref() { Expr::Ident(lhs) => { decl.variables - .push(VarDecl::new(Some(r#type.clone()), lhs.clone())); + .push(VarDecl::new(Some(r#type.clone()), lhs.clone(), Language::Go)); decl.expressions.push(Some(expr.rhs.as_ref().clone())); } unknown => eprintln!("Expected Ident got {:#?}", unknown), }, Expr::Ident(id) => { decl.variables - .push(VarDecl::new(Some(r#type.clone()), id.clone())); + .push(VarDecl::new(Some(r#type.clone()), id.clone(), Language::Go)); decl.expressions.push(None); } Expr::Literal(lit) => decl.expressions.push(Some(lit.clone().into())), @@ -131,7 +132,7 @@ pub(crate) fn parse_if(ast: &AST, component: &ComponentInfo) -> Option { _ => { if let Some(stmt) = parse_node(child, component) { - let stmt = to_block(stmt); + let stmt = to_block(stmt, Language::Go); if if_stmt.is_none() { if_stmt = Some(stmt); } else { @@ -142,7 +143,7 @@ pub(crate) fn parse_if(ast: &AST, component: &ComponentInfo) -> Option { } } } - let retNode = Some(Node::Stmt(IfStmt::new(guard?, if_stmt?, else_stmt).into())); + let retNode = Some(Node::Stmt(IfStmt::new(guard?, if_stmt?, else_stmt, Language::Go).into())); retNode } @@ -204,7 +205,7 @@ pub(crate) fn parse_for(ast: &AST, component: &ComponentInfo) -> Option { .into_iter() .flat_map(|p| match p { Node::Stmt(node) => Some(node), - Node::Expr(node) => Some(Stmt::ExprStmt(ExprStmt::new(node))), + Node::Expr(node) => Some(Stmt::ExprStmt(ExprStmt::new(node, Language::Go))), _ => panic!("Not supported: block in for loop init"), }) .collect() @@ -231,6 +232,7 @@ pub(crate) fn parse_for(ast: &AST, component: &ComponentInfo) -> Option { guard, post, block_node, + Language::Go, ); //return the node Some(Stmt::ForStmt(for_stmt).into()) diff --git a/src/lang/go/function_def.rs b/src/lang/go/function_def.rs index 970f407..b6c2565 100644 --- a/src/lang/go/function_def.rs +++ b/src/lang/go/function_def.rs @@ -11,6 +11,7 @@ pub(crate) fn parse_function(ast: &AST, module_name: &str, path: &str) -> Option let return_type = find_type(ast); let component = ComponentInfo { + language: Language::Go, path: path.to_string(), package_name: module_name.to_string(), instance_name: fn_identifier.clone(), @@ -48,6 +49,7 @@ pub(crate) fn parse_function(ast: &AST, module_name: &str, path: &str) -> Option let func = MethodComponent { component: ComponentInfo { + language: Language::Go, path: path.into(), package_name: module_name.to_string(), instance_name: fn_identifier.clone(), @@ -75,6 +77,7 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) -> (String, let return_type = find_type(ast); let component = ComponentInfo { + language: Language::Go, path: path.to_string(), package_name: module_name.to_string(), instance_name: method_identifier.clone(), @@ -134,6 +137,7 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) -> (String, let func = MethodComponent { component: ComponentInfo { + language: Language::Go, path: path.into(), package_name: module_name.to_string(), instance_name: method_identifier.clone(), @@ -163,6 +167,7 @@ fn parse_parameter(ast: &AST, component: &ComponentInfo) -> MethodParamComponent MethodParamComponent { component: ComponentInfo { + language: Language::Go, path: component.path.clone(), package_name: component.package_name.clone(), instance_name: component.instance_name.clone(), From bd59ab9cbd39cabdb3d830ca10e877d19e2ebb29 Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Mon, 22 Nov 2021 18:13:42 -0600 Subject: [PATCH 19/21] vastly improved body parsing --- src/lang/go/function_body/expr.rs | 27 +++++----- src/lang/go/function_body/mod.rs | 1 + src/lang/go/function_body/node.rs | 2 +- src/lang/go/function_body/stmt.rs | 75 ++++++++++++++++++++++---- src/lang/go/function_def.rs | 32 ++++++++--- src/lang/go/util/vartype.rs | 89 +++++++++++++++++++++++++++++-- 6 files changed, 188 insertions(+), 38 deletions(-) diff --git a/src/lang/go/function_body/expr.rs b/src/lang/go/function_body/expr.rs index c595788..6fa076d 100644 --- a/src/lang/go/function_body/expr.rs +++ b/src/lang/go/function_body/expr.rs @@ -10,9 +10,9 @@ use super::is_common_junk_tag; pub(crate) fn parse_expr(ast: &AST, component: &ComponentInfo) -> Option { match &*ast.r#type { // Variables and initialization - "identifier" => parse_ident(ast, component), + "identifier" | "field_identifier" => parse_ident(ast, component), "int_literal" | - "interpreted_string_literal" => Some(Expr::Literal(Literal::new(ast.value.clone(), Language::Go))), + "interpreted_string_literal" | "nil" | "true" | "false" => Some(Expr::Literal(Literal::new(ast.value.clone(), Language::Go))), "assignment_statement" => parse_assignment(ast, component), //language specific @@ -22,6 +22,7 @@ pub(crate) fn parse_expr(ast: &AST, component: &ComponentInfo) -> Option { //function and method calls "call_expression" => parse_function(ast, component), + "selector_expression" => Some(parse_dot_expr(ast, component)?.into()), unknown => None, } @@ -168,7 +169,7 @@ fn parse_function(ast: &AST, component: &ComponentInfo) -> Option { //determine the type of function call if selector.find_child_by_type(&["."]).is_some() { //member functions - let function_name = parse_dot_expr(selector)?; + let function_name = parse_dot_expr(selector, component)?; Some(CallExpr::new(Box::new(function_name.into()), args, Language::Go).into()) } else { @@ -176,21 +177,17 @@ fn parse_function(ast: &AST, component: &ComponentInfo) -> Option { let name = Ident::new(parse_identifier(&selector.children[0]), Language::Go); Some(CallExpr::new(Box::new(name.into()), args, Language::Go).into()) } - - - - - - - } -fn parse_dot_expr(node: &AST) -> Option{ +fn parse_dot_expr(node: &AST, component: &ComponentInfo) -> Option{ //get the name of what called the function - let lhs = Ident::new(parse_identifier(&node.children[0]), Language::Go); - let rhs = Ident::new(parse_identifier(&node.children[2]), Language::Go); - + //let lhs = Ident::new(parse_identifier(&node.children[0]), Language::Go); + let lhs = parse_expr(&node.children[0], component)?; + //let rhs = Ident::new(parse_identifier(&node.children[2]), Language::Go); + let rhs = parse_expr(&node.children[2], component)?; - Some(DotExpr::new(Box::new(lhs.into()), Box::new(rhs.into()), Language::Go)) + Some(DotExpr::new(Box::new(lhs), Box::new(rhs), Language::Go)) } + + diff --git a/src/lang/go/function_body/mod.rs b/src/lang/go/function_body/mod.rs index 9841383..2cec44f 100644 --- a/src/lang/go/function_body/mod.rs +++ b/src/lang/go/function_body/mod.rs @@ -9,6 +9,7 @@ mod stmt; /// Parse the body of a method, static block, constructor, etc. pub(crate) fn parse_block(ast: &AST, component: &ComponentInfo) -> Block { Block::new(parse_child_nodes(ast, component), Language::Go) + } /* diff --git a/src/lang/go/function_body/node.rs b/src/lang/go/function_body/node.rs index 5709456..41cfea6 100644 --- a/src/lang/go/function_body/node.rs +++ b/src/lang/go/function_body/node.rs @@ -18,7 +18,7 @@ pub(crate) fn parse_child_nodes(ast: &AST, component: &ComponentInfo) -> Vec Option { match &*ast.r#type { "var_declaration" => Some(Node::Stmt(parse_decl(ast, component).into())), - "short_var_declaration" => Some(Node::Stmt(parse_short_decl(ast, component).into())), + "short_var_declaration" => Some(Node::Stmt(parse_short_decl(ast, component)?.into())), "if_statement" => parse_if(ast, component), "block" => Some(parse_block(ast, component).into()), diff --git a/src/lang/go/function_body/stmt.rs b/src/lang/go/function_body/stmt.rs index 48f88f8..30bd085 100644 --- a/src/lang/go/function_body/stmt.rs +++ b/src/lang/go/function_body/stmt.rs @@ -1,7 +1,8 @@ -use crate::ast::{to_block, DeclStmt, Expr, ExprStmt, ForStmt, IfStmt, Node, Stmt, VarDecl}; +use crate::ast::{to_block, DeclStmt, Expr, ExprStmt, ForStmt, IfStmt, Node, Stmt, VarDecl, Ident}; use crate::ComponentInfo; use crate::AST; use crate::Language; +use crate::go::util::identifier::parse_identifier; use super::{expr::parse_expr, is_common_junk_tag, node::parse_node, parse_block}; use crate::go::function_body::node::parse_child_nodes; @@ -60,9 +61,11 @@ pub(crate) fn parse_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt { decl.into() } -pub(crate) fn parse_short_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt { +pub(crate) fn parse_short_decl(ast: &AST, component: &ComponentInfo) -> Option { let mut r#type = "N/A".to_string(); let mut i = 0; + + /* for expr in ast.find_all_children_by_type(&["expression_list"]).get_or_insert(vec![]).iter() { if i == 0 { i+= 1; @@ -71,16 +74,45 @@ pub(crate) fn parse_short_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt r#type = determine_var_type(expr); } } - + */ + + let expr_lists = ast.find_all_children_by_type(&["expression_list"]).unwrap_or_default(); + let lhs = *expr_lists.first()?; + let rhs = *expr_lists.last()?; + //println!("{:#?}", ast); // Determine the value it was set to - let rhs = parse_child_nodes(ast, component); + let var_names = lhs.children.iter() + .filter(|child| child.r#type == "identifier") + .map(|node| parse_identifier(node)) + .map(|variable| VarDecl::new(None, Ident::new(variable, Language::Go), Language::Go)) + .collect::>(); - let mut decl = DeclStmt::new(vec![], vec![], Language::Go); - for var in rhs.iter() { + + // let rhs_vals = parse_child_nodes(rhs, component).into_iter().map(|node| match node { + // Node::Expr(expr) => Some(expr), + // var_name => { + // println!("{:#?}", var_name); + // None + // } + // }).collect::>(); + + + let rhs_vals = rhs.children.iter() + .map(|child| parse_expr(child, component)) + .collect(); + + println!("{:#?}", rhs_vals); + + Some(DeclStmt::new(var_names, rhs_vals, Language::Go)) + + /* + ///FIX ME!!!! need base to hold a vector of Ident, right now it is only getting the first var! + for var in lhs.iter() { // Extract expression from the hierarchy + /* let base = match var { Node::Stmt(Stmt::ExprStmt(ExprStmt { expr, .. })) | Node::Expr(expr) => expr, _ => { @@ -88,8 +120,13 @@ pub(crate) fn parse_short_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt continue; } }; + */ + + //println!("{:#?}", base); + //println!("{:#?}", lhs); // Parse variable + /* match base { Expr::BinaryExpr(expr) => match expr.lhs.as_ref() { Expr::Ident(lhs) => { @@ -105,10 +142,16 @@ pub(crate) fn parse_short_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt decl.expressions.push(None); } Expr::Literal(lit) => decl.expressions.push(Some(lit.clone().into())), + + //Expr::DotExpr() unknown => { - eprintln!("Expected BinaryExpr or Ident, got {:#?}", unknown); + eprintln!("Expected BinaryExpr, Ident or Literal, got {:#?}", unknown); } } + */ + + + //decl.expressions.push(Some(base.clone())); } for var_decl in decl.variables.iter_mut() { @@ -117,6 +160,9 @@ pub(crate) fn parse_short_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt var_decl.var_type = Some(r#type.clone()); } decl.into() + */ + + } pub(crate) fn parse_if(ast: &AST, component: &ComponentInfo) -> Option { @@ -126,6 +172,7 @@ pub(crate) fn parse_if(ast: &AST, component: &ComponentInfo) -> Option { for child in ast.children.iter().filter(|node| node.r#type != "else") { match &*child.r#type { + "binary_expression" => { guard = parse_expr(child, component) }, @@ -153,7 +200,7 @@ pub(crate) fn parse_for(ast: &AST, component: &ComponentInfo) -> Option { let mut i = 0; //find the node containing the for clauses of the statement - let clause_node = match ast.find_child_by_type(&["for_clause"]) { + let clause_node = match ast.find_child_by_type(&["for_clause", "range_clause"]) { Some(node) => node, None => ast, }; @@ -210,10 +257,16 @@ pub(crate) fn parse_for(ast: &AST, component: &ComponentInfo) -> Option { }) .collect() }); + //parse guard condition - let guard = parts[1] - .clone() - .map_or(None, |guard| Some(to_expr(&guard)[0].clone())); + let guard = match parts.get(1) { + Some(Some(guard)) => to_expr(&guard).get(0).cloned(), + _ => None + }; + + //.clone() + //.map(|guard| to_expr(&guard).get(0).flatten()) + //.map(|guard| (*to_expr(&guard).get(0)).clone()); //parse postcondition let post = parts[2].clone().map_or(vec![], |post| to_expr(&post)); diff --git a/src/lang/go/function_def.rs b/src/lang/go/function_def.rs index b6c2565..48cef12 100644 --- a/src/lang/go/function_def.rs +++ b/src/lang/go/function_def.rs @@ -1,6 +1,8 @@ use crate::go::function_body::parse_block; use crate::go::util::identifier::parse_identifier; use crate::go::util::vartype::find_type; +use crate::go::util::vartype::find_return; +use crate::go::util::vartype::unwrap_pointer_type; use crate::parse::AST; use crate::prophet::*; @@ -8,8 +10,8 @@ pub(crate) fn parse_function(ast: &AST, module_name: &str, path: &str) -> Option //find the function name let fn_identifier = parse_identifier(ast); //get return type - let return_type = find_type(ast); - + //let return_type = find_type(ast); + let return_type = find_return(ast); let component = ComponentInfo { language: Language::Go, path: path.to_string(), @@ -74,8 +76,8 @@ pub(crate) fn parse_function(ast: &AST, module_name: &str, path: &str) -> Option pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) -> (String, MethodComponent) { let method_identifier = parse_identifier(ast); - let return_type = find_type(ast); - + //let return_type = find_type(ast); + let return_type = find_return(ast); let component = ComponentInfo { language: Language::Go, path: path.to_string(), @@ -112,7 +114,7 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) -> (String, .get_or_insert(vec![]) .iter() { - if i == 0 { + if i == 0 || i == 2 { i = 1; } else { for param_node in node.children.iter() { @@ -123,7 +125,9 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) -> (String, _ => {} } } + i = 2 } + } for member in ast.children.iter() { @@ -161,9 +165,23 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) -> (String, } fn parse_parameter(ast: &AST, component: &ComponentInfo) -> MethodParamComponent { - let mut name = parse_identifier(ast); + let mut isPtr = false; + + let myNode = unwrap_pointer_type(ast); + + let mut name = "".to_string(); + if(isPtr) { + //name = "*".to_string(); + } + + name += &parse_identifier(ast); //let mut modifier = Modifier::new(); - let param_type = find_type(ast); + let mut param_type = "".to_string(); + if(isPtr) { + //param_type = "*".to_string(); + } + param_type += &find_type(myNode); + //let param_type = find_type(myNode); MethodParamComponent { component: ComponentInfo { diff --git a/src/lang/go/util/vartype.rs b/src/lang/go/util/vartype.rs index 0fe74a1..4183aac 100644 --- a/src/lang/go/util/vartype.rs +++ b/src/lang/go/util/vartype.rs @@ -5,17 +5,98 @@ pub const NO_TYPE: &str = "N/A"; pub(crate) fn find_type(ast: &AST) -> String { - let id_node = match ast.find_child_by_type(&["type_identifier"]) { - Some(node) => node, - None => ast, + let r#type = match ast.find_child_by_type(&["qualified_type"]) { + Some(node) => { + parse_qualified_type(node) + }, + None => { + let id_node = match ast.find_child_by_type(&["type_identifier"]) { + Some(node) => node, + None => ast, + }; + let str = parse_type(id_node); + str + } }; - let r#type = parse_type(id_node); + r#type } +pub(crate) fn find_return(ast: &AST) -> String { + let mut mul_rets = false; + let mut param_lists = 0; + let mut type_identifier = 0; + let mut i = 0; + let mut ret = "".to_string(); + + for node in ast.children.iter() { + match &*node.r#type { + "parameter_list" => { + //if it has multiple return values + if i == 4 { + for subNode in node.children.iter() { + match &*subNode.r#type { + "parameter_declaration" => { + ret += &find_type(unwrap_pointer_type(subNode)); + ret += ", " + }, + _ => {} + } + + } + + ret.pop(); + ret.pop(); + } + }, + "type_identifier" => { + //if it ends with a single return + if i == 4 { + ret = node.value.clone(); + } + }, + _ => {} + } + i += 1; + } + + + ret +} + +pub(crate) fn unwrap_pointer_type(ast: &AST) -> &AST { + let mut myNode = ast; + + for node in ast.children.iter() { + match &*node.r#type { + "pointer_type" => { + myNode = node; + }, + _ => {} + } + } + + myNode +} + fn parse_type(ast: &AST) -> String { match &*ast.r#type { "type_identifier" => ast.value.clone(), _ => NO_TYPE.into() } +} + +fn parse_qualified_type(ast: &AST) -> String { + let mut type_str = "".to_string(); + + for node in ast.children.iter() { + match &*node.r#type { + "package_identifier" | "." | "type_identifier" => { + type_str += &node.value; + }, + _ => {} + } + } + + type_str } \ No newline at end of file From b7501bddaf0d0d76e78aac4d84cd4c3ab0a472cc Mon Sep 17 00:00:00 2001 From: Alehman74 Date: Sun, 5 Dec 2021 16:53:40 -0600 Subject: [PATCH 20/21] Updated go parser --- src/lang/go/class_def.rs | 1 + src/lang/go/mod.rs | 5 ++++- src/lang/go/util/vartype.rs | 15 +++++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index 5335015..852d29a 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -1,5 +1,6 @@ use crate::go::util::identifier::parse_identifier; use crate::go::util::vartype::find_type; +use crate::go::util::vartype::unwrap_pointer_type; use crate::parse::AST; use crate::prophet::*; diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 4a56887..2395112 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -57,8 +57,11 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec { //create a copy of the instance of the original struct and add the method to it diff --git a/src/lang/go/util/vartype.rs b/src/lang/go/util/vartype.rs index 4183aac..d4a4fa6 100644 --- a/src/lang/go/util/vartype.rs +++ b/src/lang/go/util/vartype.rs @@ -5,12 +5,20 @@ pub const NO_TYPE: &str = "N/A"; pub(crate) fn find_type(ast: &AST) -> String { - let r#type = match ast.find_child_by_type(&["qualified_type"]) { + let my_node = unwrap_pointer_type(ast); + let mut is_ptr = false; + + match my_node.find_child_by_type(&["*"]) { + Some(node) => {is_ptr = true;}, + None => {} + } + + let mut r#type = match my_node.find_child_by_type(&["qualified_type"]) { Some(node) => { parse_qualified_type(node) }, None => { - let id_node = match ast.find_child_by_type(&["type_identifier"]) { + let id_node = match my_node.find_child_by_type(&["type_identifier"]) { Some(node) => node, None => ast, }; @@ -19,6 +27,9 @@ pub(crate) fn find_type(ast: &AST) -> String { } }; + if is_ptr == true { + r#type = format!("*{}", r#type); + } r#type } From 39ba25442aa42a8c73de50beeb4cf561d7baacd8 Mon Sep 17 00:00:00 2001 From: austinlehman Date: Tue, 1 Mar 2022 17:14:30 -0600 Subject: [PATCH 21/21] commit for paper --- src/lang/go/class_def.rs | 5 ++--- src/lang/go/function_body/expr.rs | 4 ++-- src/lang/go/function_body/stmt.rs | 12 ++++++------ src/lang/go/function_def.rs | 18 +++++++----------- src/lang/go/mod.rs | 2 +- src/lang/go/util/mod.rs | 8 ++++++-- src/lang/go/util/vartype.rs | 17 +++++++---------- 7 files changed, 31 insertions(+), 35 deletions(-) diff --git a/src/lang/go/class_def.rs b/src/lang/go/class_def.rs index 852d29a..14b06d6 100644 --- a/src/lang/go/class_def.rs +++ b/src/lang/go/class_def.rs @@ -1,6 +1,5 @@ use crate::go::util::identifier::parse_identifier; use crate::go::util::vartype::find_type; -use crate::go::util::vartype::unwrap_pointer_type; use crate::parse::AST; use crate::prophet::*; @@ -69,7 +68,7 @@ pub(crate) fn parse_type_internal( // Define default values let stereotype = ContainerStereotype::Entity; // TODO determine properly let mut fields = vec![]; - let mut constructors = vec![]; + let constructors = vec![]; let mut methods = vec![]; //let mut modifier = Modifier::new(); @@ -101,7 +100,7 @@ pub(crate) fn parse_type_internal( fn parse_struct_body( ast: &AST, component: &ComponentInfo, - methods: &mut Vec, + _methods: &mut Vec, fields: &mut Vec, ) { for node in ast.children.iter() { diff --git a/src/lang/go/function_body/expr.rs b/src/lang/go/function_body/expr.rs index 6fa076d..8f06f0f 100644 --- a/src/lang/go/function_body/expr.rs +++ b/src/lang/go/function_body/expr.rs @@ -24,7 +24,7 @@ pub(crate) fn parse_expr(ast: &AST, component: &ComponentInfo) -> Option { "call_expression" => parse_function(ast, component), "selector_expression" => Some(parse_dot_expr(ast, component)?.into()), - unknown => None, + _ => None, } } @@ -39,7 +39,7 @@ pub(crate) fn parse_expr_stmt(ast: &AST, component: &ComponentInfo) -> Option Option { +fn parse_ident(ast: &AST, _component: &ComponentInfo) -> Option { let ident: Expr = Ident::new(ast.value.clone(), Language::Go).into(); Some(ident.into()) } diff --git a/src/lang/go/function_body/stmt.rs b/src/lang/go/function_body/stmt.rs index 30bd085..a151232 100644 --- a/src/lang/go/function_body/stmt.rs +++ b/src/lang/go/function_body/stmt.rs @@ -62,8 +62,8 @@ pub(crate) fn parse_decl(ast: &AST, component: &ComponentInfo) -> DeclStmt { } pub(crate) fn parse_short_decl(ast: &AST, component: &ComponentInfo) -> Option { - let mut r#type = "N/A".to_string(); - let mut i = 0; + //let mut r#type = "N/A".to_string(); + //let mut i = 0; /* for expr in ast.find_all_children_by_type(&["expression_list"]).get_or_insert(vec![]).iter() { @@ -190,8 +190,8 @@ pub(crate) fn parse_if(ast: &AST, component: &ComponentInfo) -> Option { } } } - let retNode = Some(Node::Stmt(IfStmt::new(guard?, if_stmt?, else_stmt, Language::Go).into())); - retNode + let ret_node = Some(Node::Stmt(IfStmt::new(guard?, if_stmt?, else_stmt, Language::Go).into())); + ret_node } @@ -291,7 +291,7 @@ pub(crate) fn parse_for(ast: &AST, component: &ComponentInfo) -> Option { Some(Stmt::ForStmt(for_stmt).into()) } - +/* fn determine_var_type(node: &AST) -> String { let mut toRet = String::from("N/A"); @@ -306,4 +306,4 @@ fn determine_var_type(node: &AST) -> String { toRet } - +*/ diff --git a/src/lang/go/function_def.rs b/src/lang/go/function_def.rs index 48cef12..81fa566 100644 --- a/src/lang/go/function_def.rs +++ b/src/lang/go/function_def.rs @@ -27,7 +27,7 @@ pub(crate) fn parse_function(ast: &AST, module_name: &str, path: &str) -> Option //parse parameter list let mut parameters = vec![]; - let param_list = match ast.find_child_by_type(&["parameter_list"]) { + let _param_list = match ast.find_child_by_type(&["parameter_list"]) { Some(list) => { //iterate through the list, pushing each parameter to parameters for node in list.children.iter() { @@ -92,7 +92,7 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) -> (String, let line_begin = span.0 as i32; let line_end = span.2 as i32; - //parse first parameter list, which ideally is where the actual parent struct is + //parse first parameter list, which ideally is the one containing the receiver let mut parent_struct_type_name = String::new(); match ast.find_child_by_type(&["parameter_list"]) { Some(parameter_list) => { @@ -165,22 +165,18 @@ pub(crate) fn parse_method(ast: &AST, module_name: &str, path: &str) -> (String, } fn parse_parameter(ast: &AST, component: &ComponentInfo) -> MethodParamComponent { - let mut isPtr = false; + - let myNode = unwrap_pointer_type(ast); + let my_node = unwrap_pointer_type(ast); let mut name = "".to_string(); - if(isPtr) { - //name = "*".to_string(); - } + name += &parse_identifier(ast); //let mut modifier = Modifier::new(); let mut param_type = "".to_string(); - if(isPtr) { - //param_type = "*".to_string(); - } - param_type += &find_type(myNode); + + param_type += &find_type(my_node); //let param_type = find_type(myNode); MethodParamComponent { diff --git a/src/lang/go/mod.rs b/src/lang/go/mod.rs index 2395112..f24d186 100644 --- a/src/lang/go/mod.rs +++ b/src/lang/go/mod.rs @@ -91,7 +91,7 @@ fn find_components_internal(ast: AST, mut package: String, path: &str) -> Vec(vector: Vec) -> Option> { if !vector.is_empty() { @@ -11,7 +12,9 @@ pub(crate) fn fold_vec(vector: Vec) -> Option> { None } } +*/ +/* /// Convert the children of a provided tree into a single, consecutive string pub(crate) fn stringify_tree_children(ast: &AST) -> String { let mut buffer = String::new(); @@ -19,4 +22,5 @@ pub(crate) fn stringify_tree_children(ast: &AST) -> String { buffer.push_str(&*member.value); } buffer -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/lang/go/util/vartype.rs b/src/lang/go/util/vartype.rs index d4a4fa6..f74e2d1 100644 --- a/src/lang/go/util/vartype.rs +++ b/src/lang/go/util/vartype.rs @@ -9,7 +9,7 @@ pub(crate) fn find_type(ast: &AST) -> String { let mut is_ptr = false; match my_node.find_child_by_type(&["*"]) { - Some(node) => {is_ptr = true;}, + Some(_node) => {is_ptr = true;}, None => {} } @@ -34,9 +34,6 @@ pub(crate) fn find_type(ast: &AST) -> String { } pub(crate) fn find_return(ast: &AST) -> String { - let mut mul_rets = false; - let mut param_lists = 0; - let mut type_identifier = 0; let mut i = 0; let mut ret = "".to_string(); @@ -45,10 +42,10 @@ pub(crate) fn find_return(ast: &AST) -> String { "parameter_list" => { //if it has multiple return values if i == 4 { - for subNode in node.children.iter() { - match &*subNode.r#type { + for sub_node in node.children.iter() { + match &*sub_node.r#type { "parameter_declaration" => { - ret += &find_type(unwrap_pointer_type(subNode)); + ret += &find_type(unwrap_pointer_type(sub_node)); ret += ", " }, _ => {} @@ -76,18 +73,18 @@ pub(crate) fn find_return(ast: &AST) -> String { } pub(crate) fn unwrap_pointer_type(ast: &AST) -> &AST { - let mut myNode = ast; + let mut my_node = ast; for node in ast.children.iter() { match &*node.r#type { "pointer_type" => { - myNode = node; + my_node = node; }, _ => {} } } - myNode + my_node } fn parse_type(ast: &AST) -> String {