forked from phoedos/pmd
Merge pull request #4387 from adangel/pmd7-language-versions
This commit is contained in:
commit
f2f83576ed
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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")));
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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"));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user