diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java index f52b0f2a2ac..7d1838c2977 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java @@ -222,7 +222,7 @@ private void determineLanguage(RuleContext ctx) { ctx.setLanguageVersion(forceLanguage); } else { // otherwise determine by file extension - LanguageVersion languageVersion = configuration.getLanguageVersionOfFile(ctx.getSourceCodeFile().toString()); + LanguageVersion languageVersion = configuration.getLanguageVersionOfFile(ctx.getSourceCodeFilename()); ctx.setLanguageVersion(languageVersion); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionDiscoverer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionDiscoverer.java index 27c72898e1e..4e22b03a4f1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionDiscoverer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionDiscoverer.java @@ -5,8 +5,6 @@ package net.sourceforge.pmd.lang; import java.io.File; -import java.io.IOException; -import java.nio.file.Path; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -14,7 +12,6 @@ import org.apache.commons.lang3.StringUtils; -import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.internal.util.AssertionUtil; /** @@ -27,8 +24,6 @@ public class LanguageVersionDiscoverer { private LanguageVersion forcedVersion; - private Map forcedVersionByFile = new HashMap<>(); - public LanguageVersionDiscoverer() { this(null); } @@ -102,13 +97,10 @@ public LanguageVersion getDefaultLanguageVersionForFile(File sourceFile) { * file. */ public LanguageVersion getDefaultLanguageVersionForFile(String fileName) { - LanguageVersion languageVersion = forcedVersionByFile.get(fileName); - - if (languageVersion == null) { - List languages = getLanguagesForFile(fileName); - if (!languages.isEmpty()) { - languageVersion = getDefaultLanguageVersion(languages.get(0)); - } + List languages = getLanguagesForFile(fileName); + LanguageVersion languageVersion = null; + if (!languages.isEmpty()) { + languageVersion = getDefaultLanguageVersion(languages.get(0)); } return languageVersion; } @@ -150,16 +142,4 @@ private String getExtension(String fileName) { } - - @InternalApi - @Deprecated - public void recordLanguageVersionForFile(Path file, LanguageVersion languageVersion) { - String fileName; - try { - fileName = file.toRealPath().toString(); - } catch (IOException e) { - fileName = file.toAbsolutePath().toString(); - } - forcedVersionByFile.put(fileName, languageVersion); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/FileCollector.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/FileCollector.java index 51d84106c4a..8db97175c36 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/FileCollector.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/FileCollector.java @@ -155,10 +155,8 @@ public boolean addFile(Path file, Language language) { reporter.error("Not a regular file {0}", file); return false; } - LanguageVersion languageVersion = discoverer.getDefaultLanguageVersion(language); - NioTextFile nioTextFile = new NioTextFile(file, charset, languageVersion, getDisplayName(file)); + NioTextFile nioTextFile = new NioTextFile(file, charset, discoverer.getDefaultLanguageVersion(language), getDisplayName(file)); addFileImpl(nioTextFile); - discoverer.recordLanguageVersionForFile(file, languageVersion); return true; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java index c7d77e1de88..8fc154967a1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java @@ -17,7 +17,7 @@ import net.sourceforge.pmd.lang.LanguageVersion; 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.FileDataSourceWithLanguage; /** * A {@link TextFile} backed by a file in some {@link FileSystem}. @@ -73,7 +73,7 @@ public String readContents() throws IOException { @Override public DataSource toDataSourceCompat() { - return new FileDataSource(path.toFile()); + return new FileDataSourceWithLanguage(path.toFile(), languageVersion); } @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/StringTextFile.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/StringTextFile.java index 598823e555c..db2f537eeeb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/StringTextFile.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/StringTextFile.java @@ -11,7 +11,7 @@ import net.sourceforge.pmd.internal.util.AssertionUtil; 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.ReaderDataSourceWithLanguage; /** * Read-only view on a string. @@ -64,9 +64,10 @@ public String readContents() { @Override public DataSource toDataSourceCompat() { - return new ReaderDataSource( + return new ReaderDataSourceWithLanguage( new StringReader(content), - pathId + pathId, + languageVersion ); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java index da91fbd95a6..e4b1d75de62 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java @@ -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; /** * @@ -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()); + } sourceCodeProcessor.processSourceCode(stream, tc.ruleSets, tc.ruleContext); } catch (PMDException pmde) { addError(report, pmde, "Error while processing file: " + fileName); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/internal/FileDataSourceWithLanguage.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/internal/FileDataSourceWithLanguage.java new file mode 100644 index 00000000000..7ca0e1c8a46 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/internal/FileDataSourceWithLanguage.java @@ -0,0 +1,26 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.util.datasource.internal; + +import java.io.File; + +import net.sourceforge.pmd.annotation.InternalApi; +import net.sourceforge.pmd.lang.LanguageVersion; +import net.sourceforge.pmd.util.datasource.FileDataSource; + +@InternalApi +public class FileDataSourceWithLanguage extends FileDataSource implements LanguageAwareDataSource { + private final LanguageVersion languageVersion; + + public FileDataSourceWithLanguage(File file, LanguageVersion languageVersion) { + super(file); + this.languageVersion = languageVersion; + } + + @Override + public LanguageVersion getLanguageVersion() { + return languageVersion; + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/internal/LanguageAwareDataSource.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/internal/LanguageAwareDataSource.java new file mode 100644 index 00000000000..69dbf67059d --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/internal/LanguageAwareDataSource.java @@ -0,0 +1,13 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.util.datasource.internal; + +import net.sourceforge.pmd.annotation.InternalApi; +import net.sourceforge.pmd.lang.LanguageVersion; + +@InternalApi +public interface LanguageAwareDataSource { + LanguageVersion getLanguageVersion(); +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/internal/ReaderDataSourceWithLanguage.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/internal/ReaderDataSourceWithLanguage.java new file mode 100644 index 00000000000..e96429e65d6 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/internal/ReaderDataSourceWithLanguage.java @@ -0,0 +1,26 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.util.datasource.internal; + +import java.io.Reader; + +import net.sourceforge.pmd.annotation.InternalApi; +import net.sourceforge.pmd.lang.LanguageVersion; +import net.sourceforge.pmd.util.datasource.ReaderDataSource; + +@InternalApi +public class ReaderDataSourceWithLanguage extends ReaderDataSource implements LanguageAwareDataSource { + private final LanguageVersion languageVersion; + + public ReaderDataSourceWithLanguage(Reader reader, String dataSourceName, LanguageVersion languageVersion) { + super(reader, dataSourceName); + this.languageVersion = languageVersion; + } + + @Override + public LanguageVersion getLanguageVersion() { + return languageVersion; + } +} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/PmdAnalysisTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/PmdAnalysisTest.java index 797f4e0569d..a1f2f0f1569 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/PmdAnalysisTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/PmdAnalysisTest.java @@ -24,6 +24,7 @@ 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; @@ -90,6 +91,28 @@ public void testFileWithSpecificLanguage() { 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()); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/SimpleTestTextFile.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/SimpleTestTextFile.java new file mode 100644 index 00000000000..6f663471427 --- /dev/null +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/SimpleTestTextFile.java @@ -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); + } +}