diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java index 5834c406d4..9f41239702 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java @@ -316,7 +316,7 @@ public final class FileUtil { public static TextFileBuilder buildNioTextFile(PMDConfiguration config, Path file) { LanguageVersion langVersion = config.getLanguageVersionOfFile(file.toString()); - return TextFile.forPath(file, config.getSourceEncoding(), langVersion) + return TextFile.builderForPath(file, config.getSourceEncoding(), langVersion) .withDisplayName(displayName(config, file)); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/document/TextFile.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/document/TextFile.java index 848304f361..b1e4008d52 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/document/TextFile.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/document/TextFile.java @@ -136,9 +136,8 @@ public interface TextFile extends Closeable { /** * Returns an instance of this interface reading and writing to a file. - * The returned instance may be read-only. If the file is not a regular - * file (eg, a directory), or does not exist, then {@link TextFile#readContents()} - * will throw. + * See {@link #builderForPath(Path, Charset, LanguageVersion) builderForPath} + * for more info. * * @param path Path to the file * @param charset Encoding to use @@ -146,7 +145,26 @@ public interface TextFile extends Closeable { * * @throws NullPointerException If any parameter is null */ - static TextFileBuilder forPath(Path path, Charset charset, LanguageVersion languageVersion) { + static TextFile forPath(Path path, Charset charset, LanguageVersion languageVersion) { + return builderForPath(path, charset, languageVersion).build(); + } + + /** + * Returns a builder for a textfile that reads and write to the file. + * The returned instance may be read-only. If the file is not a regular + * file (eg, a directory), or does not exist, then {@link TextFile#readContents()} + * will throw. + * + *

The display name is by default the given path (without normalization), + * while the path id is the absolute path. + * + * @param path Path to the file + * @param charset Encoding to use + * @param languageVersion Language version to use + * + * @throws NullPointerException If any parameter is null + */ + static TextFileBuilder builderForPath(Path path, Charset charset, LanguageVersion languageVersion) { return new ForNio(languageVersion, path, charset); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeExportCli.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeExportCli.java index 68ca015ef5..6fe89fcdb9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeExportCli.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeExportCli.java @@ -170,7 +170,7 @@ public class TreeExportCli { System.err.println("Reading from stdin..."); textFile = TextFile.forCharSeq(readFromSystemIn(), "stdin", langVersion); } else { - textFile = TextFile.forPath(Paths.get(file), Charset.forName(encoding), langVersion).build(); + textFile = TextFile.forPath(Paths.get(file), Charset.forName(encoding), langVersion); } // disable warnings for deprecated attributes diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java index 8c0d67ec0a..683e79d7da 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java @@ -374,7 +374,7 @@ public class RuleSetTest { @Test public void testIncludeExcludeApplies() { - TextFile file = TextFile.forPath(Paths.get("C:\\myworkspace\\project\\some\\random\\package\\RandomClass.java"), Charset.defaultCharset(), dummyLang.getDefaultVersion()).build(); + TextFile file = TextFile.forPath(Paths.get("C:\\myworkspace\\project\\some\\random\\package\\RandomClass.java"), Charset.defaultCharset(), dummyLang.getDefaultVersion()); RuleSet ruleSet = createRuleSetBuilder("ruleset").build(); assertTrue("No patterns", ruleSet.applies(file)); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cache/FileAnalysisCacheTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cache/FileAnalysisCacheTest.java index 23adfd5212..9d008df6c5 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cache/FileAnalysisCacheTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/cache/FileAnalysisCacheTest.java @@ -66,7 +66,7 @@ public class FileAnalysisCacheTest { newCacheFile = new File(tempFolder.getRoot(), "pmd-analysis.cache"); emptyCacheFile = tempFolder.newFile(); File sourceFile = tempFolder.newFile("Source.java"); - this.sourceFileBackend = TextFile.forPath(sourceFile.toPath(), Charset.defaultCharset(), dummyVersion).build(); + this.sourceFileBackend = TextFile.forPath(sourceFile.toPath(), Charset.defaultCharset(), dummyVersion); this.sourceFile = TextDocument.create(sourceFileBackend); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java index b97252b610..2a81aaf73b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.java.ast; import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.ast.AstVisitor; import net.sourceforge.pmd.lang.ast.impl.javacc.AbstractJjtreeNode; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParser.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParser.java index aacac74140..943a1e4e0d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParser.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParser.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.java.ast; -import org.apache.commons.lang3.StringUtils; - import net.sourceforge.pmd.lang.ast.AstInfo; import net.sourceforge.pmd.lang.ast.CharStream; import net.sourceforge.pmd.lang.ast.ParseException; diff --git a/pmd-visualforce/src/main/java/net/sourceforge/pmd/lang/vf/ast/ApexClassPropertyTypes.java b/pmd-visualforce/src/main/java/net/sourceforge/pmd/lang/vf/ast/ApexClassPropertyTypes.java index 760ddb31d3..1cf4db8e5c 100644 --- a/pmd-visualforce/src/main/java/net/sourceforge/pmd/lang/vf/ast/ApexClassPropertyTypes.java +++ b/pmd-visualforce/src/main/java/net/sourceforge/pmd/lang/vf/ast/ApexClassPropertyTypes.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.vf.ast; -import java.io.BufferedReader; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -12,7 +11,6 @@ import java.nio.file.Path; import java.util.List; import java.util.logging.Logger; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.exception.ContextedRuntimeException; import org.apache.commons.lang3.tuple.Pair; @@ -24,6 +22,8 @@ import net.sourceforge.pmd.lang.ast.Parser; import net.sourceforge.pmd.lang.ast.Parser.ParserTask; import net.sourceforge.pmd.lang.ast.SemanticErrorReporter; import net.sourceforge.pmd.lang.vf.DataType; +import net.sourceforge.pmd.util.document.TextDocument; +import net.sourceforge.pmd.util.document.TextFile; import apex.jorje.semantic.symbol.type.BasicType; @@ -48,46 +48,37 @@ class ApexClassPropertyTypes extends SalesforceFieldTypes { for (Path apexDirectory : apexDirectories) { Path apexFilePath = apexDirectory.resolve(className + APEX_CLASS_FILE_SUFFIX); if (Files.exists(apexFilePath) && Files.isRegularFile(apexFilePath)) { - Node node = parse(expression, apexFilePath); - ApexClassPropertyTypesVisitor visitor = new ApexClassPropertyTypesVisitor(); - node.acceptVisitor(visitor, null); + LanguageVersion languageVersion = LanguageRegistry.getLanguage(ApexLanguageModule.NAME).getDefaultVersion(); + Parser parser = languageVersion.getLanguageVersionHandler().getParser(); - for (Pair variable : visitor.getVariables()) { - putDataType(variable.getKey(), DataType.fromBasicType(variable.getValue())); - } + try (TextDocument textDocument = TextDocument.create(TextFile.forPath(apexFilePath, StandardCharsets.UTF_8, languageVersion))) { + ParserTask task = new ParserTask( + textDocument, + SemanticErrorReporter.noop() + ); - if (containsExpression(expression)) { - // Break out of the loop if a variable was found - break; + Node node = parser.parse(task); + ApexClassPropertyTypesVisitor visitor = new ApexClassPropertyTypesVisitor(); + node.acceptVisitor(visitor, null); + + for (Pair variable : visitor.getVariables()) { + putDataType(variable.getKey(), DataType.fromBasicType(variable.getValue())); + } + + if (containsExpression(expression)) { + // Break out of the loop if a variable was found + break; + } + } catch (IOException e) { + throw new ContextedRuntimeException(e) + .addContextValue("expression", expression) + .addContextValue("apexFilePath", apexFilePath); } } } } } - private Node parse(String expression, Path apexFilePath) { - String fileText; - try (BufferedReader reader = Files.newBufferedReader(apexFilePath, StandardCharsets.UTF_8)) { - fileText = IOUtils.toString(reader); - } catch (IOException e) { - throw new ContextedRuntimeException(e) - .addContextValue("expression", expression) - .addContextValue("apexFilePath", apexFilePath); - } - - LanguageVersion languageVersion = LanguageRegistry.getLanguage(ApexLanguageModule.NAME).getDefaultVersion(); - Parser parser = languageVersion.getLanguageVersionHandler().getParser(); - - ParserTask task = new ParserTask( - languageVersion, - apexFilePath.toString(), - fileText, - SemanticErrorReporter.noop() - ); - - return parser.parse(task); - } - @Override protected DataType putDataType(String name, DataType dataType) { DataType previousType = super.putDataType(name, dataType); diff --git a/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/ast/ApexClassPropertyTypesVisitorTest.java b/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/ast/ApexClassPropertyTypesVisitorTest.java index 280c7e1956..099b972f18 100644 --- a/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/ast/ApexClassPropertyTypesVisitorTest.java +++ b/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/ast/ApexClassPropertyTypesVisitorTest.java @@ -8,13 +8,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.io.IOException; -import java.nio.file.Files; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Hashtable; import java.util.List; import java.util.Map; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.tuple.Pair; import org.junit.Test; @@ -25,20 +24,25 @@ import net.sourceforge.pmd.lang.ast.Parser; import net.sourceforge.pmd.lang.ast.Parser.ParserTask; import net.sourceforge.pmd.lang.ast.SemanticErrorReporter; import net.sourceforge.pmd.lang.vf.VFTestUtils; +import net.sourceforge.pmd.util.document.TextDocument; +import net.sourceforge.pmd.util.document.TextFile; import apex.jorje.semantic.symbol.type.BasicType; public class ApexClassPropertyTypesVisitorTest { + @Test + @SuppressWarnings("PMD.CloseResource") public void testApexClassIsProperlyParsed() throws IOException { LanguageVersion languageVersion = LanguageRegistry.getLanguage(ApexLanguageModule.NAME).getDefaultVersion(); Parser parser = languageVersion.getLanguageVersionHandler().getParser(); Path apexPath = VFTestUtils.getMetadataPath(this, VFTestUtils.MetadataFormat.SFDX, VFTestUtils.MetadataType.Apex) - .resolve("ApexController.cls").toAbsolutePath(); - ParserTask task = new ParserTask(languageVersion, - apexPath.toString(), - IOUtils.toString(Files.newBufferedReader(apexPath)), + .resolve("ApexController.cls"); + + TextFile textFile = TextFile.forPath(apexPath, StandardCharsets.UTF_8, languageVersion); + + ParserTask task = new ParserTask(TextDocument.create(textFile), SemanticErrorReporter.noop()); ApexClassPropertyTypesVisitor visitor = new ApexClassPropertyTypesVisitor(); parser.parse(task).acceptVisitor(visitor, null); @@ -59,5 +63,7 @@ public class ApexClassPropertyTypesVisitorTest { assertEquals(BasicType.ID, variableNameToVariableType.get("ApexController.InnerController.InnerAccountIdProp")); assertEquals(BasicType.ID, variableNameToVariableType.get("ApexController.InnerController.InnerAccountId")); assertEquals(BasicType.STRING, variableNameToVariableType.get("ApexController.InnerController.InnerAccountName")); + + textFile.close(); } }