diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 311abf5f12..1c8fec70b3 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -30,6 +30,13 @@ not change the result of your rules*, if it does, please report a bug at https:/ Note that XPath 1.0 support, the default XPath version, is deprecated since PMD 6.22.0. **We highly recommend that you upgrade your rules to XPath 2.0**. Please refer to the [migration guide](https://pmd.github.io/latest/pmd_userdocs_extending_writing_xpath_rules.html#migrating-from-10-to-20). +#### Javascript improvements for ES6 + +PMD uses the [Rhino](https://github.com/mozilla/rhino) library to parse Javascript. +The default version has been set to `ES6`, so that some ECMAScript 2015 features are +supported. E.g. `let` statements and `for-of` loops are now parsed. However Rhino does +not support all features. + #### New Rules * The new Apex rule {% rule "apex/codestyle/FieldDeclarationsShouldBeAtStart" %} (`apex-codestyle`) @@ -59,6 +66,9 @@ Note that XPath 1.0 support, the default XPath version, is deprecated since PMD * [#2402](https://github.com/pmd/pmd/issues/2402): \[java] CloseResource possible false positive with Primitive Streams * java-multithreading * [#2313](https://github.com/pmd/pmd/issues/2313): \[java] Documenation for DoNotUseThreads is outdated +* javascript + * [#1235](https://github.com/pmd/pmd/issues/1235): \[javascript] Use of let results in an Empty Statement in the AST + * [#2379](https://github.com/pmd/pmd/issues/2379): \[javascript] Support for-of loop ### API Changes diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java index a30f20b4bc..981ce19fb5 100644 --- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java +++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java @@ -26,7 +26,8 @@ public class EcmascriptParserOptions extends ParserOptions { VERSION_1_5("1.5", Context.VERSION_1_5), VERSION_1_6("1.6", Context.VERSION_1_6), VERSION_1_7("1.7", Context.VERSION_1_7), - VERSION_1_8("1.8", Context.VERSION_1_8); + VERSION_1_8("1.8", Context.VERSION_1_8), + VERSION_ES6("ES6", Context.VERSION_ES6); private final String name; private final int version; @@ -49,7 +50,7 @@ public class EcmascriptParserOptions extends ParserOptions { Version.VERSION_1_0.getLabel(), Version.VERSION_1_1.getLabel(), Version.VERSION_1_2.getLabel(), Version.VERSION_1_3.getLabel(), Version.VERSION_1_4.getLabel(), Version.VERSION_1_5.getLabel(), Version.VERSION_1_6.getLabel(), Version.VERSION_1_7.getLabel(), - Version.VERSION_1_8.getLabel(), }; + Version.VERSION_1_8.getLabel(), Version.VERSION_ES6.getLabel()}; // Note: The UI order values are chosen to be larger than those built into // XPathRule. @@ -64,8 +65,8 @@ public class EcmascriptParserOptions extends ParserOptions { 4.0f); public static final EnumeratedProperty RHINO_LANGUAGE_VERSION = new EnumeratedProperty<>( "rhinoLanguageVersion", - "Specifies the Rhino Language Version to use for parsing. Defaults to Rhino default.", VERSION_LABELS, - Version.values(), 0, Version.class, 5.0f); + "Specifies the Rhino Language Version to use for parsing. Defaults to ES6.", VERSION_LABELS, + Version.values(), Version.VERSION_ES6.ordinal(), Version.class, 5.0f); private boolean recordingComments; private boolean recordingLocalJsDocComments; diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoop.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoop.java index beba25df6b..edb6a01e60 100644 --- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoop.java +++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoop.java @@ -11,9 +11,6 @@ public class ASTForInLoop extends AbstractEcmascriptNode { super(forInLoop); } - /** - * Accept the visitor. - */ @Override public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) { return visitor.visit(this, data); @@ -34,4 +31,8 @@ public class ASTForInLoop extends AbstractEcmascriptNode { public boolean isForEach() { return node.isForEach(); } + + public boolean isForOf() { + return node.isForOf(); + } } diff --git a/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptionsTest.java b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptionsTest.java index b1d7b18315..da18981777 100644 --- a/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptionsTest.java +++ b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptionsTest.java @@ -24,13 +24,13 @@ public class EcmascriptParserOptionsTest { EcmascriptParserOptions parserOptions = new EcmascriptParserOptions(); assertTrue(parserOptions.isRecordingComments()); assertTrue(parserOptions.isRecordingLocalJsDocComments()); - assertEquals(EcmascriptParserOptions.Version.VERSION_DEFAULT, parserOptions.getRhinoLanguageVersion()); + assertEquals(EcmascriptParserOptions.Version.VERSION_ES6, parserOptions.getRhinoLanguageVersion()); MyRule rule = new MyRule(); parserOptions = (EcmascriptParserOptions) rule.getParserOptions(); assertTrue(parserOptions.isRecordingComments()); assertTrue(parserOptions.isRecordingLocalJsDocComments()); - assertEquals(EcmascriptParserOptions.Version.VERSION_DEFAULT, parserOptions.getRhinoLanguageVersion()); + assertEquals(EcmascriptParserOptions.Version.VERSION_ES6, parserOptions.getRhinoLanguageVersion()); } @Test @@ -108,8 +108,4 @@ public class EcmascriptParserOptionsTest { private static final class MyRule extends AbstractEcmascriptRule { } - - public static junit.framework.Test suite() { - return new junit.framework.JUnit4TestAdapter(EcmascriptParserOptionsTest.class); - } } diff --git a/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoopTest.java b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoopTest.java new file mode 100644 index 0000000000..2f35c9f1c0 --- /dev/null +++ b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoopTest.java @@ -0,0 +1,33 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + + +package net.sourceforge.pmd.lang.ecmascript.ast; + +import org.junit.Assert; +import org.junit.Test; + +public class ASTForInLoopTest extends EcmascriptParserTestBase { + + /** + * Note: for each loops are deprecated. + * + * @see for each...in + */ + @Test + public void testForEachLoop() { + ASTAstRoot node = js.parse("for each (var item in items) {}"); + ASTForInLoop loop = (ASTForInLoop) node.getChild(0); + Assert.assertFalse(loop.isForOf()); + Assert.assertTrue(loop.isForEach()); + } + + @Test + public void testForOfLoop() { + ASTAstRoot node = js.parse("for (var item of items) {}"); + ASTForInLoop loop = (ASTForInLoop) node.getChild(0); + Assert.assertTrue(loop.isForOf()); + Assert.assertFalse(loop.isForEach()); + } +} diff --git a/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableDeclarationTest.java b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableDeclarationTest.java new file mode 100644 index 0000000000..ec8aae6f06 --- /dev/null +++ b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableDeclarationTest.java @@ -0,0 +1,24 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + + +package net.sourceforge.pmd.lang.ecmascript.ast; + +import org.junit.Assert; +import org.junit.Test; + +public class ASTVariableDeclarationTest extends EcmascriptParserTestBase { + + @Test + public void testLet() { + ASTAstRoot node = js.parse("let x = 1;"); + ASTVariableDeclaration varDecl = (ASTVariableDeclaration) node.getChild(0); + Assert.assertTrue(varDecl.isLet()); + + ASTVariableInitializer varInit = (ASTVariableInitializer) varDecl.getChild(0); + ASTName name = (ASTName) varInit.getChild(0); + Assert.assertEquals("x", name.getImage()); + } + +}