Skip to content

Commit

Permalink
Rewriting ResharperParser parser tomasbjerre#101
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasbjerre committed Sep 27, 2020
1 parent 91d02fa commit dcf86f7
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 167 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ Changelog of Violations lib.
## Unreleased
### GitHub [#101](https://github.com/tomasbjerre/violations-lib/issues/101) Replace the regexp xml-parsing with STL xml parser

**Rewriting PiTestParser parser**


[91d02fa7e169df1](https://github.com/tomasbjerre/violations-lib/commit/91d02fa7e169df1) Tomas Bjerre *2020-09-27 15:04:27*

**Rewriting LintParser parser**


Expand Down
95 changes: 54 additions & 41 deletions src/main/java/se/bjurr/violations/lib/parsers/ResharperParser.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package se.bjurr.violations.lib.parsers;

import static java.nio.charset.StandardCharsets.UTF_8;
import static se.bjurr.violations.lib.model.SEVERITY.ERROR;
import static se.bjurr.violations.lib.model.SEVERITY.INFO;
import static se.bjurr.violations.lib.model.SEVERITY.WARN;
Expand All @@ -8,61 +9,73 @@
import static se.bjurr.violations.lib.util.ViolationParserUtils.findAttribute;
import static se.bjurr.violations.lib.util.ViolationParserUtils.findIntegerAttribute;
import static se.bjurr.violations.lib.util.ViolationParserUtils.getAttribute;
import static se.bjurr.violations.lib.util.ViolationParserUtils.getChunks;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import se.bjurr.violations.lib.ViolationsLogger;
import se.bjurr.violations.lib.model.SEVERITY;
import se.bjurr.violations.lib.model.Violation;
import se.bjurr.violations.lib.util.ViolationParserUtils;

public class ResharperParser implements ViolationsParser {

@Override
public Set<Violation> parseReportOutput(final String string, ViolationsLogger violationsLogger)
throws Exception {
public Set<Violation> parseReportOutput(
final String content, final ViolationsLogger violationsLogger) throws Exception {
final Set<Violation> violations = new TreeSet<>();
final List<String> issueTypeChunks = getChunks(string, "<IssueType ", "/>");
final Map<String, Map<String, String>> issueTypesPerTypeId = new HashMap<>();
for (final String issueTypesChunk : issueTypeChunks) {
final Map<String, String> issueType = new HashMap<>();
final String id = getAttribute(issueTypesChunk, "Id");
issueType.put("category", getAttribute(issueTypesChunk, "Category"));
final Optional<String> description = findAttribute(issueTypesChunk, "Description");
issueType.put("description", description.orElse(id));
issueType.put("severity", getAttribute(issueTypesChunk, "Severity"));
issueType.put("url", findAttribute(issueTypesChunk, "WikiUrl").orElse(null));
issueTypesPerTypeId.put(id, issueType);
}

final List<String> issueChunks = getChunks(string, "<Issue ", "/>");
for (final String issueChunk : issueChunks) {
final String typeId = getAttribute(issueChunk, "TypeId");
final String filename = getAttribute(issueChunk, "File");
final String url = issueTypesPerTypeId.get(typeId).get("url");
final String message =
findAttribute(issueChunk, "Message").orElse("")
+ ". "
+ issueTypesPerTypeId.get(typeId).get("category")
+ ". "
+ issueTypesPerTypeId.get(typeId).get("description")
+ (url != null ? ". For more info, visit " + url : "");
final Integer line = findIntegerAttribute(issueChunk, "Line").orElse(0);
final String severity = issueTypesPerTypeId.get(typeId).get("severity");
violations.add( //
violationBuilder() //
.setParser(RESHARPER) //
.setStartLine(line) //
.setFile(filename) //
.setSeverity(this.toSeverity(severity)) //
.setMessage(message) //
.setRule(typeId) //
.build() //
);
try (InputStream input = new ByteArrayInputStream(content.getBytes(UTF_8))) {
final XMLStreamReader xmlr = ViolationParserUtils.createXmlReader(input);
final Map<String, Map<String, String>> issueTypesPerTypeId = new HashMap<>();
while (xmlr.hasNext()) {
final int eventType = xmlr.next();
if (eventType == XMLStreamConstants.START_ELEMENT) {
if (xmlr.getLocalName().equalsIgnoreCase("IssueType")) {
final Map<String, String> issueType = new HashMap<>();
final String id = getAttribute(xmlr, "Id");
issueType.put("category", getAttribute(xmlr, "Category"));
final Optional<String> description = findAttribute(xmlr, "Description");
issueType.put(
"description",
!description.isPresent() || description.get().isEmpty()
? id
: description.orElse(""));
issueType.put("severity", getAttribute(xmlr, "Severity"));
issueType.put("url", findAttribute(xmlr, "WikiUrl").orElse(null));
issueTypesPerTypeId.put(id, issueType);
}
if (xmlr.getLocalName().equalsIgnoreCase("Issue")) {
final String typeId = getAttribute(xmlr, "TypeId");
final String filename = getAttribute(xmlr, "File");
final String url = issueTypesPerTypeId.get(typeId).get("url");
final String message =
findAttribute(xmlr, "Message").orElse("")
+ ". "
+ issueTypesPerTypeId.get(typeId).get("category")
+ ". "
+ issueTypesPerTypeId.get(typeId).get("description")
+ (url != null ? ". For more info, visit " + url : "");
final Integer line = findIntegerAttribute(xmlr, "Line").orElse(0);
final String severity = issueTypesPerTypeId.get(typeId).get("severity");
final Violation violation =
violationBuilder() //
.setParser(RESHARPER) //
.setStartLine(line) //
.setFile(filename) //
.setSeverity(this.toSeverity(severity)) //
.setMessage(message) //
.setRule(typeId) //
.build();
violations.add(violation);
}
}
}
}
return violations;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import static java.lang.Integer.parseInt;
import static java.util.Optional.empty;
import static java.util.Optional.ofNullable;
import static java.util.regex.Pattern.DOTALL;
import static java.util.regex.Pattern.quote;
import static se.bjurr.violations.lib.util.StringUtils.xmlDecode;

import java.io.InputStream;
import java.io.StringWriter;
Expand Down Expand Up @@ -38,31 +36,10 @@ public static String asString(final XMLStreamReader xmlr) throws Exception {
return stringWriter.toString();
}

public static Optional<String> findAttribute(final String in, final String attribute) {
Pattern pattern = Pattern.compile("[\\s<^]" + attribute + "='([^']+?)'");
Matcher matcher = pattern.matcher(in);
if (matcher.find()) {
return ofNullable(xmlDecode(matcher.group(1)));
}
pattern = Pattern.compile("[\\s<^]" + attribute + "=\"([^\"]+?)\"");
matcher = pattern.matcher(in);
if (matcher.find()) {
return ofNullable(xmlDecode(matcher.group(1)));
}
return empty();
}

public static Optional<String> findAttribute(final XMLStreamReader in, final String attribute) {
return ofNullable(in.getAttributeValue("", attribute));
}

public static Optional<Integer> findIntegerAttribute(final String in, final String attribute) {
if (findAttribute(in, attribute).isPresent()) {
return ofNullable(parseInt(getAttribute(in, attribute)));
}
return empty();
}

public static Optional<Integer> findIntegerAttribute(
final XMLStreamReader in, final String attribute) {
final String attr = in.getAttributeValue("", attribute);
Expand All @@ -73,14 +50,6 @@ public static Optional<Integer> findIntegerAttribute(
}
}

public static String getAttribute(final String in, final String attribute) {
final Optional<String> foundOpt = findAttribute(in, attribute);
if (foundOpt.isPresent()) {
return foundOpt.get();
}
throw new RuntimeException("\"" + attribute + "\" not found in \"" + in + "\"");
}

public static String getAttribute(final XMLStreamReader in, final String attribute) {
final String foundOpt = in.getAttributeValue("", attribute);
if (foundOpt == null) {
Expand All @@ -95,48 +64,10 @@ public static String getAttribute(final XMLStreamReader in, final String attribu
return foundOpt;
}

public static List<String> getChunks(
final String in, final String includingStart, final String includingEnd) {
final Pattern pattern =
Pattern.compile("(" + includingStart + ".+?" + includingEnd + ")", DOTALL);
final Matcher matcher = pattern.matcher(in);
final List<String> chunks = new ArrayList<>();
while (matcher.find()) {
chunks.add(matcher.group());
}
return chunks;
}

public static String getContent(final String in, final String tag) {
Pattern pattern =
Pattern.compile(
"<" + tag + "\\s?[^>]*>[^<]*<!\\[CDATA\\[(" + ".+?" + ")\\]\\]>[^<]*</" + tag + ">",
DOTALL);
Matcher matcher = pattern.matcher(in);
if (matcher.find()) {
return matcher.group(1);
}
pattern = Pattern.compile("<" + tag + "\\s?[^>]*>(" + ".+?" + ")</" + tag + ">", DOTALL);
matcher = pattern.matcher(in);
if (matcher.find()) {
return matcher.group(1);
}
throw new RuntimeException("\"" + tag + "\" not found in " + in);
}

public static Integer getIntegerAttribute(final String in, final String attribute) {
return parseInt(getAttribute(in, attribute));
}

public static Integer getIntegerAttribute(final XMLStreamReader in, final String attribute) {
return parseInt(getAttribute(in, attribute));
}

public static Integer getIntegerContent(final String in, final String tag) {
final String content = getContent(in, tag);
return parseInt(content);
}

public static List<String> getLines(final String string) {
return Arrays.asList(string.split("\n"));
}
Expand Down
38 changes: 0 additions & 38 deletions src/test/java/se/bjurr/violations/lib/ViolationsParserTest.java

This file was deleted.

49 changes: 30 additions & 19 deletions src/test/resources/resharper/main.xml
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by InspectCode 8.1.23.523 -->
<Report ToolsVersion="8.1">
<Information>
<Solution>CSharpPlayground.sln</Solution>
<InspectionScope>
<Element>9B2650A2-C7C6-435F-80D6-D6C7B522FFF9</Element>
</InspectionScope>
</Information>
<IssueTypes>
<IssueType Id="JoinDeclarationAndInitializer" Category="Common Practices and Code Improvements" Description="Join local variable declaration and assignment" Severity="SUGGESTION" />
<IssueType Id="RedundantUsingDirective" Category="Redundancies in Code" Description="Redundant using directive" Severity="WARNING" WikiUrl="http://confluence.jetbrains.net/display/ReSharper/Redundant+using+directive" />
<IssueType Id="CSharpErrors" Category="C# Compiler Errors" Description="" Severity="ERROR"/>
</IssueTypes>
<Issues>
<Project Name="MyLibrary">
<Issue TypeId="RedundantUsingDirective" File="MyLibrary\Class1.cs" Offset="0-13" Message="Using directive is not required by the code and can be safely removed" />
<Issue TypeId="JoinDeclarationAndInitializer" File="MyLibrary\Class1.cs" Offset="138-144" Line="9" Message="Join declaration and assignment" />
<Issue TypeId="RedundantUsingDirective" File="MyLibrary\Properties\AssemblyInfo.cs" Offset="26-64" Line="2" Message="Using directive is not required by the code and can be safely removed" />
<Issue TypeId="CSharpErrors" File="MyLibrary\Class1.cs" Offset="1-10" Line="10" Message="Cannot resolve symbol 'GetError'" />
</Project>
</Issues>
<Information>
<Solution>CSharpPlayground.sln</Solution>
<InspectionScope>
<Element>9B2650A2-C7C6-435F-80D6-D6C7B522FFF9</Element>
</InspectionScope>
</Information>
<IssueTypes>
<IssueType Id="JoinDeclarationAndInitializer" Category="Common Practices and Code Improvements"
Description="Join local variable declaration and assignment"
Severity="SUGGESTION" />
<IssueType Id="RedundantUsingDirective" Category="Redundancies in Code"
Description="Redundant using directive" Severity="WARNING"
WikiUrl="http://confluence.jetbrains.net/display/ReSharper/Redundant+using+directive" />
<IssueType Id="CSharpErrors" Category="C# Compiler Errors"
Description="" Severity="ERROR" />
</IssueTypes>
<Issues>
<Project Name="MyLibrary">
<Issue TypeId="RedundantUsingDirective" File="MyLibrary\Class1.cs"
Offset="0-13"
Message="Using directive is not required by the code and can be safely removed" />
<Issue TypeId="JoinDeclarationAndInitializer" File="MyLibrary\Class1.cs"
Offset="138-144" Line="9" Message="Join declaration and assignment" />
<Issue TypeId="RedundantUsingDirective" File="MyLibrary\Properties\AssemblyInfo.cs"
Offset="26-64" Line="2"
Message="Using directive is not required by the code and can be safely removed" />
<Issue TypeId="CSharpErrors" File="MyLibrary\Class1.cs" Offset="1-10"
Line="10" Message="Cannot resolve symbol 'GetError'" />
</Project>
</Issues>
</Report>

0 comments on commit dcf86f7

Please sign in to comment.