Skip to content

Commit

Permalink
Merge pull request #399 from guillermocalvo/report-only-summary
Browse files Browse the repository at this point in the history
New option to make reports less verbose `--report-only-summary`
  • Loading branch information
siom79 authored Jul 21, 2024
2 parents 7e1d97a + 3b46f6b commit 8124a53
Show file tree
Hide file tree
Showing 14 changed files with 168 additions and 2 deletions.
6 changes: 6 additions & 0 deletions japicmp-ant-task/src/main/java/japicmp/ant/JApiCmpTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class JApiCmpTask extends Task {
private boolean noAnnotations = false;
private boolean semanticVersioning = false;
private boolean reportOnlyFilename = false;
private boolean reportOnlySummary = false;
private boolean ignoreMissingClasses = false;
private boolean includeExclusively = false;
private boolean excludeExclusively = false;
Expand Down Expand Up @@ -91,6 +92,10 @@ public void setReportOnlyFilename(String reportOnlyFilename) {
this.reportOnlyFilename = Project.toBoolean(reportOnlyFilename);
}

public void setReportOnlySummary(String reportOnlySummary) {
this.reportOnlySummary = Project.toBoolean(reportOnlySummary);
}

public void setIgnoreMissingClasses(String ignoreMissingClasses) {
this.ignoreMissingClasses = Project.toBoolean(ignoreMissingClasses);
}
Expand Down Expand Up @@ -242,6 +247,7 @@ private Options createOptionsFromAntAttrs() {
options.addIgnoreMissingClassRegularExpression(missingClassRegEx);
}
options.setReportOnlyFilename(reportOnlyFilename);
options.setReportOnlySummary(reportOnlySummary);
options.setErrorOnSemanticIncompatibility(errorOnSemanticIncompatibility);
options.setErrorOnExclusionIncompatibility(errorOnExclusionIncompatibility);
options.setErrorOnSourceIncompatibility(errorOnSourceIncompatibility);
Expand Down
11 changes: 11 additions & 0 deletions japicmp-ant-task/src/test/java/japicmp/ant/JApiCmpTaskTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.junit.Rule;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;

Expand All @@ -28,6 +29,16 @@ public void testCompare() {
containsString("---! REMOVED METHOD: PUBLIC(-) java.util.List<japicmp.model.JApiClass> compare(java.io.File, java.io.File)"));
}

@Test
public void testReportOnlySummary() {
rule.executeTarget("summary");
String logContents = rule.getLog();
assertThat("Incorrect log message (expected modified class)", logContents,
containsString("***! MODIFIED CLASS: PUBLIC japicmp.cmp.JarArchiveComparator (not serializable)"));
assertThat("Incorrect log message (expected removed method)", logContents,
not(containsString("---! REMOVED METHOD: PUBLIC(-) java.util.List<japicmp.model.JApiClass> compare(java.io.File, java.io.File)")));
}

@Test(expected = BuildException.class)
public void testBreakOnBinaryIncompatibility() {
rule.executeTarget("binary");
Expand Down
5 changes: 5 additions & 0 deletions japicmp-ant-task/src/test/resources/japicmp/japicmptask.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
classpathref="compare.classpath" onlybinaryincompatible="true"/>
</target>

<target name="summary" depends="init">
<japicmp oldjar="${japicmp.reference.jar}" newjar="${japicmp.current.jar}" reportOnlySummary="true"
classpathref="compare.classpath" onlybinaryincompatible="true"/>
</target>

<target name="binary" depends="init">
<japicmp oldjar="${japicmp.reference.jar}" newjar="${japicmp.current.jar}" ignoremissingclasses="true"
classpathref="compare.classpath" erroronbinaryincompatibility="true"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ Options getOptions(PluginParameters pluginParameters, MavenParameters mavenParam
}
this.options.setNoAnnotations(parameterParam.getNoAnnotations());
this.options.setReportOnlyFilename(parameterParam.isReportOnlyFilename());
this.options.setReportOnlySummary(parameterParam.isReportOnlySummary());
}
return this.options;
}
Expand Down
10 changes: 10 additions & 0 deletions japicmp-maven-plugin/src/main/java/japicmp/maven/Parameter.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public class Parameter {
@org.apache.maven.plugins.annotations.Parameter(required = false)
private boolean reportOnlyFilename;
@org.apache.maven.plugins.annotations.Parameter(required = false)
private boolean reportOnlySummary;
@org.apache.maven.plugins.annotations.Parameter(required = false)
private List<String> includeModules;
@org.apache.maven.plugins.annotations.Parameter(required = false)
private List<String> excludeModules;
Expand Down Expand Up @@ -323,6 +325,14 @@ public void setReportOnlyFilename(boolean reportOnlyFileName) {
this.reportOnlyFilename = reportOnlyFileName;
}

public boolean isReportOnlySummary() {
return reportOnlySummary;
}

public void setReportOnlySummary(boolean reportOnlySummary) {
this.reportOnlySummary = reportOnlySummary;
}

public boolean getIgnoreMissingNewVersion() {
return ignoreMissingNewVersion;
}
Expand Down
9 changes: 8 additions & 1 deletion japicmp/src/main/java/japicmp/cli/CliParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ public Options parse(String[] args) throws IllegalArgumentException {
options.setNoAnnotations(true);
} else if ("--report-only-filename".equals(arg)) {
options.setReportOnlyFilename(true);
} else if ("--report-only-summary".equals(arg)) {
options.setReportOnlySummary(true);
} else if ("--error-on-binary-incompatibility".equals(arg)) {
options.setErrorOnBinaryIncompatibility(true);
} else if ("--error-on-source-incompatibility".equals(arg)) {
Expand Down Expand Up @@ -123,7 +125,8 @@ public static void printHelp() {
" [(-n <pathToNewVersionJar> | --new <pathToNewVersionJar>)]\n" +
" [--new-classpath <newClassPath>] [--no-annotations]\n" +
" [(-o <pathToOldVersionJar> | --old <pathToOldVersionJar>)]\n" +
" [--old-classpath <oldClassPath>] [--report-only-filename]\n" +
" [--old-classpath <oldClassPath>]\n" +
" [--report-only-filename] [--report-only-summary]\n" +
" [(-s | --semantic-versioning)]\n" +
" [(-x <pathToXmlOutputFile> | --xml-file <pathToXmlOutputFile>)]\n" +
" [--error-on-binary-incompatibility]\n" +
Expand Down Expand Up @@ -205,6 +208,10 @@ public static void printHelp() {
" --report-only-filename\n" +
" Reports just filenames (not full paths) in report description.\n" +
"\n" +
" --report-only-summary\n" +
" Reports only a breakdown of classes and their status\n" +
" when generating plain text or html reports.\n" +
"\n" +
" -s, --semantic-versioning\n" +
" Tells you which part of the version to increment.\n" +
"\n" +
Expand Down
9 changes: 9 additions & 0 deletions japicmp/src/main/java/japicmp/config/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class Options {
private JApiCli.ClassPathMode classPathMode = JApiCli.ClassPathMode.ONE_COMMON_CLASSPATH;
private boolean noAnnotations = false;
private boolean reportOnlyFilename;
private boolean reportOnlySummary;
private boolean semanticVersioning;
private boolean errorOnBinaryIncompatibility;
private boolean errorOnSourceIncompatibility;
Expand Down Expand Up @@ -306,6 +307,14 @@ public void setReportOnlyFilename(boolean reportOnlyFilename) {
this.reportOnlyFilename = reportOnlyFilename;
}

public boolean isReportOnlySummary() {
return reportOnlySummary;
}

public void setReportOnlySummary(boolean reportOnlySummary) {
this.reportOnlySummary = reportOnlySummary;
}

public String getDifferenceDescription() {
Joiner joiner = Joiner.on(";");
StringBuilder sb = new StringBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ public HtmlOutput generate() {
}

private void classes(StringBuilder sb) {
if (options.isReportOnlySummary()) {
return;
}
sb.append(jApiClasses.stream()
.map(jApiClass -> templateEngine.loadAndFillTemplate("/html/class-entry.html", mapOf(
"fullyQualifiedName", jApiClass.getFullyQualifiedName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ public String generate() {
if (!jApiClasses.isEmpty()) {
for (JApiClass jApiClass : jApiClasses) {
processClass(sb, jApiClass);
if (options.isReportOnlySummary()) {
continue;
}
processConstructors(sb, jApiClass);
processMethods(sb, jApiClass);
processAnnotations(sb, jApiClass, 1);
Expand Down Expand Up @@ -319,6 +322,9 @@ private String tabs(int numberOfTabs) {

private void appendClass(StringBuilder sb, String signs, JApiClass jApiClass) {
sb.append(signs).append(" ").append(jApiClass.getChangeStatus()).append(" ").append(processClassType(jApiClass)).append(": ").append(accessModifierAsString(jApiClass)).append(abstractModifierAsString(jApiClass)).append(staticModifierAsString(jApiClass)).append(finalModifierAsString(jApiClass)).append(syntheticModifierAsString(jApiClass)).append(jApiClass.getFullyQualifiedName()).append(" ").append(javaObjectSerializationStatus(jApiClass)).append("\n");
if (options.isReportOnlySummary()) {
return;
}
processClassFileFormatVersionChanges(sb, jApiClass);
processGenericTemplateChanges(sb, jApiClass, 1);
processInterfaceChanges(sb, jApiClass);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import javassist.NotFoundException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Evaluator;
import org.junit.Test;

import java.nio.charset.StandardCharsets;
Expand All @@ -20,6 +21,7 @@
import java.util.Collections;
import java.util.List;

import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.StringContains.containsString;
Expand Down Expand Up @@ -60,4 +62,62 @@ public List<CtClass> createNewClasses(ClassPool classPool) throws CannotCompileE
assertThat(document.select("#meta-accessmodifier-value").text(), is("PROTECTED"));
assertThat(document.select("#warning-missingclasses").text(), containsString("WARNING"));
}

@Test
public void testSummaryOnly() throws Exception {
JarArchiveComparatorOptions jarArchiveComparatorOptions = new JarArchiveComparatorOptions();
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(jarArchiveComparatorOptions, new ClassesHelper.ClassesGenerator() {
@Override
public List<CtClass> createOldClasses(ClassPool classPool) throws Exception {
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").withAnnotation("japicmp.Annotation").addToClassPool(classPool);
CtFieldBuilder.create().type(CtClass.intType).name("foo").addToClass(ctClass);
CtMethodBuilder.create().publicAccess().returnType(CtClass.intType).name("bar").addToClass(ctClass);
CtConstructorBuilder.create().publicAccess().addToClass(ctClass);
return Collections.singletonList(ctClass);
}

@Override
public List<CtClass> createNewClasses(ClassPool classPool) {
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
return Collections.singletonList(ctClass);
}
});

Options reportOptions = Options.newDefault();
reportOptions.setIgnoreMissingClasses(true);
HtmlOutputGenerator generator = new HtmlOutputGenerator(jApiClasses, reportOptions, new HtmlOutputGeneratorOptions());

HtmlOutput htmlOutput = generator.generate();

Document document = Jsoup.parse(htmlOutput.getHtml());
assertThat(document.select("#meta-accessmodifier-value").text(), is("PROTECTED"));
assertThat(document.select("#warning-missingclasses").text(), containsString("WARNING"));

String summary = document.select("#toc").text();
assertThat(summary, containsString("MODIFIED"));
assertThat(summary, containsString("japicmp.Test"));

String details = document.select(new Evaluator.Id("japicmp.Test")).text();
assertThat(details, containsString("FIELD_REMOVED"));
assertThat(details, containsString("CONSTRUCTOR_REMOVED"));
assertThat(details, containsString("METHOD_REMOVED"));
assertThat(details, containsString("ANNOTATION_REMOVED"));

reportOptions.setReportOnlySummary(true);
htmlOutput = generator.generate();

document = Jsoup.parse(htmlOutput.getHtml());
assertThat(document.select("#meta-accessmodifier-value").text(), is("PROTECTED"));
assertThat(document.select("#warning-missingclasses").text(), containsString("WARNING"));

summary = document.select("#toc").text();
assertThat(summary, containsString("MODIFIED"));
assertThat(summary, containsString("japicmp.Test"));

details = document.select(new Evaluator.Id("japicmp.Test")).text();
assertThat(details, not(containsString("FIELD_REMOVED")));
assertThat(details, not(containsString("CONSTRUCTOR_REMOVED")));
assertThat(details, not(containsString("METHOD_REMOVED")));
assertThat(details, not(containsString("ANNOTATION_REMOVED")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import japicmp.model.AccessModifier;
import japicmp.model.JApiClass;
import japicmp.util.CtClassBuilder;
import japicmp.util.CtConstructorBuilder;
import japicmp.util.CtFieldBuilder;
import japicmp.util.CtInterfaceBuilder;
import japicmp.util.CtMethodBuilder;
Expand Down Expand Up @@ -144,4 +145,44 @@ public List<CtClass> createNewClasses(ClassPool classPool) throws Exception {
String generated = generator.generate();
Assert.assertTrue(generated.contains("===* UNCHANGED FIELD: PUBLIC java.util.List<java.lang.Short>(<- <java.lang.Byte>) list"));
}

@Test
public void testSummaryOnly() throws Exception {
JarArchiveComparatorOptions jarArchiveComparatorOptions = new JarArchiveComparatorOptions();
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(jarArchiveComparatorOptions, new ClassesHelper.ClassesGenerator() {
@Override
public List<CtClass> createOldClasses(ClassPool classPool) throws Exception {
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").withAnnotation("japicmp.Annotation").addToClassPool(classPool);
CtFieldBuilder.create().type(CtClass.intType).name("foo").addToClass(ctClass);
CtMethodBuilder.create().publicAccess().returnType(CtClass.intType).name("bar").addToClass(ctClass);
CtConstructorBuilder.create().publicAccess().addToClass(ctClass);
return Collections.singletonList(ctClass);
}

@Override
public List<CtClass> createNewClasses(ClassPool classPool) {
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
return Collections.singletonList(ctClass);
}
});
Options options = Options.newDefault();
StdoutOutputGenerator generator = new StdoutOutputGenerator(options, jApiClasses);
String generated = generator.generate();
Assert.assertTrue(generated.contains("***! MODIFIED CLASS: PUBLIC japicmp.Test"));
Assert.assertTrue(generated.contains("=== CLASS FILE FORMAT VERSION"));
Assert.assertTrue(generated.contains("=== UNCHANGED SUPERCLASS"));
Assert.assertTrue(generated.contains("---! REMOVED FIELD"));
Assert.assertTrue(generated.contains("---! REMOVED CONSTRUCTOR"));
Assert.assertTrue(generated.contains("---! REMOVED METHOD"));
Assert.assertTrue(generated.contains("--- REMOVED ANNOTATION"));
options.setReportOnlySummary(true);
generated = generator.generate();
Assert.assertTrue(generated.contains("***! MODIFIED CLASS: PUBLIC japicmp.Test"));
Assert.assertFalse(generated.contains("=== CLASS FILE FORMAT VERSION"));
Assert.assertFalse(generated.contains("=== UNCHANGED SUPERCLASS"));
Assert.assertFalse(generated.contains("---! REMOVED FIELD"));
Assert.assertFalse(generated.contains("---! REMOVED CONSTRUCTOR"));
Assert.assertFalse(generated.contains("---! REMOVED METHOD"));
Assert.assertFalse(generated.contains("--- REMOVED ANNOTATION"));
}
}
1 change: 1 addition & 0 deletions src/site/markdown/AntTask.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ The following table gives an overview of all available parameters of the Ant tas
| includeSynthetic | true | false | If true, track changes for synthetic classes and class members.|
| noAnnotations | true | false | If true, disable the evaluation of annotations completely.|
| reportOnlyFilename | true | false | If true, report only filenames (not full paths). |
| reportOnlySummary | true | false | If true, report only a breakdown of classes and their status when generating plain text or html reports. |
| ignoreMissingClasses | true | n.a. | Ignore all superclasses/interfaces missing on the classpath. |
| ignoreMissingClassesbyRegularExpressions | true | n.a. | Ignore only those superclasses/interface missing on the classpath that are selected by a regular expression. |
| accessModifier | true | protected | Ignore changes below the access modifier level (public, package, protected, private).|
Expand Down
7 changes: 6 additions & 1 deletion src/site/markdown/CliTool.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ SYNOPSIS
[(-n <pathToNewVersionJar> | --new <pathToNewVersionJar>)]
[--new-classpath <newClassPath>] [--no-annotations]
[(-o <pathToOldVersionJar> | --old <pathToOldVersionJar>)]
[--old-classpath <oldClassPath>] [--report-only-filename]
[--old-classpath <oldClassPath>]
[--report-only-filename] [--report-only-summary]
[(-s | --semantic-versioning)]
[(-x <pathToXmlOutputFile> | --xml-file <pathToXmlOutputFile>)]
[--error-on-binary-incompatibility]
Expand Down Expand Up @@ -97,6 +98,10 @@ OPTIONS
--report-only-filename
Reports just filenames (not full paths) in report description.
--report-only-summary
Reports only a breakdown of classes and their status
when generating plain text or html reports.
-s, --semantic-versioning
Tells you which part of the version to increment.
Expand Down
1 change: 1 addition & 0 deletions src/site/markdown/MavenPlugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ the &lt;dependency&gt; element. Through the &lt;parameter&gt; element you can pr
| includeSynthetic | true | false | If set to true, changes for synthetic classes and class members are tracked. |
| noAnnotations | true | false | Setting this option to true disables the evaluation of annotations completely. |
| reportOnlyFilename | true | false | If set to true, report will include only the artifact filename, not the complete artifact file path. |
| reportOnlySummary | true | false | If set to true, report only a breakdown of classes and their status when generating plain text or html reports. |
| ignoreMissingClasses | true | false | If set to true, superclasses and interfaces that cannot be resolved are ignored. Pleases note that in this case the results for the affected classes may not be accurate. |
| ignoreMissingClassesByRegularExpressions | true | n.a. | List of regular expressions for superclasses and interfaces that cannot be resolved and that should be ignored. In contrast to the option ignoreMissingClasses, which ignores all missing classes, this options allows a fine-grained selection. |
| accessModifier | true | protected | Sets the access modifier level (public, protected, package_protected, private). |
Expand Down

0 comments on commit 8124a53

Please sign in to comment.