Skip to content

Commit

Permalink
Add support for Opencover format based on opencover plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
jonesbusy committed Nov 9, 2023
1 parent bb3017d commit 12ee519
Show file tree
Hide file tree
Showing 7 changed files with 7,820 additions and 0 deletions.
168 changes: 168 additions & 0 deletions src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package edu.hm.hafner.coverage.parser;

import java.io.Reader;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.UUID;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import edu.hm.hafner.coverage.CoverageParser;
import edu.hm.hafner.coverage.FileNode;
import edu.hm.hafner.coverage.ModuleNode;
import edu.hm.hafner.coverage.Node;
import edu.hm.hafner.coverage.PackageNode;
import edu.hm.hafner.util.FilteredLog;
import edu.hm.hafner.util.PathUtil;
import edu.hm.hafner.util.SecureXmlParserFactory;
import edu.hm.hafner.util.SecureXmlParserFactory.ParsingException;

/**
* A parser which parses reports made by OpenCover into a Java Object Model.
*
*/
public class OpenCoverParser extends CoverageParser {

private static final long serialVersionUID = 1L;

private static final PathUtil PATH_UTIL = new PathUtil();

/** XML elements. */
private static final QName MODULE = new QName("Module");
private static final QName CLASS = new QName("Class");
private static final QName METHOD = new QName("Method");

Check warning on line 39 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedPrivateField

NORMAL: Avoid unused private fields such as 'METHOD'.
Raw output
Detects when a private field is declared and/or assigned a value, but not used. Since PMD 6.50.0 private fields are ignored, if the fields are annotated with any annotation or the enclosing class has any annotation. Annotations often enable a framework (such as dependency injection, mocking or e.g. Lombok) which use the fields by reflection or other means. This usage can't be detected by static code analysis. Previously these frameworks where explicitly allowed by listing their annotations in the property "ignoredAnnotations", but that turned out to be prone of false positive for any not explicitly considered framework. <pre> <code> public class Something { private static int FOO = 2; // Unused private int i = 5; // Unused private int j = 6; public int addOne() { return j++; } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedprivatefield"> See PMD documentation. </a>
private static final QName CLASS_NAME = new QName("FullName");
private static final QName METHOD_NAME = new QName("Name");

Check warning on line 41 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedPrivateField

NORMAL: Avoid unused private fields such as 'METHOD_NAME'.
Raw output
Detects when a private field is declared and/or assigned a value, but not used. Since PMD 6.50.0 private fields are ignored, if the fields are annotated with any annotation or the enclosing class has any annotation. Annotations often enable a framework (such as dependency injection, mocking or e.g. Lombok) which use the fields by reflection or other means. This usage can't be detected by static code analysis. Previously these frameworks where explicitly allowed by listing their annotations in the property "ignoredAnnotations", but that turned out to be prone of false positive for any not explicitly considered framework. <pre> <code> public class Something { private static int FOO = 2; // Unused private int i = 5; // Unused private int j = 6; public int addOne() { return j++; } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedprivatefield"> See PMD documentation. </a>
private static final QName MODULE_NAME = new QName("ModuleName");
private static final QName FILE = new QName("File");

private static final QName UID = new QName("uid");
private static final QName FULL_PATH = new QName("fullPath");
private static final QName CLASS_COMPLEXITY = new QName("maxCyclomaticComplexity");

Check warning on line 47 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedPrivateField

NORMAL: Avoid unused private fields such as 'CLASS_COMPLEXITY'.
Raw output
Detects when a private field is declared and/or assigned a value, but not used. Since PMD 6.50.0 private fields are ignored, if the fields are annotated with any annotation or the enclosing class has any annotation. Annotations often enable a framework (such as dependency injection, mocking or e.g. Lombok) which use the fields by reflection or other means. This usage can't be detected by static code analysis. Previously these frameworks where explicitly allowed by listing their annotations in the property "ignoredAnnotations", but that turned out to be prone of false positive for any not explicitly considered framework. <pre> <code> public class Something { private static int FOO = 2; // Unused private int i = 5; // Unused private int j = 6; public int addOne() { return j++; } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedprivatefield"> See PMD documentation. </a>
private static final QName METHOD_COMPLEXITY = new QName("cyclomaticComplexity");

Check warning on line 48 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedPrivateField

NORMAL: Avoid unused private fields such as 'METHOD_COMPLEXITY'.
Raw output
Detects when a private field is declared and/or assigned a value, but not used. Since PMD 6.50.0 private fields are ignored, if the fields are annotated with any annotation or the enclosing class has any annotation. Annotations often enable a framework (such as dependency injection, mocking or e.g. Lombok) which use the fields by reflection or other means. This usage can't be detected by static code analysis. Previously these frameworks where explicitly allowed by listing their annotations in the property "ignoredAnnotations", but that turned out to be prone of false positive for any not explicitly considered framework. <pre> <code> public class Something { private static int FOO = 2; // Unused private int i = 5; // Unused private int j = 6; public int addOne() { return j++; } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedprivatefield"> See PMD documentation. </a>

@Override
protected ModuleNode parseReport(final Reader reader, final FilteredLog log) {
try {
var eventReader = new SecureXmlParserFactory().createXmlEventReader(reader);
var root = new ModuleNode("-");
boolean isEmpty = true;
while (eventReader.hasNext()) {
XMLEvent event = eventReader.nextEvent();
if (event.isStartElement()) {
var startElement = event.asStartElement();
var tagName = startElement.getName();
if (MODULE.equals(tagName)) {
readPackage(eventReader, root, startElement, log);

Check warning on line 62 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 62 (VoidMethodCallMutator)
Raw output
Survived mutations:
- removed call to edu/hm/hafner/coverage/parser/OpenCoverParser::readPackage (org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator)
isEmpty = false;
}

Check warning on line 64 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / CPD

CPD

LOW: Found duplicated code.
Raw output
<pre><code>&#64;Override protected ModuleNode parseReport(final Reader reader, final FilteredLog log) { try { var eventReader &#61; new SecureXmlParserFactory().createXmlEventReader(reader); var root &#61; new ModuleNode(&#34;-&#34;); boolean isEmpty &#61; true; while (eventReader.hasNext()) { XMLEvent event &#61; eventReader.nextEvent(); if (event.isStartElement()) { var startElement &#61; event.asStartElement(); var tagName &#61; startElement.getName(); if (SOURCE.equals(tagName)) {<!-- --></code></pre>
}
}
if (isEmpty) {
throw new NoSuchElementException("No coverage information found in the specified file.");
}
return root;

Check warning on line 70 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 70 (NullReturnValsMutator)
Raw output
Survived mutations:
- replaced return value with null for edu/hm/hafner/coverage/parser/OpenCoverParser::parseReport (org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator)
}
catch (XMLStreamException exception) {
throw new ParsingException(exception);
}
}

private void readPackage(final XMLEventReader reader, final ModuleNode root,
final StartElement currentStartElement, final FilteredLog log) throws XMLStreamException {

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'currentStartElement' is never used.

Check warning on line 78 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedFormalParameter

NORMAL: Avoid unused method parameters such as 'currentStartElement'.
Raw output
Reports parameters of methods and constructors that are not referenced them in the method body. Parameters whose name starts with `ignored` or `unused` are filtered out. Removing unused formal parameters from public methods could cause a ripple effect through the code base. Hence, by default, this rule only considers private methods. To include non-private methods, set the `checkAll` property to `true`. <pre> <code> public class Foo { private void bar(String howdy) { // howdy is not used } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedformalparameter"> See PMD documentation. </a>

Check warning on line 78 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / CPD

CPD

LOW: Found duplicated code.
Raw output
<pre><code>else if (PACKAGE.equals(tagName)) { readPackage(eventReader, root, startElement, log); isEmpty &#61; false; } } } if (isEmpty) { throw new NoSuchElementException(&#34;No coverage information found in the specified file.&#34;); } return root; } catch (XMLStreamException exception) { throw new ParsingException(exception); } } private void readPackage(final XMLEventReader reader, final ModuleNode root, final StartElement currentStartElement, final FilteredLog log) throws XMLStreamException {<!-- --></code></pre>

Map<String, String> files = new LinkedHashMap<>();
PackageNode packageNode = null;
while (reader.hasNext()) {

Check warning on line 82 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 82 (NegateConditionalsMutator)
Raw output
Survived mutations:
- negated conditional (org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator)
XMLEvent event = reader.nextEvent();
if (event.isStartElement()) {
var nextElement = event.asStartElement();
if (CLASS.equals(nextElement.getName())) {

Check warning on line 86 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 86 (NegateConditionalsMutator)
Raw output
Survived mutations:
- negated conditional (org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator)
readClass(reader, nextElement, log);

Check warning on line 87 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 87 (VoidMethodCallMutator)
Raw output
Survived mutations:
- removed call to edu/hm/hafner/coverage/parser/OpenCoverParser::readClass (org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator)
}

Check warning on line 88 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / CPD

CPD

LOW: Found duplicated code.
Raw output
<pre><code>while (reader.hasNext()) { XMLEvent event &#61; reader.nextEvent(); if (event.isStartElement()) { var nextElement &#61; event.asStartElement(); if (CLASS.equals(nextElement.getName())) { readClass(reader, packageNode, packageName, nextElement);</code></pre>
else if (FILE.equals(nextElement.getName())) {

Check warning on line 89 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / CPD

CPD

LOW: Found duplicated code.
Raw output
<pre><code>PackageNode packageNode &#61; null; while (reader.hasNext()) { XMLEvent event &#61; reader.nextEvent(); if (event.isStartElement()) { var nextElement &#61; event.asStartElement(); if (CLASS.equals(nextElement.getName())) { readClass(reader, nextElement, log); } else if (FILE.equals(nextElement.getName())) {<!-- --></code></pre>
var fileName = getValueOf(nextElement, FULL_PATH);
var uid = getValueOf(nextElement, UID);
var relativePath = PATH_UTIL.getRelativePath(fileName);
files.put(uid, relativePath);
}
else if (MODULE_NAME.equals(nextElement.getName())) {

Check warning on line 95 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 95 (NegateConditionalsMutator)
Raw output
Survived mutations:
- negated conditional (org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator)
String packageName = reader.nextEvent().asCharacters().getData();
packageNode = root.findOrCreatePackageNode(packageName);
}
}
}

// Creating all file nodes
for (var entry : files.entrySet()) {
packageNode.findOrCreateFileNode(getFileName(entry.getValue()), getTreeStringBuilder().intern(entry.getValue()));

Check warning

Code scanning / CodeQL

Dereferenced variable may be null Warning

Variable
packageNode
may be null at this access because of
this
assignment.
}

}

private void readFile(final XMLEventReader reader, final ModuleNode root,
final StartElement currentStartElement, final FilteredLog log) throws XMLStreamException {

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'currentStartElement' is never used.

Check warning on line 110 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedFormalParameter

NORMAL: Avoid unused method parameters such as 'currentStartElement'.
Raw output
Reports parameters of methods and constructors that are not referenced them in the method body. Parameters whose name starts with `ignored` or `unused` are filtered out. Removing unused formal parameters from public methods could cause a ripple effect through the code base. Hence, by default, this rule only considers private methods. To include non-private methods, set the `checkAll` property to `true`. <pre> <code> public class Foo { private void bar(String howdy) { // howdy is not used } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedformalparameter"> See PMD documentation. </a>

PackageNode packageNode = null;

Check notice

Code scanning / CodeQL

Unread local variable Note

Variable 'PackageNode packageNode' is never read.

Check warning on line 112 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedLocalVariable

NORMAL: Avoid unused local variables such as 'packageNode'.
Raw output
Detects when a local variable is declared and/or assigned, but not used. Variables whose name starts with `ignored` or `unused` are filtered out. <pre> <code> public class Foo { public void doSomething() { int i = 5; // Unused } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedlocalvariable"> See PMD documentation. </a>

Check warning on line 112 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedAssignment

NORMAL: The initializer for variable 'packageNode' is never used (overwritten on line 122).
Raw output
Reports assignments to variables that are never used before the variable is overwritten, or goes out of scope. Unused assignments are those for which 1. The variable is never read after the assignment, or 2. The assigned value is always overwritten by other assignments before the next read of the variable. The rule doesn't consider assignments to fields except for those of `this` in a constructor, or static fields of the current class in static initializers. The rule may be suppressed with the standard `@SuppressWarnings("unused")` tag. The rule subsumes {% rule "UnusedLocalVariable" %}, and {% rule "UnusedFormalParameter" %}. Those violations are filtered out by default, in case you already have enabled those rules, but may be enabled with the property `reportUnusedVariables`. Variables whose name starts with `ignored` or `unused` are filtered out, as is standard practice for exceptions. Limitations: * The rule currently cannot know which method calls throw exceptions, or which exceptions they throw. In the body of a try block, every method or constructor call is assumed to throw. This may cause false-negatives. The only other language construct that is assumed to throw is the `throw` statement, in particular, things like `assert` statements, or NullPointerExceptions on dereference are ignored. * The rule cannot resolve assignments across constructors, when they're called with the special `this(...)` syntax. This may cause false-negatives. Both of those limitations may be partly relaxed in PMD 7. <pre> <code> class A { // this field initializer is redundant, // it is always overwritten in the constructor int f = 1; A(int f) { this.f = f; } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedassignment"> See PMD documentation. </a>
while (reader.hasNext()) {
XMLEvent event = reader.nextEvent();
if (event.isStartElement()) {
var nextElement = event.asStartElement();
if (CLASS.equals(nextElement.getName())) {
readClass(reader, nextElement, log);
}

Check warning on line 119 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / CPD

CPD

LOW: Found duplicated code.
Raw output
<pre><code>while (reader.hasNext()) { XMLEvent event &#61; reader.nextEvent(); if (event.isStartElement()) { var nextElement &#61; event.asStartElement(); if (CLASS.equals(nextElement.getName())) { readClass(reader, packageNode, packageName, nextElement);</code></pre>
else if (MODULE_NAME.equals(nextElement.getName())) {

Check warning on line 120 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / CPD

CPD

LOW: Found duplicated code.
Raw output
<pre><code>PackageNode packageNode &#61; null; while (reader.hasNext()) { XMLEvent event &#61; reader.nextEvent(); if (event.isStartElement()) { var nextElement &#61; event.asStartElement(); if (CLASS.equals(nextElement.getName())) { readClass(reader, nextElement, log); } else if (FILE.equals(nextElement.getName())) {<!-- --></code></pre>
String packageName = reader.nextEvent().asCharacters().getData();
packageNode = root.findOrCreatePackageNode(packageName);

Check warning on line 122 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / SpotBugs

DLS_DEAD_LOCAL_STORE

LOW: Dead store to packageNode in edu.hm.hafner.coverage.parser.OpenCoverParser.readFile(XMLEventReader, ModuleNode, StartElement, FilteredLog)
Raw output
<p> This instruction assigns a value to a local variable, but the value is not read or used in any subsequent instruction. Often, this indicates an error, because the value computed is never used. </p> <p> Note that Sun's javac compiler often generates dead stores for final local variables. Because SpotBugs is a bytecode-based tool, there is no easy way to eliminate these false positives. </p>

Check warning on line 122 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedAssignment

NORMAL: The value assigned to variable 'packageNode' is never used (reassigned every iteration).
Raw output
Reports assignments to variables that are never used before the variable is overwritten, or goes out of scope. Unused assignments are those for which 1. The variable is never read after the assignment, or 2. The assigned value is always overwritten by other assignments before the next read of the variable. The rule doesn't consider assignments to fields except for those of `this` in a constructor, or static fields of the current class in static initializers. The rule may be suppressed with the standard `@SuppressWarnings("unused")` tag. The rule subsumes {% rule "UnusedLocalVariable" %}, and {% rule "UnusedFormalParameter" %}. Those violations are filtered out by default, in case you already have enabled those rules, but may be enabled with the property `reportUnusedVariables`. Variables whose name starts with `ignored` or `unused` are filtered out, as is standard practice for exceptions. Limitations: * The rule currently cannot know which method calls throw exceptions, or which exceptions they throw. In the body of a try block, every method or constructor call is assumed to throw. This may cause false-negatives. The only other language construct that is assumed to throw is the `throw` statement, in particular, things like `assert` statements, or NullPointerExceptions on dereference are ignored. * The rule cannot resolve assignments across constructors, when they're called with the special `this(...)` syntax. This may cause false-negatives. Both of those limitations may be partly relaxed in PMD 7. <pre> <code> class A { // this field initializer is redundant, // it is always overwritten in the constructor int f = 1; A(int f) { this.f = f; } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedassignment"> See PMD documentation. </a>
}
}
}
}

Check warning on line 126 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 112-126 are not covered by tests

Check warning on line 126 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / SpotBugs

UPM_UNCALLED_PRIVATE_METHOD

LOW: Private method edu.hm.hafner.coverage.parser.OpenCoverParser.readFile(XMLEventReader, ModuleNode, StartElement, FilteredLog) is never called
Raw output
<p> This private method is never called. Although it is possible that the method will be invoked through reflection, it is more likely that the method is never used, and should be removed. </p>

private void readClass(final XMLEventReader reader, final StartElement parentElement, final FilteredLog log) throws XMLStreamException {

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'parentElement' is never used.

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'log' is never used.

Check warning on line 128 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedFormalParameter

NORMAL: Avoid unused method parameters such as 'log'.
Raw output
Reports parameters of methods and constructors that are not referenced them in the method body. Parameters whose name starts with `ignored` or `unused` are filtered out. Removing unused formal parameters from public methods could cause a ripple effect through the code base. Hence, by default, this rule only considers private methods. To include non-private methods, set the `checkAll` property to `true`. <pre> <code> public class Foo { private void bar(String howdy) { // howdy is not used } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedformalparameter"> See PMD documentation. </a>

Check warning on line 128 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedFormalParameter

NORMAL: Avoid unused method parameters such as 'parentElement'.
Raw output
Reports parameters of methods and constructors that are not referenced them in the method body. Parameters whose name starts with `ignored` or `unused` are filtered out. Removing unused formal parameters from public methods could cause a ripple effect through the code base. Hence, by default, this rule only considers private methods. To include non-private methods, set the `checkAll` property to `true`. <pre> <code> public class Foo { private void bar(String howdy) { // howdy is not used } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedformalparameter"> See PMD documentation. </a>
while (reader.hasNext()) {

Check warning on line 129 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 129 (NegateConditionalsMutator)
Raw output
Survived mutations:
- negated conditional (org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator)
XMLEvent event = reader.nextEvent();
if (event.isStartElement()) {
var nextElement = event.asStartElement();
if (CLASS_NAME.equals(nextElement.getName())) {
String className = reader.nextEvent().asCharacters().getData();

Check notice

Code scanning / CodeQL

Unread local variable Note

Variable 'String className' is never read.

Check warning on line 134 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / SpotBugs

DLS_DEAD_LOCAL_STORE

LOW: Dead store to $L6 in edu.hm.hafner.coverage.parser.OpenCoverParser.readClass(XMLEventReader, StartElement, FilteredLog)
Raw output
<p> This instruction assigns a value to a local variable, but the value is not read or used in any subsequent instruction. Often, this indicates an error, because the value computed is never used. </p> <p> Note that Sun's javac compiler often generates dead stores for final local variables. Because SpotBugs is a bytecode-based tool, there is no easy way to eliminate these false positives. </p>

Check warning on line 134 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedLocalVariable

NORMAL: Avoid unused local variables such as 'className'.
Raw output
Detects when a local variable is declared and/or assigned, but not used. Variables whose name starts with `ignored` or `unused` are filtered out. <pre> <code> public class Foo { public void doSomething() { int i = 5; // Unused } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedlocalvariable"> See PMD documentation. </a>
}
}
}
}

private int readComplexity(final String c) {
try {
return Math.round(Float.parseFloat(c)); // some reports use float values
}
catch (NumberFormatException ignore) {
return 0;

Check warning on line 145 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / SpotBugs

UPM_UNCALLED_PRIVATE_METHOD

LOW: Private method edu.hm.hafner.coverage.parser.OpenCoverParser.readComplexity(String) is never called
Raw output
<p> This private method is never called. Although it is possible that the method will be invoked through reflection, it is more likely that the method is never used, and should be removed. </p>
}
}

private Node createClassNode(final FileNode file, final StartElement parentElement) {

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'parentElement' is never used.

Check warning on line 149 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / PMD

UnusedFormalParameter

NORMAL: Avoid unused method parameters such as 'parentElement'.
Raw output
Reports parameters of methods and constructors that are not referenced them in the method body. Parameters whose name starts with `ignored` or `unused` are filtered out. Removing unused formal parameters from public methods could cause a ripple effect through the code base. Hence, by default, this rule only considers private methods. To include non-private methods, set the `checkAll` property to `true`. <pre> <code> public class Foo { private void bar(String howdy) { // howdy is not used } } </code> </pre> <a href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedformalparameter"> See PMD documentation. </a>
// Read summary has name
return file.createClassNode(UUID.randomUUID().toString());

Check warning on line 151 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 142-151 are not covered by tests

Check warning on line 151 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / SpotBugs

UPM_UNCALLED_PRIVATE_METHOD

LOW: Private method edu.hm.hafner.coverage.parser.OpenCoverParser.createClassNode(FileNode, StartElement) is never called
Raw output
<p> This private method is never called. Although it is possible that the method will be invoked through reflection, it is more likely that the method is never used, and should be removed. </p>
}

protected static String getValueOf(final StartElement element, final QName attribute) {
return getOptionalValueOf(element, attribute).orElseThrow(

Check warning on line 155 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 155 (EmptyObjectReturnValsMutator)
Raw output
Survived mutations:
- replaced return value with "" for edu/hm/hafner/coverage/parser/OpenCoverParser::getValueOf (org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator)
() -> new NoSuchElementException(String.format(

Check warning on line 156 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 156 is not covered by tests
"Could not obtain attribute '%s' from element '%s'", attribute, element)));
}

private String getFileName(final String relativePath) {
var path = Paths.get(PATH_UTIL.getAbsolutePath(relativePath)).getFileName();
if (path == null) {

Check warning on line 162 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 162 is only partially covered, one branch is missing

Check warning on line 162 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 162 (NegateConditionalsMutator)
Raw output
Survived mutations:
- negated conditional (org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator)
return relativePath;

Check warning on line 163 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 163 is not covered by tests
}
return path.toString();

Check warning on line 165 in src/main/java/edu/hm/hafner/coverage/parser/OpenCoverParser.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 165 (EmptyObjectReturnValsMutator)
Raw output
Survived mutations:
- replaced return value with "" for edu/hm/hafner/coverage/parser/OpenCoverParser::getFileName (org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import edu.hm.hafner.coverage.CoverageParser.ProcessingMode;
import edu.hm.hafner.coverage.parser.CoberturaParser;
import edu.hm.hafner.coverage.parser.JacocoParser;
import edu.hm.hafner.coverage.parser.OpenCoverParser;
import edu.hm.hafner.coverage.parser.PitestParser;

/**
Expand All @@ -15,6 +16,7 @@ public class ParserRegistry {
/** Supported parsers. */
public enum CoverageParserType {
COBERTURA,
OPENCOVER,
JACOCO,
PIT
}
Expand Down Expand Up @@ -52,6 +54,8 @@ public CoverageParser getParser(final CoverageParserType parser, final Processin
switch (parser) {
case COBERTURA:
return new CoberturaParser(processingMode);
case OPENCOVER:
return new OpenCoverParser();
case JACOCO:
return new JacocoParser();
case PIT:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package edu.hm.hafner.coverage.parser;

import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.DefaultLocale;

import edu.hm.hafner.coverage.CoverageParser;
import edu.hm.hafner.coverage.ModuleNode;

@DefaultLocale("en")
class OpenCoverParserTest extends AbstractParserTest {

@Override
CoverageParser createParser() {
return new OpenCoverParser();
}

@Test
void shouldReadReport() {
readExampleReport();
}

private ModuleNode readExampleReport() {
return readReport("opencover.xml", new OpenCoverParser());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import edu.hm.hafner.coverage.CoverageParser.ProcessingMode;
import edu.hm.hafner.coverage.parser.CoberturaParser;
import edu.hm.hafner.coverage.parser.JacocoParser;
import edu.hm.hafner.coverage.parser.OpenCoverParser;
import edu.hm.hafner.coverage.registry.ParserRegistry.CoverageParserType;

import static org.assertj.core.api.Assertions.*;
Expand All @@ -16,6 +17,7 @@ void shouldCreateSomeParsers() {

assertThat(registry.getParser(CoverageParserType.COBERTURA.name(), ProcessingMode.FAIL_FAST)).isInstanceOf(CoberturaParser.class);
assertThat(registry.getParser(CoverageParserType.JACOCO, ProcessingMode.IGNORE_ERRORS)).isInstanceOf(JacocoParser.class);
assertThat(registry.getParser(CoverageParserType.OPENCOVER, ProcessingMode.IGNORE_ERRORS)).isInstanceOf(OpenCoverParser.class);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<CoverageSession>
<Summary numSequencePoints="15" visitedSequencePoints="9" numBranchPoints="6" visitedBranchPoints="3" sequenceCoverage="60" branchCoverage="50" maxCyclomaticComplexity="6" minCyclomaticComplexity="6" visitedClasses="1" numClasses="1" visitedMethods="1" numMethods="1" />
<Modules>
<Module hash="31750BAB-054A-4C4B-8763-D76F95F0353A">
<ModulePath>ClassLibrary.dll</ModulePath>
<ModuleTime>2019-12-13T01:36:13</ModuleTime>
<ModuleName>ClassLibrary</ModuleName>
<Files>
<File uid="1" fullPath="[PLACEHOLDER]" />
</Files>
<Classes>
<Class>
<Summary numSequencePoints="15" visitedSequencePoints="9" numBranchPoints="6" visitedBranchPoints="3" sequenceCoverage="60" branchCoverage="50" maxCyclomaticComplexity="6" minCyclomaticComplexity="6" visitedClasses="1" numClasses="1" visitedMethods="1" numMethods="1" />
<FullName>ClassLibrary.LibraryClass</FullName>
<Methods>
<Method cyclomaticComplexity="6" nPathComplexity="0" sequenceCoverage="60" branchCoverage="50" isConstructor="False" isGetter="False" isSetter="False" isStatic="True">
<Summary numSequencePoints="15" visitedSequencePoints="9" numBranchPoints="6" visitedBranchPoints="3" sequenceCoverage="60" branchCoverage="50" maxCyclomaticComplexity="6" minCyclomaticComplexity="6" visitedClasses="0" numClasses="0" visitedMethods="1" numMethods="1" />
<MetadataToken />
<Name>System.Int32 ClassLibrary.LibraryClass::Sum(System.Int32,System.Int32)</Name>
<FileRef uid="1" />
<SequencePoints>
<SequencePoint vc="2" uspid="8" ordinal="0" sl="8" sc="1" el="8" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="2" uspid="9" ordinal="1" sl="9" sc="1" el="9" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="2" uspid="10" ordinal="2" sl="10" sc="1" el="10" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="0" uspid="13" ordinal="3" sl="13" sc="1" el="13" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="0" uspid="14" ordinal="4" sl="14" sc="1" el="14" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="0" uspid="16" ordinal="5" sl="16" sc="1" el="16" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="0" uspid="17" ordinal="6" sl="17" sc="1" el="17" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="0" uspid="19" ordinal="7" sl="19" sc="1" el="19" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="0" uspid="20" ordinal="8" sl="20" sc="1" el="20" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="1" uspid="22" ordinal="9" sl="22" sc="1" el="22" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="1" uspid="23" ordinal="10" sl="23" sc="1" el="23" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="1" uspid="25" ordinal="11" sl="25" sc="1" el="25" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="1" uspid="26" ordinal="12" sl="26" sc="1" el="26" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="2" uspid="28" ordinal="13" sl="28" sc="1" el="28" ec="2" bec="0" bev="0" fileid="1" />
<SequencePoint vc="2" uspid="29" ordinal="14" sl="29" sc="1" el="29" ec="2" bec="0" bev="0" fileid="1" />
</SequencePoints>
<BranchPoints>
<BranchPoint vc="0" uspid="10" ordinal="1" path="1" offset="8" offsetend="35" sl="10" fileid="1" />
<BranchPoint vc="0" uspid="10" ordinal="2" path="2" offset="8" offsetend="44" sl="10" fileid="1" />
<BranchPoint vc="0" uspid="10" ordinal="3" path="3" offset="8" offsetend="53" sl="10" fileid="1" />
<BranchPoint vc="1" uspid="10" ordinal="4" path="4" offset="8" offsetend="62" sl="10" fileid="1" />
<BranchPoint vc="1" uspid="10" ordinal="5" path="5" offset="8" offsetend="71" sl="10" fileid="1" />
<BranchPoint vc="2" uspid="10" ordinal="0" path="0" offset="8" offsetend="80" sl="10" fileid="1" />
</BranchPoints>
<MethodPoint vc="9" uspid="0" p8:type="SequencePoint" ordinal="0" offset="0" sc="0" sl="8" ec="1" el="29" bec="0" bev="0" fileid="1" xmlns:p8="xsi" />
</Method>
</Methods>
</Class>
</Classes>
</Module>
</Modules>
</CoverageSession>
Loading

0 comments on commit 12ee519

Please sign in to comment.