55import java .util .Collections ;
66import java .util .List ;
77import java .util .NavigableMap ;
8+ import java .util .NavigableSet ;
9+ import java .util .Set ;
810import java .util .TreeMap ;
11+ import java .util .TreeSet ;
912import java .util .stream .Collectors ;
1013
1114import org .apache .commons .lang3 .math .Fraction ;
1417import edu .hm .hafner .coverage .FileNode ;
1518import edu .hm .hafner .coverage .Metric ;
1619import edu .hm .hafner .coverage .Node ;
20+ import edu .hm .hafner .coverage .Value ;
1721import edu .hm .hafner .util .VisibleForTesting ;
1822
1923import hudson .Functions ;
@@ -87,20 +91,48 @@ ChecksDetails extractChecksDetails() {
8791 .withName (checksName )
8892 .withStatus (ChecksStatus .COMPLETED )
8993 .withConclusion (getCheckConclusion (action .getQualityGateResult ().getOverallStatus ()))
90- .withDetailsURL (getCoverageReportBaseUrl ())
94+ .withDetailsURL (getBaseUrl ())
9195 .withOutput (output )
9296 .build ();
9397 }
9498
9599 private String getChecksTitle () {
96- return String .format ("%s: %s" ,
97- FORMATTER .getDisplayName (Baseline .MODIFIED_LINES ),
98- action .formatValue (Baseline .MODIFIED_LINES , Metric .LINE ));
100+ Baseline baseline = selectBaseline ();
101+ return getMetricsForTitle ().stream ()
102+ .filter (metric -> action .hasValue (baseline , metric ))
103+ .map (metric -> format (baseline , metric ))
104+ .collect (Collectors .joining (", " , "" , "." ));
105+ }
106+
107+ private Baseline selectBaseline () {
108+ if (action .hasBaselineResult (Baseline .MODIFIED_LINES )) {
109+ return Baseline .MODIFIED_LINES ;
110+ }
111+ else {
112+ return Baseline .PROJECT ;
113+ }
114+ }
115+
116+ private String format (final Baseline baseline , final Metric metric ) {
117+ String suffix ;
118+ if (action .hasDelta (baseline , metric )) {
119+ suffix = String .format (" (%s)" , action .formatDelta (baseline , metric ));
120+ }
121+ else {
122+ suffix = "" ;
123+ }
124+ return String .format ("%s: %s%s" ,
125+ FORMATTER .getDisplayName (metric ), action .formatValue (baseline , metric ), suffix );
126+ }
127+
128+ private NavigableSet <Metric > getMetricsForTitle () {
129+ return new TreeSet <>(
130+ Set .of (Metric .LINE , Metric .BRANCH , Metric .MUTATION ));
99131 }
100132
101133 private String getSummary () {
102134 var root = rootNode ;
103- return getOverallCoverageSummary (root ) + "\n \n "
135+ return getOverallCoverageSummary () + "\n \n "
104136 + getQualityGatesSummary () + "\n \n "
105137 + getProjectMetricsSummary (root );
106138 }
@@ -132,7 +164,10 @@ private Collection<? extends ChecksAnnotation> getMissingLines(final FileNode fi
132164 var builder = createAnnotationBuilder (fileNode ).withTitle ("Not covered line" );
133165
134166 return fileNode .getMissedLines ().stream ()
135- .map (line -> builder .withMessage ("Line " + line + " is not covered by tests" ).withStartLine (line ).build ())
167+ .map (line -> builder .withMessage ("Line " + line + " is not covered by tests" )
168+ .withStartLine (line )
169+ .withEndLine (line )
170+ .build ())
136171 .collect (Collectors .toList ());
137172 }
138173
@@ -141,7 +176,9 @@ private Collection<? extends ChecksAnnotation> getSurvivedMutations(final FileNo
141176
142177 return fileNode .getSurvivedMutations ().entrySet ().stream ()
143178 .map (entry -> builder .withMessage (createMutationMessage (entry .getKey (), entry .getValue ()))
144- .withStartLine (entry .getKey ()).build ())
179+ .withStartLine (entry .getKey ())
180+ .withEndLine (entry .getKey ())
181+ .build ())
145182 .collect (Collectors .toList ());
146183 }
147184
@@ -157,7 +194,9 @@ private Collection<? extends ChecksAnnotation> getPartiallyCoveredLines(final Fi
157194
158195 return fileNode .getPartiallyCoveredLines ().entrySet ().stream ()
159196 .map (entry -> builder .withMessage (createBranchMessage (entry .getKey (), entry .getValue ()))
160- .withStartLine (entry .getKey ()).build ())
197+ .withStartLine (entry .getKey ())
198+ .withEndLine (entry .getKey ())
199+ .build ())
161200 .collect (Collectors .toList ());
162201 }
163202
@@ -175,79 +214,32 @@ private ChecksAnnotationBuilder createAnnotationBuilder(final FileNode fileNode)
175214 .withAnnotationLevel (ChecksAnnotationLevel .WARNING );
176215 }
177216
178- private String getCoverageReportBaseUrl () {
217+ private String getBaseUrl () {
179218 return jenkinsFacade .getAbsoluteUrl (action .getOwner ().getUrl (), action .getUrlName ());
180219 }
181220
182- private String getOverallCoverageSummary (final Node root ) {
183- String sectionHeader = getSectionHeader (2 , Messages .Checks_Summary ());
184-
185- var modifiedFilesCoverageRoot = root .filterByModifiedFiles ();
186- var modifiedLinesCoverageRoot = root .filterByModifiedLines ();
187- var indirectlyChangedCoverage = root .filterByIndirectChanges ();
188-
189- var projectCoverageHeader = getBulletListItem (1 ,
190- formatText (TextFormat .BOLD , getUrlText (Baseline .PROJECT_DELTA .getTitle (),
191- getCoverageReportBaseUrl () + Baseline .PROJECT_DELTA .getUrl ())));
192- var modifiedFilesCoverageHeader = getBulletListItem (1 ,
193- formatText (TextFormat .BOLD , getUrlText (Baseline .MODIFIED_FILES_DELTA .getTitle (),
194- getCoverageReportBaseUrl () + Baseline .MODIFIED_FILES_DELTA .getUrl ())));
195- var modifiedLinesCoverageHeader = getBulletListItem (1 ,
196- formatText (TextFormat .BOLD , getUrlText (Baseline .MODIFIED_LINES_DELTA .getTitle (),
197- getCoverageReportBaseUrl () + Baseline .MODIFIED_LINES_DELTA .getUrl ())));
198- var indirectCoverageChangesHeader = getBulletListItem (1 ,
199- formatText (TextFormat .BOLD , getUrlText (Baseline .INDIRECT .getTitle (),
200- getCoverageReportBaseUrl () + Baseline .INDIRECT .getUrl ())));
201-
202- var projectCoverageLine = getBulletListItem (2 ,
203- formatCoverageForMetric (Metric .LINE , Baseline .PROJECT ));
204- var projectCoverageBranch = getBulletListItem (2 ,
205- formatCoverageForMetric (Metric .BRANCH , Baseline .PROJECT ));
206- var projectCoverageComplexity = getBulletListItem (2 , formatRootValueOfMetric (root , Metric .COMPLEXITY_DENSITY ));
207- var projectCoverageLoc = getBulletListItem (2 , formatRootValueOfMetric (root , Metric .LOC ));
208-
209- var modifiedFilesCoverageLine = getBulletListItem (2 ,
210- formatCoverageForMetric (Metric .LINE , Baseline .MODIFIED_FILES ));
211- var modifiedFilesCoverageBranch = getBulletListItem (2 ,
212- formatCoverageForMetric (Metric .BRANCH , Baseline .MODIFIED_FILES ));
213- var modifiedFilesCoverageComplexity = getBulletListItem (2 ,
214- formatRootValueOfMetric (modifiedFilesCoverageRoot , Metric .COMPLEXITY_DENSITY ));
215- var modifiedFilesCoverageLoc = getBulletListItem (2 ,
216- formatRootValueOfMetric (modifiedFilesCoverageRoot , Metric .LOC ));
217-
218- var modifiedLinesCoverageLine = getBulletListItem (2 ,
219- formatCoverageForMetric (Metric .LINE , Baseline .MODIFIED_LINES ));
220- var modifiedLinesCoverageBranch = getBulletListItem (2 ,
221- formatCoverageForMetric (Metric .BRANCH , Baseline .MODIFIED_LINES ));
222- var modifiedLinesCoverageLoc = getBulletListItem (2 ,
223- formatRootValueOfMetric (modifiedLinesCoverageRoot , Metric .LOC ));
224-
225- var indirectCoverageChangesLine = getBulletListItem (2 ,
226- formatCoverageForMetric (Metric .LINE , Baseline .INDIRECT ));
227- var indirectCoverageChangesBranch = getBulletListItem (2 ,
228- formatCoverageForMetric (Metric .BRANCH , Baseline .INDIRECT ));
229- var indirectCoverageChangesLoc = getBulletListItem (2 ,
230- formatRootValueOfMetric (indirectlyChangedCoverage , Metric .LOC ));
221+ private List <Baseline > getBaselines () {
222+ return List .of (Baseline .PROJECT , Baseline .MODIFIED_FILES , Baseline .MODIFIED_LINES , Baseline .INDIRECT );
223+ }
231224
232- return sectionHeader
233- + projectCoverageHeader
234- + projectCoverageLine
235- + projectCoverageBranch
236- + projectCoverageComplexity
237- + projectCoverageLoc
238- + modifiedFilesCoverageHeader
239- + modifiedFilesCoverageLine
240- + modifiedFilesCoverageBranch
241- + modifiedFilesCoverageComplexity
242- + modifiedFilesCoverageLoc
243- + modifiedLinesCoverageHeader
244- + modifiedLinesCoverageLine
245- + modifiedLinesCoverageBranch
246- + modifiedLinesCoverageLoc
247- + indirectCoverageChangesHeader
248- + indirectCoverageChangesLine
249- + indirectCoverageChangesBranch
250- + indirectCoverageChangesLoc ;
225+ private String getOverallCoverageSummary () {
226+ StringBuilder description = new StringBuilder (getSectionHeader (2 , Messages .Checks_Summary ()));
227+
228+ for (Baseline baseline : getBaselines ()) {
229+ if (action .hasBaselineResult (baseline )) {
230+ description .append (getBulletListItem (1 ,
231+ formatText (TextFormat .BOLD ,
232+ getUrlText (action .getTitle (baseline ), getBaseUrl () + baseline .getUrl ()))));
233+ for (Value value : action .getValues (baseline )) {
234+ String display = FORMATTER .formatDetailedValueWithMetric (value );
235+ if (action .hasDelta (baseline , value .getMetric ())) {
236+ display += String .format (" - Delta: %s" , action .formatDelta (baseline , value .getMetric ()));
237+ }
238+ description .append (getBulletListItem (2 , display ));
239+ }
240+ }
241+ }
242+ return description .toString ();
251243 }
252244
253245 /**
@@ -289,17 +281,6 @@ private String getProjectMetricsSummary(final Node result) {
289281 + projectCoverageDeltaRow ;
290282 }
291283
292- private String formatCoverageForMetric (final Metric metric , final Baseline baseline ) {
293- return String .format ("%s: %s / %s" , FORMATTER .getDisplayName (metric ),
294- action .formatValue (baseline , metric ), action .formatDelta (baseline , metric ));
295- }
296-
297- private String formatRootValueOfMetric (final Node root , final Metric metric ) {
298- var value = root .getValue (metric );
299- return value .map (FORMATTER ::formatValueWithMetric )
300- .orElseGet (() -> FORMATTER .getDisplayName (metric ) + ": " + Messages .Coverage_Not_Available ());
301- }
302-
303284 private String formatText (final TextFormat format , final String text ) {
304285 switch (format ) {
305286 case BOLD :
0 commit comments