Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
Resolved Issue: JENKINS-17794
Implementet Violations-StyleCopParser as Native-Parser.
Implementet Test-File for StyleCopParser.
  • Loading branch information
schlangguru committed Jun 9, 2013
1 parent 8dfc6c0 commit 1d9c7c02915064974a5c06ce5e14b4b7066c65d8
Showing 4 changed files with 246 additions and 0 deletions.
@@ -0,0 +1,134 @@
package hudson.plugins.warnings.parser.stylecop;

import java.io.IOException;
import java.io.Reader;
import java.util.Collection;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.google.common.collect.Lists;

import hudson.plugins.analysis.util.model.FileAnnotation;
import hudson.plugins.analysis.util.model.Priority;
import hudson.plugins.warnings.parser.AbstractWarningsParser;
import hudson.plugins.warnings.parser.Messages;
import hudson.plugins.warnings.parser.ParsingCanceledException;
import hudson.plugins.warnings.parser.Warning;

import hudson.util.IOException2;

/**
* Parses a StyleCop (http://code.msdn.microsoft.com/sourceanalysis/) xml report file.
*
*/
public class StyleCopParser extends AbstractWarningsParser {
private static final long serialVersionUID = 1L;

static final String TYPE_NAME = "stylecop";

@edu.umd.cs.findbugs.annotations.SuppressWarnings("SE")
private transient List<FileAnnotation> warnings;

/**
* Creates a new instance of {@link StyleCopParser}.
*/
public StyleCopParser() {
super(Messages._Warnings_StyleCop_ParserName(),
Messages._Warnings_StyleCop_LinkName(),
Messages._Warnings_StyleCop_TrendName());
}

@Override
public Collection<FileAnnotation> parse(final Reader reader) throws IOException, ParsingCanceledException {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
try {
warnings = Lists.newArrayList();

docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse(new InputSource(reader));

// Pre v4.3 uses SourceAnalysisViolations as the parent node name
NodeList mainNode = doc.getElementsByTagName("SourceAnalysisViolations");
if (mainNode.getLength() == 0) {
// v4.3 uses StyleCopViolations as the parent node name
mainNode = doc.getElementsByTagName("StyleCopViolations");
}

Element rootElement = (Element) mainNode.item(0);
parseViolations(XmlElementUtil.getNamedChildElements(rootElement, "Violation"));

// findSourceFiles(model, projectPath.getPath(), sourcePaths);
}
catch (ParserConfigurationException pce) {
throw new IOException2(pce);
}
catch (SAXException se) {
throw new IOException2(se);
}

return warnings;
}

/**
* Parse the Violation tag and add it to the warnings.
* @param elements list of Violation tags
*/
private void parseViolations(final List<Element> elements) {

for (Element element : elements) {
Warning warning = createWarning(getString(element, "Source"), getInt(element, "LineNumber"),
TYPE_NAME,
TYPE_NAME,
element.getTextContent(),
Priority.NORMAL);

warnings.add(warning);
}
}

/***
* Returns the value for the named attribute if it exists.
* @param element the element to check for an attribute
* @param name the name of the attribute
* @return the value of the attribute; "" if there is no such attribute.
*/
private String getString(final Element element, final String name) {
if (element.hasAttribute(name)) {
return element.getAttribute(name);
}
else {
return "";
}
}

/***
* Returns the value for the named attribute if it exists.
* @param element the element to check for an attribute
* @param name the name of the attribute
* @return the value of the attribute; -1 if there is no such attribute or
* the Attribute isn't an integer.
*/
private int getInt(final Element element, final String name) {
if (element.hasAttribute(name)) {
try {
return Integer.parseInt(element.getAttribute(name));
}
catch (NumberFormatException e) {
return -1;
}
}
else {
return -1;
}
}
}
@@ -0,0 +1,38 @@
package hudson.plugins.warnings.parser.stylecop;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

//CHECKSTYLE:OFF
@SuppressWarnings({"PMD", "all"})
public class XmlElementUtil {

private XmlElementUtil() {
}

public static List<Element> getNamedChildElements(final Element parent, final String name) {
List<Element> elements = new ArrayList<Element>();
if (parent != null) {
Node child = parent.getFirstChild();
while (child != null) {
if ((child.getNodeType() == Node.ELEMENT_NODE) && (child.getNodeName().equals(name))) {
elements.add((Element) child);
}
child = child.getNextSibling();
}
}
return elements;
}

public static Element getFirstElementByTagName(final Element parent, final String tagName) {
List<Element> foundElements = getNamedChildElements(parent, tagName);
if (foundElements.size() > 0) {
return foundElements.get(0);
} else {
return null;
}
}
}
@@ -0,0 +1,52 @@
package hudson.plugins.warnings.parser;

import static org.junit.Assert.*;

import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;

import org.junit.Test;

import hudson.plugins.analysis.util.model.FileAnnotation;
import hudson.plugins.analysis.util.model.Priority;
import hudson.plugins.warnings.parser.fxcop.FxCopParser;
import hudson.plugins.warnings.parser.stylecop.StyleCopParser;

/**
* Tests the class {@link FxCopParser}.
*
* @author Ulli Hafner
*/
public class StyleCopParserTest extends ParserTester {
/**
* Verifies that the StyleCop parser works as expected.
*
* @throws IOException
* if the file could not be read
*/
@Test
public void testStyleCop() throws IOException {
Collection<FileAnnotation> result = new StyleCopParser().parse(openFile());

assertEquals(WRONG_NUMBER_OF_WARNINGS_DETECTED, 2, result.size());

Iterator<FileAnnotation> iterator = result.iterator();
checkWarning(iterator.next(), 18,
"The call to components must begin with the 'this.' prefix to indicate that the item is a member of the class.",
"Form1.Designer.cs",
"stylecop",
Priority.NORMAL);
checkWarning(iterator.next(), 16,
"The call to components must begin with the 'this.' prefix to indicate that the item is a member of the class.",
"Form1.Designer.cs",
"stylecop",
Priority.NORMAL);
}

@Override
protected String getWarningsFile() {
return "stylecop.xml";
}
}

@@ -0,0 +1,22 @@
<StyleCopViolations>
<Violation
Section="Root.ListViewProblem.Form1.Dispose%bool"
LineNumber="18"
Source="Form1.Designer.cs"
RuleNamespace="Microsoft.StyleCop.CSharp.ReadabilityRules"
Rule="PrefixLocalCallsWithThis"
RuleId="SA1101">
The call to components must begin with the 'this.' prefix to indicate that the item is a member of the class.
</Violation>


<Violation
Section="Root.ListViewProblem.Form1.Dispose%bool"
LineNumber="16"
Source="Form1.Designer.cs"
RuleNamespace="Microsoft.StyleCop.CSharp.ReadabilityRules"
Rule="PrefixLocalCallsWithThis"
RuleId="SA1101">
The call to components must begin with the 'this.' prefix to indicate that the item is a member of the class.
</Violation>
</StyleCopViolations>

0 comments on commit 1d9c7c0

Please sign in to comment.