diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index 376df38be3..f0a57382be 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -160,24 +160,6 @@ entries: - title: Security output: web, pdf url: /pmd_rules_apex_security.html - - title: null - output: web, pdf - subfolders: - - title: Ecmascript Rules - output: web, pdf - subfolderitems: - - title: Index - output: web, pdf - url: /pmd_rules_ecmascript.html - - title: Best Practices - output: web, pdf - url: /pmd_rules_ecmascript_bestpractices.html - - title: Code Style - output: web, pdf - url: /pmd_rules_ecmascript_codestyle.html - - title: Error Prone - output: web, pdf - url: /pmd_rules_ecmascript_errorprone.html - title: null output: web, pdf subfolders: @@ -247,6 +229,24 @@ entries: - title: Security output: web, pdf url: /pmd_rules_jsp_security.html + - title: null + output: web, pdf + subfolders: + - title: JavaScript Rules + output: web, pdf + subfolderitems: + - title: Index + output: web, pdf + url: /pmd_rules_ecmascript.html + - title: Best Practices + output: web, pdf + url: /pmd_rules_ecmascript_bestpractices.html + - title: Code Style + output: web, pdf + url: /pmd_rules_ecmascript_codestyle.html + - title: Error Prone + output: web, pdf + url: /pmd_rules_ecmascript_errorprone.html - title: null output: web, pdf subfolders: diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 86c89181b6..2d877db318 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -153,9 +153,9 @@ See {% jdoc core::lang.ast.NodeStream %} for more details. #### JavaScript support The JS specific parser options have been removed. The parser now always retains comments and uses version ES6. -The language module registers only one version (as before), now correctly with version "ES6" instead of "3". -Since there is only one version available for JavaScript there is actually no need to selected a specific version. -The default version is always ES6. +The language module registers a couple of different versions. The latest version, which supports ES6 and also some +new constructs (see [Rhino](https://github.com/mozilla/rhino)]), is the default. This should be fine for most +use cases. #### New Rules @@ -254,6 +254,7 @@ The following previously deprecated rules have been finally removed: * [#3782](https://github.com/pmd/pmd/issues/3782): \[core] Language lifecycle * [#3902](https://github.com/pmd/pmd/issues/3902): \[core] Violation decorators * [#4035](https://github.com/pmd/pmd/issues/4035): \[core] ConcurrentModificationException in DefaultRuleViolationFactory + * [#4120](https://github.com/pmd/pmd/issues/4120): \[core] Explicitly name all language versions * cli * [#3828](https://github.com/pmd/pmd/issues/3828): \[core] Progress reporting * [#4079](https://github.com/pmd/pmd/issues/4079): \[cli] Split off CLI implementation into a pmd-cli submodule diff --git a/docs/pages/pmd/userdocs/cli_reference.md b/docs/pages/pmd/userdocs/cli_reference.md index 19f5ad547e..2489a494fa 100644 --- a/docs/pages/pmd/userdocs/cli_reference.md +++ b/docs/pages/pmd/userdocs/cli_reference.md @@ -239,7 +239,14 @@ non-preview version. If you want to use an older version, so that e.g. rules tha that are not available yet won't be executed, you need to specify a specific version via the `--use-version` parameter. -These parameters are irrelevant for languages that don't support different versions. +The selected language version can also influence which rules are applied. Some rules might be relevant for +just a specific version of the language. Such rules are marked with either `minimumLanguageVersion` or +`maximumLanguageVersion` or both. Most rules apply for all language versions. + +These parameters are most of the time irrelevant, if the rules apply for all versions. + +The available versions depend on the language. You can get a list of the currently supported language versions +via the CLI option `--help`. Example: @@ -260,7 +267,6 @@ Example: * [plsql](pmd_rules_plsql.html) * [pom](pmd_rules_pom.html) (Maven POM) * [scala](pmd_rules_scala.html) - * Supported Versions: 2.10, 2.11, 2.12, 2.13 (default) * [swift](pmd_rules_swift.html) * [vf](pmd_rules_vf.html) (Salesforce VisualForce) * [vm](pmd_rules_vm.html) (Apache Velocity) diff --git a/docs/pages/pmd/userdocs/tools/ant.md b/docs/pages/pmd/userdocs/tools/ant.md index cd873cb09e..ae3abbcbab 100644 --- a/docs/pages/pmd/userdocs/tools/ant.md +++ b/docs/pages/pmd/userdocs/tools/ant.md @@ -211,49 +211,12 @@ sense with Java 1.7 and later. If your project uses Java 1.5, then you should co accordingly and this rule won't be executed. The specific version of a language to be used is selected via the `sourceLanguage` -nested element. Possible values are: +nested element. Example: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +The available versions depend on the language. You can get a list of the currently supported language versions +via the CLI option `--help`. ### Postprocessing the report file with XSLT diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/cpd/ApexLanguage.java b/pmd-apex/src/main/java/net/sourceforge/pmd/cpd/ApexLanguage.java index 0bb7bd7014..5ca6959052 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/cpd/ApexLanguage.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/cpd/ApexLanguage.java @@ -6,6 +6,8 @@ package net.sourceforge.pmd.cpd; import java.util.Properties; +import net.sourceforge.pmd.lang.apex.ApexLanguageModule; + public class ApexLanguage extends AbstractLanguage { public ApexLanguage() { @@ -13,7 +15,7 @@ public class ApexLanguage extends AbstractLanguage { } public ApexLanguage(Properties properties) { - super("Apex", "apex", new ApexTokenizer(), ".cls"); + super(ApexLanguageModule.NAME, ApexLanguageModule.TERSE_NAME, new ApexTokenizer(), ApexLanguageModule.EXTENSIONS); setProperties(properties); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexLanguageModule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexLanguageModule.java index 7b57934bd7..8bb3084136 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexLanguageModule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexLanguageModule.java @@ -4,22 +4,33 @@ package net.sourceforge.pmd.lang.apex; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageModuleBase; import net.sourceforge.pmd.lang.LanguageProcessor; import net.sourceforge.pmd.lang.LanguagePropertyBundle; import net.sourceforge.pmd.lang.LanguageRegistry; -import apex.jorje.services.Version; - public class ApexLanguageModule extends LanguageModuleBase { public static final String NAME = "Apex"; public static final String TERSE_NAME = "apex"; + @InternalApi + public static final List EXTENSIONS = listOf("cls", "trigger"); + public ApexLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("cls", "trigger") - .addDefaultVersion(String.valueOf((int) Version.CURRENT.getExternal()))); + super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions(EXTENSIONS) + .addVersion("52") + .addVersion("53") + .addVersion("54") + .addVersion("55") + .addVersion("56") + .addDefaultVersion("57")); } @Override diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/LanguageVersionTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/LanguageVersionTest.java index fe132bcb61..0379b1a16a 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/LanguageVersionTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/LanguageVersionTest.java @@ -12,7 +12,7 @@ import net.sourceforge.pmd.AbstractLanguageVersionTest; class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { - return Arrays.asList(new TestDescriptor(ApexLanguageModule.NAME, ApexLanguageModule.TERSE_NAME, "35", - getLanguage("Apex").getVersion("35"))); + return Arrays.asList(new TestDescriptor(ApexLanguageModule.NAME, ApexLanguageModule.TERSE_NAME, "57", + ApexLanguageModule.getInstance().getDefaultVersion())); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java index 7e08eccf8a..4045ddbf16 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java @@ -11,6 +11,7 @@ import java.util.Arrays; import java.util.List; import java.util.Properties; import java.util.function.Predicate; +import java.util.stream.Collectors; import net.sourceforge.pmd.internal.util.PredicateUtil; @@ -22,11 +23,23 @@ public abstract class AbstractLanguage implements Language { private final List extensions; public AbstractLanguage(String name, String terseName, Tokenizer tokenizer, String... extensions) { + this(name, terseName, tokenizer, Arrays.asList(extensions)); + } + + protected AbstractLanguage(String name, String terseName, Tokenizer tokenizer, List extensions) { this.name = name; this.terseName = terseName; this.tokenizer = tokenizer; - this.fileFilter = PredicateUtil.toNormalizedFileFilter(PredicateUtil.getFileExtensionFilter(extensions).or(it -> Files.isDirectory(Paths.get(it)))); - this.extensions = Arrays.asList(extensions); + List extensionsWithDot = extensions.stream().map(e -> { + if (e.length() > 0 && e.charAt(0) != '.') { + return "." + e; + } + return e; + }).collect(Collectors.toList()); + this.fileFilter = PredicateUtil.toNormalizedFileFilter( + PredicateUtil.getFileExtensionFilter(extensionsWithDot.toArray(new String[0])) + .or(it -> Files.isDirectory(Paths.get(it)))); + this.extensions = extensionsWithDot; } @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageModuleBase.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageModuleBase.java index 8133d732fb..0d1d45553f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageModuleBase.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageModuleBase.java @@ -8,6 +8,7 @@ import static net.sourceforge.pmd.util.CollectionUtil.setOf; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -21,7 +22,6 @@ import org.apache.commons.lang3.StringUtils; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import net.sourceforge.pmd.lang.LanguageModuleBase.LanguageMetadata.LangVersionMetadata; import net.sourceforge.pmd.util.AssertionUtil; import net.sourceforge.pmd.util.StringUtil; @@ -44,7 +44,7 @@ public abstract class LanguageModuleBase implements Language { * Construct a module instance using the given metadata. The metadata must * be properly constructed. * - * @throws IllegalStateException If the metadata is invalid (eg missing extensions or name) + * @throws IllegalStateException If the metadata is invalid (eg missing extensions or name or no versions) */ protected LanguageModuleBase(LanguageMetadata metadata) { this.meta = metadata; @@ -55,10 +55,7 @@ public abstract class LanguageModuleBase implements Language { LanguageVersion defaultVersion = null; if (metadata.versionMetadata.isEmpty()) { - // Many languages have just one version, which is implicitly - // created here. - // TODO #4120 remove this branch, before 7.0.0 - metadata.versionMetadata.add(new LangVersionMetadata("", Collections.emptyList(), true)); + throw new IllegalStateException("No versions for '" + getId() + "'"); } int i = 0; @@ -269,7 +266,7 @@ public abstract class LanguageModuleBase implements Language { /** * Record the {@linkplain Language#getExtensions() extensions} - * assigned to the language. Parameters should not start with a period + * assigned to the language. Extensions should not start with a period * {@code .}. * * @param e1 First extensions @@ -283,6 +280,25 @@ public abstract class LanguageModuleBase implements Language { return this; } + /** + * Record the {@linkplain Language#getExtensions() extensions} + * assigned to the language. Extensions should not start with a period + * {@code .}. At least one extension must be provided. + * + * @param extensions the extensions + * + * @throws NullPointerException If any extension is null + * @throws IllegalArgumentException If no extensions are provided + */ + public LanguageMetadata extensions(Collection extensions) { + this.extensions = new ArrayList<>(new HashSet<>(extensions)); + AssertionUtil.requireContainsNoNullValue("extensions", this.extensions); + if (this.extensions.isEmpty()) { + throw new IllegalArgumentException("At least one extension is required."); + } + return this; + } + /** * Add a new version by its name. * @@ -290,7 +306,7 @@ public abstract class LanguageModuleBase implements Language { * @param aliases Additional names that are mapped to this version. Must contain no spaces. * * @throws NullPointerException If any parameter is null - * @throws IllegalArgumentException If the name or aliases contain spaces + * @throws IllegalArgumentException If the name or aliases are empty or contain spaces */ public LanguageMetadata addVersion(String name, String... aliases) { @@ -305,7 +321,7 @@ public abstract class LanguageModuleBase implements Language { * @param aliases Additional names that are mapped to this version. Must contain no spaces. * * @throws NullPointerException If any parameter is null - * @throws IllegalArgumentException If the name or aliases contain spaces + * @throws IllegalArgumentException If the name or aliases are empty or contain spaces */ public LanguageMetadata addDefaultVersion(String name, String... aliases) { versionMetadata.add(new LangVersionMetadata(name, Arrays.asList(aliases), true)); @@ -351,7 +367,7 @@ public abstract class LanguageModuleBase implements Language { } private static void checkVersionName(String name) { - if (SPACE_PAT.matcher(name).find()) { // TODO #4120 also check that the name is non-empty + if (StringUtils.isBlank(name) || SPACE_PAT.matcher(name).find()) { throw new IllegalArgumentException("Invalid version name: " + StringUtil.inSingleQuotes(name)); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/PlainTextLanguage.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/PlainTextLanguage.java index 29afc7d45d..3c14dd61de 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/PlainTextLanguage.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/PlainTextLanguage.java @@ -31,7 +31,9 @@ public final class PlainTextLanguage extends SimpleLanguageModuleBase { static final String TERSE_NAME = "text"; private PlainTextLanguage() { - super(LanguageMetadata.withId(TERSE_NAME).name("Plain text").extensions("plain-text-file-goo-extension"), + super(LanguageMetadata.withId(TERSE_NAME).name("Plain text") + .extensions("plain-text-file-goo-extension") + .addDefaultVersion("default"), new TextLvh()); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/LanguageModuleBaseTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/LanguageModuleBaseTest.java index 64fae5a9c8..91e56eff8d 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/LanguageModuleBaseTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/LanguageModuleBaseTest.java @@ -28,6 +28,16 @@ class LanguageModuleBaseTest { assertInvalidId("C"); assertInvalidId("ab-c"); assertThrows(NullPointerException.class, () -> LanguageMetadata.withId(null)); + + Exception e = assertThrows(IllegalArgumentException.class, () -> LanguageMetadata.withId("dummy").addVersion(""), + "Empty versions should not be allowed."); + assertEquals("Invalid version name: ''", e.getMessage()); + assertThrows(IllegalArgumentException.class, () -> LanguageMetadata.withId("dummy").addVersion(" "), + "Empty versions should not be allowed."); + assertThrows(IllegalArgumentException.class, () -> LanguageMetadata.withId("dummy").addVersion(null), + "Empty versions should not be allowed."); + assertThrows(IllegalArgumentException.class, () -> LanguageMetadata.withId("dummy").addVersion("1.0", ""), + "Empty versions should not be allowed."); } @Test @@ -36,6 +46,13 @@ class LanguageModuleBaseTest { assertThat(lang.getDefaultVersion(), equalTo(lang.getVersion("abc"))); } + @Test + void testMissingVersions() { + Exception e = assertThrows(IllegalStateException.class, () -> makeLanguage(LanguageMetadata.withId("dumdum").name("Name").extensions("o")), + "Languages without versions should not be allowed."); + assertEquals("No versions for 'dumdum'", e.getMessage()); + } + @Test void testNoExtensions() { Exception ex = assertThrows(IllegalStateException.class, () -> makeLanguage(LanguageMetadata.withId("dumdum").name("Name").addVersion("abc"))); diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AllRulesIT.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AllRulesIT.java index 74faa00fbc..9a32b681a1 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AllRulesIT.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AllRulesIT.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.it; +import static org.hamcrest.Matchers.containsString; + import java.io.File; import java.util.Arrays; @@ -30,7 +32,8 @@ class AllRulesIT extends AbstractBinaryDistributionTest { } private static void assertDefaultExecutionResult(ExecutionResult result) { - result.assertExecutionResult(4, ""); + result.assertExitCode(4) + .assertStdOut(containsString("")); result.assertNoError("Exception applying rule"); result.assertNoError("Ruleset not found"); diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AnalysisCacheIT.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AnalysisCacheIT.java index ef010cb850..b9a4478ec3 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AnalysisCacheIT.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AnalysisCacheIT.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.it; +import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; @@ -25,7 +26,7 @@ class AnalysisCacheIT extends AbstractBinaryDistributionTest { // Ensure we have violations and a non-empty cache file assertTrue(cacheFile.toFile().length() > 0, "cache file is empty after run"); - result.assertExecutionResult(4, "", srcDir + File.separator + "JumbledIncrementer.java:8:\tJumbledIncrementer:\t"); + result.assertExitCode(4).assertReport(containsString(srcDir + File.separator + "JumbledIncrementer.java:8:\tJumbledIncrementer:\t")); // rerun from cache ExecutionResult resultFromCache = PMDExecutor.runPMD(createTemporaryReportFile(), tempDir, "-d", srcDir, "-R", "src/test/resources/rulesets/sample-ruleset.xml", @@ -45,7 +46,8 @@ class AnalysisCacheIT extends AbstractBinaryDistributionTest { // Ensure we have violations and a non-empty cache file assertTrue(cacheFile.toFile().length() > 0, "cache file is empty after run"); - result.assertExecutionResult(4, "", srcDir + File.separator + "JumbledIncrementer.java:8:\tJumbledIncrementer:\t"); + result.assertExitCode(4) + .assertReport(containsString(srcDir + File.separator + "JumbledIncrementer.java:8:\tJumbledIncrementer:\t")); // rerun from cache with relativized paths ExecutionResult resultFromCache = PMDExecutor.runPMD(createTemporaryReportFile(), tempDir, "-d", Paths.get(".").toAbsolutePath().relativize(Paths.get(srcDir)).toString(), "-R", "src/test/resources/rulesets/sample-ruleset.xml", @@ -54,7 +56,8 @@ class AnalysisCacheIT extends AbstractBinaryDistributionTest { resultFromCache.assertErrorOutputContains("Incremental Analysis cache HIT"); // An error with the relative path should exist, but no with the absolute one - resultFromCache.assertExecutionResult(4, "", "src/test/resources/sample-source/java/JumbledIncrementer.java:8:\tJumbledIncrementer:\t".replace('/', File.separatorChar)); + result.assertExitCode(4) + .assertReport(containsString("src/test/resources/sample-source/java/JumbledIncrementer.java:8:\tJumbledIncrementer:\t".replace('/', File.separatorChar))); resultFromCache.assertNoErrorInReport(srcDir + File.separator + "JumbledIncrementer.java:8:\tJumbledIncrementer:\t"); } } diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AntIT.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AntIT.java index f28e430273..bc4ca8be7d 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AntIT.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AntIT.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.it; +import static org.hamcrest.Matchers.containsString; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -38,8 +40,11 @@ class AntIT extends AbstractBinaryDistributionTest { File antTestProjectFolder = prepareAntTestProjectFolder(); ExecutionResult result = runAnt(antBasepath, pmdHome, antTestProjectFolder); - result.assertExecutionResult(0, "BUILD SUCCESSFUL"); - result.assertExecutionResult(0, "NoPackage"); // the no package rule + result.assertExitCode(0) + .assertStdOut(containsString("BUILD SUCCESSFUL")); + // the no package rule + result.assertExitCode(0) + .assertStdOut(containsString("NoPackage")); } diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java index fa17f07414..431d5f1bcf 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java @@ -4,6 +4,9 @@ package net.sourceforge.pmd.it; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.matchesRegex; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -11,7 +14,10 @@ import java.io.File; import java.io.IOException; import java.util.Enumeration; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -21,29 +27,50 @@ import net.sourceforge.pmd.PMDVersion; class BinaryDistributionIT extends AbstractBinaryDistributionTest { - private static final String SUPPORTED_LANGUAGES_CPD; - private static final String SUPPORTED_LANGUAGES_PMD; + private static final List SUPPORTED_LANGUAGES_CPD = listOf( + "apex", "cpp", "cs", "dart", "ecmascript", + "fortran", "gherkin", "go", "groovy", "html", "java", "jsp", + "kotlin", "lua", "matlab", "modelica", "objectivec", "perl", + "php", "plsql", "python", "ruby", "scala", "swift", "tsql", + "vf", "xml" + ); + + private static final List SUPPORTED_LANGUAGES_PMD = listOf( + "apex-52", "apex-53", "apex-54", "apex-55", + "apex-56", "apex-57", "ecmascript-3", "ecmascript-5", + "ecmascript-6", "ecmascript-7", "ecmascript-8", + "ecmascript-9", "ecmascript-ES2015", + "ecmascript-ES2016", "ecmascript-ES2017", + "ecmascript-ES2018", "ecmascript-ES6", "html-4", + "html-5", "java-1.10", "java-1.3", "java-1.4", "java-1.5", + "java-1.6", "java-1.7", "java-1.8", "java-1.9", "java-10", + "java-11", "java-12", "java-13", "java-14", "java-15", + "java-16", "java-17", "java-18", "java-19", + "java-19-preview", "java-20", "java-20-preview", + "java-5", "java-6", "java-7", + "java-8", "java-9", "jsp-2", "jsp-3", "kotlin-1.6", + "kotlin-1.7", "modelica-3.4", "modelica-3.5", + "plsql-11g", "plsql-12.1", "plsql-12.2", + "plsql-12c_Release_1", "plsql-12c_Release_2", + "plsql-18c", "plsql-19c", "plsql-21c", "pom-4.0.0", + "scala-2.10", "scala-2.11", "scala-2.12", "scala-2.13", + "swift-4.2", "swift-5.0", "swift-5.1", "swift-5.2", + "swift-5.3", "swift-5.4", "swift-5.5", "swift-5.6", + "swift-5.7", "vf-52", "vf-53", "vf-54", "vf-55", "vf-56", + "vf-57", "vm-2.0", "vm-2.1", "vm-2.2", "vm-2.3", "wsdl-1.1", + "wsdl-2.0", "xml-1.0", "xml-1.1", "xsl-1.0", "xsl-2.0", + "xsl-3.0" + ); - static { - SUPPORTED_LANGUAGES_CPD = "Valid values: apex, cpp, cs, dart, ecmascript," + System.lineSeparator() - + " fortran, gherkin, go, groovy, html, java, jsp," + System.lineSeparator() - + " kotlin, lua, matlab, modelica, objectivec, perl," + System.lineSeparator() - + " php, plsql, python, ruby, scala, swift, tsql," + System.lineSeparator() - + " vf, xml"; - SUPPORTED_LANGUAGES_PMD = "Valid values: apex-54, ecmascript-ES6, html-," + System.lineSeparator() - + " java-1.10, java-1.3, java-1.4, java-1.5, java-1." + System.lineSeparator() - + " 6, java-1.7, java-1.8, java-1.9, java-10," + System.lineSeparator() - + " java-11, java-12, java-13, java-14, java-15," + System.lineSeparator() - + " java-16, java-17, java-18, java-19," + System.lineSeparator() - + " java-19-preview, java-20, java-20-preview," + System.lineSeparator() - + " java-5, java-6, java-7, java-8, java-9, jsp-," + System.lineSeparator() - + " kotlin-1.6, kotlin-1.6-rfc+0.1, modelica-," + System.lineSeparator() - + " plsql-, pom-, scala-2.10, scala-2.11, scala-2.12," + System.lineSeparator() - + " scala-2.13, swift-, vf-, vm-, wsdl-, xml-, xsl-"; - } private final String srcDir = new File(".", "src/test/resources/sample-source/java/").getAbsolutePath(); + private static Pattern toListPattern(List items) { + String pattern = items.stream().map(Pattern::quote) + .collect(Collectors.joining(",\\s+", ".*Valid values: ", ".*")); + return Pattern.compile(pattern, Pattern.DOTALL); + } + @Test void testFileExistence() { assertTrue(getBinaryDistribution().exists()); @@ -85,46 +112,49 @@ class BinaryDistributionIT extends AbstractBinaryDistributionTest { @Test void testPmdJavaQuickstart() throws Exception { ExecutionResult result = PMDExecutor.runPMDRules(createTemporaryReportFile(), tempDir, srcDir, "rulesets/java/quickstart.xml"); - result.assertExecutionResult(4, ""); + result.assertExitCode(4) + .assertStdOut(containsString("")); } @Test void testPmdXmlFormat() throws Exception { ExecutionResult result = PMDExecutor.runPMDRules(createTemporaryReportFile(), tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml", "xml"); - result.assertExecutionResult(4, "", "JumbledIncrementer.java\">"); - result.assertExecutionResult(4, "", "")); + result.assertExitCode(4).assertReport(containsString(""); - result.assertExecutionResult(4, "Class1.java\"/>"); - result.assertExecutionResult(4, "Class2.java\"/>"); + result.assertExitCode(4) + .assertStdOut(containsString("")); + result.assertExitCode(4) + .assertStdOut(containsString("Class1.java\"/>")); + result.assertExitCode(4) + .assertStdOut(containsString("Class2.java\"/>")); result = CpdExecutor.runCpd(tempDir, "--minimum-tokens", "1000", "--format", "text", "--dir", srcDir); - result.assertExecutionResult(0); + result.assertExitCode(0); } } diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/ExecutionResult.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/ExecutionResult.java index 4304dff04c..0d51c4e48a 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/ExecutionResult.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/ExecutionResult.java @@ -4,13 +4,12 @@ package net.sourceforge.pmd.it; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -import net.sourceforge.pmd.PMD; +import org.hamcrest.Matcher; /** * Collects the result of a command execution in order to verify it. @@ -32,96 +31,40 @@ public class ExecutionResult { @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("ExecutionResult:") - .append(PMD.EOL) - .append(" exit code: ").append(exitCode).append(PMD.EOL) - .append(" output:").append(PMD.EOL).append(output).append(PMD.EOL) - .append(" errorOutput:").append(PMD.EOL).append(errorOutput).append(PMD.EOL) - .append(" report:").append(PMD.EOL).append(report).append(PMD.EOL); - return sb.toString(); + return "ExecutionResult:\n" + + " exit code: " + exitCode + "\n" + + " output:\n" + output + "\n" + + " errorOutput:\n" + errorOutput + "\n" + + " report:\n" + report + "\n"; } - /** - * Asserts that the command exited with the expected exit code. Any output is ignored. - * - * @param expectedExitCode the exit code, e.g. 0 if no rule violations are expected, or 4 if violations are found - */ - public void assertExecutionResult(int expectedExitCode) { - assertExecutionResult(expectedExitCode, null); - } - - /** - * Asserts that the command exited with the expected exit code and that the given expected - * output is contained in the actual command output. - * - * @param expectedExitCode the exit code, e.g. 0 if no rule violations are expected, or 4 if violations are found - * @param expectedOutput the output to search for - */ - public void assertExecutionResult(int expectedExitCode, String expectedOutput) { - assertExecutionResult(expectedExitCode, expectedOutput, null); - } - - /** - * Asserts that the command exited with the expected exit code and that the given expected - * output is contained in the actual command output and the given expected report is in the - * generated report. - * - * @param expectedExitCode the exit code, e.g. 0 if no rule violations are expected, or 4 if violations are found - * @param expectedOutput the output to search for - * @param expectedReport the string to search for tin the report - */ - public void assertExecutionResult(int expectedExitCode, String expectedOutput, String expectedReport) { - assertExecResultImpl(expectedExitCode, output, expectedOutput, expectedReport); - } - - /** - * Asserts that the command exited with the expected exit code and that the given expected - * output is contained in the actual command ERROR output, and the given expected report is in the - * generated report. - * - * @param expectedExitCode the exit code, e.g. 0 if no rule violations are expected, or 4 if violations are found - * @param expectedErrorOutput the output to search for in stderr - * @param expectedReport the string to search for tin the report - */ - public void assertExecutionResultErrOutput(int expectedExitCode, String expectedErrorOutput, String expectedReport) { - assertExecResultImpl(expectedExitCode, errorOutput, expectedErrorOutput, expectedReport); - } - - /** - * Asserts that the command exited with the expected exit code and that the given expected - * output is contained in the actual command ERROR output. - * - * @param expectedExitCode the exit code, e.g. 0 if no rule violations are expected, or 4 if violations are found - * @param expectedErrorOutput the output to search for in stderr - */ - public void assertExecutionResultErrOutput(int expectedExitCode, String expectedErrorOutput) { - assertExecResultImpl(expectedExitCode, errorOutput, expectedErrorOutput, null); - } - - private void assertExecResultImpl(int expectedExitCode, String output, String expectedOutput, String expectedReport) { + public ExecutionResult assertExitCode(int expectedExitCode) { assertEquals(expectedExitCode, exitCode, "Command exited with wrong code.\nComplete result:\n\n" + this); - assertNotNull(output, "No output found"); - if (expectedOutput != null && !expectedOutput.isEmpty()) { - if (!output.contains(expectedOutput)) { - fail("Expected output '" + expectedOutput + "' not present.\nComplete result:\n\n" + this); - } - } else if (expectedOutput != null && expectedOutput.isEmpty()) { - assertTrue(output.isEmpty(), "The output should have been empty.\nComplete result:\n\n" + this); - } - if (expectedReport != null && !expectedReport.isEmpty()) { - assertTrue(report.contains(expectedReport), - "Expected report '" + expectedReport + "'.\nComplete result:\n\n" + this); - } + return this; + } + + public ExecutionResult assertReport(Matcher reportMatcher) { + assertThat("Report", report, reportMatcher); + return this; + } + + public ExecutionResult assertStdErr(Matcher matcher) { + assertThat("Standard error", errorOutput, matcher); + return this; + } + + public ExecutionResult assertStdOut(Matcher matcher) { + assertThat("Standard output", output, matcher); + return this; } /** * Asserts that the given error message is not in the error output. + * * @param errorMessage the error message to search for */ public void assertNoError(String errorMessage) { - assertFalse(errorOutput.contains(errorMessage), - "Found error message: " + errorMessage + ".\nComplete result:\n\n" + this); + assertStdErr(not(containsString(errorMessage))); } /** @@ -129,12 +72,11 @@ public class ExecutionResult { * @param errorMessage the error message to search for */ public void assertNoErrorInReport(String errorMessage) { - assertFalse(report.contains(errorMessage), - "Found error message in report: " + errorMessage + ".\nComplete result:\n\n" + this); + assertReport(not(containsString(errorMessage))); } public void assertErrorOutputContains(String message) { - assertTrue(errorOutput.contains(message), "erroroutput didn't contain " + message); + assertStdErr(containsString(message)); } public void assertIdenticalResults(ExecutionResult other) { diff --git a/pmd-doc/src/test/resources/expected/pmd_sidebar.yml b/pmd-doc/src/test/resources/expected/pmd_sidebar.yml index b7ce41869c..685cfc5851 100644 --- a/pmd-doc/src/test/resources/expected/pmd_sidebar.yml +++ b/pmd-doc/src/test/resources/expected/pmd_sidebar.yml @@ -15,15 +15,6 @@ entries: - title: Index output: web, pdf url: /pmd_rules_apex.html - - title: null - output: web, pdf - subfolders: - - title: Ecmascript Rules - output: web, pdf - subfolderitems: - - title: Index - output: web, pdf - url: /pmd_rules_ecmascript.html - title: null output: web, pdf subfolders: @@ -54,6 +45,15 @@ entries: - title: Index output: web, pdf url: /pmd_rules_jsp.html + - title: null + output: web, pdf + subfolders: + - title: JavaScript Rules + output: web, pdf + subfolderitems: + - title: Index + output: web, pdf + url: /pmd_rules_ecmascript.html - title: null output: web, pdf subfolders: diff --git a/pmd-doc/src/test/resources/net/sourceforge/pmd/docs/sidebar.yml b/pmd-doc/src/test/resources/net/sourceforge/pmd/docs/sidebar.yml index 69435aad61..0b8bcc1128 100644 --- a/pmd-doc/src/test/resources/net/sourceforge/pmd/docs/sidebar.yml +++ b/pmd-doc/src/test/resources/net/sourceforge/pmd/docs/sidebar.yml @@ -1,15 +1,3 @@ -- title: null - output: web, pdf - subfolders: - - title: Ecmascript Rules - output: web, pdf - subfolderitems: - - title: Index - output: web, pdf - url: /pmd_rules_ecmascript.html - - title: test - output: web, pdf - url: /pmd_rules_ecmascript_bestpractices.html - title: null output: web, pdf subfolders: @@ -25,6 +13,18 @@ - title: test2 output: web, pdf url: /pmd_rules_java_codestyle.html +- title: null + output: web, pdf + subfolders: + - title: JavaScript Rules + output: web, pdf + subfolderitems: + - title: Index + output: web, pdf + url: /pmd_rules_ecmascript.html + - title: test + output: web, pdf + url: /pmd_rules_ecmascript_bestpractices.html - title: null output: web, pdf subfolders: diff --git a/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/HtmlCpdLanguage.java b/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/HtmlCpdLanguage.java index 3c6c0fdbde..740acfff6b 100644 --- a/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/HtmlCpdLanguage.java +++ b/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/HtmlCpdLanguage.java @@ -11,6 +11,6 @@ import net.sourceforge.pmd.lang.html.ast.HtmlTokenizer; public final class HtmlCpdLanguage extends AbstractLanguage { public HtmlCpdLanguage() { - super("HTML", "html", new HtmlTokenizer(), ".html"); + super(HtmlLanguageModule.NAME, HtmlLanguageModule.TERSE_NAME, new HtmlTokenizer(), HtmlLanguageModule.EXTENSIONS); } } diff --git a/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/HtmlLanguageModule.java b/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/HtmlLanguageModule.java index f242c180be..900ab8c381 100644 --- a/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/HtmlLanguageModule.java +++ b/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/HtmlLanguageModule.java @@ -2,9 +2,13 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ - package net.sourceforge.pmd.lang.html; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase; @@ -12,10 +16,14 @@ public final class HtmlLanguageModule extends SimpleLanguageModuleBase { public static final String NAME = "HTML"; public static final String TERSE_NAME = "html"; + @InternalApi + public static final List EXTENSIONS = listOf("html", "htm", "xhtml", "xht", "shtml"); public HtmlLanguageModule() { super(LanguageMetadata.withId(TERSE_NAME).name(NAME) - .extensions("html", "htm", "xhtml", "xht", "shtml"), + .extensions(EXTENSIONS) + .addVersion("4") + .addDefaultVersion("5"), new HtmlHandler()); } diff --git a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/LanguageVersionTest.java b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/LanguageVersionTest.java index c1baee0c98..3534875ac5 100644 --- a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/LanguageVersionTest.java +++ b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/LanguageVersionTest.java @@ -12,7 +12,7 @@ import net.sourceforge.pmd.AbstractLanguageVersionTest; class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { - return Arrays.asList(new TestDescriptor(HtmlLanguageModule.NAME, HtmlLanguageModule.TERSE_NAME, "", + return Arrays.asList(new TestDescriptor(HtmlLanguageModule.NAME, HtmlLanguageModule.TERSE_NAME, "5", getLanguage(HtmlLanguageModule.NAME).getDefaultVersion())); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/cpd/JavaLanguage.java b/pmd-java/src/main/java/net/sourceforge/pmd/cpd/JavaLanguage.java index 0ff3638c99..2a68ea48a5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/cpd/JavaLanguage.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/cpd/JavaLanguage.java @@ -6,13 +6,15 @@ package net.sourceforge.pmd.cpd; import java.util.Properties; +import net.sourceforge.pmd.lang.java.JavaLanguageModule; + public class JavaLanguage extends AbstractLanguage { public JavaLanguage() { this(System.getProperties()); } public JavaLanguage(Properties properties) { - super("Java", "java", new JavaTokenizer(), ".java"); + super(JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, new JavaTokenizer(), JavaLanguageModule.EXTENSIONS); setProperties(properties); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java index 380ad995d5..5ab1b6e64e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java @@ -4,6 +4,11 @@ package net.sourceforge.pmd.lang.java; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageModuleBase; import net.sourceforge.pmd.lang.LanguageProcessor; @@ -19,9 +24,11 @@ public class JavaLanguageModule extends LanguageModuleBase { public static final String NAME = "Java"; public static final String TERSE_NAME = "java"; + @InternalApi + public static final List EXTENSIONS = listOf("java"); public JavaLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("java") + super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions(EXTENSIONS.get(0)) .addVersion("1.3") .addVersion("1.4") .addVersion("1.5", "5") diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/cpd/EcmascriptLanguage.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/cpd/EcmascriptLanguage.java index 2ad5fd6f41..e7edb068fd 100644 --- a/pmd-javascript/src/main/java/net/sourceforge/pmd/cpd/EcmascriptLanguage.java +++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/cpd/EcmascriptLanguage.java @@ -4,12 +4,15 @@ package net.sourceforge.pmd.cpd; +import net.sourceforge.pmd.lang.ecmascript.EcmascriptLanguageModule; + /** * * @author Zev Blut zb@ubit.com */ public class EcmascriptLanguage extends AbstractLanguage { public EcmascriptLanguage() { - super("JavaScript", "ecmascript", new EcmascriptTokenizer(), ".js"); + super(EcmascriptLanguageModule.NAME, EcmascriptLanguageModule.TERSE_NAME, new EcmascriptTokenizer(), + EcmascriptLanguageModule.EXTENSIONS); } } diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptLanguageModule.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptLanguageModule.java index e73a983d37..9d68ea6b0d 100644 --- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptLanguageModule.java +++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptLanguageModule.java @@ -4,6 +4,11 @@ package net.sourceforge.pmd.lang.ecmascript; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.ecmascript.ast.EcmascriptParser; @@ -14,12 +19,19 @@ import net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase; */ public class EcmascriptLanguageModule extends SimpleLanguageModuleBase { - public static final String NAME = "Ecmascript"; + public static final String NAME = "JavaScript"; public static final String TERSE_NAME = "ecmascript"; + @InternalApi + public static final List EXTENSIONS = listOf("js"); public EcmascriptLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("js") - .addDefaultVersion("ES6"), + super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions(EXTENSIONS) + .addVersion("3") + .addVersion("5") + .addVersion("6", "ES6", "ES2015") + .addVersion("7", "ES2016") + .addVersion("8", "ES2017") + .addDefaultVersion("9", "ES2018"), properties -> () -> new EcmascriptParser(properties)); } diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParser.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParser.java index bb80c84d5b..6f6c00b5f8 100644 --- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParser.java +++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParser.java @@ -18,6 +18,7 @@ import org.mozilla.javascript.ast.ErrorCollector; import org.mozilla.javascript.ast.ParseProblem; import net.sourceforge.pmd.lang.LanguagePropertyBundle; +import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.ast.AstInfo; import net.sourceforge.pmd.lang.ast.FileAnalysisException; import net.sourceforge.pmd.lang.ast.ParseException; @@ -30,11 +31,11 @@ public final class EcmascriptParser implements net.sourceforge.pmd.lang.ast.Pars this.properties = properties; } - private AstRoot parseEcmascript(final String sourceCode, final List parseProblems) throws ParseException { + private AstRoot parseEcmascript(final String sourceCode, final LanguageVersion version, final List parseProblems) throws ParseException { final CompilerEnvirons compilerEnvirons = new CompilerEnvirons(); compilerEnvirons.setRecordingComments(true); compilerEnvirons.setRecordingLocalJsDocComments(true); - compilerEnvirons.setLanguageVersion(Context.VERSION_ES6); + compilerEnvirons.setLanguageVersion(determineRhinoLanguageVersion(version)); // Scope's don't appear to get set right without this compilerEnvirons.setIdeMode(true); compilerEnvirons.setWarnTrailingComma(true); @@ -52,10 +53,19 @@ public final class EcmascriptParser implements net.sourceforge.pmd.lang.ast.Pars return astRoot; } + private static int determineRhinoLanguageVersion(LanguageVersion version) { + switch (version.getVersion()) { + case "3": return Context.VERSION_1_5; + case "5": return Context.VERSION_1_8; + default: return Context.VERSION_ES6; + } + } + @Override public RootNode parse(ParserTask task) throws FileAnalysisException { + final LanguageVersion version = task.getLanguageVersion(); final List parseProblems = new ArrayList<>(); - final AstRoot astRoot = parseEcmascript(task.getSourceText(), parseProblems); + final AstRoot astRoot = parseEcmascript(task.getSourceText(), version, parseProblems); final EcmascriptTreeBuilder treeBuilder = new EcmascriptTreeBuilder(parseProblems); ASTAstRoot tree = (ASTAstRoot) treeBuilder.build(astRoot); diff --git a/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/LanguageVersionTest.java b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/LanguageVersionTest.java index 5df250aff5..73a35e13db 100644 --- a/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/LanguageVersionTest.java +++ b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/LanguageVersionTest.java @@ -13,7 +13,7 @@ class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { return Arrays.asList( - new TestDescriptor(EcmascriptLanguageModule.NAME, EcmascriptLanguageModule.TERSE_NAME, "ES6", + new TestDescriptor(EcmascriptLanguageModule.NAME, EcmascriptLanguageModule.TERSE_NAME, "9", getLanguage(EcmascriptLanguageModule.NAME).getDefaultVersion())); } } diff --git a/pmd-jsp/src/main/java/net/sourceforge/pmd/cpd/JSPLanguage.java b/pmd-jsp/src/main/java/net/sourceforge/pmd/cpd/JSPLanguage.java index c4c480cecc..26b2ef171d 100644 --- a/pmd-jsp/src/main/java/net/sourceforge/pmd/cpd/JSPLanguage.java +++ b/pmd-jsp/src/main/java/net/sourceforge/pmd/cpd/JSPLanguage.java @@ -4,8 +4,10 @@ package net.sourceforge.pmd.cpd; +import net.sourceforge.pmd.lang.jsp.JspLanguageModule; + public class JSPLanguage extends AbstractLanguage { public JSPLanguage() { - super("JSP", "jsp", new JSPTokenizer(), ".jsp", ".jspx", ".jspf", ".tag"); + super(JspLanguageModule.NAME, JspLanguageModule.TERSE_NAME, new JSPTokenizer(), JspLanguageModule.EXTENSIONS); } } diff --git a/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/JspLanguageModule.java b/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/JspLanguageModule.java index 573a42b94c..09741a8d67 100644 --- a/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/JspLanguageModule.java +++ b/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/JspLanguageModule.java @@ -4,6 +4,11 @@ package net.sourceforge.pmd.lang.jsp; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase; /** @@ -13,10 +18,14 @@ public class JspLanguageModule extends SimpleLanguageModuleBase { public static final String NAME = "Java Server Pages"; public static final String TERSE_NAME = "jsp"; + @InternalApi + public static final List EXTENSIONS = listOf("jsp", "jspx", "jspf", "tag"); public JspLanguageModule() { super(LanguageMetadata.withId(TERSE_NAME).name(NAME).shortName("JSP") - .extensions("jsp", "jspx", "jspf", "tag"), + .extensions(EXTENSIONS) + .addVersion("2") + .addDefaultVersion("3"), new JspHandler()); } diff --git a/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/LanguageVersionTest.java b/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/LanguageVersionTest.java index 4707c22101..ed81a65e96 100644 --- a/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/LanguageVersionTest.java +++ b/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/LanguageVersionTest.java @@ -12,7 +12,7 @@ import net.sourceforge.pmd.AbstractLanguageVersionTest; class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { - return Arrays.asList(new TestDescriptor(JspLanguageModule.NAME, JspLanguageModule.TERSE_NAME, "", + return Arrays.asList(new TestDescriptor(JspLanguageModule.NAME, JspLanguageModule.TERSE_NAME, "3", getLanguage(JspLanguageModule.NAME).getDefaultVersion())); } } diff --git a/pmd-kotlin/src/main/java/net/sourceforge/pmd/cpd/KotlinLanguage.java b/pmd-kotlin/src/main/java/net/sourceforge/pmd/cpd/KotlinLanguage.java index 4a14aa766f..1ec0e63349 100644 --- a/pmd-kotlin/src/main/java/net/sourceforge/pmd/cpd/KotlinLanguage.java +++ b/pmd-kotlin/src/main/java/net/sourceforge/pmd/cpd/KotlinLanguage.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.cpd; +import net.sourceforge.pmd.lang.kotlin.KotlinLanguageModule; + /** * Language implementation for Kotlin */ @@ -13,6 +15,6 @@ public class KotlinLanguage extends AbstractLanguage { * Creates a new Kotlin Language instance. */ public KotlinLanguage() { - super("Kotlin", "kotlin", new KotlinTokenizer(), ".kt"); + super(KotlinLanguageModule.NAME, KotlinLanguageModule.TERSE_NAME, new KotlinTokenizer(), KotlinLanguageModule.EXTENSIONS); } } diff --git a/pmd-kotlin/src/main/java/net/sourceforge/pmd/lang/kotlin/KotlinLanguageModule.java b/pmd-kotlin/src/main/java/net/sourceforge/pmd/lang/kotlin/KotlinLanguageModule.java index 31e0d209d4..6faf72c06b 100644 --- a/pmd-kotlin/src/main/java/net/sourceforge/pmd/lang/kotlin/KotlinLanguageModule.java +++ b/pmd-kotlin/src/main/java/net/sourceforge/pmd/lang/kotlin/KotlinLanguageModule.java @@ -4,7 +4,12 @@ package net.sourceforge.pmd.lang.kotlin; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + import net.sourceforge.pmd.annotation.Experimental; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase; /** @@ -20,13 +25,17 @@ public class KotlinLanguageModule extends SimpleLanguageModuleBase { /** The terse name. */ public static final String TERSE_NAME = "kotlin"; + @InternalApi + public static final List EXTENSIONS = listOf("kt", "ktm"); + /** * Create a new instance of Kotlin Language Module. */ public KotlinLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("kt", "ktm") - .addDefaultVersion("1.6-rfc+0.1", "1.6"), + super(LanguageMetadata.withId(TERSE_NAME).name(NAME) + .extensions(EXTENSIONS) + .addVersion("1.6") + .addDefaultVersion("1.7"), new KotlinHandler()); - } } diff --git a/pmd-kotlin/src/test/java/net/sourceforge/pmd/lang/kotlin/LanguageVersionTest.java b/pmd-kotlin/src/test/java/net/sourceforge/pmd/lang/kotlin/LanguageVersionTest.java index 9417c8b537..5a6956aa8e 100644 --- a/pmd-kotlin/src/test/java/net/sourceforge/pmd/lang/kotlin/LanguageVersionTest.java +++ b/pmd-kotlin/src/test/java/net/sourceforge/pmd/lang/kotlin/LanguageVersionTest.java @@ -13,9 +13,7 @@ class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { return Arrays.asList( - new TestDescriptor(KotlinLanguageModule.NAME, KotlinLanguageModule.TERSE_NAME, "1.6-rfc+0.1", - getLanguage(KotlinLanguageModule.NAME).getDefaultVersion()), - new TestDescriptor(KotlinLanguageModule.NAME, KotlinLanguageModule.TERSE_NAME, "1.6", + new TestDescriptor(KotlinLanguageModule.NAME, KotlinLanguageModule.TERSE_NAME, "1.7", getLanguage(KotlinLanguageModule.NAME).getDefaultVersion())); } } diff --git a/pmd-modelica/src/main/java/net/sourceforge/pmd/cpd/ModelicaLanguage.java b/pmd-modelica/src/main/java/net/sourceforge/pmd/cpd/ModelicaLanguage.java index 53852955e5..c7c5a58b2c 100644 --- a/pmd-modelica/src/main/java/net/sourceforge/pmd/cpd/ModelicaLanguage.java +++ b/pmd-modelica/src/main/java/net/sourceforge/pmd/cpd/ModelicaLanguage.java @@ -8,6 +8,6 @@ import net.sourceforge.pmd.lang.modelica.ModelicaLanguageModule; public class ModelicaLanguage extends AbstractLanguage { public ModelicaLanguage() { - super(ModelicaLanguageModule.NAME, ModelicaLanguageModule.TERSE_NAME, new ModelicaTokenizer(), ".mo"); + super(ModelicaLanguageModule.NAME, ModelicaLanguageModule.TERSE_NAME, new ModelicaTokenizer(), ModelicaLanguageModule.EXTENSIONS); } } diff --git a/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/ModelicaLanguageModule.java b/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/ModelicaLanguageModule.java index 2746c21363..d43ef71c24 100644 --- a/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/ModelicaLanguageModule.java +++ b/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/ModelicaLanguageModule.java @@ -4,14 +4,24 @@ package net.sourceforge.pmd.lang.modelica; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase; public class ModelicaLanguageModule extends SimpleLanguageModuleBase { public static final String NAME = "Modelica"; public static final String TERSE_NAME = "modelica"; + @InternalApi + public static final List EXTENSIONS = listOf("mo"); public ModelicaLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("mo"), + super(LanguageMetadata.withId(TERSE_NAME).name(NAME) + .extensions(EXTENSIONS) + .addVersion("3.4") + .addDefaultVersion("3.5"), new ModelicaHandler()); } diff --git a/pmd-modelica/src/test/java/net/sourceforge/pmd/lang/modelica/LanguageVersionTest.java b/pmd-modelica/src/test/java/net/sourceforge/pmd/lang/modelica/LanguageVersionTest.java index 367e843585..f06c1c8a1a 100644 --- a/pmd-modelica/src/test/java/net/sourceforge/pmd/lang/modelica/LanguageVersionTest.java +++ b/pmd-modelica/src/test/java/net/sourceforge/pmd/lang/modelica/LanguageVersionTest.java @@ -12,7 +12,7 @@ import net.sourceforge.pmd.AbstractLanguageVersionTest; class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { - return Arrays.asList(new TestDescriptor(ModelicaLanguageModule.NAME, ModelicaLanguageModule.TERSE_NAME, "", + return Arrays.asList(new TestDescriptor(ModelicaLanguageModule.NAME, ModelicaLanguageModule.TERSE_NAME, "3.5", getLanguage(ModelicaLanguageModule.NAME).getDefaultVersion())); } } diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/cpd/PLSQLLanguage.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/cpd/PLSQLLanguage.java index 5331ec9f72..3a744e12ae 100755 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/cpd/PLSQLLanguage.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/cpd/PLSQLLanguage.java @@ -6,22 +6,15 @@ package net.sourceforge.pmd.cpd; import java.util.Properties; +import net.sourceforge.pmd.lang.plsql.PLSQLLanguageModule; + /** * * @author Stuart Turton sturton@users.sourceforge.net */ public class PLSQLLanguage extends AbstractLanguage { public PLSQLLanguage() { - super("PL/SQL", "plsql", new PLSQLTokenizer(), - ".sql", - ".trg", // Triggers - ".prc", ".fnc", // Standalone Procedures and Functions - ".pld", // Oracle*Forms - ".pls", ".plh", ".plb", // Packages - ".pck", ".pks", ".pkh", ".pkb", // Packages - ".typ", ".tyb", // Object Types - ".tps", ".tpb" // Object Types - ); + super(PLSQLLanguageModule.NAME, PLSQLLanguageModule.TERSE_NAME, new PLSQLTokenizer(), PLSQLLanguageModule.EXTENSIONS); } @Override diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLLanguageModule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLLanguageModule.java index 0b74d631c2..81d1d3b929 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLLanguageModule.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLLanguageModule.java @@ -4,6 +4,11 @@ package net.sourceforge.pmd.lang.plsql; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase; /** @@ -13,21 +18,29 @@ public class PLSQLLanguageModule extends SimpleLanguageModuleBase { public static final String NAME = "PLSQL"; public static final String TERSE_NAME = "plsql"; + @InternalApi + public static final List EXTENSIONS = listOf( + "sql", + "trg", // Triggers + "prc", "fnc", // Standalone Procedures and Functions + "pld", // Oracle*Forms + "pls", "plh", "plb", // Packages + "pck", "pks", "pkh", "pkb", // Packages + "typ", "tyb", // Object Types + "tps", "tpb" // Object Types + ); public PLSQLLanguageModule() { super( LanguageMetadata.withId(TERSE_NAME) .name(NAME) - .extensions( - "sql", - "trg", // Triggers - "prc", "fnc", // Standalone Procedures and Functions - "pld", // Oracle*Forms - "pls", "plh", "plb", // Packages - "pck", "pks", "pkh", "pkb", // Packages - "typ", "tyb", // Object Types - "tps", "tpb" // Object Types - ), + .extensions(EXTENSIONS) + .addVersion("11g") + .addVersion("12c_Release_1", "12.1") + .addVersion("12c_Release_2", "12.2") + .addVersion("18c") + .addVersion("19c") + .addDefaultVersion("21c"), new PLSQLHandler() ); } diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/LanguageVersionTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/LanguageVersionTest.java index f28d58964e..886b4c5fe5 100644 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/LanguageVersionTest.java +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/LanguageVersionTest.java @@ -12,7 +12,7 @@ import net.sourceforge.pmd.AbstractLanguageVersionTest; class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { - return Arrays.asList(new TestDescriptor(PLSQLLanguageModule.NAME, PLSQLLanguageModule.TERSE_NAME, "", + return Arrays.asList(new TestDescriptor(PLSQLLanguageModule.NAME, PLSQLLanguageModule.TERSE_NAME, "21c", getLanguage(PLSQLLanguageModule.NAME).getDefaultVersion())); } } diff --git a/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/cpd/ScalaLanguage.java b/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/cpd/ScalaLanguage.java index fd1f1b6da9..fe1e4c6f03 100644 --- a/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/cpd/ScalaLanguage.java +++ b/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/cpd/ScalaLanguage.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.cpd; +import net.sourceforge.pmd.lang.scala.ScalaLanguageModule; + /** * Language implementation for Scala. */ @@ -13,6 +15,6 @@ public class ScalaLanguage extends AbstractLanguage { * Creates a new Scala Language instance. */ public ScalaLanguage() { - super("Scala", "scala", new ScalaTokenizer(), ".scala"); + super(ScalaLanguageModule.NAME, ScalaLanguageModule.TERSE_NAME, new ScalaTokenizer(), ScalaLanguageModule.EXTENSIONS); } } diff --git a/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/lang/scala/ScalaLanguageModule.java b/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/lang/scala/ScalaLanguageModule.java index 1825eec5c6..1507c4716d 100644 --- a/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/lang/scala/ScalaLanguageModule.java +++ b/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/lang/scala/ScalaLanguageModule.java @@ -4,6 +4,10 @@ package net.sourceforge.pmd.lang.scala; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + import org.checkerframework.checker.nullness.qual.NonNull; import net.sourceforge.pmd.annotation.InternalApi; @@ -24,11 +28,15 @@ public class ScalaLanguageModule extends SimpleLanguageModuleBase { /** The terse name. */ public static final String TERSE_NAME = "scala"; + @InternalApi + public static final List EXTENSIONS = listOf("scala"); + /** * Create a new instance of Scala Language Module. */ public ScalaLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("scala") + super(LanguageMetadata.withId(TERSE_NAME).name(NAME) + .extensions(EXTENSIONS) .addVersion("2.10") .addVersion("2.11") .addVersion("2.12") diff --git a/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftLanguage.java b/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftLanguage.java index 841e0861fd..297f27cf24 100644 --- a/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftLanguage.java +++ b/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftLanguage.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.cpd; +import net.sourceforge.pmd.lang.swift.SwiftLanguageModule; + /** * Language implementation for Swift */ @@ -13,6 +15,6 @@ public class SwiftLanguage extends AbstractLanguage { * Creates a new Swift Language instance. */ public SwiftLanguage() { - super("Swift", "swift", new SwiftTokenizer(), ".swift"); + super(SwiftLanguageModule.NAME, SwiftLanguageModule.TERSE_NAME, new SwiftTokenizer(), SwiftLanguageModule.EXTENSIONS); } } diff --git a/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java b/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java index 1b05e94b4b..a2c3192477 100644 --- a/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java +++ b/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java @@ -4,6 +4,11 @@ package net.sourceforge.pmd.lang.swift; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase; /** @@ -16,10 +21,24 @@ public class SwiftLanguageModule extends SimpleLanguageModuleBase { /** The terse name. */ public static final String TERSE_NAME = "swift"; + @InternalApi + public static final List EXTENSIONS = listOf("swift"); + /** * Create a new instance of Swift Language Module. */ public SwiftLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("swift"), new SwiftHandler()); + super(LanguageMetadata.withId(TERSE_NAME).name(NAME) + .extensions(EXTENSIONS) + .addVersion("4.2") + .addVersion("5.0") + .addVersion("5.1") + .addVersion("5.2") + .addVersion("5.3") + .addVersion("5.4") + .addVersion("5.5") + .addVersion("5.6") + .addDefaultVersion("5.7"), + new SwiftHandler()); } } diff --git a/pmd-swift/src/test/java/net/sourceforge/pmd/lang/swift/LanguageVersionTest.java b/pmd-swift/src/test/java/net/sourceforge/pmd/lang/swift/LanguageVersionTest.java index e56e9f3ca9..9f5302ba72 100644 --- a/pmd-swift/src/test/java/net/sourceforge/pmd/lang/swift/LanguageVersionTest.java +++ b/pmd-swift/src/test/java/net/sourceforge/pmd/lang/swift/LanguageVersionTest.java @@ -12,7 +12,7 @@ import net.sourceforge.pmd.AbstractLanguageVersionTest; class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { - return Arrays.asList(new TestDescriptor(SwiftLanguageModule.NAME, SwiftLanguageModule.TERSE_NAME, "", + return Arrays.asList(new TestDescriptor(SwiftLanguageModule.NAME, SwiftLanguageModule.TERSE_NAME, "5.7", getLanguage(SwiftLanguageModule.NAME).getDefaultVersion())); } } diff --git a/pmd-visualforce/src/main/java/net/sourceforge/pmd/cpd/VfLanguage.java b/pmd-visualforce/src/main/java/net/sourceforge/pmd/cpd/VfLanguage.java index 301bfc15c3..5551e91a5d 100644 --- a/pmd-visualforce/src/main/java/net/sourceforge/pmd/cpd/VfLanguage.java +++ b/pmd-visualforce/src/main/java/net/sourceforge/pmd/cpd/VfLanguage.java @@ -4,12 +4,14 @@ package net.sourceforge.pmd.cpd; +import net.sourceforge.pmd.lang.vf.VfLanguageModule; + /** * @author sergey.gorbaty * */ public class VfLanguage extends AbstractLanguage { public VfLanguage() { - super("VisualForce", "vf", new VfTokenizer(), ".page", ".component"); + super(VfLanguageModule.NAME, VfLanguageModule.TERSE_NAME, new VfTokenizer(), VfLanguageModule.EXTENSIONS); } } diff --git a/pmd-visualforce/src/main/java/net/sourceforge/pmd/lang/vf/VfLanguageModule.java b/pmd-visualforce/src/main/java/net/sourceforge/pmd/lang/vf/VfLanguageModule.java index b75d9ffba6..e43738df99 100644 --- a/pmd-visualforce/src/main/java/net/sourceforge/pmd/lang/vf/VfLanguageModule.java +++ b/pmd-visualforce/src/main/java/net/sourceforge/pmd/lang/vf/VfLanguageModule.java @@ -4,13 +4,18 @@ package net.sourceforge.pmd.lang.vf; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguagePropertyBundle; import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.apex.ApexLanguageModule; import net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase; - /** * @author sergey.gorbaty */ @@ -18,14 +23,32 @@ public class VfLanguageModule extends SimpleLanguageModuleBase { public static final String NAME = "Salesforce VisualForce"; public static final String TERSE_NAME = "vf"; + @InternalApi + public static final List EXTENSIONS = listOf("page", "component"); public VfLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME) - .extensions("page", "component") - .dependsOnLanguage(ApexLanguageModule.TERSE_NAME), + super(createMetdata(), p -> new VfHandler((VfLanguageProperties) p)); } + private static LanguageMetadata createMetdata() { + LanguageMetadata languageMetadata = + LanguageMetadata.withId(TERSE_NAME).name(NAME) + .extensions(EXTENSIONS) + .dependsOnLanguage(ApexLanguageModule.TERSE_NAME); + // use the same versions as in Apex + // need to create a temporary apex module, since the global language registry is not initialized yet + ApexLanguageModule temporaryApexModule = new ApexLanguageModule(); + LanguageVersion defaultApexVersion = temporaryApexModule.getDefaultVersion(); + for (LanguageVersion languageVersion : temporaryApexModule.getVersions()) { + if (!defaultApexVersion.equals(languageVersion)) { + languageMetadata.addVersion(languageVersion.getVersion()); + } + } + languageMetadata.addDefaultVersion(defaultApexVersion.getVersion()); + return languageMetadata; + } + @Override public LanguagePropertyBundle newPropertyBundle() { return new VfLanguageProperties(); diff --git a/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/LanguageVersionTest.java b/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/LanguageVersionTest.java index 141d62ed8c..38c68b028a 100644 --- a/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/LanguageVersionTest.java +++ b/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/LanguageVersionTest.java @@ -8,11 +8,13 @@ import java.util.Arrays; import java.util.Collection; import net.sourceforge.pmd.AbstractLanguageVersionTest; +import net.sourceforge.pmd.lang.apex.ApexLanguageModule; class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { - return Arrays.asList(new TestDescriptor(VfLanguageModule.NAME, VfLanguageModule.TERSE_NAME, "", - getLanguage(VfLanguageModule.NAME).getDefaultVersion())); + return Arrays.asList(new TestDescriptor(VfLanguageModule.NAME, VfLanguageModule.TERSE_NAME, + ApexLanguageModule.getInstance().getDefaultVersion().getVersion(), + getLanguage(VfLanguageModule.NAME).getDefaultVersion())); } } diff --git a/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/VmLanguageModule.java b/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/VmLanguageModule.java index 553fb8a4e8..0cc028c236 100644 --- a/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/VmLanguageModule.java +++ b/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/VmLanguageModule.java @@ -15,7 +15,13 @@ public class VmLanguageModule extends SimpleLanguageModuleBase { public static final String TERSE_NAME = "vm"; public VmLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("vm"), new VmHandler()); + super(LanguageMetadata.withId(TERSE_NAME).name(NAME) + .extensions("vm") + .addVersion("2.0") + .addVersion("2.1") + .addVersion("2.2") + .addDefaultVersion("2.3"), + new VmHandler()); } } diff --git a/pmd-vm/src/test/java/net/sourceforge/pmd/lang/vm/LanguageVersionTest.java b/pmd-vm/src/test/java/net/sourceforge/pmd/lang/vm/LanguageVersionTest.java index 2e5645fc11..32f4877901 100644 --- a/pmd-vm/src/test/java/net/sourceforge/pmd/lang/vm/LanguageVersionTest.java +++ b/pmd-vm/src/test/java/net/sourceforge/pmd/lang/vm/LanguageVersionTest.java @@ -12,7 +12,7 @@ import net.sourceforge.pmd.AbstractLanguageVersionTest; class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { - return Arrays.asList(new TestDescriptor(VmLanguageModule.NAME, VmLanguageModule.TERSE_NAME, "", + return Arrays.asList(new TestDescriptor(VmLanguageModule.NAME, VmLanguageModule.TERSE_NAME, "2.3", getLanguage(VmLanguageModule.NAME).getDefaultVersion())); } } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/pom/PomLanguageModule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/pom/PomLanguageModule.java index 7de4d4da0b..9f91051657 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/pom/PomLanguageModule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/pom/PomLanguageModule.java @@ -12,7 +12,10 @@ public class PomLanguageModule extends SimpleLanguageModuleBase { public static final String TERSE_NAME = "pom"; public PomLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("pom"), new XmlHandler()); + super(LanguageMetadata.withId(TERSE_NAME).name(NAME) + .extensions("pom") + .addDefaultVersion("4.0.0"), + new XmlHandler()); } } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/wsdl/WsdlLanguageModule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/wsdl/WsdlLanguageModule.java index ed9512d1cb..f48d4c9ddd 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/wsdl/WsdlLanguageModule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/wsdl/WsdlLanguageModule.java @@ -15,7 +15,11 @@ public class WsdlLanguageModule extends SimpleLanguageModuleBase { public static final String TERSE_NAME = "wsdl"; public WsdlLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("wsdl"), new XmlHandler()); + super(LanguageMetadata.withId(TERSE_NAME).name(NAME) + .extensions("wsdl") + .addVersion("1.1") + .addDefaultVersion("2.0"), + new XmlHandler()); } } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/XmlLanguageModule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/XmlLanguageModule.java index 5df4a35b06..b0ab3d3b00 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/XmlLanguageModule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/XmlLanguageModule.java @@ -4,6 +4,11 @@ package net.sourceforge.pmd.lang.xml; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; + +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase; /** @@ -13,8 +18,14 @@ public class XmlLanguageModule extends SimpleLanguageModuleBase { public static final String NAME = "XML"; public static final String TERSE_NAME = "xml"; + @InternalApi + public static final List EXTENSIONS = listOf("xml"); public XmlLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("xml"), new XmlHandler()); + super(LanguageMetadata.withId(TERSE_NAME).name(NAME) + .extensions(EXTENSIONS) + .addVersion("1.0") + .addDefaultVersion("1.1"), + new XmlHandler()); } } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xsl/XslLanguageModule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xsl/XslLanguageModule.java index c51c48096a..ce0b833b44 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xsl/XslLanguageModule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xsl/XslLanguageModule.java @@ -16,7 +16,12 @@ public class XslLanguageModule extends SimpleLanguageModuleBase { public static final String TERSE_NAME = "xsl"; public XslLanguageModule() { - super(LanguageMetadata.withId(TERSE_NAME).name(NAME).extensions("xsl", "xslt"), new XmlHandler()); + super(LanguageMetadata.withId(TERSE_NAME).name(NAME) + .extensions("xsl", "xslt") + .addVersion("1.0") + .addVersion("2.0") + .addDefaultVersion("3.0"), + new XmlHandler()); } } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/xml/cpd/XmlLanguage.java b/pmd-xml/src/main/java/net/sourceforge/pmd/xml/cpd/XmlLanguage.java index 38b38c8eb3..c5c849a248 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/xml/cpd/XmlLanguage.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/xml/cpd/XmlLanguage.java @@ -5,10 +5,11 @@ package net.sourceforge.pmd.xml.cpd; import net.sourceforge.pmd.cpd.AbstractLanguage; +import net.sourceforge.pmd.lang.xml.XmlLanguageModule; public class XmlLanguage extends AbstractLanguage { public XmlLanguage() { - super("Xml", "xml", new XmlTokenizer(), ".xml"); + super(XmlLanguageModule.NAME, XmlLanguageModule.TERSE_NAME, new XmlTokenizer(), XmlLanguageModule.EXTENSIONS); } } diff --git a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/LanguageVersionTest.java b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/LanguageVersionTest.java index 4e4816f7fb..0654616943 100644 --- a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/LanguageVersionTest.java +++ b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/LanguageVersionTest.java @@ -16,13 +16,13 @@ class LanguageVersionTest extends AbstractLanguageVersionTest { static Collection data() { return Arrays.asList( - new TestDescriptor(XmlLanguageModule.NAME, XmlLanguageModule.TERSE_NAME, "", + new TestDescriptor(XmlLanguageModule.NAME, XmlLanguageModule.TERSE_NAME, "1.1", getLanguage(XmlLanguageModule.NAME).getDefaultVersion()), - new TestDescriptor(XslLanguageModule.NAME, XslLanguageModule.TERSE_NAME, "", + new TestDescriptor(XslLanguageModule.NAME, XslLanguageModule.TERSE_NAME, "3.0", getLanguage(XslLanguageModule.NAME).getDefaultVersion()), - new TestDescriptor(WsdlLanguageModule.NAME, WsdlLanguageModule.TERSE_NAME, "", + new TestDescriptor(WsdlLanguageModule.NAME, WsdlLanguageModule.TERSE_NAME, "2.0", getLanguage(WsdlLanguageModule.NAME).getDefaultVersion()), - new TestDescriptor(PomLanguageModule.NAME, PomLanguageModule.TERSE_NAME, "", + new TestDescriptor(PomLanguageModule.NAME, PomLanguageModule.TERSE_NAME, "4.0.0", getLanguage(PomLanguageModule.NAME).getDefaultVersion())); } } diff --git a/pmd-xml/src/test/resources/net/sourceforge/pmd/ant/xml/pmdtasktest.xml b/pmd-xml/src/test/resources/net/sourceforge/pmd/ant/xml/pmdtasktest.xml index 52ba35fc8c..db7406fb77 100644 --- a/pmd-xml/src/test/resources/net/sourceforge/pmd/ant/xml/pmdtasktest.xml +++ b/pmd-xml/src/test/resources/net/sourceforge/pmd/ant/xml/pmdtasktest.xml @@ -7,7 +7,7 @@ - +