forked from phoedos/pmd
Compare commits
94 Commits
pmd_releas
...
pmd_releas
Author | SHA1 | Date | |
---|---|---|---|
|
0ffbe97a04 | ||
|
06d77b371a | ||
|
972eac40f0 | ||
|
336c06fb10 | ||
|
87803ed27a | ||
|
ca2794bf7d | ||
|
d921ffe1e3 | ||
|
0f48fd501d | ||
|
e1a41bdf98 | ||
|
ad1ffa5835 | ||
|
64012cc0b4 | ||
|
2500412b14 | ||
|
9f6190f3b6 | ||
|
9e620c2661 | ||
|
ac9fd51f84 | ||
|
93b4ce9bb4 | ||
|
f242c5c5f4 | ||
|
1984f5ac8a | ||
|
b553c52ef5 | ||
|
3abfc2fccb | ||
|
100dd09b28 | ||
|
a1ab0d6657 | ||
|
f0dd2b0519 | ||
|
58292bfc38 | ||
|
bd83821dd9 | ||
|
c0c79e522f | ||
|
0027fcdd77 | ||
|
abe800dfa9 | ||
|
203e39b9b3 | ||
|
922e35453a | ||
|
22671445e2 | ||
|
e3357987f2 | ||
|
dd8262cf69 | ||
|
89a3d5dd1e | ||
|
c5216fed79 | ||
|
d182626618 | ||
|
4ecb295b06 | ||
|
0785cef364 | ||
|
0671c2e478 | ||
|
1348ed8e06 | ||
|
c2ec86bac5 | ||
|
53a1f5280c | ||
|
9d8a2dd0a5 | ||
|
e93e9224ae | ||
|
df14ea9c95 | ||
|
617ca01a68 | ||
|
ee5885065e | ||
|
0b7cca49f1 | ||
|
8dc25abcfe | ||
|
2b92e22546 | ||
|
1b35a59997 | ||
|
39eb581134 | ||
|
d28e4f1fb5 | ||
|
66c1191984 | ||
|
42726428c5 | ||
|
19a13c0ab9 | ||
|
00ff9f25ae | ||
|
793af091c0 | ||
|
2c99fbd5e5 | ||
|
2aa1942015 | ||
|
c34b55285b | ||
|
b50e49777f | ||
|
a416513fc9 | ||
|
357f206102 | ||
|
cc43e6f8be | ||
|
3c316c2018 | ||
|
cae16d39d7 | ||
|
b5e7cbbaf3 | ||
|
7d630f6cb3 | ||
|
bc41b00206 | ||
|
171fdb877f | ||
|
12bbb65ebd | ||
|
3d73198ba9 | ||
|
e2a7356ccb | ||
|
a0d116ca6d | ||
|
857ae074e1 | ||
|
770fc5763e | ||
|
fba55905b6 | ||
|
a720b93431 | ||
|
de7a81202f | ||
|
f93a7bc67e | ||
|
b6c12fe449 | ||
|
fdb54ecc0e | ||
|
1910a6844c | ||
|
342e0c4789 | ||
|
a56f5545fa | ||
|
4d03c95158 | ||
|
d8961a903a | ||
|
f310138f9d | ||
|
e8c36b34f8 | ||
|
29a32bb2a7 | ||
|
fa9a4705e6 | ||
|
63f1814c80 | ||
|
c44a89cce3 |
316
do-release.sh
Executable file
316
do-release.sh
Executable file
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>5.3.0</version>
|
||||
<version>5.3.4</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@ -228,25 +228,25 @@ public class PMDTaskImpl {
|
||||
}
|
||||
|
||||
private void setupClassLoader() {
|
||||
|
||||
if (classpath == null) {
|
||||
project.log("Using the normal ClassLoader", Project.MSG_VERBOSE);
|
||||
} else {
|
||||
project.log("Using the AntClassLoader", Project.MSG_VERBOSE);
|
||||
// must be true, otherwise you'll get ClassCastExceptions as classes
|
||||
// are loaded twice
|
||||
// and exist in multiple class loaders
|
||||
boolean parentFirst = true;
|
||||
configuration.setClassLoader(new AntClassLoader(Thread.currentThread().getContextClassLoader(), project,
|
||||
classpath, parentFirst));
|
||||
classpath = new Path(project);
|
||||
}
|
||||
/*
|
||||
* 'basedir' is added to the path to make sure that relative paths
|
||||
* such as "<ruleset>resources/custom_ruleset.xml</ruleset>" still
|
||||
* work when ant is invoked from a different directory using "-f"
|
||||
*/
|
||||
classpath.add(new Path(null, project.getBaseDir().toString()));
|
||||
|
||||
project.log("Using the AntClassLoader: " + classpath, Project.MSG_VERBOSE);
|
||||
// must be true, otherwise you'll get ClassCastExceptions as classes
|
||||
// are loaded twice
|
||||
// and exist in multiple class loaders
|
||||
boolean parentFirst = true;
|
||||
configuration.setClassLoader(new AntClassLoader(Thread.currentThread().getContextClassLoader(), project,
|
||||
classpath, parentFirst));
|
||||
|
||||
try {
|
||||
/*
|
||||
* 'basedir' is added to the path to make sure that relative paths
|
||||
* such as "<ruleset>resources/custom_ruleset.xml</ruleset>" still
|
||||
* work when ant is invoked from a different directory using "-f"
|
||||
*/
|
||||
configuration.prependClasspath(project.getBaseDir().toString());
|
||||
if (auxClasspath != null) {
|
||||
project.log("Using auxclasspath: " + auxClasspath, Project.MSG_VERBOSE);
|
||||
configuration.prependClasspath(auxClasspath.toString());
|
||||
|
@ -4,6 +4,8 @@
|
||||
package net.sourceforge.pmd.cli;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
@ -60,8 +62,9 @@ public class PMDParameters {
|
||||
@Parameter(names = { "-minimumpriority", "-min" }, description = "Rule priority threshold; rules with lower priority than configured here won't be used. Default is '5' which is the lowest priority.", converter = RulePriorityConverter.class)
|
||||
private RulePriority minimumPriority = RulePriority.LOW;
|
||||
|
||||
@Parameter(names = { "-property", "-P" }, description = "{name}={value}: Define a property for the report format.", converter = PropertyConverter.class)
|
||||
private Properties properties = new Properties();
|
||||
@Parameter(names = { "-property", "-P" }, description = "{name}={value}: Define a property for the report format.",
|
||||
converter = PropertyConverter.class)
|
||||
private List<Properties> properties = new ArrayList<Properties>();
|
||||
|
||||
@Parameter(names = { "-reportfile", "-r" }, description = "Sends report output to a file; default to System.out.")
|
||||
private String reportfile = null;
|
||||
@ -186,7 +189,11 @@ public class PMDParameters {
|
||||
}
|
||||
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
Properties result = new Properties();
|
||||
for (Properties p : properties) {
|
||||
result.putAll(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getReportfile() {
|
||||
|
@ -3,10 +3,12 @@
|
||||
*/
|
||||
package net.sourceforge.pmd.cpd;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@ -19,6 +21,7 @@ import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.AbstractConfiguration;
|
||||
import net.sourceforge.pmd.util.FileFinder;
|
||||
import net.sourceforge.pmd.util.FileUtil;
|
||||
|
||||
import com.beust.jcommander.IStringConverter;
|
||||
import com.beust.jcommander.Parameter;
|
||||
@ -173,12 +176,7 @@ public class CPDConfiguration extends AbstractConfiguration {
|
||||
}
|
||||
try {
|
||||
Renderer renderer = clazz.getDeclaredConstructor().newInstance();
|
||||
|
||||
PropertyDescriptor encodingProperty = new PropertyDescriptor("encoding", clazz);
|
||||
Method method = encodingProperty.getWriteMethod();
|
||||
if (method != null) {
|
||||
method.invoke(renderer, encoding);
|
||||
}
|
||||
setRendererEncoding(renderer, encoding);
|
||||
return renderer;
|
||||
} catch (Exception e) {
|
||||
System.err.println("Couldn't instantiate renderer, defaulting to SimpleRenderer: " + e);
|
||||
@ -186,6 +184,19 @@ public class CPDConfiguration extends AbstractConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private static void setRendererEncoding(Renderer renderer, String encoding)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
try {
|
||||
PropertyDescriptor encodingProperty = new PropertyDescriptor("encoding", renderer.getClass());
|
||||
Method method = encodingProperty.getWriteMethod();
|
||||
if (method != null) {
|
||||
method.invoke(renderer, encoding);
|
||||
}
|
||||
} catch (IntrospectionException e) {
|
||||
// ignored - maybe this renderer doesn't have a encoding property
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getRenderers() {
|
||||
String[] result = RENDERERS.keySet().toArray(new String[RENDERERS.size()]);
|
||||
Arrays.sort(result);
|
||||
@ -275,10 +286,10 @@ public class CPDConfiguration extends AbstractConfiguration {
|
||||
if (excludedFile.isDirectory()) {
|
||||
List<File> files = finder.findFilesFrom(excludedFile, languageFilter, true);
|
||||
for (File f : files) {
|
||||
exclusions.add(f.getAbsolutePath());
|
||||
exclusions.add(FileUtil.normalizeFilename(f.getAbsolutePath()));
|
||||
}
|
||||
} else {
|
||||
exclusions.add(excludedFile.getAbsolutePath());
|
||||
exclusions.add(FileUtil.normalizeFilename(excludedFile.getAbsolutePath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -286,7 +297,7 @@ public class CPDConfiguration extends AbstractConfiguration {
|
||||
FilenameFilter filter = new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
File f = new File(dir, name);
|
||||
if (exclusions.contains(f.getAbsolutePath())) {
|
||||
if (exclusions.contains(FileUtil.normalizeFilename(f.getAbsolutePath()))) {
|
||||
System.err.println("Excluding " + f.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
@ -17,6 +17,9 @@ public class Linker {
|
||||
private final static Logger LOGGER = Logger.getLogger(Linker.class.getName());
|
||||
private final static String CLASS_NAME = Linker.class.getCanonicalName();
|
||||
|
||||
/** Maximum loops to prevent hanging of PMD. See https://sourceforge.net/p/pmd/bugs/1393/ */
|
||||
private static final int MAX_LOOPS = 100;
|
||||
|
||||
private final DataFlowHandler dataFlowHandler;
|
||||
private List<StackObject> braceStack;
|
||||
private List<StackObject> continueBreakReturnStack;
|
||||
@ -37,7 +40,9 @@ public class Linker {
|
||||
// the last index of the sequence.
|
||||
LOGGER.fine("SequenceChecking continueBreakReturnStack elements");
|
||||
SequenceChecker sc = new SequenceChecker(braceStack);
|
||||
while (!sc.run()) {
|
||||
int i = 0;
|
||||
while (!sc.run() && i < MAX_LOOPS) {
|
||||
i++;
|
||||
if (LOGGER.isLoggable(Level.FINE)) {
|
||||
LOGGER.fine("After sc.run - starting Sequence checking loop with firstIndex=" + sc.getFirstIndex()
|
||||
+ ", lastIndex " + sc.getLastIndex() + " with this StackList " + dump("braceStack", braceStack));
|
||||
|
@ -17,6 +17,9 @@ import net.sourceforge.pmd.lang.dfa.NodeType;
|
||||
public class DAAPathFinder {
|
||||
private static final int MAX_PATHS = 5000;
|
||||
|
||||
/** Maximum loops to prevent hanging of PMD. See https://sourceforge.net/p/pmd/bugs/1393/ */
|
||||
private static final int MAX_LOOPS = 100;
|
||||
|
||||
private DataFlowNode rootNode;
|
||||
private Executable shim;
|
||||
private CurrentPath currentPath = new CurrentPath();
|
||||
@ -59,7 +62,9 @@ public class DAAPathFinder {
|
||||
* Builds up the path.
|
||||
* */
|
||||
private void phase2(boolean flag) {
|
||||
while (!currentPath.isEndNode()) {
|
||||
int i = 0;
|
||||
while (!currentPath.isEndNode() && i < MAX_LOOPS) {
|
||||
i++;
|
||||
if (currentPath.isBranch() || currentPath.isFirstDoStatement()) {
|
||||
if (flag) {
|
||||
addNodeToTree();
|
||||
@ -126,8 +131,9 @@ public class DAAPathFinder {
|
||||
PathElement last = (PathElement) stack.getLastLeaf().getUserObject();
|
||||
DataFlowNode inode = currentPath.getLast();
|
||||
if (inode.getChildren().size() > last.currentChild) {
|
||||
// for some unknown reasons last.currentChild might not be a children of inode, see bug 1597987
|
||||
DataFlowNode child = inode.getChildren().get(last.currentChild);
|
||||
// for some unknown reasons last.currentChild might not be a children of inode, see bug 1597987
|
||||
// see https://sourceforge.net/p/pmd/bugs/606/
|
||||
DataFlowNode child = inode.getChildren().get(last.currentChild);
|
||||
this.currentPath.addLast(child);
|
||||
}
|
||||
} else {
|
||||
@ -313,6 +319,7 @@ public class DAAPathFinder {
|
||||
int counter = 0;
|
||||
if (treeNode.getParent() != null) {
|
||||
// for some unknown reasons the parent of treeNode might be null, see bug 1597987
|
||||
// see https://sourceforge.net/p/pmd/bugs/606/
|
||||
int childCount = treeNode.getParent().getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
DefaultMutableTreeNode tNode = (DefaultMutableTreeNode) treeNode.getParent().getChildAt(i);
|
||||
|
@ -10,6 +10,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
@ -46,6 +47,20 @@ public final class FileUtil {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the filename by taking the casing into account, e.g. on Windows,
|
||||
* the filename is changed to lowercase only.
|
||||
* @param fileName the file name
|
||||
* @return the normalized file name
|
||||
*/
|
||||
public static String normalizeFilename(String fileName) {
|
||||
if (fileName != null && File.separatorChar == '\\') {
|
||||
// windows
|
||||
return fileName.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects a list of DataSources using a comma separated list of input file
|
||||
* locations to process. If a file location is a directory, the directory
|
||||
|
@ -88,7 +88,7 @@
|
||||
<exclude name="PositionLiteralsFirstInComparisons"/>
|
||||
<exclude name="PreserveStackTrace"/>
|
||||
<exclude name="UncommentedEmptyConstructor"/>
|
||||
<exclude name="UncommentedEmptyMethod"/>
|
||||
<exclude name="UncommentedEmptyMethodBody"/>
|
||||
<exclude name="UnnecessaryLocalBeforeReturn"/>
|
||||
<exclude name="AbstractClassWithoutAbstractMethod"/>
|
||||
<exclude name="AccessorClassGeneration"/>
|
||||
|
@ -35,7 +35,21 @@ public class PMDCommandLineInterfaceTest {
|
||||
|
||||
Assert.assertEquals("output_folder", params.getProperties().getProperty("outputDir"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMultipleProperties() {
|
||||
PMDParameters params = new PMDParameters();
|
||||
String[] args = { "-d", "source_folder", "-f", "ideaj", "-P", "sourcePath=/home/user/source/",
|
||||
"-P", "fileName=Foo.java",
|
||||
"-P", "classAndMethodName=Foo.method",
|
||||
"-R", "java-empty" };
|
||||
PMDCommandLineInterface.extractParameters(params, args, "PMD");
|
||||
|
||||
Assert.assertEquals("/home/user/source/", params.getProperties().getProperty("sourcePath"));
|
||||
Assert.assertEquals("Foo.java", params.getProperties().getProperty("fileName"));
|
||||
Assert.assertEquals("Foo.method", params.getProperties().getProperty("classAndMethodName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetStatusCodeOrExit_DoExit() {
|
||||
exit.expectSystemExitWithStatus(0);
|
||||
|
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.cpd;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CPDConfigurationTest {
|
||||
|
||||
@Test
|
||||
public void testRenderers() {
|
||||
Map<String, Class<? extends Renderer>> renderersToTest = new HashMap<String, Class<? extends Renderer>>();
|
||||
renderersToTest.put("csv", CSVRenderer.class);
|
||||
renderersToTest.put("xml", XMLRenderer.class);
|
||||
renderersToTest.put("csv_with_linecount_per_file", CSVWithLinecountPerFileRenderer.class);
|
||||
renderersToTest.put("vs", VSRenderer.class);
|
||||
renderersToTest.put("text", SimpleRenderer.class);
|
||||
|
||||
for (Map.Entry<String, Class<? extends Renderer>> entry : renderersToTest.entrySet()) {
|
||||
Renderer r = CPDConfiguration.getRendererFromString(entry.getKey(), "UTF-8");
|
||||
Assert.assertNotNull(r);
|
||||
Assert.assertSame(entry.getValue(), r.getClass());
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>5.3.0</version>
|
||||
<version>5.3.4</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>5.3.0</version>
|
||||
<version>5.3.4</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>5.3.0</version>
|
||||
<version>5.3.4</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@ -123,4 +123,4 @@ cygwin_paths
|
||||
|
||||
java_heapsize_settings
|
||||
|
||||
java ${HEAPSIZE} -cp "${classpath}" "${CLASSNAME}" ${@}
|
||||
java ${HEAPSIZE} -cp "${classpath}" "${CLASSNAME}" "$@"
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>5.3.0</version>
|
||||
<version>5.3.4</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>5.3.0</version>
|
||||
<version>5.3.4</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>5.3.0</version>
|
||||
<version>5.3.4</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@ -47,8 +47,11 @@ public class ASTCompilationUnit extends AbstractJavaTypeNode implements RootNode
|
||||
}
|
||||
|
||||
public ASTPackageDeclaration getPackageDeclaration() {
|
||||
Node n = jjtGetChild(0);
|
||||
return n instanceof ASTPackageDeclaration ? (ASTPackageDeclaration) n : null;
|
||||
if (jjtGetNumChildren() > 0) {
|
||||
Node n = jjtGetChild(0);
|
||||
return n instanceof ASTPackageDeclaration ? (ASTPackageDeclaration) n : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ClassTypeResolver getClassTypeResolver() {
|
||||
|
@ -104,14 +104,32 @@ public abstract class AbstractInefficientZeroCheck extends AbstractJavaRule {
|
||||
private boolean isCompare(Node equality) {
|
||||
if (isLiteralLeftHand(equality)) {
|
||||
return checkComparison(inverse.get(equality.getImage()), equality, 0);
|
||||
} else {
|
||||
} else if (isLiteralRightHand(equality)) {
|
||||
return checkComparison(equality.getImage(), equality, 1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isLiteralLeftHand(Node equality) {
|
||||
return equality.jjtGetChild(0).jjtGetChild(0).jjtGetNumChildren() > 0
|
||||
&& equality.jjtGetChild(0).jjtGetChild(0).jjtGetChild(0) instanceof ASTLiteral;
|
||||
return isLiteral(equality, 0);
|
||||
}
|
||||
|
||||
private boolean isLiteralRightHand(Node equality) {
|
||||
return isLiteral(equality, 1);
|
||||
}
|
||||
|
||||
private boolean isLiteral(Node equality, int child) {
|
||||
Node target = equality.jjtGetChild(child);
|
||||
target = getFirstChildOrThis(target);
|
||||
target = getFirstChildOrThis(target);
|
||||
return target instanceof ASTLiteral;
|
||||
}
|
||||
|
||||
private Node getFirstChildOrThis(Node node) {
|
||||
if (node.jjtGetNumChildren() > 0) {
|
||||
return node.jjtGetChild(0);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,7 +144,10 @@ public abstract class AbstractInefficientZeroCheck extends AbstractJavaRule {
|
||||
* @see #getComparisonTargets()
|
||||
*/
|
||||
private boolean checkComparison(String operator, Node equality, int i) {
|
||||
Node target = equality.jjtGetChild(i).jjtGetChild(0).jjtGetChild(0);
|
||||
Node target = equality
|
||||
.jjtGetChild(i)
|
||||
.jjtGetChild(0)
|
||||
.jjtGetChild(0);
|
||||
return target instanceof ASTLiteral && getComparisonTargets().get(operator).contains(target.getImage());
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
||||
@ -31,9 +32,11 @@ public class OnlyOneReturnRule extends AbstractJavaRule {
|
||||
|
||||
List<ASTReturnStatement> returnNodes = new ArrayList<ASTReturnStatement>();
|
||||
node.findDescendantsOfType(ASTReturnStatement.class, returnNodes, false);
|
||||
returnNodes = filterLambdaExpressions(returnNodes);
|
||||
|
||||
if (returnNodes.size() > 1) {
|
||||
for (Iterator<ASTReturnStatement> i = returnNodes.iterator(); i.hasNext();) {
|
||||
Node problem = i.next();
|
||||
Node problem = i.next();
|
||||
// skip the last one, it's OK
|
||||
if (!i.hasNext()) {
|
||||
continue;
|
||||
@ -44,4 +47,21 @@ public class OnlyOneReturnRule extends AbstractJavaRule {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the return statement is inside a lambda expression, and if
|
||||
* so, this return statement is removed.
|
||||
*
|
||||
* @param returnNodes
|
||||
* all the return statements inside the method
|
||||
* @return all return statements, that are NOT within a lambda expression.
|
||||
*/
|
||||
private List<ASTReturnStatement> filterLambdaExpressions(List<ASTReturnStatement> returnNodes) {
|
||||
List<ASTReturnStatement> filtered = new ArrayList<ASTReturnStatement>();
|
||||
for (ASTReturnStatement ret : returnNodes) {
|
||||
if (ret.getFirstParentOfType(ASTLambdaExpression.class) == null) {
|
||||
filtered.add(ret);
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ public class AvoidReassigningParametersRule extends AbstractJavaRule {
|
||||
if ((jocc.isOnLeftHandSide() || jocc.isSelfAssignment())
|
||||
&& jocc.getNameForWhichThisIsAQualifier() == null
|
||||
&& !jocc.useThisOrSuper()
|
||||
&& !decl.isVarargs()
|
||||
&& (!decl.isArray() || jocc.getLocation().jjtGetParent().jjtGetParent().jjtGetNumChildren() == 1)) {
|
||||
// not an array or no primary suffix to access the array
|
||||
// values
|
||||
|
@ -58,7 +58,7 @@ public class CloseResourceRule extends AbstractJavaRule {
|
||||
|
||||
private Set<String> closeTargets = new HashSet<String>();
|
||||
private static final StringMultiProperty CLOSE_TARGETS_DESCRIPTOR = new StringMultiProperty("closeTargets",
|
||||
"Methods which may close this resource", new String[] {}, 1.0f, ',');
|
||||
"Methods which may close this resource", new String[] {"close"}, 1.0f, ',');
|
||||
|
||||
private static final StringMultiProperty TYPES_DESCRIPTOR = new StringMultiProperty("types", "Affected types",
|
||||
new String[] { "java.sql.Connection", "java.sql.Statement", "java.sql.ResultSet" }, 2.0f, ',');
|
||||
@ -121,14 +121,8 @@ public class CloseResourceRule extends AbstractJavaRule {
|
||||
if (clazz.getType() != null && types.contains(clazz.getType().getName()) || clazz.getType() == null
|
||||
&& simpleTypes.contains(toSimpleType(clazz.getImage())) || types.contains(clazz.getImage())) {
|
||||
|
||||
// if the variables are initialized with null, then they
|
||||
// are ignored.
|
||||
// At some point later in the code, there is an
|
||||
// assignment - however, this is currently ignored
|
||||
if (!hasNullInitializer(var)) {
|
||||
ASTVariableDeclaratorId id = var.getFirstDescendantOfType(ASTVariableDeclaratorId.class);
|
||||
ids.add(id);
|
||||
}
|
||||
ASTVariableDeclaratorId id = var.getFirstDescendantOfType(ASTVariableDeclaratorId.class);
|
||||
ids.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -158,7 +152,6 @@ public class CloseResourceRule extends AbstractJavaRule {
|
||||
// What are the chances of a Connection being instantiated in a
|
||||
// for-loop init block? Anyway, I'm lazy!
|
||||
String variableToClose = id.getImage();
|
||||
String target = variableToClose + ".close";
|
||||
Node n = var;
|
||||
|
||||
while (!(n instanceof ASTBlock) && !(n instanceof ASTConstructorDeclaration)) {
|
||||
@ -182,7 +175,9 @@ public class CloseResourceRule extends AbstractJavaRule {
|
||||
// variable declaration and
|
||||
// the beginning of the try block.
|
||||
ASTBlockStatement tryBlock = t.getFirstParentOfType(ASTBlockStatement.class);
|
||||
if (parentBlock.jjtGetParent() == tryBlock.jjtGetParent()) {
|
||||
if (!hasNullInitializer(var) // no need to check for critical statements, if
|
||||
// the variable has been initialized with null
|
||||
&& parentBlock.jjtGetParent() == tryBlock.jjtGetParent()) {
|
||||
|
||||
List<ASTBlockStatement> blocks = parentBlock.jjtGetParent().findChildrenOfType(ASTBlockStatement.class);
|
||||
int parentBlockIndex = blocks.indexOf(parentBlock);
|
||||
@ -208,11 +203,7 @@ public class CloseResourceRule extends AbstractJavaRule {
|
||||
List<ASTName> names = f.findDescendantsOfType(ASTName.class);
|
||||
for (ASTName oName : names) {
|
||||
String name = oName.getImage();
|
||||
if (name.equals(target) && nullCheckIfCondition(f, oName, variableToClose)) {
|
||||
closed = true;
|
||||
break;
|
||||
}
|
||||
if (name.contains(".")) {
|
||||
if (name != null && name.contains(".")) {
|
||||
String[] parts = name.split("\\.");
|
||||
if (parts.length == 2) {
|
||||
String methodName = parts[1];
|
||||
|
@ -78,11 +78,8 @@ public class CompareObjectsWithEqualsRule extends AbstractJavaRule {
|
||||
}
|
||||
|
||||
if (nd0.isReferenceType() && nd1.isReferenceType()) {
|
||||
|
||||
ASTReferenceType type0 = (ASTReferenceType) ((Node) nd0.getAccessNodeParent()).jjtGetChild(0)
|
||||
.jjtGetChild(0);
|
||||
ASTReferenceType type1 = (ASTReferenceType) ((Node) nd1.getAccessNodeParent()).jjtGetChild(0)
|
||||
.jjtGetChild(0);
|
||||
ASTReferenceType type0 = ((Node) nd0.getAccessNodeParent()).getFirstDescendantOfType(ASTReferenceType.class);
|
||||
ASTReferenceType type1 = ((Node) nd1.getAccessNodeParent()).getFirstDescendantOfType(ASTReferenceType.class);
|
||||
// skip, if it is an enum
|
||||
if (type0.getType() != null && type0.getType().equals(type1.getType()) && type0.getType().isEnum()) {
|
||||
return data;
|
||||
|
@ -916,7 +916,7 @@ public final class ConstructorCallsOverridableMethodRule extends AbstractJavaRul
|
||||
}
|
||||
|
||||
private static List<String> getMethodDeclaratorParameterTypes(Node methodOrConstructorDeclarator) {
|
||||
List<ASTFormalParameter> parameters = methodOrConstructorDeclarator.findChildrenOfType(ASTFormalParameter.class);
|
||||
List<ASTFormalParameter> parameters = methodOrConstructorDeclarator.findDescendantsOfType(ASTFormalParameter.class);
|
||||
List<String> parameterTypes = new ArrayList<String>();
|
||||
if (parameters != null) {
|
||||
for (ASTFormalParameter p : parameters) {
|
||||
|
@ -4,6 +4,7 @@
|
||||
package net.sourceforge.pmd.lang.java.rule.design;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
@ -50,7 +51,7 @@ public class FieldDeclarationsShouldBeAtStartOfClassRule extends AbstractJavaRul
|
||||
for (int i = 0; i < parent.jjtGetNumChildren(); i++) {
|
||||
Node child = parent.jjtGetChild(i);
|
||||
if (child.jjtGetNumChildren() > 0) {
|
||||
child = child.jjtGetChild(0);
|
||||
child = skipAnnotations(child);
|
||||
}
|
||||
if (child.equals(node)) {
|
||||
break;
|
||||
@ -75,4 +76,21 @@ public class FieldDeclarationsShouldBeAtStartOfClassRule extends AbstractJavaRul
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignore all annotations, until anything, that is not an annotation and
|
||||
* return this node
|
||||
* @param child the node from where to start the search
|
||||
* @return the first child or the first child after annotations
|
||||
*/
|
||||
private Node skipAnnotations(Node child) {
|
||||
Node nextChild = child.jjtGetChild(0);
|
||||
for (int j = 0; j < child.jjtGetNumChildren(); j++) {
|
||||
if (!(child.jjtGetChild(j) instanceof ASTAnnotation)) {
|
||||
nextChild = child.jjtGetChild(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return nextChild;
|
||||
}
|
||||
}
|
||||
|
@ -98,27 +98,16 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRule {
|
||||
if (importDeclaration.isStatic()) {
|
||||
String[] importParts = importDeclaration.getImportedName().split("\\.");
|
||||
String[] nameParts = name.split("\\.");
|
||||
boolean checkClassImport = false;
|
||||
if (importDeclaration.isImportOnDemand()) {
|
||||
// Name class part matches class part of static import?
|
||||
if (nameParts[nameParts.length - 2].equals(importParts[importParts.length - 1])) {
|
||||
checkClassImport = true;
|
||||
matches.add(importDeclaration);
|
||||
}
|
||||
} else {
|
||||
// Last 2 parts match?
|
||||
if (nameParts[nameParts.length - 1].equals(importParts[importParts.length - 1])
|
||||
&& nameParts[nameParts.length - 2].equals(importParts[importParts.length - 2])) {
|
||||
checkClassImport = true;
|
||||
}
|
||||
}
|
||||
if (checkClassImport) {
|
||||
// Name class part matches a direct class import?
|
||||
String nameEnd = "." + nameParts[nameParts.length - 2];
|
||||
for (ASTImportDeclaration importDeclaration2 : imports) {
|
||||
if (!importDeclaration2.isStatic() && !importDeclaration2.isImportOnDemand()
|
||||
&& importDeclaration2.getImportedName().endsWith(nameEnd)) {
|
||||
matches.add(importDeclaration2);
|
||||
}
|
||||
matches.add(importDeclaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -126,8 +115,10 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRule {
|
||||
}
|
||||
|
||||
if (!matches.isEmpty()) {
|
||||
String importStr = matches.get(0).getImportedName() + (matches.get(0).isImportOnDemand() ? ".*" : "");
|
||||
addViolation(data, node, new Object[] { node.getImage(), importStr });
|
||||
ASTImportDeclaration firstMatch = matches.get(0);
|
||||
String importStr = firstMatch.getImportedName() + (matches.get(0).isImportOnDemand() ? ".*" : "");
|
||||
String type = firstMatch.isStatic() ? "static " : "";
|
||||
addViolation(data, node, new Object[] { node.getImage(), importStr, type });
|
||||
}
|
||||
|
||||
matches.clear();
|
||||
|
@ -3,9 +3,11 @@
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.java.rule.logging;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
|
||||
|
||||
public class GuardLogStatementJavaUtilRule extends GuardLogStatementRule {
|
||||
|
||||
@ -24,6 +26,10 @@ public class GuardLogStatementJavaUtilRule extends GuardLogStatementRule {
|
||||
|
||||
@Override
|
||||
public Object visit(ASTCompilationUnit unit, Object data) {
|
||||
if (isSlf4jOrLog4jImported(unit)) {
|
||||
return data;
|
||||
}
|
||||
|
||||
String[] logLevels = getProperty(LOG_LEVELS);
|
||||
String[] guardMethods = getProperty(GUARD_METHODS);
|
||||
|
||||
@ -37,6 +43,16 @@ public class GuardLogStatementJavaUtilRule extends GuardLogStatementRule {
|
||||
return super.visit(unit,data);
|
||||
}
|
||||
|
||||
private boolean isSlf4jOrLog4jImported(ASTCompilationUnit unit) {
|
||||
List<ASTImportDeclaration> imports = unit.findChildrenOfType(ASTImportDeclaration.class);
|
||||
for (ASTImportDeclaration i : imports) {
|
||||
if (i.getImportedName().startsWith("org.slf4j") || i.getImportedName().startsWith("org.apache.log4j")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void configureGuards(String[] logLevels, String[] guardMethods) {
|
||||
String[] methods = guardMethods;
|
||||
if (methods.length != logLevels.length) {
|
||||
|
@ -3,9 +3,14 @@
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.java.rule.naming;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMarkerAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
||||
import net.sourceforge.pmd.lang.rule.properties.BooleanProperty;
|
||||
|
||||
@ -30,6 +35,10 @@ public class MethodNamingConventionsRule extends AbstractJavaRule {
|
||||
return data;
|
||||
}
|
||||
|
||||
if (isOverriddenMethod(node)) {
|
||||
return data;
|
||||
}
|
||||
|
||||
String methodName = node.getImage();
|
||||
|
||||
if (Character.isUpperCase(methodName.charAt(0))) {
|
||||
@ -41,4 +50,15 @@ public class MethodNamingConventionsRule extends AbstractJavaRule {
|
||||
return data;
|
||||
}
|
||||
|
||||
private boolean isOverriddenMethod(ASTMethodDeclarator node) {
|
||||
ASTClassOrInterfaceBodyDeclaration declaration = node.getFirstParentOfType(ASTClassOrInterfaceBodyDeclaration.class);
|
||||
List<ASTMarkerAnnotation> annotations = declaration.findDescendantsOfType(ASTMarkerAnnotation.class);
|
||||
for (ASTMarkerAnnotation ann : annotations) {
|
||||
ASTName name = ann.getFirstChildOfType(ASTName.class);
|
||||
if (name != null && name.hasImageEqualTo("Override")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.java.rule.naming;
|
||||
|
||||
import net.sourceforge.pmd.PropertyDescriptor;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
||||
@ -111,9 +112,12 @@ public class VariableNamingConventionsRule extends AbstractJavaRule {
|
||||
}
|
||||
boolean isStatic = node.isStatic();
|
||||
boolean isFinal = node.isFinal();
|
||||
|
||||
Node type = node.jjtGetParent().jjtGetParent().jjtGetParent();
|
||||
// Anything from an interface is necessarily static and final
|
||||
if (node.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTClassOrInterfaceDeclaration
|
||||
&& ((ASTClassOrInterfaceDeclaration) node.jjtGetParent().jjtGetParent().jjtGetParent()).isInterface()) {
|
||||
// Anything inside an annotation type is also static and final
|
||||
if (type instanceof ASTClassOrInterfaceDeclaration && ((ASTClassOrInterfaceDeclaration) type).isInterface()
|
||||
|| type instanceof ASTAnnotationTypeDeclaration) {
|
||||
isStatic = true;
|
||||
isFinal = true;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user