Merge branch 'master' of https://github.com/Up2Go/pmd.git
This commit is contained in:
@ -19,7 +19,8 @@ public class ASTUserInterface extends AbstractApexNode<UserInterface> implements
|
||||
field.setAccessible(true);
|
||||
Identifier name = (Identifier) field.get(node);
|
||||
return name.value;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return super.getImage();
|
||||
|
@ -51,7 +51,8 @@ public abstract class AbstractApexNode<T extends AstNode> extends AbstractNode i
|
||||
if (loc instanceof RealLoc) {
|
||||
return ((RealLoc) loc).line;
|
||||
}
|
||||
} catch (UnexpectedCodePathException e) {
|
||||
}
|
||||
catch (UnexpectedCodePathException e) {
|
||||
// some nodes are artificially generated by the compiler and are not
|
||||
// really existing in source code
|
||||
}
|
||||
@ -70,7 +71,8 @@ public abstract class AbstractApexNode<T extends AstNode> extends AbstractNode i
|
||||
if (loc instanceof RealLoc) {
|
||||
return ((RealLoc) loc).column;
|
||||
}
|
||||
} catch (UnexpectedCodePathException e) {
|
||||
}
|
||||
catch (UnexpectedCodePathException e) {
|
||||
// some nodes are artificially generated by the compiler and are not
|
||||
// really existing in source code
|
||||
}
|
||||
@ -86,7 +88,8 @@ public abstract class AbstractApexNode<T extends AstNode> extends AbstractNode i
|
||||
RealLoc realLoc = (RealLoc) loc;
|
||||
return realLoc.endIndex - realLoc.startIndex + realLoc.column;
|
||||
}
|
||||
} catch (UnexpectedCodePathException e) {
|
||||
}
|
||||
catch (UnexpectedCodePathException e) {
|
||||
// some nodes are artificially generated by the compiler and are not
|
||||
// really existing in source code
|
||||
}
|
||||
|
@ -53,7 +53,8 @@ public class ApexParser {
|
||||
|
||||
ApexNode<UserClass> tree = treeBuilder.build(astRoot);
|
||||
return tree;
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new ParseException(e);
|
||||
}
|
||||
}
|
||||
|
@ -183,9 +183,11 @@ public final class ApexTreeBuilder extends AstVisitor<AdditionalPassScope> {
|
||||
private static <T extends AstNode> void register(Class<T> nodeType, Class<? extends ApexNode<T>> nodeAdapterType) {
|
||||
try {
|
||||
NODE_TYPE_TO_NODE_ADAPTER_TYPE.put(nodeType, nodeAdapterType.getConstructor(nodeType));
|
||||
} catch (SecurityException e) {
|
||||
}
|
||||
catch (SecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
@ -210,11 +212,14 @@ public final class ApexTreeBuilder extends AstVisitor<AdditionalPassScope> {
|
||||
"There is no Node adapter class registered for the Node class: " + node.getClass());
|
||||
}
|
||||
return constructor.newInstance(node);
|
||||
} catch (InstantiationException e) {
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e.getTargetException());
|
||||
}
|
||||
}
|
||||
@ -243,7 +248,8 @@ public final class ApexTreeBuilder extends AstVisitor<AdditionalPassScope> {
|
||||
private boolean visit(AstNode node) {
|
||||
if (parents.peek() == node) {
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
build(node);
|
||||
return false;
|
||||
}
|
||||
|
@ -80,16 +80,13 @@ public class CompilerService {
|
||||
return visitAstsFromStrings(sources, visitor, CompilerStage.POST_TYPE_RESOLVE);
|
||||
}
|
||||
|
||||
public ApexCompiler visitAstsFromStrings(List<String> sources, AstVisitor<AdditionalPassScope> visitor,
|
||||
CompilerStage compilerStage) {
|
||||
List<SourceFile> sourceFiles = sources.stream()
|
||||
.map(s -> SourceFile.builder().setBody(canonicalizeString(s)).build()).collect(Collectors.toList());
|
||||
public ApexCompiler visitAstsFromStrings(List<String> sources, AstVisitor<AdditionalPassScope> visitor, CompilerStage compilerStage) {
|
||||
List<SourceFile> sourceFiles = sources.stream().map(s -> SourceFile.builder().setBody(canonicalizeString(s)).build()).collect(Collectors.toList());
|
||||
CompilationInput compilationUnit = createCompilationInput(sourceFiles, visitor);
|
||||
return compile(compilationUnit, visitor, compilerStage);
|
||||
}
|
||||
|
||||
private ApexCompiler compile(CompilationInput compilationInput, AstVisitor<AdditionalPassScope> visitor,
|
||||
CompilerStage compilerStage) {
|
||||
private ApexCompiler compile(CompilationInput compilationInput, AstVisitor<AdditionalPassScope> visitor, CompilerStage compilerStage) {
|
||||
ApexCompiler compiler = ApexCompiler.builder().setInput(compilationInput).build();
|
||||
compiler.compile(compilerStage);
|
||||
callAdditionalPassVisitor(compiler);
|
||||
@ -125,7 +122,8 @@ public class CompilerService {
|
||||
.invoke(CompilerStage.ADDITIONAL_VALIDATE);
|
||||
operation.invoke(compilerContext, unit);
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
}
|
||||
catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,8 @@ public class DumpFacade {
|
||||
this.dump(node, prefix);
|
||||
try {
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException("Problem flushing PrintWriter.", e);
|
||||
}
|
||||
}
|
||||
@ -34,7 +35,8 @@ public class DumpFacade {
|
||||
visit((ApexNode<?>) node.jjtGetChild(i), data + " ");
|
||||
}
|
||||
return data;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,8 @@ public class ApexRuleChainVisitor extends AbstractRuleChainVisitor {
|
||||
// Rule better either be a ApexParserVisitor, or a XPathRule
|
||||
if (rule instanceof XPathRule) {
|
||||
((XPathRule) rule).evaluate(node, ctx);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
((ApexNode<?>) node).jjtAccept((ApexParserVisitor) rule, ctx);
|
||||
}
|
||||
}
|
||||
|
@ -103,24 +103,28 @@ public abstract class AbstractNcssCountRule extends AbstractStatisticalApexRule
|
||||
return lineCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTWhileLoopStatement node, Object data) {
|
||||
return countNodeChildren(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTBreakStatement node, Object data) {
|
||||
return NumericConstants.ONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTTryCatchFinallyBlockStatement node, Object data) {
|
||||
return countNodeChildren(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTReturnStatement node, Object data) {
|
||||
return countNodeChildren(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTThrowStatement node, Object data) {
|
||||
return NumericConstants.ONE;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ import net.sourceforge.pmd.lang.apex.ast.ASTForEachStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTForLoopStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTIfBlockStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTWhileLoopStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTDoLoopStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTTernaryExpression;
|
||||
import net.sourceforge.pmd.lang.apex.rule.codesize.NPathComplexityRule;
|
||||
|
||||
/**
|
||||
* @author ported from Java version of Donald A. Leckie,
|
||||
@ -18,6 +21,7 @@ import net.sourceforge.pmd.lang.apex.ast.ASTWhileLoopStatement;
|
||||
*/
|
||||
public class CyclomaticComplexityRule extends StdCyclomaticComplexityRule {
|
||||
|
||||
@Override
|
||||
public Object visit(ASTIfBlockStatement node, Object data) {
|
||||
super.visit(node, data);
|
||||
|
||||
@ -26,24 +30,25 @@ public class CyclomaticComplexityRule extends StdCyclomaticComplexityRule {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTForEachStatement node, Object data) {
|
||||
super.visit(node, data);
|
||||
|
||||
int boolCompFor = NPathComplexityRule
|
||||
.sumExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class));
|
||||
int boolCompFor = NPathComplexityRule.sumExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class));
|
||||
entryStack.peek().bumpDecisionPoints(boolCompFor);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTForLoopStatement node, Object data) {
|
||||
super.visit(node, data);
|
||||
|
||||
int boolCompFor = NPathComplexityRule
|
||||
.sumExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class));
|
||||
int boolCompFor = NPathComplexityRule.sumExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class));
|
||||
entryStack.peek().bumpDecisionPoints(boolCompFor);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTWhileLoopStatement node, Object data) {
|
||||
super.visit(node, data);
|
||||
|
||||
@ -51,4 +56,22 @@ public class CyclomaticComplexityRule extends StdCyclomaticComplexityRule {
|
||||
entryStack.peek().bumpDecisionPoints(boolCompWhile);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTDoLoopStatement node, Object data) {
|
||||
super.visit( node, data );
|
||||
|
||||
int boolCompDo = NPathComplexityRule.sumExpressionComplexity( node.getFirstChildOfType( ASTExpression.class ) );
|
||||
entryStack.peek().bumpDecisionPoints( boolCompDo );
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTTernaryExpression node, Object data) {
|
||||
super.visit(node, data);
|
||||
|
||||
int boolCompWhile = NPathComplexityRule.sumExpressionComplexity(node.getFirstChildOfType(ASTExpression.class));
|
||||
entryStack.peek().bumpDecisionPoints(boolCompWhile);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ public class ExcessiveParameterListRule extends ExcessiveNodeCountRule {
|
||||
}
|
||||
|
||||
// Count these nodes, but no others.
|
||||
@Override
|
||||
public Object visit(ASTParameter node, Object data) {
|
||||
return NumericConstants.ONE;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ public class ExcessivePublicCountRule extends ExcessiveNodeCountRule {
|
||||
/**
|
||||
* Method counts ONLY public methods.
|
||||
*/
|
||||
@Override
|
||||
public Object visit(ASTMethod node, Object data) {
|
||||
return this.getTallyOnAccessType((AccessNode) node.jjtGetParent());
|
||||
}
|
||||
@ -47,6 +48,7 @@ public class ExcessivePublicCountRule extends ExcessiveNodeCountRule {
|
||||
* Method counts ONLY public class attributes which are not PUBLIC and
|
||||
* static- these usually represent constants....
|
||||
*/
|
||||
@Override
|
||||
public Object visit(ASTField node, Object data) {
|
||||
if (node.getNode().getModifierInfo().all(PUBLIC, STATIC)) {
|
||||
return NumericConstants.ZERO;
|
||||
|
@ -6,10 +6,12 @@ package net.sourceforge.pmd.lang.apex.rule.codesize;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTBooleanExpression;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTExpression;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTForEachStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTForLoopStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTIfBlockStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTIfElseBlockStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTReturnStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTStatement;
|
||||
@ -59,6 +61,7 @@ public class NPathComplexityRule extends AbstractStatisticalApexRule {
|
||||
return npath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTMethod node, Object data) {
|
||||
int npath = complexityMultipleOf(node, 1, data);
|
||||
|
||||
@ -71,11 +74,41 @@ public class NPathComplexityRule extends AbstractStatisticalApexRule {
|
||||
return Integer.valueOf(npath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ApexNode node, Object data) {
|
||||
int npath = complexityMultipleOf(node, 1, data);
|
||||
return Integer.valueOf(npath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTIfElseBlockStatement node, Object data) {
|
||||
// (npath of if + npath of else (or 1) + bool_comp of if) * npath of
|
||||
// next
|
||||
|
||||
List<ApexNode> statementChildren = new ArrayList<>();
|
||||
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
|
||||
if (node.jjtGetChild(i).getClass() == ASTStatement.class) {
|
||||
statementChildren.add((ApexNode) node.jjtGetChild(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (statementChildren.isEmpty() || statementChildren.size() == 1 && true
|
||||
|| statementChildren.size() != 1 && false) {
|
||||
throw new IllegalStateException("If node has wrong number of children");
|
||||
}
|
||||
|
||||
// add path for not taking if
|
||||
int complexity = 1;
|
||||
|
||||
for (ApexNode element : statementChildren) {
|
||||
complexity += (Integer) element.jjtAccept(this, data);
|
||||
}
|
||||
|
||||
int boolCompIf = sumExpressionComplexity(node.getFirstChildOfType(ASTExpression.class));
|
||||
return Integer.valueOf(boolCompIf + complexity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTIfBlockStatement node, Object data) {
|
||||
// (npath of if + npath of else (or 1) + bool_comp of if) * npath of
|
||||
// next
|
||||
@ -87,16 +120,12 @@ public class NPathComplexityRule extends AbstractStatisticalApexRule {
|
||||
}
|
||||
}
|
||||
|
||||
if (statementChildren.isEmpty() || statementChildren.size() == 1 && node.hasElse()
|
||||
|| statementChildren.size() != 1 && !node.hasElse()) {
|
||||
if (statementChildren.isEmpty() || statementChildren.size() == 1 && false || statementChildren.size() != 1) {
|
||||
throw new IllegalStateException("If node has wrong number of children");
|
||||
}
|
||||
|
||||
// add path for not taking if
|
||||
int complexity = 0;
|
||||
if (!node.hasElse()) {
|
||||
complexity++;
|
||||
}
|
||||
|
||||
for (ApexNode element : statementChildren) {
|
||||
complexity += (Integer) element.jjtAccept(this, data);
|
||||
@ -106,6 +135,7 @@ public class NPathComplexityRule extends AbstractStatisticalApexRule {
|
||||
return Integer.valueOf(boolCompIf + complexity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTWhileLoopStatement node, Object data) {
|
||||
// (npath of while + bool_comp of while + 1) * npath of next
|
||||
|
||||
@ -116,6 +146,7 @@ public class NPathComplexityRule extends AbstractStatisticalApexRule {
|
||||
return Integer.valueOf(boolCompWhile + nPathWhile + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTForLoopStatement node, Object data) {
|
||||
// (npath of for + bool_comp of for + 1) * npath of next
|
||||
|
||||
@ -136,6 +167,7 @@ public class NPathComplexityRule extends AbstractStatisticalApexRule {
|
||||
return Integer.valueOf(boolCompFor + nPathFor + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTReturnStatement node, Object data) {
|
||||
// return statements are valued at 1, or the value of the boolean
|
||||
// expression
|
||||
@ -159,6 +191,7 @@ public class NPathComplexityRule extends AbstractStatisticalApexRule {
|
||||
return NumericConstants.ONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTTryCatchFinallyBlockStatement node, Object data) {
|
||||
/*
|
||||
* This scenario was not addressed by the original paper. Based on the
|
||||
@ -189,17 +222,9 @@ public class NPathComplexityRule extends AbstractStatisticalApexRule {
|
||||
return 0;
|
||||
}
|
||||
|
||||
List<ASTConditionalAndExpression> andNodes = expr.findDescendantsOfType(ASTConditionalAndExpression.class);
|
||||
List<ASTConditionalOrExpression> orNodes = expr.findDescendantsOfType(ASTConditionalOrExpression.class);
|
||||
|
||||
int children = 0;
|
||||
|
||||
for (ASTConditionalOrExpression element : orNodes) {
|
||||
children += element.jjtGetNumChildren();
|
||||
children--;
|
||||
}
|
||||
|
||||
for (ASTConditionalAndExpression element : andNodes) {
|
||||
for (ASTBooleanExpression element : expr.findDescendantsOfType(ASTBooleanExpression.class)) {
|
||||
children += element.jjtGetNumChildren();
|
||||
children--;
|
||||
}
|
||||
@ -209,6 +234,7 @@ public class NPathComplexityRule extends AbstractStatisticalApexRule {
|
||||
|
||||
@Override
|
||||
public Object[] getViolationParameters(DataPoint point) {
|
||||
return new String[] { ((ASTMethod) point.getNode()).getMethodName(), String.valueOf((int) point.getScore()) };
|
||||
return new String[] { ((ASTMethod) point.getNode()).getNode().getMethodInfo().getName(),
|
||||
String.valueOf((int) point.getScore()) };
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.apex.rule.codesize;
|
||||
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
||||
import net.sourceforge.pmd.stat.DataPoint;
|
||||
|
||||
/**
|
||||
* Non-commented source statement counter for methods.
|
||||
*
|
||||
* @author Jason Bennett
|
||||
*/
|
||||
public class NcssMethodCountRule extends AbstractNcssCountRule {
|
||||
|
||||
/**
|
||||
* Count the size of all non-constructor methods.
|
||||
*/
|
||||
public NcssMethodCountRule() {
|
||||
super(ASTMethod.class);
|
||||
setProperty(MINIMUM_DESCRIPTOR, 100d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTMethod node, Object data) {
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getViolationParameters(DataPoint point) {
|
||||
return new String[] { ((ASTMethod) point.getNode()).getNode().getMethodInfo().getName(),
|
||||
String.valueOf((int) point.getScore()) };
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.apex.rule.codesize;
|
||||
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTUserClass;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface;
|
||||
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTConstructorPreambleStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTUserEnum;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclaration;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration;
|
||||
import net.sourceforge.pmd.stat.DataPoint;
|
||||
import net.sourceforge.pmd.util.NumericConstants;
|
||||
|
||||
/**
|
||||
* Non-commented source statement counter for type declarations.
|
||||
*
|
||||
* @author Jason Bennett
|
||||
*/
|
||||
public class NcssTypeCountRule extends AbstractNcssCountRule {
|
||||
|
||||
/**
|
||||
* Count type declarations. This includes classes as well as enums and
|
||||
* annotations.
|
||||
*/
|
||||
public NcssTypeCountRule() {
|
||||
super(ASTVariableDeclaration.class);
|
||||
setProperty(MINIMUM_DESCRIPTOR, 1500d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTUserClass node, Object data) {
|
||||
/*
|
||||
* if (!node.isNested()) { return super.visit(node, data); }
|
||||
*/
|
||||
return countNodeChildren(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTUserInterface node, Object data) {
|
||||
/*
|
||||
* if (!node.getNode.isNested()) { return super.visit(node, data); }
|
||||
*/
|
||||
return countNodeChildren(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTConstructorPreambleStatement node, Object data) {
|
||||
return countNodeChildren(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTUserEnum node, Object data) {
|
||||
/*
|
||||
* If the enum is a type in and of itself, don't count its declaration
|
||||
* twice.
|
||||
*/
|
||||
if (node.jjtGetParent() instanceof ASTVariableDeclaration) {
|
||||
Integer nodeCount = countNodeChildren(node, data);
|
||||
int count = nodeCount.intValue() - 1;
|
||||
return Integer.valueOf(count);
|
||||
}
|
||||
return countNodeChildren(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTMethod node, Object data) {
|
||||
return countNodeChildren(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTFieldDeclaration node, Object data) {
|
||||
return NumericConstants.ONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getViolationParameters(DataPoint point) {
|
||||
return new String[] { String.valueOf((int) point.getScore()) };
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@ import net.sourceforge.pmd.lang.apex.ast.ASTForEachStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTIfBlockStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTWhileLoopStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTDoLoopStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTTernaryExpression;
|
||||
import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule;
|
||||
import net.sourceforge.pmd.lang.rule.properties.BooleanProperty;
|
||||
import net.sourceforge.pmd.lang.rule.properties.IntegerProperty;
|
||||
@ -80,6 +82,7 @@ public class StdCyclomaticComplexityRule extends AbstractApexRule {
|
||||
definePropertyDescriptor(SHOW_METHODS_COMPLEXITY_DESCRIPTOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTCompilation node, Object data) {
|
||||
reportLevel = getProperty(REPORT_LEVEL_DESCRIPTOR);
|
||||
showClassesComplexity = getProperty(SHOW_CLASSES_COMPLEXITY_DESCRIPTOR);
|
||||
@ -88,41 +91,61 @@ public class StdCyclomaticComplexityRule extends AbstractApexRule {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTIfBlockStatement node, Object data) {
|
||||
entryStack.peek().bumpDecisionPoints();
|
||||
super.visit(node, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTTryCatchFinallyBlockStatement node, Object data) {
|
||||
entryStack.peek().bumpDecisionPoints();
|
||||
super.visit(node, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTForLoopStatement node, Object data) {
|
||||
entryStack.peek().bumpDecisionPoints();
|
||||
super.visit(node, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTForEachStatement node, Object data) {
|
||||
entryStack.peek().bumpDecisionPoints();
|
||||
super.visit(node, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTWhileLoopStatement node, Object data) {
|
||||
entryStack.peek().bumpDecisionPoints();
|
||||
super.visit(node, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTDoLoopStatement node, Object data) {
|
||||
entryStack.peek().bumpDecisionPoints();
|
||||
super.visit(node, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTTernaryExpression node, Object data) {
|
||||
entryStack.peek().bumpDecisionPoints();
|
||||
super.visit(node, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTUserInterface node, Object data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object visit(ASTUserClass node, Object data) {
|
||||
entryStack.push(new Entry(node));
|
||||
super.visit(node, data);
|
||||
@ -136,6 +159,7 @@ public class StdCyclomaticComplexityRule extends AbstractApexRule {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTMethod node, Object data) {
|
||||
entryStack.push(new Entry(node));
|
||||
super.visit(node, data);
|
||||
@ -149,15 +173,13 @@ public class StdCyclomaticComplexityRule extends AbstractApexRule {
|
||||
classEntry.highestDecisionPoints = methodDecisionPoints;
|
||||
}
|
||||
|
||||
|
||||
if (showMethodsComplexity && methodEntry.decisionPoints >= reportLevel) {
|
||||
addViolation(data, node,
|
||||
new String[] { "method", "",
|
||||
String.valueOf(methodEntry.decisionPoints) });
|
||||
addViolation(data, node, new String[] { "method", "", String.valueOf(methodEntry.decisionPoints) });
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTUserEnum node, Object data) {
|
||||
entryStack.push(new Entry(node));
|
||||
super.visit(node, data);
|
||||
|
@ -249,62 +249,6 @@ public class Foo { // This has a Cyclomatic Complexity = 12
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="ModifiedCyclomaticComplexity" since="5.1.2"
|
||||
message="The {0} ''{1}'' has a Modified Cyclomatic Complexity of {2}."
|
||||
class="net.sourceforge.pmd.lang.apex.rule.codesize.ModifiedCyclomaticComplexityRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/codesize.html#ModifiedCyclomaticComplexity">
|
||||
<description>
|
||||
<![CDATA[
|
||||
Complexity directly affects maintenance costs is determined by the number of decision points in a method
|
||||
plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls.
|
||||
Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote
|
||||
high complexity, and 11+ is very high complexity. Modified complexity treats switch statements as a single
|
||||
decision point.
|
||||
]]>
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
public class Foo { // This has a Cyclomatic Complexity = 9
|
||||
1 public void example() {
|
||||
2 if (a == b) {
|
||||
3 if (a1 == b1) {
|
||||
fiddle();
|
||||
4 } else if a2 == b2) {
|
||||
fiddle();
|
||||
} else {
|
||||
fiddle();
|
||||
}
|
||||
5 } else if (c == d) {
|
||||
6 while (c == d) {
|
||||
fiddle();
|
||||
}
|
||||
7 } else if (e == f) {
|
||||
8 for (int n = 0; n < h; n++) {
|
||||
fiddle();
|
||||
}
|
||||
} else{
|
||||
9 switch (z) {
|
||||
case 1:
|
||||
fiddle();
|
||||
break;
|
||||
case 2:
|
||||
fiddle();
|
||||
break;
|
||||
case 3:
|
||||
fiddle();
|
||||
break;
|
||||
default:
|
||||
fiddle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="ExcessivePublicCount" since="1.04"
|
||||
message="This class has a bunch of public methods and attributes"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.codesize.ExcessivePublicCountRule"
|
||||
@ -408,35 +352,6 @@ public class Foo extends Bar {
|
||||
|
||||
|
||||
|
||||
super.foo();
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="NcssConstructorCount"
|
||||
message="The constructor with {0} parameters has an NCSS line count of {1}"
|
||||
since="3.9"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.codesize.NcssConstructorCountRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/rules/apex/codesize.html#NcssConstructorCount">
|
||||
<description>
|
||||
This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines
|
||||
of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm,
|
||||
lines of code that are split are counted as one.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
public class Foo extends Bar {
|
||||
public Foo() {
|
||||
super();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//this constructor only has 1 NCSS lines
|
||||
super.foo();
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ public class ApexParserTest {
|
||||
ASTUserClass rootNode = parse(sourceCode);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
Assert.fail();
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,6 @@ public class CodesizeRulesTest extends SimpleAggregatorTst {
|
||||
addRule(RULESET, "ExcessiveClassLength");
|
||||
addRule(RULESET, "ExcessiveParameterList");
|
||||
addRule(RULESET, "ExcessiveMethodLength");
|
||||
addRule(RULESET, "ModifiedCyclomaticComplexity");
|
||||
addRule(RULESET, "NcssConstructorCount");
|
||||
addRule(RULESET, "NcssMethodCount");
|
||||
addRule(RULESET, "NcssTypeCount");
|
||||
addRule(RULESET, "NPathComplexity");
|
||||
|
@ -4,19 +4,19 @@
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public void example() {
|
||||
int x = 0;
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
int d = 0;
|
||||
int a1 = 0;
|
||||
int a2 = 0;
|
||||
int b1 = 0;
|
||||
int b2 = 0;
|
||||
int z = 0;
|
||||
int h = 0;
|
||||
int e = 0;
|
||||
int f = 0;
|
||||
Integer x = 0;
|
||||
Integer a = 0;
|
||||
Integer b = 0;
|
||||
Integer c = 0;
|
||||
Integer d = 0;
|
||||
Integer a1 = 0;
|
||||
Integer a2 = 0;
|
||||
Integer b1 = 0;
|
||||
Integer b2 = 0;
|
||||
Integer z = 0;
|
||||
Integer h = 0;
|
||||
Integer e = 0;
|
||||
Integer f = 0;
|
||||
|
||||
if (a == b) {
|
||||
if (a1 == b1) {
|
||||
@ -31,27 +31,11 @@ public class Foo {
|
||||
x = 2;
|
||||
}
|
||||
} else if (e == f) {
|
||||
for (int n = 0; n < h; n++) {
|
||||
for (Integer n = 0; n < h; n++) {
|
||||
x = 2;
|
||||
}
|
||||
} else {
|
||||
switch (z) {
|
||||
case 1:
|
||||
x = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
x = 2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
x = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
x = 2;
|
||||
break;
|
||||
}
|
||||
// taken out switch with 4 cases
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,83 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test-data>
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
short
|
||||
]]></description>
|
||||
<rule-property name="minimum">13</rule-property>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class Foo {
|
||||
public Foo() {
|
||||
bar();
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
lots of comments
|
||||
]]></description>
|
||||
<rule-property name="minimum">13</rule-property>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class Foo {
|
||||
public Foo() {
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
bar();
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
foo();
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
<code-fragment id="long method"><![CDATA[
|
||||
public class Foo {
|
||||
public Foo() {
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
bar();
|
||||
bar();
|
||||
bar();
|
||||
bar();
|
||||
bar();
|
||||
bar();
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
//nothing to see here
|
||||
foo();
|
||||
foo();
|
||||
foo();
|
||||
foo();
|
||||
foo();
|
||||
foo();
|
||||
}
|
||||
}
|
||||
]]></code-fragment>
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
long method
|
||||
]]></description>
|
||||
<rule-property name="minimum">13</rule-property>
|
||||
<expected-problems>1</expected-problems>
|
||||
<code-ref id="long method"/>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
long method - changed minimum
|
||||
]]></description>
|
||||
<!-- obtained this value by using NCSS directly -->
|
||||
<rule-property name="minimum">14</rule-property>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code-ref id="long method"/>
|
||||
</test-code>
|
||||
</test-data>
|
@ -4,19 +4,19 @@
|
||||
<![CDATA[
|
||||
public class Foo {
|
||||
public void example() {
|
||||
int x = 0;
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
int d = 0;
|
||||
int a1 = 0;
|
||||
int a2 = 0;
|
||||
int b1 = 0;
|
||||
int b2 = 0;
|
||||
int z = 0;
|
||||
int h = 0;
|
||||
int e = 0;
|
||||
int f = 0;
|
||||
Integer x = 0;
|
||||
Integer a = 0;
|
||||
Integer b = 0;
|
||||
Integer c = 0;
|
||||
Integer d = 0;
|
||||
Integer a1 = 0;
|
||||
Integer a2 = 0;
|
||||
Integer b1 = 0;
|
||||
Integer b2 = 0;
|
||||
Integer z = 0;
|
||||
Integer h = 0;
|
||||
Integer e = 0;
|
||||
Integer f = 0;
|
||||
|
||||
if (a == b) {
|
||||
if (a1 == b1) {
|
||||
@ -31,27 +31,11 @@ public class Foo {
|
||||
x = 2;
|
||||
}
|
||||
} else if (e == f) {
|
||||
for (int n = 0; n < h; n++) {
|
||||
for (Integer n = 0; n < h; n++) {
|
||||
x = 2;
|
||||
}
|
||||
} else {
|
||||
switch (z) {
|
||||
case 1:
|
||||
x = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
x = 2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
x = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
x = 2;
|
||||
break;
|
||||
}
|
||||
// taken out switch with 4 cases
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user