From f2cfd8f5a6688367deb451ef8a921853fe50ba77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 11 Feb 2023 18:43:37 +0100 Subject: [PATCH] More refactorings --- .../pmd/cli/commands/internal/CpdCommand.java | 12 +--- .../sourceforge/pmd/cpd/CPDConfiguration.java | 2 +- .../net/sourceforge/pmd/cpd/CpdAnalysis.java | 21 +++++- .../pmd/lang/PlainTextLanguage.java | 7 ++ .../{CPDTest.java => CpdAnalysisTest.java} | 64 +++++++++++-------- 5 files changed, 68 insertions(+), 38 deletions(-) rename pmd-core/src/test/java/net/sourceforge/pmd/cpd/{CPDTest.java => CpdAnalysisTest.java} (69%) diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java index af9de892b1..46f1a8335c 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.cli.commands.internal; import java.io.File; import java.io.IOException; -import java.nio.charset.Charset; import java.nio.file.Path; import java.util.Arrays; import java.util.Iterator; @@ -23,7 +22,6 @@ import net.sourceforge.pmd.cpd.CPDConfiguration; import net.sourceforge.pmd.cpd.CpdAnalysis; import net.sourceforge.pmd.cpd.Tokenizer; import net.sourceforge.pmd.internal.LogMessages; -import net.sourceforge.pmd.internal.util.IOUtil; import net.sourceforge.pmd.lang.Language; import picocli.CommandLine.Command; @@ -135,15 +133,7 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand { try (CpdAnalysis cpd = new CpdAnalysis(configuration)){ MutableBoolean hasViolations = new MutableBoolean(); - cpd.performAnalysis(report -> { - try { - configuration.getCPDReportRenderer().render(report, IOUtil.createWriter(Charset.defaultCharset(), null)); - hasViolations.setValue(!report.getMatches().isEmpty()); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - + cpd.performAnalysis(report -> hasViolations.setValue(!report.getMatches().isEmpty())); if (hasViolations.booleanValue() && configuration.isFailOnViolation()) { return CliExitCode.VIOLATIONS_FOUND; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDConfiguration.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDConfiguration.java index 30d8b2a9df..576d460c4c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDConfiguration.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDConfiguration.java @@ -51,7 +51,7 @@ public class CPDConfiguration extends AbstractConfiguration { private String rendererName; - private CPDReportRenderer cpdReportRenderer; + CPDReportRenderer cpdReportRenderer; private boolean ignoreLiterals; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CpdAnalysis.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CpdAnalysis.java index 720b8fbbc6..4d5c4eeccd 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CpdAnalysis.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CpdAnalysis.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.cpd; import java.io.File; import java.io.IOException; +import java.nio.charset.Charset; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -15,8 +16,10 @@ import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.sourceforge.pmd.cpd.renderer.CPDReportRenderer; import net.sourceforge.pmd.internal.util.FileCollectionUtil; import net.sourceforge.pmd.internal.util.FileUtil; +import net.sourceforge.pmd.internal.util.IOUtil; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguagePropertyBundle; import net.sourceforge.pmd.lang.ast.TokenMgrError; @@ -43,6 +46,14 @@ public final class CpdAnalysis implements AutoCloseable { reporter ); + if (config.getRendererName() == null) { + config.setRendererName(CPDConfiguration.DEFAULT_RENDERER); + } + if (config.cpdReportRenderer == null) { + //may throw + CPDReportRenderer renderer = CPDConfiguration.createRendererByName(config.getRendererName(), config.getSourceEncoding().name()); + config.setRenderer(renderer); + } // Add all sources extractAllSources(); @@ -118,6 +129,10 @@ public final class CpdAnalysis implements AutoCloseable { return tokens.size() - lastTokenSize - 1; /* EOF */ } + public void performAnalysis() { + performAnalysis(r -> { }); + } + public void performAnalysis(Consumer consumer) { try (SourceManager sourceManager = new SourceManager(files.getCollectedFiles())) { @@ -149,8 +164,12 @@ public final class CpdAnalysis implements AutoCloseable { LOGGER.debug("Finished: {} duplicates found", matchAlgorithm.getMatches().size()); CPDReport cpdReport = new CPDReport(sourceManager, matchAlgorithm.getMatches(), numberOfTokensPerFile); - consumer.accept(cpdReport); + if (configuration.getCPDReportRenderer() != null) { + configuration.getCPDReportRenderer().render(cpdReport, IOUtil.createWriter(Charset.defaultCharset(), null)); + } + + consumer.accept(cpdReport); } catch (Exception e) { reporter.errorEx("Exception while running CPD", e); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/PlainTextLanguage.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/PlainTextLanguage.java index 29afc7d45d..07945c453a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/PlainTextLanguage.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/PlainTextLanguage.java @@ -5,6 +5,8 @@ package net.sourceforge.pmd.lang; import net.sourceforge.pmd.annotation.Experimental; +import net.sourceforge.pmd.cpd.AnyTokenizer; +import net.sourceforge.pmd.cpd.Tokenizer; import net.sourceforge.pmd.lang.ast.AstInfo; import net.sourceforge.pmd.lang.ast.Parser; import net.sourceforge.pmd.lang.ast.Parser.ParserTask; @@ -42,6 +44,11 @@ public final class PlainTextLanguage extends SimpleLanguageModuleBase { return INSTANCE; } + @Override + public Tokenizer createCpdTokenizer(LanguagePropertyBundle bundle) { + return new AnyTokenizer(); + } + private static final class TextLvh implements LanguageVersionHandler { @Override public Parser getParser() { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdAnalysisTest.java similarity index 69% rename from pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDTest.java rename to pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdAnalysisTest.java index 8ac89bcf74..4ee0b61541 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdAnalysisTest.java @@ -10,33 +10,34 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.File; -import java.util.Iterator; +import java.nio.file.Paths; +import java.util.List; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import net.sourceforge.pmd.lang.PlainTextLanguage; + /** - * Unit test for {@link CPD} + * Unit test for {@link CpdAnalysis} */ -class CPDTest { +class CpdAnalysisTest { private static final String BASE_TEST_RESOURCE_PATH = "src/test/resources/net/sourceforge/pmd/cpd/files/"; private static final String TARGET_TEST_RESOURCE_PATH = "target/classes/net/sourceforge/pmd/cpd/files/"; - private CPD cpd; // Symlinks are not well supported under Windows - so the tests are // simply executed only on linux. private boolean canTestSymLinks = SystemUtils.IS_OS_UNIX; + CPDConfiguration config = new CPDConfiguration(); @BeforeEach void setup() throws Exception { - CPDConfiguration theConfiguration = new CPDConfiguration(); - theConfiguration.setLanguage(new AnyLanguage("any")); - theConfiguration.setMinimumTileSize(10); - theConfiguration.postContruct(); - cpd = new CPD(theConfiguration); + config.setLanguage(PlainTextLanguage.getInstance()); + config.setMinimumTileSize(10); + config.postContruct(); } /** @@ -72,9 +73,12 @@ class CPDTest { prepareSymLinks(); NoFileAssertListener listener = new NoFileAssertListener(0); - cpd.setCpdListener(listener); + try (CpdAnalysis cpd = new CpdAnalysis(config)) { + cpd.setCpdListener(listener); + cpd.files().addFile(Paths.get(BASE_TEST_RESOURCE_PATH, "this-is-a-broken-sym-link-for-test")); + cpd.performAnalysis(); + } - cpd.add(new File(BASE_TEST_RESOURCE_PATH, "this-is-a-broken-sym-link-for-test")); listener.verify(); } @@ -90,10 +94,13 @@ class CPDTest { prepareSymLinks(); NoFileAssertListener listener = new NoFileAssertListener(1); - cpd.setCpdListener(listener); + try (CpdAnalysis cpd = new CpdAnalysis(config)) { + cpd.setCpdListener(listener); + cpd.files().addFile(Paths.get(BASE_TEST_RESOURCE_PATH, "real-file.txt")); + cpd.files().addFile(Paths.get(BASE_TEST_RESOURCE_PATH, "symlink-for-real-file.txt")); + cpd.performAnalysis(); + } - cpd.add(new File(BASE_TEST_RESOURCE_PATH, "real-file.txt")); - cpd.add(new File(BASE_TEST_RESOURCE_PATH, "symlink-for-real-file.txt")); listener.verify(); } @@ -107,9 +114,12 @@ class CPDTest { @Test void testFileAddedWithRelativePath() throws Exception { NoFileAssertListener listener = new NoFileAssertListener(1); - cpd.setCpdListener(listener); + try (CpdAnalysis cpd = new CpdAnalysis(config)) { + cpd.setCpdListener(listener); + cpd.files().addFile(Paths.get("./" + BASE_TEST_RESOURCE_PATH, "real-file.txt")); + cpd.performAnalysis(); + } - cpd.add(new File("./" + BASE_TEST_RESOURCE_PATH, "real-file.txt")); listener.verify(); } @@ -120,17 +130,21 @@ class CPDTest { */ @Test void testFileOrderRelevance() throws Exception { - cpd.add(new File("./" + BASE_TEST_RESOURCE_PATH, "dup2.java")); - cpd.add(new File("./" + BASE_TEST_RESOURCE_PATH, "dup1.java")); - cpd.go(); + try (CpdAnalysis cpd = new CpdAnalysis(config)) { + cpd.files().addFile(Paths.get("./" + BASE_TEST_RESOURCE_PATH, "dup2.java")); + cpd.files().addFile(Paths.get("./" + BASE_TEST_RESOURCE_PATH, "dup1.java")); + cpd.performAnalysis(report -> { - Iterator matches = cpd.getMatches(); - while (matches.hasNext()) { - Match match = matches.next(); - // the file added first was dup2. - assertTrue(match.getFirstMark().getFilename().endsWith("dup2.java")); - assertTrue(match.getSecondMark().getFilename().endsWith("dup1.java")); + + List matches = report.getMatches(); + for (Match match : matches) { + // the file added first was dup2. + assertTrue(match.getFirstMark().getFilename().endsWith("dup2.java")); + assertTrue(match.getSecondMark().getFilename().endsWith("dup1.java")); + } + }); } + } /**