Merge branch 'master' into pmd/7.0.x

This commit is contained in:
Andreas Dangel
2020-04-19 21:06:32 +02:00
79 changed files with 1636 additions and 573 deletions

View File

@ -11,6 +11,7 @@ import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.ast.ArrayComprehension;
import org.mozilla.javascript.ast.ArrayComprehensionLoop;
import org.mozilla.javascript.ast.ArrayLiteral;
@ -220,13 +221,18 @@ public final class EcmascriptTreeBuilder implements NodeVisitor {
TrailingCommaNode trailingCommaNode = (TrailingCommaNode) node;
int nodeStart = node.getNode().getAbsolutePosition();
int nodeEnd = nodeStart + node.getNode().getLength() - 1;
// This will fetch the localized message
// See https://github.com/pmd/pmd/issues/384
String trailingCommaLocalizedMessage = ScriptRuntime.getMessage0("msg.extra.trailing.comma");
for (ParseProblem parseProblem : parseProblems) {
// The node overlaps the comma (i.e. end of the problem)?
int problemStart = parseProblem.getFileOffset();
int commaPosition = problemStart + parseProblem.getLength() - 1;
if (nodeStart <= commaPosition && commaPosition <= nodeEnd) {
if ("Trailing comma is not legal in an ECMA-262 object initializer"
.equals(parseProblem.getMessage())) {
if (trailingCommaLocalizedMessage.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);

View File

@ -18,6 +18,7 @@ Rules which enforce generally accepted best practices.
<description>Avoid using with - it's bad news</description>
<priority>1</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
@ -79,10 +80,11 @@ Global variables can lead to side-effects that are hard to debug.
</description>
<priority>1</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
//Assignment[Name/@GlobalName = 'true']
//Assignment[Name/@GlobalName = true()]
]]>
</value>
</property>
@ -116,6 +118,7 @@ is better to explicitly scope the variable name to the nearest enclosing scope w
</description>
<priority>1</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
@ -171,6 +174,7 @@ See also: [parseInt()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/R
</description>
<priority>1</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[

View File

@ -22,20 +22,21 @@ indicative of the bug where the assignment operator '=' was used instead of the
</description>
<priority>2</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
//IfStatement[$allowIf = "false"]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]]
//IfStatement[$allowIf = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
|
//WhileLoop[$allowWhile = "false"]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]]
//WhileLoop[$allowWhile = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
|
//DoLoop[$allowWhile = "false"]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]]
//DoLoop[$allowWhile = false()]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
|
//ForLoop[$allowFor = "false"]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]]
//ForLoop[$allowFor = false()]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
|
//ConditionalExpression[$allowTernary = "false"]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]]
//ConditionalExpression[$allowTernary = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
|
//ConditionalExpression[$allowTernaryResults = "false"]/child::node()[position() = 2 or position() = 3]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]]
//ConditionalExpression[$allowTernaryResults = false()]/child::node()[position() = 2 or position() = 3]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
]]>
</value>
</property>
@ -72,6 +73,7 @@ Avoid using 'for' statements without using curly braces.
</description>
<priority>3</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
@ -107,10 +109,11 @@ Avoid using if..else statements without using curly braces.
</description>
<priority>3</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
//ExpressionStatement[parent::IfStatement[@Else = "true"]]
//ExpressionStatement[parent::IfStatement[@Else = true()]]
[not(child::Scope)]
[not(child::IfStatement)]
]]>
@ -146,10 +149,11 @@ Avoid using if statements without using curly braces.
</description>
<priority>3</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
//IfStatement[@Else = "false" and not(child::Scope)]
//IfStatement[@Else = false() and not(child::Scope)]
]]>
</value>
</property>
@ -182,10 +186,11 @@ See also: &lt;http://eslint.org/docs/rules/no-else-return>
</description>
<priority>3</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
//IfStatement[@Else="true"][Scope[1]/ReturnStatement]
//IfStatement[@Else=true()][Scope[1]/ReturnStatement]
]]>
</value>
</property>
@ -221,6 +226,7 @@ be misleading. Considering removing this unnecessary Block.
</description>
<priority>3</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
@ -256,6 +262,7 @@ if (bar) {
<description>Unnecessary parentheses should be removed.</description>
<priority>4</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
@ -285,6 +292,7 @@ will never execute. This is a bug, or extremely poor style.
</description>
<priority>1</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
@ -326,6 +334,7 @@ Avoid using 'while' statements without using curly braces.
</description>
<priority>3</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[

View File

@ -20,12 +20,13 @@ This rule helps improve code portability due to differences in browser treatment
</description>
<priority>1</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
//ObjectLiteral[$allowObjectLiteral = "false" and @TrailingComma = 'true']
//ObjectLiteral[$allowObjectLiteral = false() and @TrailingComma = true()]
|
//ArrayLiteral[$allowArrayLiteral = "false" and @TrailingComma = 'true']
//ArrayLiteral[$allowArrayLiteral = false() and @TrailingComma = true()]
]]>
</value>
</property>
@ -57,14 +58,14 @@ same type. The === operator avoids the casting.
</description>
<priority>3</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
//InfixExpression[(@Image = "==" or @Image = "!=")
//InfixExpression[
(@Image = "==" or @Image = "!=")
and
(child::KeywordLiteral[@Image = "true" or @Image = "false"]
or
child::NumberLiteral)
(KeywordLiteral[@Image='true' or @Image = 'false'] or NumberLiteral)
]
]]>
</value>
@ -104,10 +105,11 @@ precision in a floating point number. This may result in numeric calculations b
</description>
<priority>2</priority>
<properties>
<property name="version" value="2.0"/>
<property name="xpath">
<value>
<![CDATA[
//NumberLiteral[@NormalizedImage != @Number]
//NumberLiteral[@NormalizedImage != string(@Number)]
]]>
</value>
</property>

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.Locale;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/**
* A JUnit rule to change the system locale during a test.
*/
public class DefaultLocale implements TestRule {
private boolean statementIsExecuting = false;
private Locale loc = Locale.getDefault();
/** Set the locale value (overwrites previously set value). */
public void set(Locale locale) {
if (statementIsExecuting) {
Locale.setDefault(locale);
} else {
this.loc = locale;
}
}
@Override
public Statement apply(Statement base, Description description) {
return new EnvironmentVariablesStatement(base);
}
private class EnvironmentVariablesStatement extends Statement {
final Statement baseStatement;
EnvironmentVariablesStatement(Statement baseStatement) {
this.baseStatement = baseStatement;
}
@Override
public void evaluate() throws Throwable {
Locale prev = Locale.getDefault();
statementIsExecuting = true;
try {
Locale.setDefault(loc);
baseStatement.evaluate();
} finally {
statementIsExecuting = false;
Locale.setDefault(prev);
}
}
}
}

View File

@ -0,0 +1,41 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.ecmascript.ast;
import java.util.Locale;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
public class TrailingCommaTest extends EcmascriptParserTestBase {
@Rule
public DefaultLocale defaultLocale = new DefaultLocale();
@Test
public void testTrailingCommaDefaultLocale() {
testTrailingComma();
}
@Test
public void testTrailingCommaFrFr() {
defaultLocale.set(Locale.FRANCE);
testTrailingComma();
}
@Test
public void testTrailingCommaRootLocale() {
defaultLocale.set(Locale.ROOT);
testTrailingComma();
}
public void testTrailingComma() {
ASTAstRoot node = js.parse("x = {a : 1, };\n");
ASTObjectLiteral fn = node.getFirstDescendantOfType(ASTObjectLiteral.class);
Assert.assertTrue(fn.isTrailingComma());
}
}