Skip to content

Commit

Permalink
introduce VS renderer provided by CPD (#47)
Browse files Browse the repository at this point in the history
what it is required for ;-)
  • Loading branch information
aaschmid committed Nov 3, 2019
1 parent 56a4cc6 commit fe8efce
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 45 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,14 @@ Additionally, one can configure the following reports for every task analogous t
[Reporting](https://gradle.org/docs/current/dsl/org.gradle.api.reporting.Reporting.html) as for any other reporting plugin. See also
the example in [Usage](#usage) section above.

| Report | Default | Further options and their defaults |
| ------ |:--------:| ----------------------------------------------------- |
| csv | disabled | ```separator = ','```, ```includeLineCount = true```¹ |
| text | disabled | ```lineSeparator = '====================================================================='```, ```trimLeadingCommonSourceWhitespaces = false``` |
| xml | enabled | ```encoding = <<System default>>``` |

¹: Since [v3.1][] but note that property `includeLineCount` is originally named `lineCountPerFile` and meaning is inverted which means that
| Report | Default | since | Further options and their defaults |
| ------ |:--------:| -------- | --------------------------------------------------------- |
| csv | disabled | [v0.1][] | ```separator = ','```, ```includeLineCount = true```**²** |
| text | disabled | [v0.1][] | ```lineSeparator = '====================================================================='```, ```trimLeadingCommonSourceWhitespaces = false``` |
| vs | disabled | [v3.1][] | ```encoding = <<System default>>``` |
| xml | enabled | [v0.1][] | ```encoding = <<System default>>``` |

²: Since [v3.1][] but note that property `includeLineCount` is originally named `lineCountPerFile` and meaning is inverted which means that
`false` shows line count and `true` hides it, see
[here](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CSVRenderer.java#L63).

Expand Down
9 changes: 6 additions & 3 deletions src/main/java/de/aaschmid/gradle/plugins/cpd/Cpd.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,19 @@ private List<Report> createReportParameters(CpdReports reports) {
if (report instanceof CpdCsvFileReport) {
Character separator = ((CpdCsvFileReport) report).getSeparator();
boolean includeLineCount = ((CpdCsvFileReport) report).isIncludeLineCount();
result.add(new Report.Csv(getEncoding(), report.getDestination(), separator, includeLineCount));
result.add(new Report.Csv(report.getDestination(), separator, includeLineCount));

} else if (report instanceof CpdTextFileReport) {
String lineSeparator = ((CpdTextFileReport) report).getLineSeparator();
boolean trimLeadingCommonSourceWhitespaces = ((CpdTextFileReport) report).getTrimLeadingCommonSourceWhitespaces();
result.add(new Report.Text(getEncoding(), report.getDestination(), lineSeparator, trimLeadingCommonSourceWhitespaces));
result.add(new Report.Text(report.getDestination(), lineSeparator, trimLeadingCommonSourceWhitespaces));

} else if (report instanceof CpdVsFileReport) {
result.add(new Report.Vs(report.getDestination()));

} else if (report instanceof CpdXmlFileReport) {
String encoding = getXmlRendererEncoding((CpdXmlFileReport) report);
result.add(new Report.Xml(encoding, report.getDestination()));
result.add(new Report.Xml(report.getDestination(), encoding));

} else {
throw new IllegalArgumentException(String.format("Report of type '%s' not available.", report.getClass().getSimpleName()));
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/de/aaschmid/gradle/plugins/cpd/CpdVsFileReport.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package de.aaschmid.gradle.plugins.cpd;

import org.gradle.api.reporting.SingleFileReport;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Optional;

/**
* The single file simple text report for code/paste (= duplication) detection.
*
* @see CpdPlugin
*/
public interface CpdVsFileReport extends SingleFileReport {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package de.aaschmid.gradle.plugins.cpd.internal;

import de.aaschmid.gradle.plugins.cpd.CpdVsFileReport;
import org.gradle.api.Task;
import org.gradle.api.reporting.internal.TaskGeneratedSingleFileReport;

public class CpdVsFileReportImpl extends TaskGeneratedSingleFileReport implements CpdVsFileReport {

public CpdVsFileReportImpl(String name, Task task) {
super(name, task);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import java.util.List;

import de.aaschmid.gradle.plugins.cpd.internal.worker.CpdWorkParameters.Report;
import de.aaschmid.gradle.plugins.cpd.internal.worker.CpdWorkParameters.Report.Xml;
import net.sourceforge.pmd.cpd.CSVRenderer;
import net.sourceforge.pmd.cpd.Match;
import net.sourceforge.pmd.cpd.SimpleRenderer;
import net.sourceforge.pmd.cpd.VSRenderer;
import net.sourceforge.pmd.cpd.XMLRenderer;
import net.sourceforge.pmd.cpd.renderer.CPDRenderer;
import org.gradle.api.GradleException;
Expand Down Expand Up @@ -68,8 +70,11 @@ CPDRenderer createRendererFor(Report report) {
setTrimLeadingWhitespacesByReflection(result, trimLeadingCommonSourceWhitespaces);
return result;

} else if (report instanceof Report.Vs) {
return new VSRenderer();

} else if (report instanceof Report.Xml) {
String encoding = report.getEncoding();
String encoding = ((Xml) report).getEncoding();
if (logger.isDebugEnabled()) {
logger.debug("Creating XML renderer to generate with encoding '{}'.", encoding);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,12 @@ public interface CpdWorkParameters extends WorkParameters {


abstract class Report implements Serializable {
private final String encoding;
private final File destination;

Report(String encoding, File destination) {
this.encoding = requireNonNull(encoding, "'encoding' must not be null for any report.");
Report( File destination) {
this.destination = requireNonNull(destination, "'destination' must not be null for any report.");
}

String getEncoding() {
return encoding;
}

File getDestination() {
return destination;
}
Expand All @@ -60,8 +54,8 @@ public static class Csv extends Report {
private final Character separator;
private final boolean includeLineCount;

public Csv(String encoding, File destination, Character separator, boolean includeLineCount) {
super(encoding, destination);
public Csv(File destination, Character separator, boolean includeLineCount) {
super(destination);
this.separator = separator;
this.includeLineCount = includeLineCount;
}
Expand All @@ -70,7 +64,7 @@ Character getSeparator() {
return separator;
}

public boolean isIncludeLineCount() {
boolean isIncludeLineCount() {
return includeLineCount;
}
}
Expand All @@ -79,8 +73,8 @@ public static class Text extends Report {
private final String lineSeparator;
private final boolean trimLeadingCommonSourceWhitespaces;

public Text(String encoding, File destination, String lineSeparator, boolean trimLeadingCommonSourceWhitespaces) {
super(encoding, destination);
public Text(File destination, String lineSeparator, boolean trimLeadingCommonSourceWhitespaces) {
super(destination);
this.lineSeparator = lineSeparator;
this.trimLeadingCommonSourceWhitespaces = trimLeadingCommonSourceWhitespaces;
}
Expand All @@ -94,9 +88,22 @@ boolean isTrimLeadingCommonSourceWhitespaces() {
}
}

public static class Vs extends Report {
public Vs(File destination) {
super(destination);
}
}

public static class Xml extends Report {
public Xml(String encoding, File destination) {
super(encoding, destination);
private final String encoding;

public Xml(File destination, String encoding) {
super(destination);
this.encoding = encoding;
}

String getEncoding() {
return encoding;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.aaschmid.gradle.plugins.cpd.internal;

import de.aaschmid.gradle.plugins.cpd.Cpd;
import de.aaschmid.gradle.plugins.cpd.test.GradleExtension;
import org.gradle.api.tasks.TaskProvider;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(GradleExtension.class)
class CpdVsFileReportImplTest {

@Test
void CpdVsFileReportImpl_shouldHaveNullAsDefaultEncoding(TaskProvider<Cpd> cpdCheck) {
// When:
CpdVsFileReportImpl result = new CpdVsFileReportImpl("vs", cpdCheck.get());

// Then:
assertThat(result).isNotNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public CpdWorkParameters getParameters() {
void execute_shouldForwardCallCorrectly(Project project) {
// Given:
Set<File> sourceFiles = singleton(testFile(JAVA, "de/aaschmid/clazz/Clazz.java"));
List<Report> reports = singletonList(new Report.Csv("UTF-8", new File("cpd.csv"), ';', true));
List<Report> reports = singletonList(new Report.Csv(new File("cpd.csv"), ';', true));

List<Match> matches = singletonList(mock(Match.class));
when(executor.run(any(), eq(sourceFiles))).thenReturn(matches);
Expand All @@ -92,7 +92,7 @@ void execute_shouldForwardCallCorrectly(Project project) {
@Test
void execute_shouldThrowGradleExceptionIfIgnoreFailuresIsFalse(Project project) {
// Given:
Report.Xml report = new Report.Xml("UTF-8", new File("cpd.xml"));
Report.Xml report = new Report.Xml(new File("cpd.xml"), "UTF-8");

List<Match> matches = singletonList(mock(Match.class));
when(executor.run(any(), any())).thenReturn(matches);
Expand Down Expand Up @@ -180,7 +180,7 @@ void execute_shouldSetCorrectCppProperties(Project project) {

private void stubParametersWithDefaults(Project project) {
Set<File> sourceFiles = singleton(testFile(JAVA, "de/aaschmid/clazz/Clazz.java"));
Report.Text report = new Report.Text("UTF-8", new File("cpd.text"), "\n", false);
Report.Text report = new Report.Text(new File("cpd.text"), "\n", false);

when(parameters.getEncoding()).thenReturn(property("US-ASCII"));
when(parameters.getIgnoreAnnotations()).thenReturn(property(false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
import net.sourceforge.pmd.cpd.SourceCode;
import net.sourceforge.pmd.cpd.SourceCode.StringCodeLoader;
import net.sourceforge.pmd.cpd.TokenEntry;
import net.sourceforge.pmd.cpd.VSRenderer;
import net.sourceforge.pmd.cpd.XMLRenderer;
import net.sourceforge.pmd.cpd.renderer.CPDRenderer;
import org.gradle.api.GradleException;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down Expand Up @@ -66,23 +68,25 @@ void generate_shouldReThrowRendererThrownIoExceptionAsGradleException(@TempDir P

}

static Arguments[] generate_shouldGenerateReport() {
return new Arguments[] {
of(true, "lines,tokens,occurrences\n"),
of(false, "tokens,occurrences\n"),
};
}

@Tag(TestTag.INTEGRATION_TEST)
@ParameterizedTest
@MethodSource
void generate_shouldGenerateReport(boolean includeLineCount, String expectedHeaderLine, @TempDir Path tempDir) {
@Test // ParameterizedTest not possible because Source provider does not allow arguments like @TempDir
void generate_shouldGenerateReport(@TempDir Path tempDir) {
// Given:
File csvReportFile = tempDir.resolve("cpd.csv").toFile();
Report.Csv csvReport = new Report.Csv("UTF-8", csvReportFile, ',', true);
Report.Csv csvReport = new Report.Csv(csvReportFile, ',', true);

File csvReportFileWithoutLines = tempDir.resolve("cpdWithoutLines.csv").toFile();
Report.Csv csvReportWithoutLines = new Report.Csv(csvReportFileWithoutLines, ';', false);

File textReportFile = tempDir.resolve("cpd.text").toFile();
Report.Text textReport = new Report.Text("UTF-8", textReportFile, "#######", false);
Report.Text textReport = new Report.Text(textReportFile, "#######", false);

File vsReportFile = tempDir.resolve("cpd.vs").toFile();
Report.Vs vsReport = new Report.Vs(vsReportFile);

File xmlReportFile = tempDir.resolve("cpd.xml").toFile();
Report.Xml xmlReport = new Report.Xml(xmlReportFile, "ISO-8859-15");


Mark mark = new Mark(new TokenEntry("1", "Clazz1.java", 1));
mark.setLineCount(1);
Expand All @@ -91,17 +95,20 @@ void generate_shouldGenerateReport(boolean includeLineCount, String expectedHead
Match match = new Match(5, mark, mark);

// When:
underTest.generate(asList(csvReport, textReport), asList(match, match));
underTest.generate(asList(csvReport, csvReportWithoutLines, textReport, vsReport, xmlReport), asList(match, match));

// Then:
assertThat(contentOf(csvReportFile)).startsWith("lines,tokens,occurrences\n");
assertThat(contentOf(csvReportFileWithoutLines)).startsWith("tokens;occurrences\n");
assertThat(contentOf(textReportFile)).startsWith("Found a 1 line (5 tokens) duplication in the following files: \n");
assertThat(contentOf(vsReportFile)).startsWith("Clazz1.java(1): Between lines 1 and 2\n");
assertThat(contentOf(xmlReportFile)).startsWith("<?xml version=\"1.0\" encoding=\"ISO-8859-15\"?>\n");
}

@Test
void createRendererFor_shouldReturnCorrectlyConfiguredCsvRenderer() {
// Given:
Report.Csv report = new Report.Csv("UTF-8", new File("cpd.csv"), ';', true);
Report.Csv report = new Report.Csv(new File("cpd.csv"), ';', true);

// When:
CPDRenderer result = underTest.createRendererFor(report);
Expand All @@ -116,7 +123,7 @@ void createRendererFor_shouldReturnCorrectlyConfiguredCsvRenderer() {
@Test
void createRendererFor_shouldReturnCorrectlyConfiguredSimpleRenderer() {
// Given:
Report.Text report = new Report.Text("UTF-8", new File("cpd.txt"), "---", true);
Report.Text report = new Report.Text(new File("cpd.txt"), "---", true);

// When:
CPDRenderer result = underTest.createRendererFor(report);
Expand All @@ -128,10 +135,22 @@ void createRendererFor_shouldReturnCorrectlyConfiguredSimpleRenderer() {
.hasFieldOrPropertyWithValue("trimLeadingWhitespace", true);
}

@Test
void createRendererFor_shouldReturnCorrectlyConfiguredVsRenderer() {
// Given:
Report.Vs report = new Report.Vs(new File("cpd.vs"));

// When:
CPDRenderer result = underTest.createRendererFor(report);

// Then:
assertThat(result).isInstanceOf(VSRenderer.class);
}

@Test
void createRendererFor_shouldReturnCorrectlyConfiguredXmlRenderer() {
// Given:
Report.Xml report = new Report.Xml("ISO-8859-1", new File("cpd.xml"));
Report.Xml report = new Report.Xml(new File("cpd.xml"), "ISO-8859-1");

// When:
CPDRenderer result = underTest.createRendererFor(report);
Expand All @@ -145,7 +164,7 @@ void createRendererFor_shouldReturnCorrectlyConfiguredXmlRenderer() {
@Test
void createRendererFor_shouldThrowGradleExceptionOnUnknownReportType() {
// Given:
Report report = new Report("ISO-8859-1", new File("cpd.xml")) {
Report report = new Report(new File("cpd.xml")) {
};

// Expect:
Expand Down

0 comments on commit fe8efce

Please sign in to comment.