Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Remember language when using FileCollector.addFile #3971

Merged
merged 5 commits into from Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/pages/release_notes.md
Expand Up @@ -44,6 +44,7 @@ Being based on a proper Antlr grammar, CPD can:
* apex
* [#4056](https://github.com/pmd/pmd/pull/4056): \[apex] ApexSOQLInjection: Add support count query
* core
* [#3970](https://github.com/pmd/pmd/issues/3970): \[core] FileCollector.addFile ignores language parameter
* [#4021](https://github.com/pmd/pmd/pull/4021): \[core] CPD: Add total number of tokens to XML reports
* [#4031](https://github.com/pmd/pmd/issues/4031): \[core] If report is written to stdout, stdout should not be closed
* [#4051](https://github.com/pmd/pmd/issues/4051): \[doc] Additional rulesets are not listed in documentation
Expand Down
Expand Up @@ -18,6 +18,7 @@
import net.sourceforge.pmd.util.IOUtil;
import net.sourceforge.pmd.util.datasource.DataSource;
import net.sourceforge.pmd.util.datasource.FileDataSource;
import net.sourceforge.pmd.util.datasource.internal.LanguageAwareDataSource;

/**
* A {@link TextFile} backed by a file in some {@link FileSystem}.
Expand Down Expand Up @@ -73,7 +74,7 @@ public String readContents() throws IOException {

@Override
public DataSource toDataSourceCompat() {
return new FileDataSource(path.toFile());
return new LanguageAwareDataSource(new FileDataSource(path.toFile()), languageVersion);
}

@Override
Expand Down
Expand Up @@ -12,6 +12,7 @@
import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.util.datasource.DataSource;
import net.sourceforge.pmd.util.datasource.ReaderDataSource;
import net.sourceforge.pmd.util.datasource.internal.LanguageAwareDataSource;

/**
* Read-only view on a string.
Expand Down Expand Up @@ -64,9 +65,10 @@ public String readContents() {

@Override
public DataSource toDataSourceCompat() {
return new ReaderDataSource(
return new LanguageAwareDataSource(new ReaderDataSource(
new StringReader(content),
pathId
pathId),
languageVersion
);
}

Expand Down
Expand Up @@ -21,6 +21,7 @@
import net.sourceforge.pmd.benchmark.TimeTracker;
import net.sourceforge.pmd.renderers.Renderer;
import net.sourceforge.pmd.util.datasource.DataSource;
import net.sourceforge.pmd.util.datasource.internal.LanguageAwareDataSource;

/**
*
Expand Down Expand Up @@ -82,6 +83,9 @@ public Report call() {

try (InputStream stream = new BufferedInputStream(dataSource.getInputStream())) {
tc.ruleContext.setLanguageVersion(null);
if (dataSource instanceof LanguageAwareDataSource) {
tc.ruleContext.setLanguageVersion(((LanguageAwareDataSource) dataSource).getLanguageVersion());
oowekyala marked this conversation as resolved.
Show resolved Hide resolved
}
sourceCodeProcessor.processSourceCode(stream, tc.ruleSets, tc.ruleContext);
} catch (PMDException pmde) {
addError(report, pmde, "Error while processing file: " + fileName);
Expand Down
@@ -0,0 +1,42 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/

package net.sourceforge.pmd.util.datasource.internal;

import java.io.IOException;
import java.io.InputStream;

import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.util.datasource.DataSource;

@InternalApi
public class LanguageAwareDataSource implements DataSource {
private final DataSource base; // delegate DataSource methods to this
private final LanguageVersion version;

public LanguageAwareDataSource(DataSource base, LanguageVersion version) {
this.base = base;
this.version = version;
}

public LanguageVersion getLanguageVersion() {
return version;
}

@Override
public InputStream getInputStream() throws IOException {
return base.getInputStream();
}

@Override
public String getNiceFileName(boolean shortNames, String inputFileName) {
return base.getNiceFileName(shortNames, inputFileName);
}

@Override
public void close() throws IOException {
base.close();
}
}
58 changes: 58 additions & 0 deletions pmd-core/src/test/java/net/sourceforge/pmd/PmdAnalysisTest.java
Expand Up @@ -14,10 +14,18 @@
import static org.mockito.Mockito.verify;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.mockito.ArgumentMatchers;

import net.sourceforge.pmd.lang.Dummy2LanguageModule;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.document.SimpleTestTextFile;
import net.sourceforge.pmd.lang.rule.AbstractRule;
import net.sourceforge.pmd.renderers.Renderer;

/**
Expand Down Expand Up @@ -72,4 +80,54 @@ public void testRulesetWhenSomeoneHasAnError() {
}
}

@Test
public void testFileWithSpecificLanguage() {
final Language language = Dummy2LanguageModule.getInstance();
PMDConfiguration config = new PMDConfiguration();
config.setIgnoreIncrementalAnalysis(true);
RuleSet ruleset = RuleSet.forSingleRule(new TestRule());

try (PmdAnalysis pmd = PmdAnalysis.create(config)) {
pmd.addRuleSet(ruleset);
pmd.files().addFile(Paths.get("src", "test", "resources", "sample-source", "dummy", "foo.txt"), language);
Report report = pmd.performAnalysisAndCollectReport();
for (Report.ProcessingError error : report.getProcessingErrors()) {
System.out.println("error = " + error.getMsg() + ": " + error.getDetail());
}
Assert.assertEquals(0, report.getProcessingErrors().size());
Assert.assertEquals(1, report.getViolations().size());
}
}

@Test
public void testTextFileWithSpecificLanguage() {
final Language language = Dummy2LanguageModule.getInstance();
PMDConfiguration config = new PMDConfiguration();
config.setIgnoreIncrementalAnalysis(true);
RuleSet ruleset = RuleSet.forSingleRule(new TestRule());

try (PmdAnalysis pmd = PmdAnalysis.create(config)) {
pmd.addRuleSet(ruleset);
pmd.files().addFile(new SimpleTestTextFile("test content foo", "foo.txt", "foo.txt", language.getDefaultVersion()));
Report report = pmd.performAnalysisAndCollectReport();
for (Report.ProcessingError error : report.getProcessingErrors()) {
System.out.println("error = " + error.getMsg() + ": " + error.getDetail());
}
Assert.assertEquals(0, report.getProcessingErrors().size());
Assert.assertEquals(1, report.getViolations().size());
}
}

public static class TestRule extends AbstractRule {
public TestRule() {
setLanguage(Dummy2LanguageModule.getInstance());
setMessage("dummy 2 test rule");
}

@Override
public void apply(List<? extends Node> nodes, RuleContext ctx) {
ctx.addViolation(nodes.get(0));
}
}

}
Expand Up @@ -16,4 +16,8 @@ public Dummy2LanguageModule() {
super(NAME, null, TERSE_NAME, "dummy2");
addVersion("1.0", new DummyLanguageModule.Handler(), true);
}

public static Language getInstance() {
return LanguageRegistry.getLanguage(NAME);
}
}
@@ -0,0 +1,17 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/

package net.sourceforge.pmd.lang.document;

import net.sourceforge.pmd.lang.LanguageVersion;

/**
* Makes {@link StringTextFile} publicly available for unit tests.
*/
public class SimpleTestTextFile extends StringTextFile {

public SimpleTestTextFile(String content, String pathId, String displayName, LanguageVersion languageVersion) {
super(content, pathId, displayName, languageVersion);
}
}
1 change: 1 addition & 0 deletions pmd-core/src/test/resources/sample-source/dummy/foo.txt
@@ -0,0 +1 @@
A dummy file with file extension txt.