-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
Added PMD Metrics Parser
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
package edu.hm.hafner.coverage.parser; | ||
|
||
import java.io.Reader; | ||
import java.nio.file.Paths; | ||
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 com.google.errorprone.annotations.CanIgnoreReturnValue; | ||
|
||
import edu.hm.hafner.coverage.ClassNode; | ||
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; | ||
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.TreeString; | ||
|
||
/** | ||
* Parses Metrics reports into a hierarchical Java Object Model. | ||
* | ||
* @author Maximilian Waidelich | ||
*/ | ||
@SuppressWarnings("PMD.GodClass") | ||
public class MetricsParser extends CoverageParser { | ||
private static final long serialVersionUID = -4461747681863455621L; | ||
|
||
/** XML elements. */ | ||
private static final QName METRICS = new QName("metrics"); | ||
private static final QName PACKAGE = new QName("package"); | ||
private static final QName CLASS = new QName("class"); | ||
private static final QName METHOD = new QName("method"); | ||
private static final QName METRIC = new QName("metric"); | ||
private static final QName FILE = new QName("file"); | ||
|
||
/** Attributes of the XML elements. */ | ||
private static final QName PROJECT_NAME = new QName("projectName"); | ||
private static final QName NAME = new QName("name"); | ||
private static final QName BEGIN_LINE = new QName("beginline"); | ||
private static final QName VALUE = new QName("value"); | ||
|
||
private static final String CYCLOMATIC_COMPLEXITY = "CyclomaticComplexity"; | ||
private static final String COGNITIVE_COMPLEXITY = "CognitiveComplexity"; | ||
private static final String NCSS = "NCSS"; | ||
private static final String NPATH_COMPLEXITY = "NPathComplexity"; | ||
|
||
private static final PathUtil PATH_UTIL = new PathUtil(); | ||
|
||
/** | ||
* Creates a new instance of {@link MetricsParser}. | ||
*/ | ||
public MetricsParser() { | ||
this(ProcessingMode.FAIL_FAST); | ||
} | ||
Check warning on line 62 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorNot covered lines
|
||
|
||
/** | ||
* Creates a new instance of {@link MetricsParser}. | ||
* | ||
* @param processingMode | ||
* determines whether to ignore errors | ||
*/ | ||
public MetricsParser(final ProcessingMode processingMode) { | ||
super(processingMode); | ||
} | ||
|
||
@Override | ||
protected ModuleNode parseReport(final Reader reader, final String fileName, final FilteredLog log) { | ||
try { | ||
var factory = new SecureXmlParserFactory(); | ||
var eventReader = factory.createXmlEventReader(reader); | ||
|
||
ModuleNode root = new ModuleNode(""); | ||
|
||
while (eventReader.hasNext()) { | ||
XMLEvent event = eventReader.nextEvent(); | ||
|
||
if (event.isStartElement()) { | ||
var startElement = event.asStartElement(); | ||
var tagName = startElement.getName(); | ||
if (METRICS.equals(tagName)) { | ||
Check warning on line 88 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
root = new ModuleNode(getOptionalValueOf(startElement, PROJECT_NAME).orElse("")); | ||
} | ||
else if (PACKAGE.equals(tagName)) { | ||
Check warning on line 91 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
readPackage(eventReader, root, startElement, fileName); | ||
} | ||
} | ||
} | ||
if (root.hasChildren()) { | ||
return root; | ||
} | ||
else { | ||
handleEmptyResults(fileName, log); | ||
return new ModuleNode("empty"); | ||
} | ||
} | ||
catch (XMLStreamException exception) { | ||
throw new ParsingException(exception); | ||
} | ||
} | ||
|
||
@CanIgnoreReturnValue | ||
private PackageNode readPackage(final XMLEventReader reader, final ModuleNode root, | ||
final StartElement startElement, final String fileName) throws XMLStreamException { | ||
var packageName = getValueOf(startElement, NAME); | ||
var packageNode = root.findOrCreatePackageNode(packageName); | ||
while (reader.hasNext()) { | ||
Check warning on line 114 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorPartially covered line
|
||
XMLEvent event = reader.nextEvent(); | ||
|
||
if (event.isStartElement()) { | ||
var nextElement = event.asStartElement(); | ||
if (FILE.equals(nextElement.getName())) { | ||
Check warning on line 119 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
readSourceFile(reader, packageNode, nextElement, fileName); | ||
} | ||
else if (METRIC.equals(nextElement.getName())) { | ||
Check warning on line 122 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
Check warning on line 122 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorPartially covered line
|
||
readValueCounter(packageNode, nextElement); | ||
} | ||
} | ||
else if (event.isEndElement()) { | ||
var endElement = event.asEndElement(); | ||
if (PACKAGE.equals(endElement.getName())) { | ||
Check warning on line 128 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
Check warning on line 128 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorMutation survived
Raw output
|
||
return packageNode; | ||
Check warning on line 129 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorMutation survived
Raw output
|
||
} | ||
} | ||
} | ||
throw createEofException(fileName); | ||
Check warning on line 133 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorNot covered line
|
||
} | ||
|
||
@CanIgnoreReturnValue | ||
private Node readClass(final XMLEventReader reader, final FileNode fileNode, final StartElement startElement, | ||
final String fileName, final PackageNode packageNode) throws XMLStreamException { | ||
ClassNode classNode = fileNode.findOrCreateClassNode(packageNode.getName() + "." + getValueOf(startElement, NAME)); | ||
while (reader.hasNext()) { | ||
Check warning on line 140 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorPartially covered line
|
||
XMLEvent event = reader.nextEvent(); | ||
|
||
if (event.isStartElement()) { | ||
var nextElement = event.asStartElement(); | ||
if (METHOD.equals(nextElement.getName())) { | ||
Check warning on line 145 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
readMethod(reader, classNode, nextElement, fileName); | ||
} | ||
else if (METRIC.equals(nextElement.getName())) { | ||
Check warning on line 148 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
Check warning on line 148 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorPartially covered line
|
||
readValueCounter(classNode, nextElement); | ||
} | ||
} | ||
else if (event.isEndElement()) { | ||
var endElement = event.asEndElement(); | ||
if (CLASS.equals(endElement.getName())) { | ||
Check warning on line 154 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
return classNode; | ||
Check warning on line 155 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorMutation survived
Raw output
|
||
} | ||
} | ||
} | ||
throw createEofException(fileName); | ||
Check warning on line 159 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorNot covered line
|
||
} | ||
|
||
private TreeString internPath(final String filePath) { | ||
return getTreeStringBuilder().intern(PATH_UTIL.getRelativePath(Paths.get(filePath))); | ||
} | ||
|
||
@CanIgnoreReturnValue | ||
private Node readSourceFile(final XMLEventReader reader, final PackageNode packageNode, | ||
final StartElement startElement, final String fileName) | ||
throws XMLStreamException { | ||
String sourceFileName = getSourceFileName(startElement); | ||
var fileNode = packageNode.findOrCreateFileNode(sourceFileName, | ||
internPath(getValueOf(startElement, NAME))); | ||
|
||
while (reader.hasNext()) { | ||
Check warning on line 174 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorPartially covered line
|
||
XMLEvent event = reader.nextEvent(); | ||
|
||
if (event.isStartElement()) { | ||
var nextElement = event.asStartElement(); | ||
if (CLASS.equals(nextElement.getName())) { | ||
Check warning on line 179 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
readClass(reader, fileNode, nextElement, fileName, packageNode); | ||
} | ||
else if (METRIC.equals(nextElement.getName())) { | ||
Check warning on line 182 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
Check warning on line 182 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorPartially covered line
|
||
readValueCounter(fileNode, nextElement); | ||
} | ||
} | ||
else if (event.isEndElement()) { | ||
var endElement = event.asEndElement(); | ||
if (FILE.equals(endElement.getName())) { | ||
Check warning on line 188 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
return fileNode; | ||
Check warning on line 189 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorMutation survived
Raw output
|
||
} | ||
} | ||
} | ||
throw createEofException(fileName); | ||
Check warning on line 193 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorNot covered line
|
||
} | ||
|
||
private String getSourceFileName(final StartElement startSourceFileElement) { | ||
var sourceFilePath = Paths.get(getValueOf(startSourceFileElement, NAME)).getFileName(); | ||
if (sourceFilePath == null) { | ||
Check warning on line 198 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorPartially covered line
|
||
return getValueOf(startSourceFileElement, NAME); | ||
Check warning on line 199 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorNot covered line
Check warning on line 199 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorNot covered line
|
||
} | ||
else { | ||
return sourceFilePath.toString(); | ||
} | ||
} | ||
|
||
@CanIgnoreReturnValue | ||
private Node readMethod(final XMLEventReader reader, final ClassNode classNode, | ||
final StartElement startElement, final String fileName) throws XMLStreamException { | ||
String methodName = getValueOf(startElement, NAME) + "#" + getValueOf(startElement, BEGIN_LINE); | ||
|
||
MethodNode methodNode = createMethod(startElement, methodName); | ||
classNode.addChild(methodNode); | ||
|
||
while (reader.hasNext()) { | ||
Check warning on line 214 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorPartially covered line
|
||
XMLEvent event = reader.nextEvent(); | ||
|
||
if (event.isStartElement()) { | ||
var nextElement = event.asStartElement(); | ||
if (METRIC.equals(nextElement.getName())) { | ||
Check warning on line 219 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
Check warning on line 219 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorPartially covered line
|
||
readValueCounter(methodNode, nextElement); | ||
} | ||
} | ||
else if (event.isEndElement()) { | ||
var endElement = event.asEndElement(); | ||
if (METHOD.equals(endElement.getName())) { | ||
Check warning on line 225 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
return methodNode; | ||
Check warning on line 226 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorMutation survived
Raw output
|
||
} | ||
} | ||
} | ||
throw createEofException(fileName); | ||
Check warning on line 230 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorNot covered line
|
||
} | ||
|
||
private MethodNode createMethod(final StartElement startElement, final String methodName) { | ||
return new MethodNode(methodName, "", parseInteger(getValueOf(startElement, BEGIN_LINE))); | ||
} | ||
|
||
private void readValueCounter(final Node node, final StartElement startElement) { | ||
// FIXME: create Metric Values independent of Metric Name | ||
String currentType = getValueOf(startElement, NAME); | ||
int value = parseInteger(getValueOf(startElement, VALUE)); | ||
if (CYCLOMATIC_COMPLEXITY.equals(currentType)) { | ||
Check warning on line 241 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
node.addValue(new CyclomaticComplexity(value)); | ||
} | ||
else if (COGNITIVE_COMPLEXITY.equals(currentType)) { | ||
Check warning on line 244 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
node.addValue(new CyclomaticComplexity(value, Metric.COGNITIVE_COMPLEXITY)); | ||
} | ||
else if (NCSS.equals(currentType)) { | ||
Check warning on line 247 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
|
||
node.addValue(new CyclomaticComplexity(value, Metric.NCSS)); | ||
} | ||
else if (NPATH_COMPLEXITY.equals(currentType)) { | ||
Check warning on line 250 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorError Prone: YodaCondition
Check warning on line 250 in src/main/java/edu/hm/hafner/coverage/parser/MetricsParser.java GitHub Actions / Quality MonitorPartially covered line
|
||
node.addValue(new CyclomaticComplexity(value, Metric.NPATH_COMPLEXITY)); | ||
} | ||
} | ||
} |