Compare commits

...

39 Commits

Author SHA1 Message Date
Andreas Dangel
3412d55fc6 [maven-release-plugin] prepare release pmd_releases/5.0.2 2013-02-03 18:35:37 +01:00
Andreas Dangel
436b7dcb50 pmd: set release date for 5.0.2 2013-02-03 18:29:37 +01:00
Andreas Dangel
d25dadc4b4 pmd: Prepare pmd release 5.0.2 2013-02-03 15:44:02 +01:00
Andreas Dangel
1c051674a0 pmd: update changelog for 5.0.2 2013-02-03 15:34:58 +01:00
Romain PELISSE
3daca86045 pmd: AntTask support for language
- fix  #1004 targetjdk isn't attribute of PMD task
- introduce a new element, called <language>, that replaces the already existing <version/> element
2013-02-03 15:33:46 +01:00
Romain PELISSE
d95d960de3 pmd: fix #1004 targetjdk isn't attribute of PMD task 2013-02-03 15:33:31 +01:00
Torsten Kleiber
ef7478c350 Fix for bug #1056 "Error while processing" while running on xml file with DOCTYPE reference
Change the initial value of XINCLUDE_AWARE_DESCRIPTOR to false
This does validate an invalid doctype reference as in some ide generated xml files exist.
Any xml rule, which needs this property should overwrite this value with true.
2013-02-03 15:32:54 +01:00
Romain PELISSE
c080fdda08 pmd: fix #1049 Errors in "How to write a rule" 2013-02-03 15:31:21 +01:00
Andreas Dangel
e603844a53 pmd: fix #1030 CPD Java.lang.IndexOutOfBoundsException: Index: 2013-01-26 20:08:54 +01:00
Andreas Dangel
52b8be6601 pmd: fixed #947 CloseResource rule fails if field is marked with annotation 2013-01-26 17:58:31 +01:00
Andreas Dangel
7cbb385dbb pmd: fixed #1011 CloseResource Rule ignores Constructors 2013-01-26 17:57:17 +01:00
Andreas Dangel
61c0b4ea7f pmd: fixed #1007 Parse Exception with annotation 2013-01-26 17:57:11 +01:00
Andreas Dangel
26fa85a9fa pmd: fixed #1046 ant task CPDTask doesn't accept ecmascript 2013-01-26 17:56:51 +01:00
Andreas Dangel
98b903897e pmd: fixed #1039 pmd-nicerhtml.xsl is packaged in wrong location 2013-01-26 17:55:22 +01:00
Andreas Dangel
55b5aa7f27 pmd: update rule-guidelines to changed package names 2013-01-26 17:54:09 +01:00
Andreas Dangel
ffac9894c9 pmd: fixed #1028 False-positive: Compare objects with equals for Enums 2013-01-26 17:54:03 +01:00
Andreas Dangel
d557ed9c01 pmd: verify #1020 Parsing Error 2013-01-26 17:53:56 +01:00
Andreas Dangel
e0b7f6f17c pmd: fixed #913 SignatureDeclareThrowsException is raised twice 2013-01-26 17:53:49 +01:00
Andreas Dangel
cb9861dd1f pmd: fixed #878 False positive: UnusedFormalParameter for abstract methods 2013-01-26 17:53:41 +01:00
Andreas Dangel
7ee96a6b52 pmd: fixed #1055 Please add a colon in the ant output after line,column for Oracle JDeveloper IDE usage 2013-01-26 17:53:33 +01:00
Andreas Dangel
ac8e3314a3 pmd: fixed bug #1012 False positive: Useless parentheses. 2013-01-19 19:13:09 +01:00
Andreas Dangel
7989ae1863 pmd: fixed #1060 GodClassRule >>> wrong method 2013-01-19 19:12:59 +01:00
Andreas Dangel
e3708b5030 pmd: fix #1037 Facing a showstopper issue in PMD Report Class
* wrapping the report listeners in a thread safe (synchronized) class
 * overtaking the listeners for each thread / report
2012-12-17 11:02:24 +01:00
Andreas Dangel
85e493d55f pmd: fixed #1026 PMD doesn't handle 'value =' in SuppressWarnings annotation 2012-12-16 23:12:29 +01:00
Andreas Dangel
6abbea51dd pmd: fix #1043 node.getEndLine() always returns 0 (ECMAscript)
* added commons-io dependency
 * added a SourceCodePositioner to calculate line/column from position
2012-12-16 18:16:39 +01:00
Andreas Dangel
9162917346 pmd: fix #1047 False Positive in 'for' loops for LocalVariableCouldBeFinal in 5.0.1 2012-12-16 12:10:06 +01:00
Andreas Dangel
637006674f pmd: Fixed bug 1048: CommentContent Rule, String Index out of range Exception 2012-12-07 11:17:44 +01:00
Andreas Dangel
63c1a8fe47 pmd: CLI - make sure we display the usage help text
Therefore make the -h option a help option.
Make the auxclasspath option description look nicer - newlines break the layout.
Always display the jcommander usage help text.
And exit with an error code in case there are parameter errors.
2012-12-05 22:02:49 +01:00
Andreas Dangel
063c4228e3 pmd: fix bug #1044 - update suppressing documentation with new cli paramter name 2012-12-05 22:02:40 +01:00
Andreas Dangel
4b0063dfc1 [maven-release-plugin] prepare for next development iteration 2012-11-28 21:43:38 +01:00
Andreas Dangel
13e36974a5 [maven-release-plugin] prepare release pmd_releases/5.0.1 2012-11-28 21:43:36 +01:00
Andreas Dangel
33c7af965c pmd: fix failing unit test 2012-11-28 21:25:56 +01:00
Andreas Dangel
a66bbf2193 pmd: prepare release 5.0.1 2012-11-28 21:02:35 +01:00
Andreas Dangel
38af8f2433 Merge branch 'master' into pmd/5.0.x 2012-11-28 20:42:58 +01:00
Andreas Dangel
a6bcfe2b65 pmd: added missing ssh/scp wagon support for maven3
git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/branches/pmd/5.0.x@7669 51baf565-9d33-0410-a72c-fc3788e3496d
2012-05-01 11:41:10 +00:00
Andreas Dangel
6474fde42d [maven-release-plugin] prepare for next development iteration
git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/branches/pmd/5.0.x@7668 51baf565-9d33-0410-a72c-fc3788e3496d
2012-05-01 07:43:32 +00:00
Andreas Dangel
8dcde0edb5 [maven-release-plugin] prepare release pmd_release_5_0_0
git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/branches/pmd/5.0.x@7666 51baf565-9d33-0410-a72c-fc3788e3496d
2012-05-01 07:42:56 +00:00
Andreas Dangel
70347aedd5 pmd: Prepare pmd release 5.0.0
git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/branches/pmd/5.0.x@7665 51baf565-9d33-0410-a72c-fc3788e3496d
2012-05-01 07:38:38 +00:00
Andreas Dangel
eaf1385595 update the version to the usual three components: 5.0.0-SNAPSHOT
git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/branches/pmd/5.0.x@7664 51baf565-9d33-0410-a72c-fc3788e3496d
2012-04-30 11:35:40 +00:00
64 changed files with 1178 additions and 299 deletions

View File

@ -1,4 +1,30 @@
???? ??, 2012 - 5.1.0:
February 3, 2013 - 5.0.2:
Fixed bug 878: False positive: UnusedFormalParameter for abstract methods
Fixed bug 913: SignatureDeclareThrowsException is raised twice
Fixed bug 947: CloseResource rule fails if field is marked with annotation
Fixed bug 1004: targetjdk isn't attribute of PMD task
Fixed bug 1007: Parse Exception with annotation
Fixed bug 1011: CloseResource Rule ignores Constructors
Fixed bug 1012: False positive: Useless parentheses.
Fixed bug 1020: Parsing Error
Fixed bug 1026: PMD doesn't handle 'value =' in SuppressWarnings annotation
Fixed bug 1028: False-positive: Compare objects with equals for Enums
Fixed bug 1030: CPD Java.lang.IndexOutOfBoundsException: Index:
Fixed bug 1037: Facing a showstopper issue in PMD Report Class (report listeners)
Fixed bug 1039: pmd-nicerhtml.xsl is packaged in wrong location
Fixed bug 1043: node.getEndLine() always returns 0 (ECMAscript)
Fixed bug 1044: Unknown option: -excludemarker
Fixed bug 1046: ant task CPDTask doesn't accept ecmascript
Fixed bug 1047: False Positive in 'for' loops for LocalVariableCouldBeFinal in 5.0.1
Fixed bug 1048: CommentContent Rule, String Index out of range Exception
Fixed bug 1049: Errors in "How to write a rule"
Fixed bug 1055: Please add a colon in the ant output after line,column for Oracle JDeveloper IDE usage
Fixed bug 1056: "Error while processing" while running on xml file with DOCTYPE reference
Fixed bug 1060: GodClassRule >>> wrong method
November 28, 2012 - 5.0.1:
Fixed bug 820: False+ AvoidReassigningParameters
Fixed bug 1008: pmd-5.0.0: ImmutableField false positive on self-inc/dec
@ -471,7 +497,7 @@ The RuleSet XML Schema namespace is now: http://pmd.sourceforge.net/ruleset/2.0.
The RuleSet XML Schema is located in the source at: etc/ruleset_2_0_0.xsd
The RuleSet DTD is located in the source at: etc/ruleset_2_0_0.dtd
Improved include/exclude pattern matching performance for ends-with type patterns.
Modify (and hopefully fixed) CPD algorithm thanks to a patch from Juan Jesús García de Soria.
Modify (and hopefully fixed) CPD algorithm thanks to a patch from Juan Jesús García de Soria.
Fixed character reference in xml report - thanks to Seko
Enhanced SuspiciousEqualsMethodName rule - thanks to Andy Throgmorton
Add a script to launch CPDGUI on Unix system - thanks to Tom Wheeler
@ -535,7 +561,7 @@ Fixed bug 2835074 - False -: DoubleCheckedLocking with reversed null check
Fixed bug 2826119 - False +: DoubleCheckedLocking warning with volatile field
Fixed bug 2904832 - Type resolution not working for ASTType when using an inner class
Modify (and hopefully fixed) CPD algorithm thanks to a patch from Juan Jesús García de Soria.
Modify (and hopefully fixed) CPD algorithm thanks to a patch from Juan Jesús García de Soria.
Correct -benchmark reporting of Rule visits via the RuleChain
Fix issue with Type Resolution incorrectly handling of Classes with same name as a java.lang Class.
The JSP/JSF parser can now parse Unicode input.

View File

@ -1,4 +1,12 @@
/**
* Fix ForStatement to allow Annotations within the initializer.
*
* Andreas Dangel 01/2013
* ===================================================================
* Fix wrong consumption of modifiers (e.g. "final") in a for-each loop.
*
* Andreas Dangel 12/2012
* ===================================================================
* Enhance grammar to use LocalVariableDeclaration in a for-each loop.
* This enhances the symbol table to recognize variables declared in such
* a for-each loop.
@ -1914,9 +1922,9 @@ void ForStatement() :
{
"for" "("
(
LOOKAHEAD(Modifiers() Type() <IDENTIFIER> ":")
LOOKAHEAD(LocalVariableDeclaration() ":")
{checkForBadJDK15ForLoopSyntaxArgumentsUsage();}
Modifiers() LocalVariableDeclaration() ":" Expression()
LocalVariableDeclaration() ":" Expression()
|
[ ForInit() ] ";"
[ Expression() ] ";"
@ -1928,7 +1936,7 @@ void ForStatement() :
void ForInit() :
{}
{
LOOKAHEAD( [ "final" ] Type() <IDENTIFIER> )
LOOKAHEAD( LocalVariableDeclaration() )
LocalVariableDeclaration()
|
StatementExpressionList()

View File

@ -1,11 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<name>PMD</name>
<version>5.1.0-SNAPSHOT</version>
<version>5.0.2</version>
<parent>
<groupId>org.sonatype.oss</groupId>
@ -233,6 +232,7 @@
<connection>scm:git:git://github.com/pmd/pmd.git</connection>
<developerConnection>scm:git:ssh://git@github.com/pmd/pmd.git</developerConnection>
<url>https://github.com/pmd/pmd</url>
<tag>pmd_releases/5.0.2</tag>
</scm>
<organization>
<name>InfoEther</name>
@ -246,7 +246,7 @@
If the xdocs files stay in src/site/xdoc/, mvn tries to copy over the generated
one, and complains... -->
<src.xdocs.dir>src/site/xdocs</src.xdocs.dir>
<pmd.website.baseurl>http://pmd.sourceforge.net/snapshot</pmd.website.baseurl>
<pmd.website.baseurl>http://pmd.sourceforge.net/pmd-${project.version}</pmd.website.baseurl>
</properties>
<build>
@ -333,10 +333,8 @@
<configuration>
<target>
<ant antfile="src/main/ant/alljavacc.xml">
<property name="target"
value="${project.build.directory}/generated-sources/javacc" />
<property name="javacc.jar"
value="${settings.localRepository}/net/java/dev/javacc/javacc/${javacc.version}/javacc-${javacc.version}.jar" />
<property name="target" value="${project.build.directory}/generated-sources/javacc" />
<property name="javacc.jar" value="${settings.localRepository}/net/java/dev/javacc/javacc/${javacc.version}/javacc-${javacc.version}.jar" />
</ant>
</target>
</configuration>
@ -350,15 +348,11 @@
<configuration>
<target>
<echo>PMD specific tasks: generating xdocs from rulesets</echo>
<mkdir
dir="${project.build.directory}/generated-xdocs/" />
<copy
toDir="${project.build.directory}/generated-xdocs/"
overwrite="true" verbose="true">
<mkdir dir="${project.build.directory}/generated-xdocs/" />
<copy toDir="${project.build.directory}/generated-xdocs/" overwrite="true" verbose="true">
<fileset dir="${src.xdocs.dir}" />
<filterset>
<filter token="VERSION"
value="${project.version}" />
<filter token="VERSION" value="${project.version}" />
</filterset>
</copy>
</target>
@ -374,25 +368,18 @@
<target>
<echo>PMD site specific tasks</echo>
<echo>1. Copying missing images to site directory.</echo>
<copy
todir="${project.build.directory}/site/images/">
<fileset dir="${src.xdocs.dir}/images/"
includes="**/*.*" />
<copy todir="${project.build.directory}/site/images/">
<fileset dir="${src.xdocs.dir}/images/" includes="**/*.*" />
</copy>
<echo>2. Adding missing text files to site.</echo>
<copy todir="${project.build.directory}/site/">
<fileset dir="${src.xdocs.dir}/"
includes="**/*.txt" />
<fileset dir="${src.xdocs.dir}/" includes="**/*.txt" />
</copy>
<echo>3. Deleting useless generated files.</echo>
<delete quiet="true">
<fileset dir="${src.xdocs.dir}/rules"
includes="**/*.xml" />
<fileset dir="${src.xdocs.dir}/"
includes="mergedruleset.xml" />
<fileset
dir="${project.build.directory}"
includes="site/mergedruleset.html" />
<fileset dir="${src.xdocs.dir}/rules" includes="**/*.xml" />
<fileset dir="${src.xdocs.dir}/" includes="mergedruleset.xml" />
<fileset dir="${project.build.directory}" includes="site/mergedruleset.html" />
</delete>
</target>
</configuration>
@ -407,10 +394,8 @@
<target>
<echo>PMD specific tasks: cleaning generated xdocs</echo>
<delete quiet="true">
<fileset dir="${src.xdocs.dir}/rules"
includes="**/*.xml" />
<fileset dir="${src.xdocs.dir}/"
includes="mergedruleset.xml" />
<fileset dir="${src.xdocs.dir}/rules" includes="**/*.xml" />
<fileset dir="${src.xdocs.dir}/" includes="mergedruleset.xml" />
</delete>
</target>
</configuration>
@ -620,6 +605,11 @@
<artifactId>javacc</artifactId>
<version>${javacc.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
<reporting>

View File

@ -335,8 +335,6 @@ public class PMD {
return languages;
}
private static final int ERROR_STATUS = 1;
/**
* Entry to invoke PMD as command line tool
*
@ -367,7 +365,7 @@ public class PMD {
} catch (Exception e) {
PMDCommandLineInterface.buildUsageText();
System.out.println(e.getMessage());
status = ERROR_STATUS;
status = PMDCommandLineInterface.ERROR_STATUS;
} finally {
logHandlerManager.close();
LOG.setLevel(oldLogLevel);

View File

@ -22,15 +22,18 @@ import net.sourceforge.pmd.util.StringUtil;
public class Report {
public static Report createReport(RuleContext ctx, String fileName) {
Report report = new Report();
ctx.setReport(report);
ctx.setSourceCodeFilename(fileName);
ctx.setSourceCodeFile(new File(fileName));
return report;
}
public static Report createReport(RuleContext ctx, String fileName) {
Report report = new Report();
// overtake the listener
report.addSynchronizedListeners(ctx.getReport().getSynchronizedListeners());
ctx.setReport(report);
ctx.setSourceCodeFilename(fileName);
ctx.setSourceCodeFile(new File(fileName));
return report;
}
public static class ReadableDuration {
private final long duration;
@ -112,7 +115,7 @@ public class Report {
// Note that this and the above data structure are both being maintained for a bit
private final List<RuleViolation> violations = new ArrayList<RuleViolation>();
private final Set<Metric> metrics = new HashSet<Metric>();
private final List<ReportListener> listeners = new ArrayList<ReportListener>();
private final List<SynchronizedReportListener> listeners = new ArrayList<SynchronizedReportListener>();
private List<ProcessingError> errors;
private List<RuleConfigurationError> configErrors;
private Map<Integer, String> linesToSuppress = new HashMap<Integer, String>();
@ -164,7 +167,7 @@ public class Report {
}
public void addListener(ReportListener listener) {
listeners.add(listener);
listeners.add(new SynchronizedReportListener(listener));
}
public List<SuppressedViolation> getSuppressedRuleViolations() {
@ -266,13 +269,13 @@ public class Report {
}
public Iterator<ProcessingError> errors() {
return errors == null ? EmptyIterator.instance : errors.iterator();
return errors == null ? EmptyIterator.<ProcessingError> instance() : errors.iterator();
}
public Iterator<RuleConfigurationError> configErrors() {
return configErrors == null ? EmptyIterator.instance : errors.iterator();
return configErrors == null ? EmptyIterator.<RuleConfigurationError> instance() : configErrors.iterator();
}
public int treeSize() {
return violationTree.size();
}
@ -292,4 +295,12 @@ public class Report {
public long getElapsedTimeInMillis() {
return end - start;
}
public List<SynchronizedReportListener> getSynchronizedListeners() {
return listeners;
}
public void addSynchronizedListeners(List<SynchronizedReportListener> synchronizedListeners) {
listeners.addAll(synchronizedListeners);
}
}

View File

@ -42,10 +42,11 @@ public class RuleContext {
}
/**
* Constructor which shares attributes with the given RuleContext.
* Constructor which shares attributes and report listeners with the given RuleContext.
*/
public RuleContext(RuleContext ruleContext) {
this.attributes = ruleContext.attributes;
this.report.addSynchronizedListeners(ruleContext.getReport().getSynchronizedListeners());
}
/**

View File

@ -0,0 +1,27 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd;
import net.sourceforge.pmd.stat.Metric;
/**
* Wraps a report listener in order to synchronize calls to it.
*/
public final class SynchronizedReportListener implements ReportListener {
private final ReportListener wrapped;
public SynchronizedReportListener(ReportListener listener) {
this.wrapped = listener;
}
public synchronized void ruleViolationAdded(RuleViolation ruleViolation) {
wrapped.ruleViolationAdded(ruleViolation);
}
public synchronized void metricAdded(Metric metric) {
wrapped.metricAdded(metric);
}
}

View File

@ -26,7 +26,6 @@ import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.RuleSetFactory;
import net.sourceforge.pmd.RuleSetNotFoundException;
import net.sourceforge.pmd.RuleSets;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.renderers.AbstractRenderer;
import net.sourceforge.pmd.renderers.Renderer;
@ -110,24 +109,10 @@ public class PMDTask extends Task {
formatters.add(f);
}
public void addConfiguredVersion(Version version) {
LanguageVersion languageVersion = LanguageVersion.findByTerseName(version.getTerseName());
public void addConfiguredSourceLanguage(SourceLanguage version) {
LanguageVersion languageVersion = LanguageVersion.findVersionsForLanguageTerseName(version.getName(), version.getVersion());
if (languageVersion == null) {
StringBuilder buf = new StringBuilder("The <version> element, if used, must be one of ");
boolean first = true;
for (Language language : Language.values()) {
if (language.getVersions().size() > 2) {
for (LanguageVersion v : language.getVersions()) {
if (!first) {
buf.append(", ");
}
buf.append('\'').append(v.getTerseName()).append('\'');
first = false;
}
}
}
buf.append('.');
throw new BuildException(buf.toString());
throw new BuildException("The following language is not supported:" + version + ".");
}
configuration.setDefaultLanguageVersion(languageVersion);
}

View File

@ -0,0 +1,33 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.ant;
/**
* Stores LanguageVersion terse name value.
*/
public class SourceLanguage {
private String name;
private String version;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "<language name=\"" + this.name + "\" version=\"" + this.version + "\" />";
}
}

View File

@ -1,19 +0,0 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.ant;
/**
* Stores LanguageVersion terse name value.
*/
public class Version {
private String terseName;
public void addText(String text) {
this.terseName = text;
}
public String getTerseName() {
return terseName;
}
}

View File

@ -27,17 +27,24 @@ public class PMDCommandLineInterface {
public static final String NO_EXIT_AFTER_RUN = "net.sourceforge.pmd.cli.noExit";
public static final String STATUS_CODE_PROPERTY = "net.sourceforge.pmd.cli.status";
public static final int ERROR_STATUS = 1;
public static PMDParameters extractParameters(PMDParameters arguments, String[] args, String progName) {
jcommander = new JCommander(arguments);
jcommander.setProgramName(progName);
try {
jcommander = new JCommander(arguments, args);
jcommander.setProgramName(progName);
jcommander.parse(args);
if (arguments.isHelp()) {
jcommander.usage();
System.exit(0);
System.out.println(buildUsageText());
setStatusCodeOrExit(0);
}
} catch (ParameterException e) {
jcommander.usage();
System.out.println(buildUsageText());
System.out.println(e.getMessage());
setStatusCodeOrExit(ERROR_STATUS);
}
return arguments;
}
@ -61,7 +68,7 @@ public class PMDCommandLineInterface {
+ "3) A ruleset filename or a comma-delimited string of ruleset filenames" + PMD.EOL
+ PMD.EOL
+ "For example: " + PMD.EOL
+ "c:\\> " + launchCmd + "-d c:\\my\\source\\code -f html -R java-unusedcode" + PMD.EOL
+ "c:\\> " + launchCmd + " -d c:\\my\\source\\code -f html -R java-unusedcode" + PMD.EOL
+ PMD.EOL;
fullText += supportedVersions() + PMD.EOL;
@ -148,12 +155,16 @@ public class PMDCommandLineInterface {
}
public static void run(String[] args) {
if ( isExitAfterRunSet() )
System.exit(PMD.run(args));
else
setStatusCode(PMD.run(args));
setStatusCodeOrExit(PMD.run(args));
}
public static void setStatusCodeOrExit(int status) {
if ( isExitAfterRunSet() )
System.exit(status);
else
setStatusCode(status);
}
private static boolean isExitAfterRunSet() {
return (System.getenv(NO_EXIT_AFTER_RUN) == null ? false : true);
}

View File

@ -28,7 +28,7 @@ public class PMDParameters {
@Parameter(names = {"-debug", "-verbose", "-D", "-V"}, description = "Debug mode")
private boolean debug = false;
@Parameter(names = {"-help","-h","-H"}, description = "Display help on usage")
@Parameter(names = {"-help","-h","-H"}, description = "Display help on usage", help = true)
private boolean help = false;
@Parameter(names= {"-encoding", "-e"} , description = "specifies the character set encoding of the source code files PMD is reading (i.e., UTF-8)")
@ -67,7 +67,7 @@ public class PMDParameters {
@Parameter(names = {"-language", "-l"}, description = "specify version of a language PMD should use")
private String language = Language.getDefaultLanguage().getTerseName();
@Parameter(names = "-auxclasspath", description = "specifies the classpath for libraries used by the source code (used by type resolution)\n(alternatively, a 'file://' URL to a text file containing path elements on consecutive lines")
@Parameter(names = "-auxclasspath", description = "specifies the classpath for libraries used by the source code. This is used by the type resolution. Alternatively, a 'file://' URL to a text file containing path elements on consecutive lines can be specified.")
private String auxclasspath;
class PropertyConverter implements IStringConverter<Properties> {

View File

@ -31,6 +31,8 @@ public class CPD {
public CPD(CPDConfiguration theConfiguration) {
configuration = theConfiguration;
// before we start any tokenizing (add(File...)), we need to reset the static TokenEntry status
TokenEntry.clearImages();
}
public void setCpdListener(CPDListener cpdListener) {
@ -38,7 +40,6 @@ public class CPD {
}
public void go() {
TokenEntry.clearImages();
matchAlgorithm = new MatchAlgorithm(
source, tokens,
configuration.minimumTileSize(),

View File

@ -188,16 +188,9 @@ public class CPDTask extends Task {
}
}
/*
* FIXME Can't we do something cleaner and
* more dynamic ? Maybe externalise to a properties files that will
* be generated when building pmd ? This will not have to add manually
* new language here ?
*/
public static class LanguageAttribute extends EnumeratedAttribute {
private static final String[] LANGUAGES = new String[]{"java","jsp","cpp", "c","php", "ruby", "fortran", "cs"};
public String[] getValues() {
return LANGUAGES;
return LanguageFactory.supportedLanguages;
}
}
}

View File

@ -106,19 +106,22 @@ public class GUI implements CPDListener {
{"Fortran", new LanguageConfig() {
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("fortran"); }
public String[] extensions() { return new String[] {".rb" }; }; } },
{"by extension...", new LanguageConfig() {
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage(LanguageFactory.BY_EXTENSION, p); }
public String[] extensions() { return new String[] {"" }; }; } },
{"PHP", new LanguageConfig() {
{"PHP", new LanguageConfig() {
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("php"); }
public String[] extensions() { return new String[] {".php" }; }; } },
{"C#", new LanguageConfig() {
{"C#", new LanguageConfig() {
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("cs"); }
public String[] extensions() { return new String[] {".cs" }; }; } },
{"Ecmascript", new LanguageConfig() {
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage("js"); }
public String[] extensions() { return new String[] {".js" }; }; } },
{"by extension...", new LanguageConfig() {
public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage(LanguageFactory.BY_EXTENSION, p); }
public String[] extensions() { return new String[] {"" }; }; } },
};
private static final int DEFAULT_CPD_MINIMUM_LENGTH = 75;
private static final Map LANGUAGE_CONFIGS_BY_LABEL = new HashMap(LANGUAGE_SETS.length);
private static final Map<String, LanguageConfig> LANGUAGE_CONFIGS_BY_LABEL = new HashMap<String, LanguageConfig>(LANGUAGE_SETS.length);
private static final KeyStroke COPY_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_C,ActionEvent.CTRL_MASK,false);
private static final KeyStroke DELETE_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
@ -148,12 +151,12 @@ public class GUI implements CPDListener {
static {
for (int i=0; i<LANGUAGE_SETS.length; i++) {
LANGUAGE_CONFIGS_BY_LABEL.put(LANGUAGE_SETS[i][0], LANGUAGE_SETS[i][1]);
LANGUAGE_CONFIGS_BY_LABEL.put((String)LANGUAGE_SETS[i][0], (LanguageConfig)LANGUAGE_SETS[i][1]);
}
}
private static LanguageConfig languageConfigFor(String label) {
return (LanguageConfig)LANGUAGE_CONFIGS_BY_LABEL.get(label);
return LANGUAGE_CONFIGS_BY_LABEL.get(label);
}
private static class CancelListener implements ActionListener {

View File

@ -7,9 +7,16 @@ import java.util.Properties;
public class LanguageFactory {
// TODO derive and provide this at runtime instead, used by outside IDEs
public static String[] supportedLanguages = new String[]{"java", "jsp", "cpp", "c", "php", "ruby","fortran", "ecmascript","cs" };
/*
* TODO derive and provide this at runtime instead, used by outside IDEs
* FIXME Can't we do something cleaner and
* more dynamic ? Maybe externalise to a properties files that will
* be generated when building pmd ? This will not have to add manually
* new language here ?
*/
public static String[] supportedLanguages =
new String[]{"java", "jsp", "cpp", "c", "php", "ruby", "fortran", "ecmascript", "cs"};
private static final String SUFFIX = "Language";
public static final String EXTENSION = "extension";
public static final String BY_EXTENSION = "by_extension";

View File

@ -200,6 +200,23 @@ public enum LanguageVersion {
return versionsAvailable;
}
/**
* A utility method to retrieve the appropriate enum, given the provided parameters
*
* @param languageTerseName The LanguageVersion terse name.
* @param languageVersion The version of the language requested.
* @return A list of versions associated with the terse name.
*/
public static LanguageVersion findVersionsForLanguageTerseName(String languageTerseName, String languageVersion) {
List<LanguageVersion> versionsAvailable = findVersionsForLanguageTerseName(languageTerseName);
for ( LanguageVersion version : versionsAvailable ) {
if ( version.getVersion().equalsIgnoreCase(languageVersion) )
return version;
}
return null;
}
/**
* Return a comma-separated list of LanguageVersion terse names.
* @param languageVersions The language versions.

View File

@ -119,7 +119,7 @@ public abstract class AbstractNode implements Node {
if (children != null && children.length > 0) {
return children[0].getBeginColumn();
} else {
throw new RuntimeException("Unable to determine begining line of Node.");
throw new RuntimeException("Unable to determine beginning line of Node.");
}
}
}

View File

@ -7,18 +7,27 @@ import net.sourceforge.pmd.lang.ast.AbstractNode;
import org.mozilla.javascript.ast.AstNode;
public abstract class AbstractEcmascriptNode<T extends AstNode> extends AbstractNode implements EcmascriptNode {
public abstract class AbstractEcmascriptNode<T extends AstNode> extends AbstractNode implements EcmascriptNode<T> {
protected final T node;
public AbstractEcmascriptNode(T node) {
super(node.getType());
this.node = node;
this.beginLine = node.getLineno() + 1;
this.beginLine = node.getLineno() + 1;
// TODO Implement positions, or figure out how to do begin/end lines/column
//this.beginPosition = node.getAbsolutePosition();
//this.endPosition = this.beginPosition + node.getLength();
}
/* package private */
void calculateLineNumbers(SourceCodePositioner positioner) {
int startOffset = node.getAbsolutePosition();
int endOffset = startOffset + node.getLength();
this.beginLine = positioner.lineNumberFromOffset(startOffset);
this.beginColumn = positioner.columnFromOffset(startOffset);
this.endLine = positioner.lineNumberFromOffset(endOffset);
this.endColumn = positioner.columnFromOffset(endOffset) - 1; // end column is inclusive
if (this.endColumn < 0) {
this.endColumn = 0;
}
}
/**
@ -34,7 +43,9 @@ public abstract class AbstractEcmascriptNode<T extends AstNode> extends Abstract
public Object childrenAccept(EcmascriptParserVisitor visitor, Object data) {
if (children != null) {
for (int i = 0; i < children.length; ++i) {
((EcmascriptNode) children[i]).jjtAccept(visitor, data);
@SuppressWarnings("unchecked") // we know that the children here are all EcmascriptNodes
EcmascriptNode<T> ecmascriptNode = (EcmascriptNode<T>) children[i];
ecmascriptNode.jjtAccept(visitor, data);
}
}
return data;
@ -52,11 +63,6 @@ public abstract class AbstractEcmascriptNode<T extends AstNode> extends Abstract
return node.hasSideEffects();
}
@Override
public int getBeginColumn() {
return -1;
}
@Override
public String toString() {
return node.shortName();

View File

@ -11,6 +11,7 @@ import java.util.List;
import net.sourceforge.pmd.lang.ast.ParseException;
import net.sourceforge.pmd.lang.ecmascript.EcmascriptParserOptions;
import org.apache.commons.io.IOUtils;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.Parser;
import org.mozilla.javascript.ast.AstRoot;
@ -24,7 +25,7 @@ public class EcmascriptParser {
this.parserOptions = parserOptions;
}
protected AstRoot parseEcmascript(final Reader reader, final List<ParseProblem> parseProblems) throws ParseException {
protected AstRoot parseEcmascript(final String sourceCode, final List<ParseProblem> parseProblems) throws ParseException {
final CompilerEnvirons compilerEnvirons = new CompilerEnvirons();
compilerEnvirons.setRecordingComments(parserOptions.isRecordingComments());
compilerEnvirons.setRecordingLocalJsDocComments(parserOptions.isRecordingLocalJsDocComments());
@ -35,23 +36,23 @@ public class EcmascriptParser {
// TODO We should do something with Rhino errors...
final ErrorCollector errorCollector = new ErrorCollector();
final Parser parser = new Parser(compilerEnvirons, errorCollector);
// TODO Fix hardcode
final String sourceURI = "unknown";
final int beginLineno = 1;
AstRoot astRoot = parser.parse(sourceCode, sourceURI, beginLineno);
parseProblems.addAll(errorCollector.getErrors());
return astRoot;
}
public EcmascriptNode<AstRoot> parse(final Reader reader) {
try {
// TODO Fix hardcode
final String sourceURI = "unknown";
// TODO Fix hardcode
final int lineno = 0;
AstRoot astRoot = parser.parse(reader, sourceURI, lineno);
parseProblems.addAll(errorCollector.getErrors());
return astRoot;
} catch (final IOException e) {
final List<ParseProblem> parseProblems = new ArrayList<ParseProblem>();
final String sourceCode = IOUtils.toString(reader);
final AstRoot astRoot = parseEcmascript(sourceCode, parseProblems);
final EcmascriptTreeBuilder treeBuilder = new EcmascriptTreeBuilder(sourceCode, parseProblems);
return treeBuilder.build(astRoot);
} catch (IOException e) {
throw new ParseException(e);
}
}
public EcmascriptNode parse(final Reader reader) {
final List<ParseProblem> parseProblems = new ArrayList<ParseProblem>();
final AstRoot astRoot = parseEcmascript(reader, parseProblems);
final EcmascriptTreeBuilder treeBuilder = new EcmascriptTreeBuilder(parseProblems);
return treeBuilder.build(astRoot);
}
}

View File

@ -65,9 +65,9 @@ import org.mozilla.javascript.ast.XmlExpression;
import org.mozilla.javascript.ast.XmlMemberGet;
import org.mozilla.javascript.ast.XmlString;
public class EcmascriptTreeBuilder implements NodeVisitor {
public final class EcmascriptTreeBuilder implements NodeVisitor {
protected static final Map<Class<? extends AstNode>, Constructor<? extends EcmascriptNode>> NODE_TYPE_TO_NODE_ADAPTER_TYPE = new HashMap<Class<? extends AstNode>, Constructor<? extends EcmascriptNode>>();
private static final Map<Class<? extends AstNode>, Constructor<? extends EcmascriptNode<?>>> NODE_TYPE_TO_NODE_ADAPTER_TYPE = new HashMap<Class<? extends AstNode>, Constructor<? extends EcmascriptNode<?>>>();
static {
register(ArrayComprehension.class, ASTArrayComprehension.class);
register(ArrayComprehensionLoop.class, ASTArrayComprehensionLoop.class);
@ -120,7 +120,7 @@ public class EcmascriptTreeBuilder implements NodeVisitor {
register(XmlString.class, ASTXmlString.class);
}
protected static void register(Class<? extends AstNode> nodeType, Class<? extends EcmascriptNode> nodeAdapterType) {
private static <T extends AstNode> void register(Class<T> nodeType, Class<? extends EcmascriptNode<T>> nodeAdapterType) {
try {
NODE_TYPE_TO_NODE_ADAPTER_TYPE.put(nodeType, nodeAdapterType.getConstructor(nodeType));
} catch (SecurityException e) {
@ -139,13 +139,18 @@ public class EcmascriptTreeBuilder implements NodeVisitor {
// The Rhino nodes with children to build.
protected Stack<AstNode> parents = new Stack<AstNode>();
public EcmascriptTreeBuilder(List<ParseProblem> parseProblems) {
private final SourceCodePositioner sourceCodePositioner;
public EcmascriptTreeBuilder(String sourceCode, List<ParseProblem> parseProblems) {
this.sourceCodePositioner = new SourceCodePositioner(sourceCode);
this.parseProblems = parseProblems;
}
protected EcmascriptNode createNodeAdapter(AstNode node) {
private <T extends AstNode> EcmascriptNode<T> createNodeAdapter(T node) {
try {
Constructor<? extends EcmascriptNode> constructor = NODE_TYPE_TO_NODE_ADAPTER_TYPE.get(node.getClass());
@SuppressWarnings("unchecked") // the register function makes sure only EcmascriptNode<T> can be added,
// where T is "T extends AstNode".
Constructor<? extends EcmascriptNode<T>> constructor = (Constructor<? extends EcmascriptNode<T>>) NODE_TYPE_TO_NODE_ADAPTER_TYPE.get(node.getClass());
if (constructor == null) {
throw new IllegalArgumentException("There is no Node adapter class registered for the Node class: "
+ node.getClass());
@ -160,8 +165,10 @@ public class EcmascriptTreeBuilder implements NodeVisitor {
}
}
public EcmascriptNode build(AstNode astNode) {
EcmascriptNode node = buildInternal(astNode);
public <T extends AstNode> EcmascriptNode<T> build(T astNode) {
EcmascriptNode<T> node = buildInternal(astNode);
calculateLineNumbers(node);
// Set all the trailing comma nodes
for (TrailingCommaNode trailingCommaNode : parseProblemToNode.values()) {
@ -171,9 +178,9 @@ public class EcmascriptTreeBuilder implements NodeVisitor {
return node;
}
protected EcmascriptNode buildInternal(AstNode astNode) {
private <T extends AstNode> EcmascriptNode<T> buildInternal(T astNode) {
// Create a Node
EcmascriptNode node = createNodeAdapter(astNode);
EcmascriptNode<T> node = createNodeAdapter(astNode);
// Append to parent
Node parent = nodes.isEmpty() ? null : nodes.peek();
@ -203,7 +210,7 @@ public class EcmascriptTreeBuilder implements NodeVisitor {
}
}
private void handleParseProblems(EcmascriptNode node) {
private void handleParseProblems(EcmascriptNode<? extends AstNode> node) {
if (node instanceof TrailingCommaNode) {
TrailingCommaNode trailingCommaNode = (TrailingCommaNode) node;
int nodeStart = node.getNode().getAbsolutePosition();
@ -216,7 +223,7 @@ public class EcmascriptTreeBuilder implements NodeVisitor {
if ("Trailing comma is not legal in an ECMA-262 object initializer".equals(parseProblem.getMessage())) {
// Report on the shortest code block containing the
// problem (i.e. inner most code in nested structures).
EcmascriptNode currentNode = (EcmascriptNode) parseProblemToNode.get(parseProblem);
EcmascriptNode<? extends AstNode> currentNode = (EcmascriptNode<? extends AstNode>) parseProblemToNode.get(parseProblem);
if (currentNode == null || node.getNode().getLength() < currentNode.getNode().getLength()) {
parseProblemToNode.put(parseProblem, trailingCommaNode);
}
@ -225,4 +232,15 @@ public class EcmascriptTreeBuilder implements NodeVisitor {
}
}
}
private void calculateLineNumbers(EcmascriptNode<?> node) {
EcmascriptParserVisitorAdapter visitor = new EcmascriptParserVisitorAdapter() {
@Override
public Object visit(EcmascriptNode node, Object data) {
((AbstractEcmascriptNode<?>)node).calculateLineNumbers(sourceCodePositioner);
return super.visit(node, data); // also visit the children
}
};
node.jjtAccept(visitor, null);
}
}

View File

@ -0,0 +1,56 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.ecmascript.ast;
import java.util.Arrays;
/**
* Calculates from an absolute offset in the source file the line/column coordinate.
* This is needed as Rhino only offers absolute positions for each node.
*
* Idea from: http://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/javascript/jscomp/SourceFile.java
*/
public class SourceCodePositioner {
private int[] lineOffsets;
public SourceCodePositioner(String sourceCode) {
analyzeLineOffsets(sourceCode);
}
private void analyzeLineOffsets(String sourceCode) {
String[] lines = sourceCode.split("\n");
int startOffset = 0;
int lineNumber = 0;
lineOffsets = new int[lines.length];
for (String line : lines) {
lineOffsets[lineNumber] = startOffset;
lineNumber++;
startOffset += line.length() + 1; // +1 for the "\n" character
}
}
public int lineNumberFromOffset(int offset) {
int search = Arrays.binarySearch(lineOffsets, offset);
int lineNumber;
if (search >= 0) {
lineNumber = search;
} else {
int insertionPoint = search;
insertionPoint += 1;
insertionPoint *= -1;
lineNumber = insertionPoint - 1; // take the insertion point one before
}
return lineNumber + 1; // 1-based line numbers
}
public int columnFromOffset(int offset) {
int lineNumber = lineNumberFromOffset(offset);
int columnOffset = offset - lineOffsets[lineNumber - 1];
return columnOffset + 1; // 1-based column offsets
}
}

View File

@ -6,6 +6,7 @@ import java.util.Arrays;
import java.util.List;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.lang.ast.Node;
public class ASTAnnotation extends AbstractJavaNode {
@ -27,20 +28,27 @@ public class ASTAnnotation extends AbstractJavaNode {
if (jjtGetChild(0) instanceof ASTSingleMemberAnnotation) {
ASTSingleMemberAnnotation n = (ASTSingleMemberAnnotation) jjtGetChild(0);
return checkAnnototation(n, ruleAnno, rule);
} else if (jjtGetChild(0) instanceof ASTNormalAnnotation) {
ASTNormalAnnotation n = (ASTNormalAnnotation) jjtGetChild(0);
return checkAnnototation(n, ruleAnno, rule);
}
return false;
}
if (n.jjtGetChild(0) instanceof ASTName) {
ASTName annName = (ASTName) n.jjtGetChild(0);
private boolean checkAnnototation(Node n, String ruleAnno, Rule rule) {
if (n.jjtGetChild(0) instanceof ASTName) {
ASTName annName = (ASTName) n.jjtGetChild(0);
if (annName.getImage().equals("SuppressWarnings")) {
List<ASTLiteral> nodes = n.findDescendantsOfType(ASTLiteral.class);
for (ASTLiteral element : nodes) {
if (element.hasImageEqualTo("\"PMD\"") || element.hasImageEqualTo(ruleAnno)
// Check for standard annotations values
|| element.hasImageEqualTo("\"all\"")
|| element.hasImageEqualTo("\"serial\"") && serialRules.contains(rule.getName())
|| element.hasImageEqualTo("\"unused\"") && unusedRules.contains(rule.getName())) {
return true;
}
if (annName.getImage().equals("SuppressWarnings")) {
List<ASTLiteral> nodes = n.findDescendantsOfType(ASTLiteral.class);
for (ASTLiteral element : nodes) {
if (element.hasImageEqualTo("\"PMD\"") || element.hasImageEqualTo(ruleAnno)
// Check for standard annotations values
|| element.hasImageEqualTo("\"all\"")
|| element.hasImageEqualTo("\"serial\"") && serialRules.contains(rule.getName())
|| element.hasImageEqualTo("\"unused\"") && unusedRules.contains(rule.getName())) {
return true;
}
}
}

View File

@ -1,3 +1,6 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.comments;
import java.util.ArrayList;
@ -95,7 +98,7 @@ public abstract class AbstractCommentRule extends AbstractJavaRule {
continue;
}
if (line.charAt(0) == '*') {
if (line.length() > 0 && line.charAt(0) == '*') {
filteredLines.add(line.substring(1));
continue;
}
@ -122,7 +125,7 @@ public abstract class AbstractCommentRule extends AbstractJavaRule {
continue;
}
if (line.charAt(0) == '*') {
if (line.length() > 0 && line.charAt(0) == '*') {
filteredLines.add(line.substring(1));
continue;
}

View File

@ -14,6 +14,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
import net.sourceforge.pmd.lang.java.ast.ASTBlock;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTName;
@ -71,8 +72,19 @@ public class CloseResourceRule extends AbstractJavaRule {
return super.visit(node, data);
}
@Override
public Object visit(ASTConstructorDeclaration node, Object data) {
checkForResources(node, data);
return data;
}
@Override
public Object visit(ASTMethodDeclaration node, Object data) {
checkForResources(node, data);
return data;
}
private void checkForResources(Node node, Object data) {
List<ASTLocalVariableDeclaration> vars = node.findDescendantsOfType(ASTLocalVariableDeclaration.class);
List<ASTVariableDeclaratorId> ids = new ArrayList<ASTVariableDeclaratorId>();
@ -85,7 +97,7 @@ public class CloseResourceRule extends AbstractJavaRule {
if (ref.jjtGetChild(0) instanceof ASTClassOrInterfaceType) {
ASTClassOrInterfaceType clazz = (ASTClassOrInterfaceType) ref.jjtGetChild(0);
if (types.contains(clazz.getImage())) {
ASTVariableDeclaratorId id = (ASTVariableDeclaratorId) var.jjtGetChild(1).jjtGetChild(0);
ASTVariableDeclaratorId id = var.getFirstDescendantOfType(ASTVariableDeclaratorId.class);
ids.add(id);
}
}
@ -96,7 +108,6 @@ public class CloseResourceRule extends AbstractJavaRule {
for (ASTVariableDeclaratorId x : ids) {
ensureClosed((ASTLocalVariableDeclaration) x.jjtGetParent().jjtGetParent(), x, data);
}
return data;
}
private void ensureClosed(ASTLocalVariableDeclaration var,
@ -107,11 +118,11 @@ public class CloseResourceRule extends AbstractJavaRule {
String target = variableToClose + ".close";
Node n = var;
while (!(n instanceof ASTBlock)) {
while (!(n instanceof ASTBlock) && !(n instanceof ASTConstructorDeclaration)) {
n = n.jjtGetParent();
}
ASTBlock top = (ASTBlock) n;
Node top = n;
List<ASTTryStatement> tryblocks = top.findDescendantsOfType(ASTTryStatement.class);
@ -206,7 +217,7 @@ public class CloseResourceRule extends AbstractJavaRule {
List<ASTReturnStatement> returns = new ArrayList<ASTReturnStatement>();
top.findDescendantsOfType(ASTReturnStatement.class, returns, true);
for (ASTReturnStatement returnStatement : returns) {
ASTName name = returnStatement.getFirstChildOfType(ASTName.class);
ASTName name = returnStatement.getFirstDescendantOfType(ASTName.class);
if ((name != null) && name.getImage().equals(variableToClose)) {
closed = true;
break;
@ -216,7 +227,7 @@ public class CloseResourceRule extends AbstractJavaRule {
// if all is not well, complain
if (!closed) {
ASTType type = (ASTType) var.jjtGetChild(0);
ASTType type = var.getFirstChildOfType(ASTType.class);
ASTReferenceType ref = (ASTReferenceType) type.jjtGetChild(0);
ASTClassOrInterfaceType clazz = (ASTClassOrInterfaceType) ref.jjtGetChild(0);
addViolation(data, id, clazz.getImage());

View File

@ -5,6 +5,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
import net.sourceforge.pmd.lang.java.ast.ASTInitializer;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
@ -65,6 +66,14 @@ 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);
// skip, if it is an enum
if (type0.getType() != null && type0.getType().equals(type1.getType()) && type0.getType().isEnum()) {
return data;
}
addViolation(data, node);
}
}

View File

@ -73,7 +73,7 @@ public class GenericClassCounterRule extends AbstractJavaRule {
private int threshold;
private static String counterLabel;
public GenericClassCounterRule() {
definePropertyDescriptor(NAME_MATCH_DESCRIPTOR);
definePropertyDescriptor(OPERAND_DESCRIPTOR);
@ -178,7 +178,7 @@ public class GenericClassCounterRule extends AbstractJavaRule {
}
// Cleaning the context for the others rules
ctx.removeAttribute(counterLabel);
super.start(ctx);
super.end(ctx);
}
}
}

View File

@ -154,18 +154,20 @@ public class GodClassRule extends AbstractJavaRule {
int pairs = 0;
if (methodCount > 1) {
for (int i = 0; i < methodCount - 1; i++) {
String firstMethodName = methods.get(i);
String secondMethodName = methods.get(i + 1);
Set<String> accessesOfFirstMethod = methodAttributeAccess.get(firstMethodName);
Set<String> accessesOfSecondMethod = methodAttributeAccess.get(secondMethodName);
Set<String> combinedAccesses = new HashSet<String>();
combinedAccesses.addAll(accessesOfFirstMethod);
combinedAccesses.addAll(accessesOfSecondMethod);
if (combinedAccesses.size() < (accessesOfFirstMethod.size() + accessesOfSecondMethod.size())) {
pairs++;
for (int i = 0; i < methodCount; i++) {
for (int j = i + 1; j < methodCount; j++) {
String firstMethodName = methods.get(i);
String secondMethodName = methods.get(j);
Set<String> accessesOfFirstMethod = methodAttributeAccess.get(firstMethodName);
Set<String> accessesOfSecondMethod = methodAttributeAccess.get(secondMethodName);
Set<String> combinedAccesses = new HashSet<String>();
combinedAccesses.addAll(accessesOfFirstMethod);
combinedAccesses.addAll(accessesOfSecondMethod);
if (combinedAccesses.size() < (accessesOfFirstMethod.size() + accessesOfSecondMethod.size())) {
pairs++;
}
}
}
}

View File

@ -1,5 +1,6 @@
package net.sourceforge.pmd.lang.java.rule.strictexception;
import java.util.Collections;
import java.util.List;
import net.sourceforge.pmd.lang.ast.Node;
@ -8,6 +9,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTNameList;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
/**
@ -46,7 +48,11 @@ public class SignatureDeclareThrowsExceptionRule extends AbstractJavaRule {
return super.visit(methodDeclaration, o);
}
List<ASTName> exceptionList = methodDeclaration.findDescendantsOfType(ASTName.class);
List<ASTName> exceptionList = Collections.emptyList();
ASTNameList nameList = methodDeclaration.getFirstChildOfType(ASTNameList.class);
if (nameList != null) {
exceptionList = nameList.findDescendantsOfType(ASTName.class);
}
if (!exceptionList.isEmpty()) {
evaluateExceptions(exceptionList, o);
}

View File

@ -33,7 +33,7 @@ public class UnusedFormalParameterRule extends AbstractJavaRule {
if (!node.isPrivate() && !getProperty(CHECKALL_DESCRIPTOR)) {
return data;
}
if (!node.isNative()) {
if (!node.isNative() && !node.isAbstract()) {
check(node, data);
}
return data;

Some files were not shown because too many files have changed in this diff Show More