Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
[FIXED JENKINS-17788] Use JS-Lint parser when parsing CSS-Lint files.
  • Loading branch information
uhafner committed Jun 15, 2013
1 parent d55329a commit 368852ec17f95a6bf6f61f111b9792b5c8baaa3e
Showing 9 changed files with 314 additions and 114 deletions.
@@ -295,6 +295,20 @@ public String getLargeImage() {
* @return the line number
*/
protected final int getLineNumber(final String lineNumber) {
return convertLineNumber(lineNumber);
}

/**
* Converts a string line number to an integer value. If the string is not a
* valid line number, then 0 is returned which indicates a warning at the
* top of the file.
*
* @param lineNumber
* the line number (as a string)
* @return the line number
* @since 4.37
*/
public static int convertLineNumber(final String lineNumber) {
if (StringUtils.isNotBlank(lineNumber)) {
try {
return Integer.parseInt(lineNumber);
@@ -0,0 +1,22 @@
package hudson.plugins.warnings.parser;

import hudson.Extension;

/**
* A parser for CSS-Lint checks warnings.
*
* @author Ulli Hafner
*/
@Extension
public class CssLintParser extends LintParser {
private static final long serialVersionUID = 8613418992526753095L;

/**
* Creates a new instance of {@link CssLintParser}.
*/
public CssLintParser() {
super(Messages._Warnings_CssLint_ParserName(),
Messages._Warnings_CssLint_LinkName(),
Messages._Warnings_CssLint_TrendName());
}
}
@@ -1,42 +1,15 @@
package hudson.plugins.warnings.parser;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.lang.StringUtils;
import org.apache.tools.ant.util.ReaderInputStream;
import org.kohsuke.stapler.framework.io.IOException2;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import hudson.Extension;

import hudson.plugins.analysis.util.model.FileAnnotation;
import hudson.plugins.analysis.util.model.Priority;

/**
* A parser for JSLint checks warnings.
*
* @author Gavin Mogan <gavin@kodekoan.com>
*/
@Extension
public class JSLintParser extends AbstractWarningsParser {
public class JSLintParser extends LintParser {
private static final long serialVersionUID = 8613418992526753095L;
private static final Logger LOGGER = Logger.getLogger(JSLintParser.class.toString());

/** Categories. */
static final String CATEGORY_PARSING = "Parsing";
static final String CATEGORY_UNDEFINED_VARIABLE = "Undefined Variable";
static final String CATEGORY_FORMATTING = "Formatting";

/**
* Creates a new instance of {@link JSLintParser}.
@@ -46,84 +19,4 @@ public JSLintParser() {
Messages._Warnings_JSLint_LinkName(),
Messages._Warnings_JSLint_TrendName());
}

@Override
public Collection<FileAnnotation> parse(final Reader file) throws IOException, ParsingCanceledException {
try {
List<FileAnnotation> warnings = new ArrayList<FileAnnotation>();
SAXParserFactory parserFactory = SAXParserFactory.newInstance();

SAXParser parser = parserFactory.newSAXParser();
parser.parse(new ReaderInputStream(file, "UTF-8"), new JSLintXMLSaxParser(warnings));

return warnings;
}
catch (SAXException exception) {
throw new IOException2(exception);
}
catch (ParserConfigurationException exception) {
throw new IOException2(exception);
}
}

/**
* Handles parsing.
*/
private class JSLintXMLSaxParser extends DefaultHandler {
private final List<FileAnnotation> warnings;
private String fileName;

public JSLintXMLSaxParser(final List<FileAnnotation> warnings) {
super();

this.warnings = warnings;
}

@Override
public void startElement(final String namespaceURI, final String localName,
final String qName, final Attributes atts) throws SAXException {
String key = qName;

if ("jslint".equals(key)) {
return; // Start element, good to skip
}
if ("file".equals(key)) {
fileName = atts.getValue("name");
return;
}
if ("issue".equals(key)) {
String category = StringUtils.EMPTY;
Priority priority = Priority.NORMAL;

String message = atts.getValue("reason");
if (message.startsWith("Expected")) {
priority = Priority.HIGH;
category = JSLintParser.CATEGORY_PARSING;
}
else if (message.endsWith(" is not defined.")) {
priority = Priority.HIGH;
category = JSLintParser.CATEGORY_UNDEFINED_VARIABLE;
}
else if (message.contains("Mixed spaces and tabs")) {
priority = Priority.LOW;
category = JSLintParser.CATEGORY_FORMATTING;
}
else if (message.contains("Unnecessary semicolon")) {
category = JSLintParser.CATEGORY_FORMATTING;
}
else if (message.contains("is better written in dot notation")) {
category = JSLintParser.CATEGORY_FORMATTING;
}

int lineNumber = getLineNumber(atts.getValue("line"));
Warning warning = createWarning(fileName, lineNumber, category, message, priority);

warnings.add(warning);
return;
}
else {
LOGGER.info("Unknown jslint xml tag: " + key);
}
}
}
}
@@ -0,0 +1,93 @@
package hudson.plugins.warnings.parser;

import java.util.List;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import hudson.plugins.analysis.util.model.FileAnnotation;
import hudson.plugins.analysis.util.model.Priority;

/**
* Handles parsing.
*/
public class JSLintXMLSaxParser extends DefaultHandler {
private static final Logger LOGGER = Logger.getLogger(JSLintXMLSaxParser.class.toString());
private final List<FileAnnotation> warnings;
private String fileName;
private final String type;

/** Categories. */
private static final String CATEGORY_PARSING = "Parsing";
private static final String CATEGORY_UNDEFINED_VARIABLE = "Undefined Variable";
private static final String CATEGORY_FORMATTING = "Formatting";

/**
* Creates a new instance of {@link JSLintXMLSaxParser}.
*
* @param type
* type of the parser
* @param warnings
* the warnings output
*/
public JSLintXMLSaxParser(final String type, final List<FileAnnotation> warnings) {
super();

this.type = type;
this.warnings = warnings;
}

@Override
public void startElement(final String namespaceURI, final String localName, final String qName,
final Attributes atts) throws SAXException {
String key = qName;

if (isLintDerivate(key)) {
return; // Start element, good to skip
}
if ("file".equals(key)) {
fileName = atts.getValue("name");
return;
}
if ("issue".equals(key)) {
String category = StringUtils.EMPTY;
Priority priority = Priority.NORMAL;

String message = atts.getValue("reason");
if (message.startsWith("Expected")) {
priority = Priority.HIGH;
category = CATEGORY_PARSING;
}
else if (message.endsWith(" is not defined.")) {
priority = Priority.HIGH;
category = CATEGORY_UNDEFINED_VARIABLE;
}
else if (message.contains("Mixed spaces and tabs")) {
priority = Priority.LOW;
category = CATEGORY_FORMATTING;
}
else if (message.contains("Unnecessary semicolon")) {
category = CATEGORY_FORMATTING;
}
else if (message.contains("is better written in dot notation")) {
category = CATEGORY_FORMATTING;
}

int lineNumber = AbstractWarningsParser.convertLineNumber(atts.getValue("line"));
Warning warning = new Warning(fileName, lineNumber, type, category, message, priority);

warnings.add(warning);
return;
}
else {
LOGGER.info("Unknown jslint xml tag: " + key);
}
}

private boolean isLintDerivate(final String key) {
return key != null && key.contains("lint");
}
}
@@ -0,0 +1,60 @@
package hudson.plugins.warnings.parser;

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

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.tools.ant.util.ReaderInputStream;
import org.jvnet.localizer.Localizable;
import org.kohsuke.stapler.framework.io.IOException2;
import org.xml.sax.SAXException;

import hudson.plugins.analysis.util.model.FileAnnotation;

/**
* Base class for parsers based on {@link JSLintXMLSaxParser}.
*
* @author Ulli Hafner
*/
public abstract class LintParser extends AbstractWarningsParser {
private static final long serialVersionUID = 3341424685245834156L;

/**
* Creates a new instance of {@link LintParser}.
*
* @param parserName
* name of the parser
* @param linkName
* name of the project action link
* @param trendName
* name of the trend graph
*/
protected LintParser(final Localizable parserName, final Localizable linkName, final Localizable trendName) {
super(parserName, linkName, trendName);
}

@Override
public Collection<FileAnnotation> parse(final Reader file) throws IOException, ParsingCanceledException {
try {
List<FileAnnotation> warnings = new ArrayList<FileAnnotation>();
SAXParserFactory parserFactory = SAXParserFactory.newInstance();

SAXParser parser = parserFactory.newSAXParser();
parser.parse(new ReaderInputStream(file, "UTF-8"), new JSLintXMLSaxParser(getGroup(), warnings));

return warnings;
}
catch (SAXException exception) {
throw new IOException2(exception);
}
catch (ParserConfigurationException exception) {
throw new IOException2(exception);
}
}
}
@@ -3,7 +3,6 @@
import java.util.List;

import hudson.plugins.violations.types.codenarc.CodenarcParser;
import hudson.plugins.violations.types.csslint.CssLintParser;
import hudson.plugins.violations.types.gendarme.GendarmeParser;
import hudson.plugins.violations.types.jcreport.JcReportParser;
import hudson.plugins.violations.types.pep8.Pep8Parser;
@@ -27,10 +26,6 @@ public static void addParsers(final List<AbstractWarningsParser> parsers) {
Messages._Warnings_Codenarc_ParserName(),
Messages._Warnings_Codenarc_LinkName(),
Messages._Warnings_Codenarc_TrendName()));
parsers.add(new ViolationsAdapter(new CssLintParser(),
Messages._Warnings_CssLint_ParserName(),
Messages._Warnings_CssLint_LinkName(),
Messages._Warnings_CssLint_TrendName()));
parsers.add(new ViolationsAdapter(new GendarmeParser(),
Messages._Warnings_Gendarme_ParserName(),
Messages._Warnings_Gendarme_LinkName(),
@@ -0,0 +1,43 @@
package hudson.plugins.warnings.parser;

import static org.junit.Assert.*;

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

import org.junit.Test;

import hudson.plugins.analysis.util.model.FileAnnotation;

/**
* Tests the class {@link JSLintParser}.
*
* @author Ulli Hafner
*/
public class CssLintParserTest extends ParserTester {
/**
* Tests parsing of CSS-Lint files.
*
* @throws IOException
* in case of an error
*/
@Test
public void testCssLint() throws IOException {
Collection<FileAnnotation> results = createParser().parse(openFile());
assertEquals(WRONG_NUMBER_OF_WARNINGS_DETECTED, 51, results.size());
}

/**
* Creates the parser.
*
* @return the warnings parser
*/
protected AbstractWarningsParser createParser() {
return new CssLintParser();
}

@Override
protected String getWarningsFile() {
return "jslint/csslint.xml";
}
}

0 comments on commit 368852e

Please sign in to comment.