Skip to content

Commit 4987e90

Browse files
authored
Implement Halstead for Java (#811)
1 parent b5496f8 commit 4987e90

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

src/getter.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,4 +524,43 @@ impl Getter for JavaCode {
524524
_ => SpaceKind::Unknown,
525525
}
526526
}
527+
528+
fn get_op_type(node: &Node) -> HalsteadType {
529+
use Java::*;
530+
// Some guides that informed grammar choice for Halstead
531+
// keywords, operators, literals: https://docs.oracle.com/javase/specs/jls/se18/html/jls-3.html#jls-3.12
532+
// https://www.geeksforgeeks.org/software-engineering-halsteads-software-metrics/?msclkid=5e181114abef11ecbb03527e95a34828
533+
let typ = node.object().kind_id();
534+
535+
match typ.into() {
536+
// Operator: function calls
537+
MethodInvocation
538+
// Operator: control flow
539+
| If | Else | Switch | Case | Try | Catch | Throw | Throws | Throws2 | For | While | Continue | Break | Do | Finally
540+
// Operator: keywords
541+
| New | Return | Default | Abstract | Assert | Instanceof | Extends | Final | Implements | Transient | Synchronized | Super | This | VoidType
542+
// Operator: brackets and comma and terminators (separators)
543+
| SEMI | COMMA | COLONCOLON | LBRACE | LBRACK | LPAREN | RBRACE | RBRACK | RPAREN | DOTDOTDOT | DOT
544+
// Operator: operators
545+
| EQ | LT | GT | BANG | TILDE | QMARK | COLON // no grammar for lambda operator ->
546+
| EQEQ | LTEQ | GTEQ | BANGEQ | AMPAMP | PIPEPIPE | PLUSPLUS | DASHDASH
547+
| PLUS | DASH | STAR | SLASH | AMP | PIPE | CARET | PERCENT| LTLT | GTGT | GTGTGT
548+
| PLUSEQ | DASHEQ | STAREQ | SLASHEQ | AMPEQ | PIPEEQ | CARETEQ | PERCENTEQ | LTLTEQ | GTGTEQ | GTGTGTEQ
549+
// type identifier
550+
| TypeIdentifier | IntegralType | FloatingPointType | BooleanType
551+
=> {
552+
HalsteadType::Operator
553+
},
554+
// Operands: variables, constants, literals
555+
Identifier | NullLiteral | ClassLiteral | StringLiteral | CharacterLiteral | HexIntegerLiteral | OctalIntegerLiteral
556+
| BinaryIntegerLiteral | DecimalIntegerLiteral | HexFloatingPointLiteral | DecimalFloatingPointLiteral => {
557+
HalsteadType::Operand
558+
},
559+
_ => {
560+
HalsteadType::Unknown
561+
},
562+
}
563+
}
564+
565+
get_operator!(Java);
527566
}

src/metrics/halstead.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,9 +325,14 @@ impl Halstead for CppCode {
325325
}
326326
}
327327

328+
impl Halstead for JavaCode {
329+
fn compute<'a>(node: &Node<'a>, code: &'a [u8], halstead_maps: &mut HalsteadMaps<'a>) {
330+
compute_halstead::<Self>(node, code, halstead_maps);
331+
}
332+
}
333+
328334
impl Halstead for PreprocCode {}
329335
impl Halstead for CcommentCode {}
330-
impl Halstead for JavaCode {}
331336

332337
#[cfg(test)]
333338
mod tests {
@@ -521,4 +526,27 @@ mod tests {
521526
]
522527
);
523528
}
529+
530+
#[test]
531+
fn java_operators_and_operands() {
532+
check_metrics!(
533+
"public class Main {
534+
public static void main(String args[]) {
535+
int a, b, c, avg;
536+
a = 5; b = 5; c = 5;
537+
avg = (a + b + c) / 3;
538+
MessageFormat.format(\"{0}\", avg);
539+
}
540+
}",
541+
"foo.java",
542+
JavaParser,
543+
halstead,
544+
[
545+
(u_operators, 16, usize), // { void ; ( String [ ] ) , int = + / format . }
546+
(operators, 34, usize),
547+
(u_operands, 12, usize), // Main main args a b c avg 5 3 MessageFormat format "{0}"
548+
(operands, 22, usize)
549+
]
550+
);
551+
}
524552
}

0 commit comments

Comments
 (0)