forked from phoedos/pmd
Cleanup some TODOs
This commit is contained in:
@ -150,7 +150,6 @@ public class Formatter {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
// FIXME - hm, what about this consoleRenderer thing... need a test for this
|
||||
Renderer createRenderer() {
|
||||
if (StringUtils.isBlank(type)) {
|
||||
throw new BuildException(unknownRendererMessage("<unspecified>"));
|
||||
|
@ -4,13 +4,22 @@
|
||||
|
||||
package net.sourceforge.pmd.ant;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import net.sourceforge.pmd.internal.util.IOUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Romain Pelisse <belaran@gmail.com>
|
||||
@ -24,10 +33,13 @@ class CPDTaskTest extends AbstractAntTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBasic() {
|
||||
void testBasic() throws IOException {
|
||||
executeTarget("testBasic");
|
||||
// FIXME: This clearly needs to be improved - but I don't like to write
|
||||
// test, so feel free to contribute :)
|
||||
assertTrue(new File("target/cpd.ant.tests").exists());
|
||||
Path report = Paths.get("target/cpd.ant.tests");
|
||||
assertTrue(Files.exists(report), "Report was not created");
|
||||
String reportContent = IOUtil.readFileToString(report.toFile(), StandardCharsets.UTF_8);
|
||||
assertThat(reportContent, containsString("Found a 1 line (21 tokens) duplication in the following files:"));
|
||||
assertThat(reportContent, containsString("sample.dummy"));
|
||||
assertThat(reportContent, containsString("sample2.dummy"));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
Content does not matter as long as the extension is "dummy", so that the DummyLanguageModule/Parser is used.
|
@ -1,7 +1,7 @@
|
||||
<project name="pmdtasktest" default="all">
|
||||
|
||||
<property name="pmd.home" value="${user.dir}"/>
|
||||
<property name="src" value="src/main/java"/>
|
||||
<property name="src" value="src/test/resources/net/sourceforge/pmd/ant/src"/>
|
||||
|
||||
<taskdef name="cpd" classname="net.sourceforge.pmd.ant.CPDTask"/>
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
|
||||
<target name="testBasic">
|
||||
<cpd minimumTokenCount="20" outputFile="${pmd.home}/target/cpd.ant.tests" language="dummy">
|
||||
<fileset dir="${pmd.home}/src/main/">
|
||||
<include name="**/*.java"/>
|
||||
<fileset dir="${pmd.home}/${src}">
|
||||
<include name="**/*.dummy"/>
|
||||
</fileset>
|
||||
</cpd>
|
||||
</target>
|
||||
|
@ -8,4 +8,12 @@ Test Rule 2
|
||||
Test Rule 3
|
||||
</violation>
|
||||
</file>
|
||||
<file name="sample2.dummy">
|
||||
<violation beginline="1" endline="1" begincolumn="1" endcolumn="110" rule="SampleXPathRule" ruleset="Test Ruleset" package="foo" externalInfoUrl="${pmd.website.baseurl}/rules/dummy/basic.xml#SampleXPathRule" priority="3">
|
||||
Test Rule 2
|
||||
</violation>
|
||||
<violation beginline="1" endline="1" begincolumn="1" endcolumn="110" rule="DeprecatedRule" ruleset="Test Ruleset" package="foo" externalInfoUrl="${pmd.website.baseurl}/rules/dummy/basic.xml#deprecatedrule" priority="3">
|
||||
Test Rule 3
|
||||
</violation>
|
||||
</file>
|
||||
</pmd>
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.sourceforge.pmd.lang.LanguagePropertyBundle;
|
||||
import net.sourceforge.pmd.properties.PropertyDescriptor;
|
||||
import net.sourceforge.pmd.properties.PropertyFactory;
|
||||
@ -13,11 +15,11 @@ import net.sourceforge.pmd.properties.PropertyFactory;
|
||||
*/
|
||||
public class ApexLanguageProperties extends LanguagePropertyBundle {
|
||||
|
||||
// todo change that to optional<file> when properties are updated
|
||||
public static final PropertyDescriptor<String> MULTIFILE_DIRECTORY =
|
||||
public static final PropertyDescriptor<Optional<String>> MULTIFILE_DIRECTORY =
|
||||
PropertyFactory.stringProperty("rootDirectory")
|
||||
.desc("The root directory of the Salesforce metadata, where `sfdx-project.json` resides.")
|
||||
.defaultValue("") // is this ok?
|
||||
.toOptional("")
|
||||
.build();
|
||||
|
||||
public ApexLanguageProperties() {
|
||||
|
@ -4,9 +4,12 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@ -16,6 +19,7 @@ import java.util.stream.Collectors;
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public final class ApexQualifiedName {
|
||||
private static final Pattern QUALIFIED_NAME_PATTERN = Pattern.compile("(?<class1>\\w+)(?:.(?<class2>\\w+))?(?:#(?<operation>\\w+\\(.*\\)))?");
|
||||
|
||||
private final String[] classes;
|
||||
private final String operation;
|
||||
@ -105,7 +109,6 @@ public final class ApexQualifiedName {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a string conforming to the format defined below and returns an ApexQualifiedName.
|
||||
*
|
||||
@ -119,9 +122,17 @@ public final class ApexQualifiedName {
|
||||
*
|
||||
* @return An ApexQualifiedName, or null if the string couldn't be parsed
|
||||
*/
|
||||
// private static final Pattern FORMAT = Pattern.compile("(\\w+)(.(\\w+))?(#(\\w+))?"); // TODO
|
||||
public static ApexQualifiedName ofString(String toParse) {
|
||||
throw new UnsupportedOperationException();
|
||||
Matcher matcher = QUALIFIED_NAME_PATTERN.matcher(toParse);
|
||||
if (matcher.matches()) {
|
||||
List<String> classNames = new ArrayList<>();
|
||||
classNames.add(matcher.group("class1"));
|
||||
if (matcher.group("class2") != null) {
|
||||
classNames.add(matcher.group("class2"));
|
||||
}
|
||||
return new ApexQualifiedName(classNames.toArray(new String[0]), matcher.group("operation"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,6 +10,7 @@ import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
@ -52,20 +53,20 @@ public final class ApexMultifileAnalysis {
|
||||
|
||||
|
||||
ApexMultifileAnalysis(ApexLanguageProperties properties) {
|
||||
String rootDir = properties.getProperty(ApexLanguageProperties.MULTIFILE_DIRECTORY);
|
||||
Optional<String> rootDir = properties.getProperty(ApexLanguageProperties.MULTIFILE_DIRECTORY);
|
||||
LOG.debug("MultiFile Analysis created for {}", rootDir);
|
||||
|
||||
Org org = null;
|
||||
try {
|
||||
// Load the package into the org, this can take some time!
|
||||
if (rootDir != null && !rootDir.isEmpty()) {
|
||||
Path projectPath = Paths.get(rootDir);
|
||||
if (rootDir.isPresent() && !rootDir.get().isEmpty()) {
|
||||
Path projectPath = Paths.get(rootDir.get());
|
||||
Path sfdxProjectJson = projectPath.resolve("sfdx-project.json");
|
||||
|
||||
// Limit analysis to SFDX Projects
|
||||
// MDAPI analysis is currently supported but is expected to be deprecated soon
|
||||
if (Files.isDirectory(projectPath) && Files.isRegularFile(sfdxProjectJson)) {
|
||||
org = Org.newOrg(rootDir);
|
||||
org = Org.newOrg(rootDir.get());
|
||||
|
||||
// FIXME: Syntax & Semantic errors found during Org loading are not currently being reported. These
|
||||
// should be routed to the new SemanticErrorReporter but that is not available for use just yet.
|
||||
|
@ -4,9 +4,11 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.ast;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
@ -114,4 +116,24 @@ class ApexQualifiedNameTest extends ApexParserTestBase {
|
||||
assertTrue(m.getQualifiedName().toString().startsWith("Outer.Inner#"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOfString() {
|
||||
assertQualifiedName(new String[] { "MyClass" }, true, null, ApexQualifiedName.ofString("MyClass"));
|
||||
assertQualifiedName(new String[] { "Outer", "MyClass" }, true, null, ApexQualifiedName.ofString("Outer.MyClass"));
|
||||
assertQualifiedName(new String[] { "Foo" }, false, "foo(String, Foo)", ApexQualifiedName.ofString("Foo#foo(String, Foo)"));
|
||||
}
|
||||
|
||||
private static void assertQualifiedName(String[] expectedClasses, boolean isClass, String expectedOperation, ApexQualifiedName name) {
|
||||
assertArrayEquals(expectedClasses, name.getClasses());
|
||||
assertEquals(isClass, name.isClass());
|
||||
assertEquals(!isClass, name.isOperation());
|
||||
assertEquals(expectedOperation, name.getOperation());
|
||||
|
||||
if (isClass) {
|
||||
assertSame(name, name.getClassName());
|
||||
} else {
|
||||
assertArrayEquals(expectedClasses, name.getClassName().getClasses());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -64,16 +65,12 @@ class ApexMultifileAnalysisTest {
|
||||
assertFalse(analysisInstance.isFailed());
|
||||
});
|
||||
|
||||
// TODO: log is not empty due to ANTLR versions, 4.9.1 vs 4.8, expect to resolve with apex-dev-tools switch
|
||||
log = log.replace("ANTLR Tool version 4.8 used for code generation does not match the current runtime version 4.9.1", "");
|
||||
log = log.replace("ANTLR Runtime version 4.8 used for parser compilation does not match the current runtime version 4.9.1", "");
|
||||
log = log.trim();
|
||||
assertTrue(log.isEmpty());
|
||||
}
|
||||
|
||||
private @NonNull ApexMultifileAnalysis getAnalysisForTempFolder() {
|
||||
ApexLanguageProperties props = new ApexLanguageProperties();
|
||||
props.setProperty(ApexLanguageProperties.MULTIFILE_DIRECTORY, tempFolder.toAbsolutePath().toString());
|
||||
props.setProperty(ApexLanguageProperties.MULTIFILE_DIRECTORY, Optional.of(tempFolder.toAbsolutePath().toString()));
|
||||
return new ApexMultifileAnalysis(props);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
@ -61,7 +62,7 @@ class UnusedMethodTest {
|
||||
configuration.setThreads(0); // don't use separate threads
|
||||
configuration.prependAuxClasspath(".");
|
||||
|
||||
configuration.getLanguageProperties(apexLanguage).setProperty(ApexLanguageProperties.MULTIFILE_DIRECTORY, testProjectDir.toString());
|
||||
configuration.getLanguageProperties(apexLanguage).setProperty(ApexLanguageProperties.MULTIFILE_DIRECTORY, Optional.of(testProjectDir.toString()));
|
||||
|
||||
RuleSet parsedRset = new RuleSetLoader().warnDeprecated(false).loadFromResource("category/apex/design.xml");
|
||||
Rule rule = parsedRset.getRuleByName("UnusedMethod");
|
||||
|
@ -64,7 +64,6 @@ public final class PmdRootLogger {
|
||||
// In pmd-cli, we use slf4j-simple.
|
||||
|
||||
// create a top-level reporter
|
||||
// TODO CLI errors should also be reported through this
|
||||
PmdReporter pmdReporter = new SimpleMessageReporter(log);
|
||||
// always install java.util.logging to slf4j bridge
|
||||
Slf4jSimpleConfiguration.installJulBridge();
|
||||
|
@ -211,7 +211,7 @@ public final class PmdAnalysis implements AutoCloseable {
|
||||
}
|
||||
|
||||
// TODO replace those with actual language properties when the
|
||||
// CLI syntax is implemented.
|
||||
// CLI syntax is implemented. #2947
|
||||
props.setProperty(LanguagePropertyBundle.SUPPRESS_MARKER, config.getSuppressMarker());
|
||||
if (props instanceof JvmLanguagePropertyBundle) {
|
||||
((JvmLanguagePropertyBundle) props).setClassLoader(config.getClassLoader());
|
||||
|
@ -22,7 +22,6 @@ import net.sourceforge.pmd.properties.PropertyFactory;
|
||||
*/
|
||||
public class JvmLanguagePropertyBundle extends LanguagePropertyBundle {
|
||||
|
||||
// TODO make that a PropertyDescriptor<ClassLoader>
|
||||
public static final PropertyDescriptor<String> AUX_CLASSPATH
|
||||
= PropertyFactory.stringProperty("auxClasspath")
|
||||
.desc("A classpath to use to resolve references to external types in the analysed sources. "
|
||||
|
@ -149,7 +149,7 @@ public final class LanguageProcessorRegistry implements AutoCloseable {
|
||||
return new LanguageProcessorRegistry(processors);
|
||||
}
|
||||
|
||||
// TODO this should be reused when implementing the CLI
|
||||
// TODO this should be reused when implementing the CLI - see https://github.com/pmd/pmd/issues/2947
|
||||
public static Map<Language, LanguagePropertyBundle> derivePropertiesFromStrings(
|
||||
Map<Language, Properties> stringProperties,
|
||||
PmdReporter reporter
|
||||
|
@ -23,6 +23,7 @@ public class LanguagePropertyBundle extends AbstractPropertySource {
|
||||
|
||||
// todo for now i think an empty value might interpret every comment
|
||||
// as a suppression. I think it should disable suppression comments.
|
||||
// #4846
|
||||
public static final PropertyDescriptor<String> SUPPRESS_MARKER
|
||||
= PropertyFactory.stringProperty("suppressMarker")
|
||||
.desc("Marker to identify suppression comments. "
|
||||
|
@ -105,7 +105,7 @@ import net.sourceforge.pmd.lang.ast.internal.StreamImpl;
|
||||
* equivalent to {@link Stream#findAny()}. The method {@link #first()}
|
||||
* is an equivalent to {@link Stream#findFirst()}. There is however a
|
||||
* {@link #last()} method, which may be implemented efficiently on some
|
||||
* streams (eg {@link #children()}). TODO maybe implement reverse
|
||||
* streams (eg {@link #children()}).
|
||||
*
|
||||
* <p>Node streams are most of the time ordered in document order (w.r.t. the XPath specification),
|
||||
* a.k.a. prefix order. Some operations which explicitly manipulate the order of nodes, like
|
||||
|
@ -22,10 +22,6 @@ import net.sourceforge.pmd.util.AssertionUtil;
|
||||
*
|
||||
* <p>This should replace the text coordinates methods in {@link Node},
|
||||
* {@link GenericToken}, and {@link RuleViolation} at least (see {@link Reportable}).
|
||||
*
|
||||
* TODO the end line/end column are barely used, mostly ignored even by
|
||||
* renderers. Maybe these could be optional, or replaced by just a length
|
||||
* in case a renderer wants to cut out a piece of the file.
|
||||
*/
|
||||
public final class FileLocation {
|
||||
|
||||
|
@ -22,6 +22,8 @@ import java.util.zip.Checksum;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.sourceforge.pmd.internal.util.IOUtil;
|
||||
|
||||
@ -29,6 +31,7 @@ import net.sourceforge.pmd.internal.util.IOUtil;
|
||||
* Contents of a text file.
|
||||
*/
|
||||
public final class TextFileContent {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TextFileContent.class);
|
||||
|
||||
// the three line terminators we handle.
|
||||
private static final String CRLF = "\r\n";
|
||||
@ -298,7 +301,8 @@ public final class TextFileContent {
|
||||
if (curLineTerm.equals(newLineTerm)) {
|
||||
return curLineTerm;
|
||||
} else {
|
||||
// todo maybe we should report a warning
|
||||
// todo maybe we should report a warning with filename
|
||||
LOGGER.debug("Detect mixed line terminators. Falling back to system default.");
|
||||
return fallback; // mixed line terminators, fallback to system default
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class RuleSet implements ChecksumAware {
|
||||
fileName = builder.fileName;
|
||||
name = Objects.requireNonNull(builder.name, MISSING_RULESET_NAME);
|
||||
description = Objects.requireNonNull(builder.description, MISSING_RULESET_DESCRIPTION);
|
||||
// TODO: ideally, the rules would be unmodifiable, too. But removeDysfunctionalRules might change the rules.
|
||||
// TODO: ideally, the rules would be unmodifiable, too. But removeDysfunctionalRules might change the rules. #3868
|
||||
rules = builder.rules;
|
||||
excludePatterns = Collections.unmodifiableList(new ArrayList<>(builder.excludePatterns));
|
||||
includePatterns = Collections.unmodifiableList(new ArrayList<>(builder.includePatterns));
|
||||
|
@ -19,13 +19,9 @@ import java.util.Objects;
|
||||
*/
|
||||
public abstract class AbstractPropertySource implements PropertySource {
|
||||
|
||||
// setProperty should probably be hidden from Rule implementations, they have no business using that
|
||||
// TODO setProperty should probably be hidden from Rule implementations, they have no business using that
|
||||
// The apex rules that do that could be refactored to do it in the XML
|
||||
|
||||
// TODO RuleReference should extend this class
|
||||
// This would avoid duplicating the implementation between Rule and RuleReference,
|
||||
// which should use exactly the same mechanism to override properties (XML).
|
||||
|
||||
/**
|
||||
* The list of known properties that can be configured.
|
||||
*/
|
||||
|
@ -25,7 +25,6 @@ public class IDEAJRenderer extends AbstractIncrementingRenderer {
|
||||
|
||||
public static final String NAME = "ideaj";
|
||||
|
||||
// TODO 7.0.0 use PropertyDescriptor<String>
|
||||
public static final PropertyDescriptor<String> FILE_NAME =
|
||||
PropertyFactory.stringProperty("fileName").desc("File name.").defaultValue("").build();
|
||||
public static final PropertyDescriptor<String> SOURCE_PATH =
|
||||
|
@ -24,10 +24,6 @@ import com.google.gson.stream.JsonWriter;
|
||||
public class JsonRenderer extends AbstractIncrementingRenderer {
|
||||
public static final String NAME = "json";
|
||||
|
||||
// TODO do we make this public? It would make it possible to write eg
|
||||
// if (jsonObject.getInt("formatVersion") > JsonRenderer.FORMAT_VERSION)
|
||||
// /* handle unsupported version */
|
||||
// because the JsonRenderer.FORMAT_VERSION would be hardcoded by the compiler
|
||||
private static final int FORMAT_VERSION = 0;
|
||||
|
||||
private static final Map<String, String> SUPPRESSION_TYPE_FORMAT_0 = new HashMap<>();
|
||||
|
@ -39,7 +39,6 @@ public class XMLRenderer extends AbstractIncrementingRenderer {
|
||||
|
||||
public static final String NAME = "xml";
|
||||
|
||||
// TODO 7.0.0 use PropertyDescriptor<String> or something more specialized
|
||||
public static final PropertyDescriptor<String> ENCODING =
|
||||
PropertyFactory.stringProperty("encoding").desc("XML encoding format").defaultValue("UTF-8").build();
|
||||
|
||||
|
@ -41,8 +41,11 @@ public class XSLTRenderer extends XMLRenderer {
|
||||
|
||||
public static final String NAME = "xslt";
|
||||
|
||||
// TODO 7.0.0 use PropertyDescriptor<Optional<File>>
|
||||
public static final PropertyDescriptor<String> XSLT_FILENAME = PropertyFactory.stringProperty("xsltFilename").desc("The XSLT file name.").defaultValue("").build();
|
||||
public static final PropertyDescriptor<String> XSLT_FILENAME = PropertyFactory
|
||||
.stringProperty("xsltFilename")
|
||||
.desc("The XSLT file name.")
|
||||
.defaultValue("")
|
||||
.build();
|
||||
|
||||
private Transformer transformer;
|
||||
private String xsltFilename = "/pmd-nicerhtml.xsl";
|
||||
|
@ -28,7 +28,6 @@ import net.sourceforge.pmd.util.StringUtil;
|
||||
public class YAHTMLRenderer extends AbstractAccumulatingRenderer {
|
||||
|
||||
public static final String NAME = "yahtml";
|
||||
// TODO 7.0.0 use PropertyDescriptor<Optional<File>> with a constraint that the file is an existing directory
|
||||
public static final PropertyDescriptor<String> OUTPUT_DIR =
|
||||
PropertyFactory.stringProperty("outputDir")
|
||||
.desc("Output directory.")
|
||||
|
@ -12,9 +12,8 @@ import net.sourceforge.pmd.lang.document.FileLocation;
|
||||
* Interface implemented by those objects that can be the target of
|
||||
* a {@link RuleViolation}. {@link Node}s and {@link GenericToken tokens}
|
||||
* implement this interface.
|
||||
*
|
||||
* TODO use this in RuleViolationFactory
|
||||
*/
|
||||
// TODO use this in RuleContext where RuleViolations are created
|
||||
public interface Reportable {
|
||||
|
||||
// todo add optional method to get the nearest node, to implement
|
||||
|
@ -14,8 +14,6 @@ import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol;
|
||||
*
|
||||
* <p>Compact record constructors must be declared "public".
|
||||
*
|
||||
* TODO make implicit formal parameter node and implement ASTExecutableDeclaration.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* CompactConstructorDeclaration ::= {@link ASTModifierList Modifiers}
|
||||
@ -24,6 +22,8 @@ import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol;
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
// TODO make implicit formal parameter node and implement ASTExecutableDeclaration.
|
||||
// This might help UnusedAssignmentRule / DataflowPass.ReachingDefsVisitor, see also #4603
|
||||
public final class ASTCompactConstructorDeclaration extends AbstractJavaNode implements ASTBodyDeclaration, SymbolDeclaratorNode, ModifierOwner {
|
||||
|
||||
ASTCompactConstructorDeclaration(int id) {
|
||||
|
@ -29,7 +29,6 @@ public final class ASTSwitchCase extends AbstractEcmascriptNode<SwitchCase> {
|
||||
}
|
||||
|
||||
public int getNumStatements() {
|
||||
// TODO Tell Rhino folks about null Statements, should be empty List?
|
||||
return node.getStatements() != null ? node.getStatements().size() : 0;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.mozilla.javascript.CompilerEnvirons;
|
||||
import org.mozilla.javascript.Context;
|
||||
@ -16,6 +18,8 @@ import org.mozilla.javascript.ast.AstRoot;
|
||||
import org.mozilla.javascript.ast.Comment;
|
||||
import org.mozilla.javascript.ast.ErrorCollector;
|
||||
import org.mozilla.javascript.ast.ParseProblem;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.sourceforge.pmd.lang.LanguagePropertyBundle;
|
||||
import net.sourceforge.pmd.lang.LanguageVersion;
|
||||
@ -23,15 +27,19 @@ import net.sourceforge.pmd.lang.ast.AstInfo;
|
||||
import net.sourceforge.pmd.lang.ast.FileAnalysisException;
|
||||
import net.sourceforge.pmd.lang.ast.ParseException;
|
||||
import net.sourceforge.pmd.lang.ast.RootNode;
|
||||
import net.sourceforge.pmd.lang.document.FileId;
|
||||
import net.sourceforge.pmd.lang.document.FileLocation;
|
||||
import net.sourceforge.pmd.lang.document.TextPos2d;
|
||||
|
||||
public final class EcmascriptParser implements net.sourceforge.pmd.lang.ast.Parser {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(EcmascriptParser.class);
|
||||
private final LanguagePropertyBundle properties;
|
||||
|
||||
public EcmascriptParser(LanguagePropertyBundle properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
private AstRoot parseEcmascript(final String sourceCode, final LanguageVersion version, final List<ParseProblem> parseProblems) throws ParseException {
|
||||
private AstRoot parseEcmascript(final FileId fileId, final String sourceCode, final LanguageVersion version, final List<ParseProblem> parseProblems) throws ParseException {
|
||||
final CompilerEnvirons compilerEnvirons = new CompilerEnvirons();
|
||||
compilerEnvirons.setRecordingComments(true);
|
||||
compilerEnvirons.setRecordingLocalJsDocComments(true);
|
||||
@ -42,11 +50,9 @@ public final class EcmascriptParser implements net.sourceforge.pmd.lang.ast.Pars
|
||||
// see bug #1150 "EmptyExpression" for valid statements!
|
||||
compilerEnvirons.setReservedKeywordAsIdentifier(true);
|
||||
|
||||
// TODO We should do something with Rhino errors...
|
||||
final ErrorCollector errorCollector = new ErrorCollector();
|
||||
final Parser parser = new Parser(compilerEnvirons, errorCollector);
|
||||
// TODO Fix hardcode
|
||||
final String sourceURI = "unknown";
|
||||
final String sourceURI = fileId.getOriginalPath();
|
||||
final int beginLineno = 1;
|
||||
AstRoot astRoot = parser.parse(sourceCode, sourceURI, beginLineno);
|
||||
parseProblems.addAll(errorCollector.getErrors());
|
||||
@ -65,7 +71,22 @@ public final class EcmascriptParser implements net.sourceforge.pmd.lang.ast.Pars
|
||||
public RootNode parse(ParserTask task) throws FileAnalysisException {
|
||||
final LanguageVersion version = task.getLanguageVersion();
|
||||
final List<ParseProblem> parseProblems = new ArrayList<>();
|
||||
final AstRoot astRoot = parseEcmascript(task.getSourceText(), version, parseProblems);
|
||||
final AstRoot astRoot = parseEcmascript(task.getFileId(), task.getSourceText(), version, parseProblems);
|
||||
|
||||
List<ParseProblem> errors = parseProblems.stream().filter(p -> p.getType() == ParseProblem.Type.Error).collect(Collectors.toList());
|
||||
if (!errors.isEmpty()) {
|
||||
String errorMessage = errors.stream().map(p -> {
|
||||
TextPos2d textPos2d = task.getTextDocument().lineColumnAtOffset(p.getFileOffset());
|
||||
FileLocation caret = FileLocation.caret(task.getFileId(), textPos2d.getLine(), textPos2d.getColumn());
|
||||
return caret.startPosToStringWithFile() + ": " + p.getMessage();
|
||||
}).collect(Collectors.joining(System.lineSeparator()));
|
||||
|
||||
// TODO throw new ParseException(errors.size() + " problems found:" + System.lineSeparator() + errorMessage);
|
||||
// can't throw ParseException as that would fail many analysis. The parser replaced the errors with
|
||||
// EmptyStatement.
|
||||
LOGGER.warn("{} javascript problems found:{}{}", errors.size(), System.lineSeparator(), errorMessage);
|
||||
}
|
||||
|
||||
final EcmascriptTreeBuilder treeBuilder = new EcmascriptTreeBuilder(parseProblems);
|
||||
ASTAstRoot tree = (ASTAstRoot) treeBuilder.build(astRoot);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user