Merge pull request #4387 from adangel/pmd7-language-versions

This commit is contained in:
Clément Fournier 2023-02-26 23:49:06 +01:00 committed by GitHub
commit f2f83576ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 499 additions and 310 deletions

View File

@ -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:

View File

@ -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

View File

@ -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)

View File

@ -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:
<sourceLanguage name="apex" version="48"/>
<sourceLanguage name="ecmascript" version="3"/>
<sourceLanguage name="java" version="1.3"/>
<sourceLanguage name="java" version="1.4"/>
<sourceLanguage name="java" version="1.5"/>
<sourceLanguage name="java" version="5"/> <!-- alias for 1.5 -->
<sourceLanguage name="java" version="1.6"/>
<sourceLanguage name="java" version="6"/> <!-- alias for 1.6 -->
<sourceLanguage name="java" version="1.7"/>
<sourceLanguage name="java" version="7"/> <!-- alias for 1.7 -->
<sourceLanguage name="java" version="1.8"/>
<sourceLanguage name="java" version="8"/> <!-- alias for 1.8 -->
<sourceLanguage name="java" version="9"/>
<sourceLanguage name="java" version="1.9"/> <!-- alias for 9 -->
<sourceLanguage name="java" version="10"/>
<sourceLanguage name="java" version="1.10"/> <!-- alias for 10 -->
<sourceLanguage name="java" version="11"/>
<sourceLanguage name="java" version="12"/>
<sourceLanguage name="java" version="13"/>
<sourceLanguage name="java" version="14"/>
<sourceLanguage name="java" version="15"/>
<sourceLanguage name="java" version="16"/>
<sourceLanguage name="java" version="17"/>
<sourceLanguage name="java" version="18"/>
<sourceLanguage name="java" version="19"/>
<sourceLanguage name="java" version="19-preview"/>
<sourceLanguage name="java" version="20"/> <!-- this is the default -->
<sourceLanguage name="java" version="20-preview"/>
<sourceLanguage name="jsp" version=""/>
<sourceLanguage name="modelica" version=""/>
<sourceLanguage name="pom" version=""/>
<sourceLanguage name="plsql" version=""/>
<sourceLanguage name="scala" version="2.10"/>
<sourceLanguage name="scala" version="2.11"/>
<sourceLanguage name="scala" version="2.12"/>
<sourceLanguage name="scala" version="2.13"/> <!-- this is the default -->
<sourceLanguage name="vf" version=""/>
<sourceLanguage name="vm" version=""/>
<sourceLanguage name="wsdl" version=""/>
<sourceLanguage name="xml" version=""/>
<sourceLanguage name="xsl" version=""/>
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

View File

@ -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);
}

View File

@ -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<String> 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

View File

@ -12,7 +12,7 @@ import net.sourceforge.pmd.AbstractLanguageVersionTest;
class LanguageVersionTest extends AbstractLanguageVersionTest {
static Collection<TestDescriptor> 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()));
}
}

View File

@ -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<String> 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<String> 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<String> 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

View File

@ -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<String> 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));
}
}

View File

@ -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());
}

View File

@ -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")));

View File

@ -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");

View File

@ -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");
}
}

View File

@ -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"));
}

View File

@ -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<String> 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<String> 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<String> 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, "", "<violation beginline=\"8\" endline=\"10\" begincolumn=\"13\" endcolumn=\"14\" rule=\"JumbledIncrementer\"");
result.assertExitCode(4).assertReport(containsString("JumbledIncrementer.java\">"));
result.assertExitCode(4).assertReport(containsString("<violation beginline=\"8\" endline=\"10\" begincolumn=\"13\" endcolumn=\"14\" rule=\"JumbledIncrementer\""));
}
@Test
void testPmdSample() throws Exception {
ExecutionResult result = PMDExecutor.runPMDRules(createTemporaryReportFile(), tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml");
result.assertExecutionResult(4, "", "JumbledIncrementer.java:8:");
result.assertExitCode(4).assertReport(containsString("JumbledIncrementer.java:8:"));
}
@Test
void testPmdSampleWithZippedSources() throws Exception {
ExecutionResult result = PMDExecutor.runPMDRules(createTemporaryReportFile(), tempDir, srcDir + "/sample-source-java.zip",
"src/test/resources/rulesets/sample-ruleset.xml");
result.assertExecutionResult(4, "", "JumbledIncrementer.java:8:");
result.assertExitCode(4).assertReport(containsString("JumbledIncrementer.java:8:"));
}
@Test
void testPmdSampleWithJarredSources() throws Exception {
ExecutionResult result = PMDExecutor.runPMDRules(createTemporaryReportFile(), tempDir, srcDir + "/sample-source-java.jar",
"src/test/resources/rulesets/sample-ruleset.xml");
result.assertExecutionResult(4, "", "JumbledIncrementer.java:8:");
result.assertExitCode(4).assertReport(containsString("JumbledIncrementer.java:8:"));
}
@Test
void testPmdHelp() throws Exception {
ExecutionResult result = PMDExecutor.runPMD(null, tempDir, "-h");
result.assertExecutionResult(0, SUPPORTED_LANGUAGES_PMD);
result.assertExitCode(0)
.assertStdOut(matchesRegex(toListPattern(SUPPORTED_LANGUAGES_PMD)));
}
@Test
void testPmdNoArgs() throws Exception {
ExecutionResult result = PMDExecutor.runPMD(null, tempDir); // without any argument, display usage help and error
result.assertExecutionResultErrOutput(2, "Usage: pmd check ");
result.assertExitCode(2).assertStdErr(containsString("Usage: pmd check "));
}
@Test
@ -134,13 +164,13 @@ class BinaryDistributionIT extends AbstractBinaryDistributionTest {
ExecutionResult result;
result = PMDExecutor.runPMD(createTemporaryReportFile(), tempDir, "-d", srcDir, "-R", "src/test/resources/rulesets/sample-ruleset.xml");
result.assertExecutionResult(4);
result.assertExitCode(4);
result.assertErrorOutputContains("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at INFO");
// now with debug
result = PMDExecutor.runPMD(createTemporaryReportFile(), tempDir, "-d", srcDir, "-R", "src/test/resources/rulesets/sample-ruleset.xml", "--debug");
result.assertExecutionResult(4);
result.assertExitCode(4);
result.assertErrorOutputContains("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at TRACE");
}
@ -149,7 +179,8 @@ class BinaryDistributionIT extends AbstractBinaryDistributionTest {
String srcDir = new File(".", "src/test/resources/sample-source/unparsable/").getAbsolutePath();
ExecutionResult result = PMDExecutor.runPMDRules(createTemporaryReportFile(), tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml");
result.assertExecutionResultErrOutput(0, "Run in verbose mode to see a stack-trace.");
result.assertExitCode(0).assertStdErr(containsString("Run in verbose mode to see a stack-trace."));
}
@Test
@ -159,22 +190,30 @@ class BinaryDistributionIT extends AbstractBinaryDistributionTest {
ExecutionResult result;
result = CpdExecutor.runCpd(tempDir); // without any argument, display usage help and error
result.assertExecutionResultErrOutput(2, "Usage: pmd cpd ");
result.assertExitCode(2).assertStdErr(containsString("Usage: pmd cpd "));
result = CpdExecutor.runCpd(tempDir, "-h");
result.assertExecutionResult(0, SUPPORTED_LANGUAGES_CPD);
result.assertExitCode(0)
.assertStdOut(matchesRegex(toListPattern(SUPPORTED_LANGUAGES_CPD)));
result = CpdExecutor.runCpd(tempDir, "--minimum-tokens", "10", "--format", "text", "--dir", srcDir);
result.assertExecutionResult(4, "Found a 10 line (55 tokens) duplication in the following files:");
result.assertExecutionResult(4, "Class1.java");
result.assertExecutionResult(4, "Class2.java");
result.assertExitCode(4)
.assertStdOut(containsString("Found a 10 line (55 tokens) duplication in the following files:"));
result.assertExitCode(4)
.assertStdOut(containsString("Class1.java"));
result.assertExitCode(4)
.assertStdOut(containsString("Class2.java"));
result = CpdExecutor.runCpd(tempDir, "--minimum-tokens", "10", "--format", "xml", "--dir", srcDir);
result.assertExecutionResult(4, "<duplication lines=\"10\" tokens=\"55\">");
result.assertExecutionResult(4, "Class1.java\"/>");
result.assertExecutionResult(4, "Class2.java\"/>");
result.assertExitCode(4)
.assertStdOut(containsString("<duplication lines=\"10\" tokens=\"55\">"));
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);
}
}

View File

@ -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<String> reportMatcher) {
assertThat("Report", report, reportMatcher);
return this;
}
public ExecutionResult assertStdErr(Matcher<String> matcher) {
assertThat("Standard error", errorOutput, matcher);
return this;
}
public ExecutionResult assertStdOut(Matcher<String> 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) {

View File

@ -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:

View File

@ -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:

View File

@ -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);
}
}

View File

@ -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<String> 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());
}

View File

@ -12,7 +12,7 @@ import net.sourceforge.pmd.AbstractLanguageVersionTest;
class LanguageVersionTest extends AbstractLanguageVersionTest {
static Collection<TestDescriptor> 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()));
}
}

View File

@ -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);
}

View File

@ -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<String> 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")

View File

@ -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);
}
}

View File

@ -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<String> 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));
}

View File

@ -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<ParseProblem> parseProblems) throws ParseException {
private AstRoot parseEcmascript(final String sourceCode, final LanguageVersion version, final List<ParseProblem> 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<ParseProblem> 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);

View File

@ -13,7 +13,7 @@ class LanguageVersionTest extends AbstractLanguageVersionTest {
static Collection<TestDescriptor> data() {
return Arrays.asList(
new TestDescriptor(EcmascriptLanguageModule.NAME, EcmascriptLanguageModule.TERSE_NAME, "ES6",
new TestDescriptor(EcmascriptLanguageModule.NAME, EcmascriptLanguageModule.TERSE_NAME, "9",
getLanguage(EcmascriptLanguageModule.NAME).getDefaultVersion()));
}
}

View File

@ -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);
}
}

View File

@ -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<String> 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());
}

View File

@ -12,7 +12,7 @@ import net.sourceforge.pmd.AbstractLanguageVersionTest;
class LanguageVersionTest extends AbstractLanguageVersionTest {
static Collection<TestDescriptor> 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()));
}
}

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