diff --git a/doc/dependency-graph.puml b/doc/dependency-graph.puml index 84665b5f..071de28d 100644 --- a/doc/dependency-graph.puml +++ b/doc/dependency-graph.puml @@ -6,7 +6,7 @@ skinparam rectangle { BackgroundColor<> lightBlue BackgroundColor<> lightGray } -rectangle "coverage-model\n\n0.29.0" as edu_hm_hafner_coverage_model_jar +rectangle "coverage-model\n\n0.30.0-SNAPSHOT" as edu_hm_hafner_coverage_model_jar rectangle "spotbugs-annotations\n\n4.7.3" as com_github_spotbugs_spotbugs_annotations_jar rectangle "error_prone_annotations\n\n2.23.0" as com_google_errorprone_error_prone_annotations_jar rectangle "streamex\n\n0.8.2" as one_util_streamex_jar diff --git a/src/main/java/edu/hm/hafner/coverage/parser/CoberturaParser.java b/src/main/java/edu/hm/hafner/coverage/parser/CoberturaParser.java index 5bc7786f..6eb3beeb 100644 --- a/src/main/java/edu/hm/hafner/coverage/parser/CoberturaParser.java +++ b/src/main/java/edu/hm/hafner/coverage/parser/CoberturaParser.java @@ -19,6 +19,7 @@ import edu.hm.hafner.coverage.CoverageParser; import edu.hm.hafner.coverage.CyclomaticComplexity; import edu.hm.hafner.coverage.FileNode; +import edu.hm.hafner.coverage.MethodNode; import edu.hm.hafner.coverage.Metric; import edu.hm.hafner.coverage.ModuleNode; import edu.hm.hafner.coverage.Node; @@ -98,13 +99,18 @@ protected ModuleNode parseReport(final Reader reader, final FilteredLog log) { readSource(eventReader, root); } else if (PACKAGE.equals(tagName)) { - readPackage(eventReader, root, startElement, log); + readPackage(eventReader, root, readName(startElement), log); isEmpty = false; } } } if (isEmpty) { - throw new NoSuchElementException("No coverage information found in the specified file."); + if (ignoreErrors()) { + log.logError("No coverage information found in the specified file."); + } + else { + throw new NoSuchElementException("No coverage information found in the specified file."); + } } return root; } @@ -114,20 +120,20 @@ else if (PACKAGE.equals(tagName)) { } private void readPackage(final XMLEventReader reader, final ModuleNode root, - final StartElement currentStartElement, final FilteredLog log) throws XMLStreamException { - var packageNode = root.findOrCreatePackageNode(getValueOf(currentStartElement, NAME)); + final String packageName, final FilteredLog log) throws XMLStreamException { + var packageNode = root.findOrCreatePackageNode(packageName); while (reader.hasNext()) { XMLEvent event = reader.nextEvent(); if (event.isStartElement()) { - var nextElement = event.asStartElement(); - if (CLASS.equals(nextElement.getName())) { - var fileName = getValueOf(nextElement, FILE_NAME); + var element = event.asStartElement(); + if (CLASS.equals(element.getName())) { + var fileName = getValueOf(element, FILE_NAME); var relativePath = PATH_UTIL.getRelativePath(fileName); var fileNode = packageNode.findOrCreateFileNode(getFileName(fileName), getTreeStringBuilder().intern(relativePath)); - readClassOrMethod(reader, fileNode, fileNode, nextElement, log); + readClassOrMethod(reader, fileNode, fileNode, element, log); } } else if (event.isEndElement()) { @@ -176,7 +182,7 @@ private void readClassOrMethod(final XMLEventReader reader, } lineCoverage = lineCoverage.add(currentLineCoverage); - if (CLASS.equals(element.getName())) { // Counters are stored at file level + if (CLASS.equals(element.getName())) { // Counters are stored at file level only int lineNumber = getIntegerValueOf(nextElement, NUMBER); fileNode.addCounters(lineNumber, coverage.getCovered(), coverage.getMissed()); } @@ -204,24 +210,37 @@ private Coverage computeLineCoverage(final int coverage) { } private Node createNode(final Node parentNode, final StartElement element, final FilteredLog log) { - var name = getValueOf(element, NAME); - if (StringUtils.isBlank(name)) { // each node must have a unique name - name = createId(); - } + var name = readName(element); if (CLASS.equals(element.getName())) { - if (parentNode.hasChild(name) && ignoreErrors()) { - log.logError("Found a duplicate class '%s' in '%s'", name, parentNode.getName()); - name = name + "-" + createId(); - } - return ((FileNode)parentNode).createClassNode(name); + return createClassNode(parentNode, log, name); } + return createMethodNode(parentNode, element, log, name); + } + + private MethodNode createMethodNode(final Node parentNode, final StartElement element, final FilteredLog log, + final String name) { + String className = name; var signature = getValueOf(element, SIGNATURE); var classNode = (ClassNode) parentNode; - if (classNode.findMethod(name, signature).isPresent() && ignoreErrors()) { - log.logError("Found a duplicate method '%s' with signature '%s' in '%s'", name, signature, parentNode.getName()); - name = name + "-" + createId(); + if (classNode.findMethod(className, signature).isPresent() && ignoreErrors()) { + log.logError("Found a duplicate method '%s' with signature '%s' in '%s'", + className, signature, parentNode.getName()); + className = name + "-" + createId(); + } + return classNode.createMethodNode(className, signature); + } + + private ClassNode createClassNode(final Node parentNode, final FilteredLog log, final String name) { + String className = name; + if (parentNode.hasChild(className) && ignoreErrors()) { + log.logError("Found a duplicate class '%s' in '%s'", className, parentNode.getName()); + className = name + "-" + createId(); } - return classNode.createMethodNode(name, signature); + return ((FileNode) parentNode).createClassNode(className); + } + + private String readName(final StartElement element) { + return StringUtils.defaultIfBlank(getValueOf(element, NAME), createId()); } private String createId() { diff --git a/src/test/java/edu/hm/hafner/coverage/parser/CoberturaParserTest.java b/src/test/java/edu/hm/hafner/coverage/parser/CoberturaParserTest.java index 44d50d8d..e395d670 100644 --- a/src/test/java/edu/hm/hafner/coverage/parser/CoberturaParserTest.java +++ b/src/test/java/edu/hm/hafner/coverage/parser/CoberturaParserTest.java @@ -324,7 +324,7 @@ void shouldConvertCoberturaBigToTree() { Node root = readExampleReport(); assertThat(root.getAll(MODULE)).hasSize(1); - assertThat(root.getAll(PACKAGE)).hasSize(1); + assertThat(root.getAll(PACKAGE)).hasSize(5); assertThat(root.getAll(FILE)).hasSize(4); assertThat(root.getAll(CLASS)).hasSize(5); assertThat(root.getAll(METHOD)).hasSize(10); @@ -389,7 +389,7 @@ void shouldConvertCoberturaBigToTree() { assertThat(root.aggregateValues()).containsExactly( builder.setMetric(MODULE).setCovered(1).setMissed(0).build(), - builder.setMetric(PACKAGE).setCovered(1).setMissed(0).build(), + builder.setMetric(PACKAGE).setCovered(4).setMissed(1).build(), builder.setMetric(FILE).setCovered(4).setMissed(0).build(), builder.setMetric(CLASS).setCovered(5).setMissed(0).build(), builder.setMetric(METHOD).setCovered(7).setMissed(3).build(), @@ -400,9 +400,6 @@ void shouldConvertCoberturaBigToTree() { new FractionValue(COMPLEXITY_DENSITY, 22, 63 + 19), new LinesOfCode(63 + 19)); - assertThat(root.getChildren()).extracting(Node::getName) - .containsExactly("-"); - verifyCoverageMetrics(root); List nodes = root.getAll(FILE);