package hudson.plugins.violations.types.javascriptlint; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import hudson.plugins.violations.ViolationsParser; import hudson.plugins.violations.model.FullBuildModel; import hudson.plugins.violations.model.FullFileModel; import hudson.plugins.violations.model.Severity; import hudson.plugins.violations.model.Violation; import hudson.plugins.violations.util.AbsoluteFileFinder; /** * Parser for parsing JavascriptLint reports. * * The parser only supports JavascriptLint report that has the output format * 'parseable'. * * @author Chad Metcalf */ public class JavascriptLintParser implements ViolationsParser { /** Regex pattern for the JavascriptLint errors. */ private final transient Pattern pattern; private transient AbsoluteFileFinder absoluteFileFinder = new AbsoluteFileFinder(); /** * Constructor - create the pattern. */ public JavascriptLintParser() { pattern = Pattern.compile("(.*?)\\((\\d+)\\):\\s+([\\w\\s]+):\\s+(.*)"); } /** {@inheritDoc} */ public void parse( FullBuildModel model, File projectPath, String fileName, String[] sourcePaths) throws IOException { BufferedReader reader = null; absoluteFileFinder.addSourcePath(projectPath.getAbsolutePath()); absoluteFileFinder.addSourcePaths(sourcePaths); try { reader = new BufferedReader( new FileReader(new File(projectPath, fileName))); String line = reader.readLine(); while (line != null) { parseLine(model, line, projectPath); line = reader.readLine(); } } finally { if (reader != null) { reader.close(); } } } /** * Parses a JavascriptLint line and adding a violation if regex * @param model build model to add violations to * @param line the line in the file. * @param projectPath the path to use to resolve the file. */ public void parseLine(FullBuildModel model, String line, File projectPath) { JavascriptLintViolation jsLintViolation = getJavascriptLintViolation(line); if (jsLintViolation != null) { Violation violation = new Violation(); violation.setType("javascriptlint"); violation.setLine(jsLintViolation.getLineStr()); violation.setMessage(jsLintViolation.getMessage()); violation.setSource(jsLintViolation.getViolationId()); setServerityLevel(violation, jsLintViolation.getViolationId()); FullFileModel fileModel = getFileModel(model, jsLintViolation.getFileName(), absoluteFileFinder.getFileForName(jsLintViolation.getFileName())); fileModel.addViolation(violation); } } private FullFileModel getFileModel(FullBuildModel model, String name, File sourceFile) { FullFileModel fileModel = model.getFileModel(name); File other = fileModel.getSourceFile(); if (sourceFile == null || ((other != null) && ( other.equals(sourceFile) || other.exists()))) { return fileModel; } fileModel.setSourceFile(sourceFile); fileModel.setLastModified(sourceFile.lastModified()); return fileModel; } /** * Returns a jslint violation (if it is one) * @param line a line from the JavascriptLint parseable report * @return a JavascriptLintViolation if the line contains one; null otherwise */ JavascriptLintViolation getJavascriptLintViolation(String line) { Matcher matcher = pattern.matcher(line); if (matcher.matches() && matcher.groupCount() == 4) { return new JavascriptLintViolation(matcher); } return null; } /** * Returns the Severity level as an int from the JavascriptLint message type. * * The different message types are: * lint warning: * warning: * * @param messageType the type of JavascriptLint message * @return an int is matched to the message type. */ private void setServerityLevel(Violation violation, String messageType) { if (messageType.contains("warning")) { violation.setSeverity(Severity.MEDIUM); violation.setSeverityLevel(Severity.MEDIUM_VALUE); } else { violation.setSeverity(Severity.HIGH); violation.setSeverityLevel(Severity.HIGH_VALUE); } } class JavascriptLintViolation { private final transient String lineStr; private final transient String message; private final transient String fileName; private final transient String violationId; public JavascriptLintViolation(Matcher matcher) { if (matcher.groupCount() < 4) { throw new IllegalArgumentException( "The Regex matcher could not find enough information"); } lineStr = matcher.group(2); message = matcher.group(4); violationId = matcher.group(3); fileName = matcher.group(1); } public String getLineStr() { return lineStr; } public String getMessage() { return message; } public String getFileName() { return fileName; } public String getViolationId() { return violationId; } } }