From f3c004d0c1111aaebc590d47af8784fa632ddc17 Mon Sep 17 00:00:00 2001 From: Devon Burriss Date: Fri, 25 Mar 2022 07:47:38 +0100 Subject: [PATCH 1/7] Initial halstead impl --- src/getter.rs | 55 +++++++++++++++++++++++++++++++++++++++++ src/metrics/halstead.rs | 28 ++++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/getter.rs b/src/getter.rs index 10d258905..999127470 100644 --- a/src/getter.rs +++ b/src/getter.rs @@ -524,4 +524,59 @@ impl Getter for JavaCode { _ => SpaceKind::Unknown, } } + + // fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> { + // if let Some(name) = node.object().child_by_field_name("name") { + // let code = &code[name.start_byte()..name.end_byte()]; + // std::str::from_utf8(code).ok() + // } else { + // Some("") + // } + // } + + fn get_op_type(node: &Node) -> HalsteadType { + use Java::*; + + // keywords, operators, literals: https://docs.oracle.com/javase/specs/jls/se18/html/jls-3.html#jls-3.12 + // https://www.geeksforgeeks.org/software-engineering-halsteads-software-metrics/?msclkid=5e181114abef11ecbb03527e95a34828 + // + // comments not considered + // Operator: function calls? + // Operator: control flow + // Operator: keywords + // Operator: brackets and comma and terminators + // Operator: operators + // Operator: InstanceOf + // Operator: . + // Operand: struct name + // Operand: vars and const + + let typ = node.object().kind_id(); + match typ.into() { + // LPAREN | COMMA | STAR | GTGT | COLON | SEMI | Return | Break | Continue | If | Else + // | Switch | Case | Default | For | While | New | Try | Catch | Throw | Throws + // | Throws2 | EQ | EQEQ | AMP | AMPAMP | AMPEQ | LT | LTLT | LTEQ | LTLTEQ | BANGEQ + // | GTEQ | GTGTEQ | GTGTGT | GTGTGTEQ | PLUSEQ | BANG | STAREQ | SLASHEQ | PERCENTEQ + // | CARET | CARETEQ | LBRACE | RBRACE | QMARK | Instanceof + // Operator: function calls? + MethodInvocation + // Operator: control flow + | If | Else | Switch | Case | Try | Catch | Throw | Throws | Throws2 | For | While | Continue | Break | Do | Finally + // Operator: keywords + | New | Return | Default | Abstract | Assert | Instanceof | Extends | Final | Implements | Transient | Synchronized | Super | This + // Operator: brackets and comma and terminators (separators) + | SEMI | COMMA | COLONCOLON | LBRACE | LBRACK | LPAREN | RBRACE | RBRACK | RPAREN | DOTDOTDOT | DOT + // Operator: operators + | EQ | LT | GT | BANG | TILDE | QMARK | COLON // no grammar for lambda operator -> + | EQEQ | LTEQ | GTEQ | BANGEQ | AMPAMP | PIPEPIPE | PLUSPLUS | DASHDASH + | PLUS | DASH | STAR | SLASH | AMP | PIPE | CARET | PERCENT| LTLT | GTGT | GTGTGT + | PLUSEQ | DASHEQ | STAREQ | SLASHEQ | AMPEQ | PIPEEQ | CARETEQ | PERCENTEQ | LTLTEQ | GTGTEQ | GTGTGTEQ + => HalsteadType::Operator, + // variables, constants + Identifier | Literal => HalsteadType::Operand, + _ => HalsteadType::Unknown, + } + } + + get_operator!(Java); } diff --git a/src/metrics/halstead.rs b/src/metrics/halstead.rs index 391b05db8..27a652955 100644 --- a/src/metrics/halstead.rs +++ b/src/metrics/halstead.rs @@ -325,9 +325,14 @@ impl Halstead for CppCode { } } +impl Halstead for JavaCode { + fn compute<'a>(node: &Node<'a>, code: &'a [u8], halstead_maps: &mut HalsteadMaps<'a>) { + compute_halstead::(node, code, halstead_maps); + } +} + impl Halstead for PreprocCode {} impl Halstead for CcommentCode {} -impl Halstead for JavaCode {} #[cfg(test)] mod tests { @@ -521,4 +526,25 @@ mod tests { ] ); } + + #[test] + fn java_operators_and_operands() { + check_metrics!( + "public static void main(String args[]) { + int a, b, c, avg; + a = 5; b = 5; c = 5; + avg = (a + b + c) / 3; + MessageFormat.format(\"{0}\", avg); + }", + "foo.java", + JavaParser, + halstead, + [ + (u_operators, 10, usize), // function, (), {}, var, =, +, /, ,, ., ; + // (operators, 24, usize), + // (u_operands, 11, usize), // main, a, b, c, avg, 3, 5, console.log, console, log, "{}" + // (operands, 21, usize) + ] + ); + } } From b07ef195cd5238a3dc9e4474381e0af8f49dbb18 Mon Sep 17 00:00:00 2001 From: Devon Burriss Date: Tue, 5 Apr 2022 09:16:35 +0200 Subject: [PATCH 2/7] Operator impl and assertions --- src/getter.rs | 23 +++++++++++++++++++---- src/metrics/halstead.rs | 8 ++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/getter.rs b/src/getter.rs index 999127470..114510844 100644 --- a/src/getter.rs +++ b/src/getter.rs @@ -552,6 +552,7 @@ impl Getter for JavaCode { // Operand: vars and const let typ = node.object().kind_id(); + match typ.into() { // LPAREN | COMMA | STAR | GTGT | COLON | SEMI | Return | Break | Continue | If | Else // | Switch | Case | Default | For | While | New | Try | Catch | Throw | Throws @@ -563,7 +564,7 @@ impl Getter for JavaCode { // Operator: control flow | If | Else | Switch | Case | Try | Catch | Throw | Throws | Throws2 | For | While | Continue | Break | Do | Finally // Operator: keywords - | New | Return | Default | Abstract | Assert | Instanceof | Extends | Final | Implements | Transient | Synchronized | Super | This + | New | Return | Default | Abstract | Assert | Instanceof | Extends | Final | Implements | Transient | Synchronized | Super | This | VoidType // Operator: brackets and comma and terminators (separators) | SEMI | COMMA | COLONCOLON | LBRACE | LBRACK | LPAREN | RBRACE | RBRACK | RPAREN | DOTDOTDOT | DOT // Operator: operators @@ -571,10 +572,24 @@ impl Getter for JavaCode { | EQEQ | LTEQ | GTEQ | BANGEQ | AMPAMP | PIPEPIPE | PLUSPLUS | DASHDASH | PLUS | DASH | STAR | SLASH | AMP | PIPE | CARET | PERCENT| LTLT | GTGT | GTGTGT | PLUSEQ | DASHEQ | STAREQ | SLASHEQ | AMPEQ | PIPEEQ | CARETEQ | PERCENTEQ | LTLTEQ | GTGTEQ | GTGTGTEQ - => HalsteadType::Operator, + // type identifier + | TypeIdentifier + // Literals + | IntegralType | FloatingPointType | BooleanType | NullLiteral + => { + println!("operator: {}", node.object().kind().to_string()); + HalsteadType::Operator + }, + // variables, constants - Identifier | Literal => HalsteadType::Operand, - _ => HalsteadType::Unknown, + Identifier | Literal => { + println!("operand: {} ", node.object().kind().to_string()); + HalsteadType::Operand + }, + _ => { + println!("unknown: {} ", node.object().kind().to_string()); + HalsteadType::Unknown + }, } } diff --git a/src/metrics/halstead.rs b/src/metrics/halstead.rs index 27a652955..1db5e76b1 100644 --- a/src/metrics/halstead.rs +++ b/src/metrics/halstead.rs @@ -540,10 +540,10 @@ mod tests { JavaParser, halstead, [ - (u_operators, 10, usize), // function, (), {}, var, =, +, /, ,, ., ; - // (operators, 24, usize), - // (u_operands, 11, usize), // main, a, b, c, avg, 3, 5, console.log, console, log, "{}" - // (operands, 21, usize) + (u_operators, 16, usize), // void ; ( String [ ] ) { , int = + / format . } + (operators, 33, usize), + (u_operands, 11, usize), // main, a, b, c, avg, 3, 5, MessageFormat.format, format, "{}" + (operands, 21, usize) ] ); } From 7fa7ee799b96f55e01cc5acf63964c8ef85b9c49 Mon Sep 17 00:00:00 2001 From: Devon Burriss Date: Wed, 6 Apr 2022 06:53:14 +0200 Subject: [PATCH 3/7] Operands impl and assertions --- src/getter.rs | 10 ++++------ src/metrics/halstead.rs | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/getter.rs b/src/getter.rs index 114510844..e42761e38 100644 --- a/src/getter.rs +++ b/src/getter.rs @@ -559,7 +559,7 @@ impl Getter for JavaCode { // | Throws2 | EQ | EQEQ | AMP | AMPAMP | AMPEQ | LT | LTLT | LTEQ | LTLTEQ | BANGEQ // | GTEQ | GTGTEQ | GTGTGT | GTGTGTEQ | PLUSEQ | BANG | STAREQ | SLASHEQ | PERCENTEQ // | CARET | CARETEQ | LBRACE | RBRACE | QMARK | Instanceof - // Operator: function calls? + // Operator: function calls MethodInvocation // Operator: control flow | If | Else | Switch | Case | Try | Catch | Throw | Throws | Throws2 | For | While | Continue | Break | Do | Finally @@ -573,16 +573,14 @@ impl Getter for JavaCode { | PLUS | DASH | STAR | SLASH | AMP | PIPE | CARET | PERCENT| LTLT | GTGT | GTGTGT | PLUSEQ | DASHEQ | STAREQ | SLASHEQ | AMPEQ | PIPEEQ | CARETEQ | PERCENTEQ | LTLTEQ | GTGTEQ | GTGTGTEQ // type identifier - | TypeIdentifier - // Literals - | IntegralType | FloatingPointType | BooleanType | NullLiteral + | TypeIdentifier | IntegralType | FloatingPointType | BooleanType => { println!("operator: {}", node.object().kind().to_string()); HalsteadType::Operator }, - // variables, constants - Identifier | Literal => { + // Operands: variables, constants, literals + Identifier | NullLiteral | ClassLiteral | StringLiteral | CharacterLiteral | HexIntegerLiteral | OctalIntegerLiteral | BinaryIntegerLiteral | DecimalIntegerLiteral | HexFloatingPointLiteral | DecimalFloatingPointLiteral => { println!("operand: {} ", node.object().kind().to_string()); HalsteadType::Operand }, diff --git a/src/metrics/halstead.rs b/src/metrics/halstead.rs index 1db5e76b1..890a4d75e 100644 --- a/src/metrics/halstead.rs +++ b/src/metrics/halstead.rs @@ -542,7 +542,7 @@ mod tests { [ (u_operators, 16, usize), // void ; ( String [ ] ) { , int = + / format . } (operators, 33, usize), - (u_operands, 11, usize), // main, a, b, c, avg, 3, 5, MessageFormat.format, format, "{}" + (u_operands, 11, usize), // main args a b c avg 5 3 MessageFormat format "{0}" (operands, 21, usize) ] ); From 3a8e91a20c6e38c72a31ab2de86839ce388ffc8a Mon Sep 17 00:00:00 2001 From: Devon Burriss Date: Wed, 6 Apr 2022 12:52:59 +0200 Subject: [PATCH 4/7] Adds class around Java halstead test eg --- src/metrics/halstead.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/metrics/halstead.rs b/src/metrics/halstead.rs index 890a4d75e..3c519cbc0 100644 --- a/src/metrics/halstead.rs +++ b/src/metrics/halstead.rs @@ -530,20 +530,22 @@ mod tests { #[test] fn java_operators_and_operands() { check_metrics!( - "public static void main(String args[]) { - int a, b, c, avg; - a = 5; b = 5; c = 5; - avg = (a + b + c) / 3; - MessageFormat.format(\"{0}\", avg); + "public class Main { + public static void main(String args[]) { + int a, b, c, avg; + a = 5; b = 5; c = 5; + avg = (a + b + c) / 3; + MessageFormat.format(\"{0}\", avg); + } }", "foo.java", JavaParser, halstead, [ - (u_operators, 16, usize), // void ; ( String [ ] ) { , int = + / format . } - (operators, 33, usize), - (u_operands, 11, usize), // main args a b c avg 5 3 MessageFormat format "{0}" - (operands, 21, usize) + (u_operators, 16, usize), // { void ; ( String [ ] ) , int = + / format . } + (operators, 34, usize), + (u_operands, 12, usize), // Main main args a b c avg 5 3 MessageFormat format "{0}" + (operands, 22, usize) ] ); } From 6eee4fc67020a2eec287572d48f1f16c61da8bfd Mon Sep 17 00:00:00 2001 From: Devon Burriss Date: Thu, 7 Apr 2022 06:29:40 +0200 Subject: [PATCH 5/7] Linter fixes and cleanup println still present --- src/getter.rs | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/getter.rs b/src/getter.rs index e42761e38..ab948dfa0 100644 --- a/src/getter.rs +++ b/src/getter.rs @@ -525,15 +525,6 @@ impl Getter for JavaCode { } } - // fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> { - // if let Some(name) = node.object().child_by_field_name("name") { - // let code = &code[name.start_byte()..name.end_byte()]; - // std::str::from_utf8(code).ok() - // } else { - // Some("") - // } - // } - fn get_op_type(node: &Node) -> HalsteadType { use Java::*; @@ -554,11 +545,6 @@ impl Getter for JavaCode { let typ = node.object().kind_id(); match typ.into() { - // LPAREN | COMMA | STAR | GTGT | COLON | SEMI | Return | Break | Continue | If | Else - // | Switch | Case | Default | For | While | New | Try | Catch | Throw | Throws - // | Throws2 | EQ | EQEQ | AMP | AMPAMP | AMPEQ | LT | LTLT | LTEQ | LTLTEQ | BANGEQ - // | GTEQ | GTGTEQ | GTGTGT | GTGTGTEQ | PLUSEQ | BANG | STAREQ | SLASHEQ | PERCENTEQ - // | CARET | CARETEQ | LBRACE | RBRACE | QMARK | Instanceof // Operator: function calls MethodInvocation // Operator: control flow @@ -575,17 +561,17 @@ impl Getter for JavaCode { // type identifier | TypeIdentifier | IntegralType | FloatingPointType | BooleanType => { - println!("operator: {}", node.object().kind().to_string()); + println!("operator: {}", node.object().kind()); HalsteadType::Operator }, // Operands: variables, constants, literals Identifier | NullLiteral | ClassLiteral | StringLiteral | CharacterLiteral | HexIntegerLiteral | OctalIntegerLiteral | BinaryIntegerLiteral | DecimalIntegerLiteral | HexFloatingPointLiteral | DecimalFloatingPointLiteral => { - println!("operand: {} ", node.object().kind().to_string()); + println!("operand: {} ", node.object().kind()); HalsteadType::Operand }, _ => { - println!("unknown: {} ", node.object().kind().to_string()); + println!("unknown: {} ", node.object().kind()); HalsteadType::Unknown }, } From 1f14f484e43da65ee54aa6218e7ec7284028fa8c Mon Sep 17 00:00:00 2001 From: Devon Burriss Date: Wed, 13 Apr 2022 19:24:04 +0200 Subject: [PATCH 6/7] Cleanup comments and println --- src/getter.rs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/getter.rs b/src/getter.rs index ab948dfa0..b027e0f48 100644 --- a/src/getter.rs +++ b/src/getter.rs @@ -527,21 +527,9 @@ impl Getter for JavaCode { fn get_op_type(node: &Node) -> HalsteadType { use Java::*; - + // Some guides that informed grammar choice for Halstead // keywords, operators, literals: https://docs.oracle.com/javase/specs/jls/se18/html/jls-3.html#jls-3.12 // https://www.geeksforgeeks.org/software-engineering-halsteads-software-metrics/?msclkid=5e181114abef11ecbb03527e95a34828 - // - // comments not considered - // Operator: function calls? - // Operator: control flow - // Operator: keywords - // Operator: brackets and comma and terminators - // Operator: operators - // Operator: InstanceOf - // Operator: . - // Operand: struct name - // Operand: vars and const - let typ = node.object().kind_id(); match typ.into() { @@ -561,17 +549,13 @@ impl Getter for JavaCode { // type identifier | TypeIdentifier | IntegralType | FloatingPointType | BooleanType => { - println!("operator: {}", node.object().kind()); HalsteadType::Operator }, - // Operands: variables, constants, literals Identifier | NullLiteral | ClassLiteral | StringLiteral | CharacterLiteral | HexIntegerLiteral | OctalIntegerLiteral | BinaryIntegerLiteral | DecimalIntegerLiteral | HexFloatingPointLiteral | DecimalFloatingPointLiteral => { - println!("operand: {} ", node.object().kind()); HalsteadType::Operand }, _ => { - println!("unknown: {} ", node.object().kind()); HalsteadType::Unknown }, } From fa10e445516efb7a7f2e17e8ae8c8fd0a0bd2db3 Mon Sep 17 00:00:00 2001 From: Devon Burriss Date: Sun, 29 May 2022 08:25:18 +0200 Subject: [PATCH 7/7] Split long enum line --- src/getter.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/getter.rs b/src/getter.rs index b027e0f48..43a4f08c9 100644 --- a/src/getter.rs +++ b/src/getter.rs @@ -552,7 +552,8 @@ impl Getter for JavaCode { HalsteadType::Operator }, // Operands: variables, constants, literals - Identifier | NullLiteral | ClassLiteral | StringLiteral | CharacterLiteral | HexIntegerLiteral | OctalIntegerLiteral | BinaryIntegerLiteral | DecimalIntegerLiteral | HexFloatingPointLiteral | DecimalFloatingPointLiteral => { + Identifier | NullLiteral | ClassLiteral | StringLiteral | CharacterLiteral | HexIntegerLiteral | OctalIntegerLiteral + | BinaryIntegerLiteral | DecimalIntegerLiteral | HexFloatingPointLiteral | DecimalFloatingPointLiteral => { HalsteadType::Operand }, _ => {