This commit is contained in:
akshatbahety
2018-06-08 19:05:41 +05:30
17 changed files with 199 additions and 76 deletions

View File

@ -103,11 +103,7 @@ precision in a floating point number. This may result in numeric calculations b
**This rule is defined by the following XPath expression:**
```
//NumberLiteral[
@Image != @Number
and translate(@Image, "e", "E") != @Number
and concat(@Image, ".0") != @Number
and @Image != substring-before(translate(@Number, ".", ""), "E")]
//NumberLiteral[@NormalizedImage != @Number]
```
**Example(s):**

View File

@ -20,6 +20,11 @@ This is a minor release.
### New and noteworthy
### Fixed Issues
* ecmascript
* [#861](https://github.com/pmd/pmd/issues/861): \[ecmascript] InnaccurateNumericLiteral false positive with hex literals
* java-codestyle
* [#1158](https://github.com/pmd/pmd/issues/1158): \[java] Fix IdenticalCatchBranches false positive
* xml
* [#715](https://github.com/pmd/pmd/issues/715): \[xml] ProjectVersionAsDependencyVersion false positive

View File

@ -75,8 +75,8 @@ check_lib_dir() {
}
jre_specific_vm_options() {
# java_ver is eg "18" for java 1.8, "90" for java 9.0
java_ver=$(java -version 2>&1 | sed -n ';s/^.* version "\(.*\)\.\(.*\)\..*".*$/\1\2/p;')
# java_ver is eg "18" for java 1.8, "90" for java 9.0, "100" for java 10.0.x
java_ver=$(java -version 2>&1 | sed -n -e 's/-ea/.0.0/i' -e 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1\2/p')
options=""
if [ "$java_ver" -ge 90 ] && [ "${APPNAME}" = "designer" ]

View File

@ -12,6 +12,9 @@ import java.util.Set;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTCatchStatement;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
import net.sourceforge.pmd.lang.java.ast.ASTTryStatement;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
@ -31,7 +34,7 @@ public class IdenticalCatchBranchesRule extends AbstractJavaRule {
}
// groups catch statements by equivalence class, according to the string value of their tokens.
/** groups catch statements by equivalence class, according to the equivalence {@link #areEquivalent(ASTCatchStatement, ASTCatchStatement)}. */
private Set<List<ASTCatchStatement>> equivalenceClasses(List<ASTCatchStatement> catches) {
Set<List<ASTCatchStatement>> result = new HashSet<>(catches.size());
for (ASTCatchStatement stmt : catches) {
@ -103,19 +106,15 @@ public class IdenticalCatchBranchesRule extends AbstractJavaRule {
return super.visit(node, data);
}
/**
* Checks whether two nodes has same subtree.
* Note, it wouldn't be sensitive to changes in the exception variable name.
* Checks whether two nodes define the same subtree,
* up to the renaming of one local variable.
*
* @param node1
* the first node to check
* @param node2
* the second node to check
* @param exceptionName1
* the first exception variable name
* @param exceptionName2
* the second exception variable name
* @return <code>ture</code> if two nodes has same subtree, otherwise <code>false</code>
* @param node1 the first node to check
* @param node2 the second node to check
* @param exceptionName1 the first exception variable name
* @param exceptionName2 the second exception variable name
*/
private boolean hasSameSubTree(Node node1, Node node2, String exceptionName1, String exceptionName2) {
if (node1 == null && node2 == null) {
@ -131,18 +130,7 @@ public class IdenticalCatchBranchesRule extends AbstractJavaRule {
for (int num = 0; num < node1.jjtGetNumChildren(); num++) {
//type of nodes are different
if (node1.jjtGetChild(num).getClass() != node2.jjtGetChild(num).getClass()) {
return false;
}
String image1 = node1.jjtGetChild(num).getImage();
String image2 = node2.jjtGetChild(num).getImage();
//image of nodes are different
if (!Objects.equals(image1, image2)
// wouldn't be sensitive to changes in the exception variable name
&& !Objects.equals(image1, exceptionName1) && Objects.equals(image2, exceptionName2)) {
if (!basicEquivalence(node1.jjtGetChild(num), node2.jjtGetChild(num), exceptionName1, exceptionName2)) {
return false;
}
@ -154,4 +142,44 @@ public class IdenticalCatchBranchesRule extends AbstractJavaRule {
}
return true;
}
// no subtree comparison
private boolean basicEquivalence(Node node1, Node node2, String varName1, String varName2) {
// Nodes must have the same type
if (node1.getClass() != node2.getClass()) {
return false;
}
String image1 = node1.getImage();
String image2 = node2.getImage();
// image of nodes must be the same
return Objects.equals(image1, image2)
// or must be references to the variable we allow to interchange
|| Objects.equals(image1, varName1) && Objects.equals(image2, varName2)
// which means we must filter out method references.
&& isNoMethodName(node1) && isNoMethodName(node2);
}
private boolean isNoMethodName(Node name) {
if (name instanceof ASTName
&& (name.jjtGetParent() instanceof ASTPrimaryPrefix || name.jjtGetParent() instanceof ASTPrimarySuffix)) {
Node prefixOrSuffix = name.jjtGetParent();
if (prefixOrSuffix.jjtGetParent().jjtGetNumChildren() > 1 + prefixOrSuffix.jjtGetChildIndex()) {
// there's one next sibling
Node next = prefixOrSuffix.jjtGetParent().jjtGetChild(prefixOrSuffix.jjtGetChildIndex() + 1);
if (next instanceof ASTPrimarySuffix) {
return !((ASTPrimarySuffix) next).isArguments();
}
}
}
return true;
}
}

View File

@ -71,5 +71,74 @@
</code>
</test-code>
<test-code>
<description>#1158 false positive 1</description>
<expected-problems>0</expected-problems>
<code>
<![CDATA[
class Foo {
{
try {
// do something
} catch (FieldNotFound e) {
throw new IllegalStateException("field not found", e);
} catch (FieldException | FieldConvertError e) {
throw new IllegalArgumentException("field exception ", e);
}
}
}
]]>
</code>
</test-code>
<test-code>
<description>#1158 false positive 2</description>
<expected-problems>0</expected-problems>
<code>
<![CDATA[
class Foo {
{
try {
// do something
} catch (Exception1 exception) {
throw new Exception3("Error message 1", exception);
} catch (Exception2 exception) {
throw new Exception3("Error message 2", exception);
}
}
}
]]>
</code>
</test-code>
<test-code>
<description>False positive with method name mistaken for exception parameter</description>
<expected-problems>0</expected-problems>
<code>
<![CDATA[
class Foo {
static {
try {
// do something
} catch (Exception1 exception) {
exception(exception);
} catch (Exception2 exception2) {
exception2(exception2);
}
}
private static void exception(Exception exception) {
throw new Exception3("Error message 1", exception);
}
private static exception2(Exception exception) {
throw new Exception3("Error message 2", exception);
}
}
]]>
</code>
</test-code>
</test-data>

View File

@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.ecmascript.ast;
import org.mozilla.javascript.ast.NumberLiteral;
// TODO The Rhino node does not tell us whether this was specified via decimal, octal or hexidecimal.
public class ASTNumberLiteral extends AbstractEcmascriptNode<NumberLiteral> {
public ASTNumberLiteral(NumberLiteral numberLiteral) {
super(numberLiteral);
@ -21,8 +20,20 @@ public class ASTNumberLiteral extends AbstractEcmascriptNode<NumberLiteral> {
}
public String getNormalizedImage() {
// TODO Implement
return super.getImage();
String image = getImage();
image = normalizeHexIntegerLiteral(image);
image = image.replace('e', 'E');
if (image.indexOf('.') == -1 && image.indexOf('E') == -1) {
image = image + ".0";
}
return image;
}
private String normalizeHexIntegerLiteral(String image) {
if (image.startsWith("0x") || image.startsWith("0X")) {
return String.valueOf(Integer.parseInt(image.substring(2), 16));
}
return image;
}
public double getNumber() {

View File

@ -107,11 +107,7 @@ precision in a floating point number. This may result in numeric calculations b
<property name="xpath">
<value>
<![CDATA[
//NumberLiteral[
@Image != @Number
and translate(@Image, "e", "E") != @Number
and concat(@Image, ".0") != @Number
and @Image != substring-before(translate(@Number, ".", ""), "E")]
//NumberLiteral[@NormalizedImage != @Number]
]]>
</value>
</property>

View File

@ -3,64 +3,66 @@
xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
<test-code>
<description><![CDATA[
Ok integer
]]></description>
<description>Ok integer</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
var x = 1;
]]></code>
<source-type>ecmascript 3</source-type>
</test-code>
<test-code>
<description><![CDATA[
Bad integer
]]></description>
<description>Bad integer</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
var x = 999999999999999999999999;
]]></code>
<code>var x = 999999999999999999999999;</code>
<source-type>ecmascript 3</source-type>
</test-code>
<test-code>
<description><![CDATA[
Ok float
]]></description>
<description>Ok float</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
var x = 1.1234567890123;
]]></code>
<source-type>ecmascript 3</source-type>
</test-code>
<test-code>
<description><![CDATA[
Bad float
]]></description>
<description>Bad float</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
var z = 1.12345678901234567;
]]></code>
<source-type>ecmascript 3</source-type>
</test-code>
<test-code>
<description><![CDATA[
Ok float w/ exponent
]]></description>
<description>Ok float w/ exponent</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
var x = 1.12e-4;
]]></code>
<source-type>ecmascript 3</source-type>
</test-code>
<test-code>
<description><![CDATA[
Bad float w/ exponent
]]></description>
<description>Bad float w/ exponent</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
var x = 1.12345678901234567e-4;
]]></code>
<source-type>ecmascript 3</source-type>
</test-code>
<test-code>
<description>#861 [ecmascript] InnaccurateNumericLiteral false positive</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
var hex1 = 0x20;
var hex2 = 0X20;
]]></code>
<source-type>ecmascript 3</source-type>
</test-code>
</test-data>

View File

@ -27,6 +27,15 @@
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<configuration>
<rulesets>
<ruleset>/net/sourceforge/pmd/pmd-ui-dogfood-config.xml</ruleset>
</rulesets>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -115,6 +115,7 @@ public class EditPropertyDialogController implements Initializable {
backingDescriptor.ifPresent(PropertyDescriptorSpec::unbind);
backingDescriptor.setValue(null);
backingDescriptorList.setValue(null);
this.nameProperty().setValue(""); // necessary to get the validator to reevaluate each time
}

View File

@ -47,11 +47,11 @@ public class NodeInfoPanelController implements Initializable {
@FXML
private TabPane nodeInfoTabPane;
@FXML
private Tab xpathAttributesTitledPane;
private Tab xpathAttributesTab;
@FXML
private ListView<String> xpathAttributesListView;
@FXML
private Tab metricResultsTitledPane;
private Tab metricResultsTab;
@FXML
private ListView<MetricResult> metricResultsListView;
@FXML
@ -118,9 +118,9 @@ public class NodeInfoPanelController implements Initializable {
private void notifyMetricsAvailable(long numMetrics) {
metricResultsTitledPane.setText("Metrics\t(" + (numMetrics == 0 ? "none" : numMetrics) + ")");
metricResultsTab.setText("Metrics\t(" + (numMetrics == 0 ? "none" : numMetrics) + ")");
metricsTitleLabel.setText("Metrics\t(" + (numMetrics == 0 ? "none" : numMetrics) + " available)");
metricResultsTitledPane.setDisable(numMetrics == 0);
metricResultsTab.setDisable(numMetrics == 0);
}

View File

@ -73,7 +73,7 @@ public class XPathPanelController implements Initializable, SettingsOwner {
private final ObservableXPathRuleBuilder ruleBuilder = new ObservableXPathRuleBuilder();
@FXML
private PropertyTableView propertyView;
private PropertyTableView propertyTableView;
@FXML
private CustomCodeArea xpathExpressionArea;
@FXML
@ -167,7 +167,7 @@ public class XPathPanelController implements Initializable, SettingsOwner {
DesignerUtil.rewire(getRuleBuilder().xpathExpressionProperty(), xpathExpressionProperty());
DesignerUtil.rewire(getRuleBuilder().rulePropertiesProperty(),
propertyView.rulePropertiesProperty(), propertyView::setRuleProperties);
propertyTableView.rulePropertiesProperty(), propertyTableView::setRuleProperties);
}

View File

@ -157,14 +157,13 @@ public final class DesignerUtil {
*/
public static <T> void rewire(Property<T> underlying, ObservableValue<? extends T> ui, Consumer<? super T> setter) {
setter.accept(underlying.getValue());
underlying.unbind();
underlying.bind(ui); // Bindings are garbage collected after the popup dies
rewire(underlying, ui);
}
/** Like rewire, with no initialisation. */
public static <T> void rewire(Property<T> underlying, ObservableValue<? extends T> source) {
underlying.unbind();
underlying.bind(source);
underlying.bind(source); // Bindings are garbage collected after the popup dies
}

View File

@ -6,9 +6,11 @@ package net.sourceforge.pmd.util.fxdesigner.util.beans;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
@ -90,6 +92,9 @@ public class RestorePropertyVisitor extends BeanNodeVisitor<SettingsOwner> {
Iterator<SettingsOwner> existingItems = container.iterator();
Class<?> itemType = null;
// use a buffer to avoid concurrent modification
List<SettingsOwner> itemsToAdd = new ArrayList<>();
for (SimpleBeanModelNode child : model.getChildrenNodes()) {
SettingsOwner item;
if (existingItems.hasNext()) {
@ -108,9 +113,11 @@ public class RestorePropertyVisitor extends BeanNodeVisitor<SettingsOwner> {
}
child.accept(this, item);
container.add(item);
itemsToAdd.add(item);
}
container.addAll(itemsToAdd);
try {
PropertyUtils.setProperty(target, model.getPropertyName(), container);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {

View File

@ -17,7 +17,7 @@
<TabPane fx:id="nodeInfoTabPane" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="300.0" side="LEFT" stylesheets="@../css/designer.css" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER" xmlns="http://javafx.com/javafx/9" xmlns:fx="http://javafx.com/fxml/1" fx:controller="net.sourceforge.pmd.util.fxdesigner.NodeInfoPanelController">
<tabs>
<Tab text="Attributes" fx:id="xpathAttributesTitledPane">
<Tab text="Attributes">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
@ -41,7 +41,7 @@
</AnchorPane>
</content>
</Tab>
<Tab fx:id="metricResultsTitledPane" text="Metrics">
<Tab fx:id="metricResultsTab" text="Metrics">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>

View File

@ -25,7 +25,7 @@
AnchorPane.topAnchor="0.0">
<content>
<AnchorPane>
<PropertyTableView fx:id="propertyView"
<PropertyTableView fx:id="propertyTableView"
AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0"

View File

@ -274,7 +274,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<argLine>-Xmx512m -Dfile.encoding=${project.build.sourceEncoding}</argLine>
<pmd.build-tools.version>1.1.0</pmd.build-tools.version>
<pmd.build-tools.version>1.1.1-SNAPSHOT</pmd.build-tools.version>
</properties>
<build>
@ -448,12 +448,12 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-core</artifactId>
<version>6.1.0</version>
<version>6.4.0</version>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-java</artifactId>
<version>6.1.0</version>
<version>6.4.0</version>
</dependency>
<!-- This contains the dogfood ruleset -->
<dependency>