import semmle.code.java.Member
import Commentable
/** A delegate to compute metrics on a callable */
class MetricCallable extends Callable, Commentable {
/** printable representation */
string toString() { result = Callable.super.toString() }
/** should the comments for this callable be measured? */
predicate countDoc(Commentable c) {
c.fromSource() and
((Callable)c).hasModifier("public") and
c.getNumberOfLinesOfCode() > 25
}
/** Dependency of Callables
One callable "this" depends on another callable "result"
if "this" makes some call to a method that may end up being "result".
*/
MetricCallable getADependency() {
this.polyCalls(result)
}
/** Afferent Coupling
the number of callables that depend on this method.
This is sometimes called the "fan-in" of a method.
*/
int getAfferentCoupling() {
result = count(MetricCallable m | m.getADependency() = this )
}
/** Efferent Coupling
the number of methods that this method depends on
This is sometimes called the "fan-out" of a method.
*/
int getEfferentCoupling() {
result = count(MetricCallable m | this.getADependency() = m)
}
/** Number of parameters
It is generally considered bad practice to have methods with 8
or more parameters: in those cases, it is often preferable to
encapsulate the tuple of parameters in a new class.
To find the problematic methods in your application, run the
query
from Method m, int n
where m.fromSource() and
m.getNumberOfParameters() = n and
n > 7
select m.getDeclaringType().getPackage(),
m.getDeclaringType(),
m,
n order by n desc
*/
int getNumberOfParameters() {
result = Callable.super.getNumberOfParameters()
}
/** Cyclomatic complexity
the number of branching statements (if, while, do, for,
switch, case, catch) plus the number of branching
expressions (?, && and ||) plus one.
Callables with a high cyclomatic complexity (> 10) are
hard to test and maintain, given their large number of
possible execution paths. They should be refactored.
*/
int getCyclomaticComplexity() {
result =
count(BranchingStmt stmt | stmt.getEnclosingCallable() = this) +
count(BranchingExpr expr | expr.getEnclosingCallable() = this) +
1
}
/** the Halstead length of a callable is estimated as the sum of the number of statements
and expressions within the callable, plus one for the callable itself */
int getHalsteadLength() {
result = count(Stmt s | s.getEnclosingCallable() = this)
+ count(Expr e | e.getEnclosingCallable() = this)
+ 1
}
/** the Halstead vocabulary of a callable is estimated as the number of unique Halstead IDs
of all statements and expressions within the callable */
int getHalsteadVocabulary() {
result = count(string id | exists(Stmt s | s.getEnclosingCallable() = this and id = s.getHalsteadID())
or exists(Expr e | e.getEnclosingCallable() = this and id = e.getHalsteadID()))
}
}
/** A branching statement used for the computation of
cyclomatic complexity */
class BranchingStmt extends Stmt {
BranchingStmt() {
this instanceof IfStmt or
this instanceof WhileStmt or
this instanceof DoStmt or
this instanceof ForStmt or
this instanceof EnhancedForStmt or
this instanceof SwitchStmt or
this instanceof ConstCase or
this instanceof CatchClause
}
}
/** A branching expression used for the computation of
cyclomatic complexity */
class BranchingExpr extends Expr {
BranchingExpr() {
this instanceof ConditionalExpr or
this instanceof AndLogicalExpr or
this instanceof OrLogicalExpr
}
}
|
|