PMD Apex language module providing static code analysis support for Salesforce Apex programming language.
—
Complexity and quality metrics calculation for Apex code analysis. Provides cyclomatic complexity, cognitive complexity, and weighted method count metrics.
Pre-defined metrics for measuring code complexity and quality.
/**
* Built-in metrics for Apex code analysis
*/
public class ApexMetrics {
/**
* Cyclomatic Complexity metric - measures the number of independent paths through code
* Applied to methods and constructors
*/
public static final Metric<ASTMethod, Integer> CYCLO;
/**
* Cognitive Complexity metric - measures how difficult code is to understand
* Applied to methods and constructors, considers nesting and control flow
*/
public static final Metric<ASTMethod, Integer> COGNITIVE_COMPLEXITY;
/**
* Weighted Method Count metric - sum of complexities of all methods in a class
* Applied to classes, interfaces, and enums
*/
public static final Metric<ASTUserClass, Integer> WEIGHED_METHOD_COUNT;
}Computing metrics for AST nodes using the PMD metrics framework.
/**
* Utility class for computing metrics on AST nodes
* Part of PMD core framework
*/
public class MetricsUtil {
/**
* Compute a metric for a given AST node
* @param metric - The metric to compute
* @param node - The AST node to analyze
* @return The computed metric value
*/
public static <T, R> R computeMetric(Metric<T, R> metric, T node);
/**
* Check if metrics are supported for a given node type
* @param nodeType - The class of AST node
* @return true if metrics can be computed for this node type
*/
public static boolean supportsAll(Class<?> nodeType);
}Usage Examples:
import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics;
import net.sourceforge.pmd.lang.metrics.MetricsUtil;
// Compute cyclomatic complexity for a method
public class ComplexityAnalyzer extends ApexVisitorBase<Object, Object> {
@Override
public Object visit(ASTMethod node, Object data) {
// Calculate cyclomatic complexity
int cyclomaticComplexity = MetricsUtil.computeMetric(ApexMetrics.CYCLO, node);
System.out.println("Method " + node.getName() + " has cyclomatic complexity: " + cyclomaticComplexity);
// Calculate cognitive complexity
int cognitiveComplexity = MetricsUtil.computeMetric(ApexMetrics.COGNITIVE_COMPLEXITY, node);
System.out.println("Method " + node.getName() + " has cognitive complexity: " + cognitiveComplexity);
// Flag high complexity methods
if (cyclomaticComplexity > 10) {
System.out.println("WARNING: High cyclomatic complexity in method " + node.getName());
}
return super.visit(node, data);
}
@Override
public Object visit(ASTUserClass node, Object data) {
// Calculate weighted method count for class
int weightedMethodCount = MetricsUtil.computeMetric(ApexMetrics.WEIGHED_METHOD_COUNT, node);
System.out.println("Class " + node.getQualifiedName().getClassName() +
" has weighted method count: " + weightedMethodCount);
// Flag complex classes
if (weightedMethodCount > 50) {
System.out.println("WARNING: High complexity class " + node.getQualifiedName().getClassName());
}
return super.visit(node, data);
}
}
// Use in rule or analysis tool
ComplexityAnalyzer analyzer = new ComplexityAnalyzer();
apexFile.jjtAccept(analyzer, null);
// Check if metrics are supported for a node type
boolean supportsMetrics = MetricsUtil.supportsAll(ASTMethod.class); // true
boolean supportsMetrics2 = MetricsUtil.supportsAll(ASTVariableExpression.class); // falseInstall with Tessl CLI
npx tessl i tessl/maven-net-sourceforge-pmd--pmd-apex