From 46650fab3919bf6713b776cbc77b4716476335de Mon Sep 17 00:00:00 2001 From: bvarner Date: Fri, 30 Oct 2015 14:10:16 -0400 Subject: [PATCH 1/3] Use Plexus file exclusion patterns --- README.md | 7 +- src/main/java/com/cj/jshintmojo/Mojo.java | 113 +++++++++--------- .../java/com/cj/jshintmojo/cache/Cache.java | 4 +- src/test/java/com/cj/jshintmojo/MojoTest.java | 8 +- 4 files changed, 68 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 99831f9..82b5cec 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ It's real simple and it runs [JSHint](http://www.jshint.com/) on your *.js files | globals | | List of comma-separated [JSHint globals](http://www.jshint.com/docs/#usage) | | configFile | | Path to a JSHint JSON config file. Its contents will override values set in `options` and `globals`, if present. Please note that block and line comments will be stripped prior to processing so it's OK to include them. | | directories | `src` | Locations in which the plugin will search for *.js files | -| excludes | | Excludes are resolved relative to the basedir of the module | +| excludes | | Excludes are resolved relative to the source directories. Standard maven semantics apply. | +| includes | | Includes are resolved relative to the source directories. Standard maven semantics apply. Default inclusion rule is: "**/*.js" | | reporter | | If present, JSHint will generate a reporting file which can be used for some CI tools. Currently, `jslint`, `html`, and `checkstyle` formats are supported. | | reportFile | target/jshint.xml | Path to an output reporting file | | failOnError | `true` | Controls whether the plugin fails the build when JSHint is unhappy. Setting this to `false` is discouraged, as it removes most of the benefit of using this plugin. Instead, if you have problem files that you can't fix [disable/override JSHint on a per-file basis](http://www.jshint.com/docs/#config), or tell the plugin to specifically exclude them in the `excludes` section | @@ -43,7 +44,11 @@ It's real simple and it runs [JSHint](http://www.jshint.com/) on your *.js files src/main/webapp/hackyScript.js src/main/webapp/myDirectoryForThirdyPartyStuff + **/*.min.js + + **/*.js + jslint target/jshint.xml false diff --git a/src/main/java/com/cj/jshintmojo/Mojo.java b/src/main/java/com/cj/jshintmojo/Mojo.java index 2dd9024..ffb62b4 100644 --- a/src/main/java/com/cj/jshintmojo/Mojo.java +++ b/src/main/java/com/cj/jshintmojo/Mojo.java @@ -16,19 +16,17 @@ import java.util.Map; import java.util.Set; -import org.apache.commons.io.FileUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.logging.Log; +import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.StringUtils; import com.cj.jshintmojo.cache.Cache; import com.cj.jshintmojo.cache.Result; import com.cj.jshintmojo.jshint.EmbeddedJshintCode; -import com.cj.jshintmojo.jshint.FunctionalJava; -import com.cj.jshintmojo.jshint.FunctionalJava.Fn; import com.cj.jshintmojo.jshint.JSHint; import com.cj.jshintmojo.jshint.JSHint.Error; import com.cj.jshintmojo.reporter.CheckStyleReporter; @@ -52,6 +50,11 @@ public class Mojo extends AbstractMojo { */ private final List directories = new ArrayList(); + /** + * @parameter property="includes" + */ + private final List includes = new ArrayList(); + /** * @parameter property="excludes" */ @@ -106,12 +109,13 @@ public class Mojo extends AbstractMojo { public Mojo() {} - public Mojo(String options, String globals, File basedir, List directories, List excludes, boolean failOnError, String configFile, String reporter, String reportFile, String ignoreFile) { + public Mojo(String options, String globals, File basedir, List directories, List includes, List excludes, boolean failOnError, String configFile, String reporter, String reportFile, String ignoreFile) { super(); this.options = options; this.globals = globals; this.basedir = basedir; this.directories.addAll(directories); + this.includes.addAll(includes); this.excludes.addAll(excludes); this.failOnError = failOnError; this.configFile = configFile; @@ -128,15 +132,15 @@ public void execute() throws MojoExecutionException, MojoFailureException { final JSHint jshint = new JSHint(jshintCode); final Config config = readConfig(this.options, this.globals, this.configFile, this.basedir, getLog()); - if (this.excludes.isEmpty() || (this.ignoreFile != null && !this.ignoreFile.isEmpty())) { - this.excludes.addAll(readIgnore(this.ignoreFile, this.basedir, getLog()).lines); + if (includes.isEmpty()) { + includes.add("**/*.js"); } - final Cache.Hash cacheHash = new Cache.Hash(config.options, config.globals, this.version, this.configFile, this.directories, this.excludes); - - if(directories.isEmpty()){ - directories.add("src"); - } - + if(directories.isEmpty()){ + directories.add("src"); + } + + final Cache.Hash cacheHash = new Cache.Hash(config.options, config.globals, this.version, this.configFile, this.directories, this.excludes, this.includes); + try { final File targetPath = new File(basedir, "target"); mkdirs(targetPath); @@ -191,10 +195,10 @@ private static Config readConfig(String options, String globals, String configFi static class Ignore { - final List lines; + final List files; - public Ignore(List lines) { - this.lines = lines; + public Ignore(List files) { + this.files = files; } } @@ -206,43 +210,47 @@ private static Ignore readIgnore(String ignoreFileParam, File basedir, Log log) final Ignore ignore; if (ignoreFile != null) { log.info("Using ignore file: " + ignoreFile.getAbsolutePath()); - ignore = processIgnoreFile(ignoreFile); + ignore = processIgnoreFile(basedir, ignoreFile); } else if (jshintignore != null) { log.info("Using ignore file: " + jshintignore.getAbsolutePath()); - ignore = processIgnoreFile(jshintignore); + ignore = processIgnoreFile(basedir, jshintignore); } else { - ignore = new Ignore(Collections.emptyList()); + ignore = new Ignore(Collections.emptyList()); } return ignore; } - private List findFilesToCheck() { + private List findFilesToCheck() throws MojoExecutionException { List javascriptFiles = new ArrayList(); - for(String next: directories){ - File path = new File(basedir, next); - if(!path.exists() && !path.isDirectory()){ - getLog().warn("You told me to find tests in " + next + ", but there is nothing there (" + path.getAbsolutePath() + ")"); - }else{ - collect(path, javascriptFiles); - } + String includesStr = StringUtils.join(includes.iterator(), ","); + String excludesStr = StringUtils.join(excludes.iterator(), ","); + + for(String next: directories) { + File path = new File(basedir, next); + if (!path.exists() || !path.isDirectory()) { + getLog().warn("You told me to find tests in " + next + ", but there is nothing there (" + path.getAbsolutePath() + ")"); + } else { + try { + javascriptFiles.addAll(FileUtils.getFiles(path, includesStr, excludesStr)); + } catch (IOException ioe) { + getLog().warn("Error while processing inclusion / exclusion files for directory: " + path.getAbsolutePath()); + } + } } - List matches = FunctionalJava.filter(javascriptFiles, new Fn(){ - public Boolean apply(File i) { - for(String exclude : excludes){ - File e = new File(basedir, exclude); - if(i.getAbsolutePath().startsWith(e.getAbsolutePath())){ - getLog().warn("Excluding " + i); - return Boolean.FALSE; - } - } + // Support the ignore file definitions, by removing any contents of the ignore list from the list of javascriptFiles. + // Because the MojoTest expects to see WARN level output for each file excluded, we can't do this. + // javascriptFiles.removeAll(readIgnore(this.ignoreFile, this.basedir, getLog()).files); + // And we have to do this instead. + for (File ignoredFile : readIgnore(this.ignoreFile, this.basedir, getLog()).files) { + if (javascriptFiles.remove(ignoredFile)) { + getLog().warn("Excluding " + ignoredFile.getAbsolutePath()); + } + } - return Boolean.TRUE; - } - }); - return matches; + return javascriptFiles; } private static Map lintTheFiles(final JSHint jshint, final Cache cache, List filesToCheck, final Config config, final Log log) throws FileNotFoundException { @@ -399,12 +407,6 @@ private static File findJshintignore(File cwd) { return null; } - private static boolean nullSafeEquals(String a, String b) { - if(a==null && b==null) return true; - else if(a==null || b==null) return false; - else return a.equals(b); - } - private Cache readCache(File path, Cache.Hash hash){ try { if(path.exists()){ @@ -423,16 +425,6 @@ private Cache readCache(File path, Cache.Hash hash){ return new Cache(hash); } - - private void collect(File directory, List files) { - for(File next : directory.listFiles()){ - if(next.isDirectory()){ - collect(next, files); - }else if(next.getName().endsWith(".js")){ - files.add(next); - } - } - } /** * Read contents of the specified config file and use the values defined there instead of the ones defined directly in pom.xml config. @@ -442,7 +434,7 @@ private void collect(File directory, List files) { private static Config processConfigFile(File configFile) throws MojoExecutionException { byte[] configFileContents; try { - configFileContents = FileUtils.readFileToByteArray(configFile); + configFileContents = org.apache.commons.io.FileUtils.readFileToByteArray(configFile); } catch (IOException e) { throw new MojoExecutionException("Unable to read config file located in " + configFile); } @@ -473,9 +465,14 @@ private static Config processConfigFile(File configFile) throws MojoExecutionExc * * @throws MojoExecutionException if the specified file cannot be processed */ - private static Ignore processIgnoreFile(File ignoreFile) throws MojoExecutionException { + private static Ignore processIgnoreFile(File basedir, File ignoreFile) throws MojoExecutionException { try { - return new Ignore(FileUtils.readLines(ignoreFile, "UTF-8")); + List lines = org.apache.commons.io.FileUtils.readLines(ignoreFile, "UTF-8"); + List files = new ArrayList(lines.size()); + for (String line : lines) { + files.add(new File(basedir, line)); + } + return new Ignore(files); } catch (IOException e) { throw new MojoExecutionException("Unable to read ignore file located in " + ignoreFile, e); } diff --git a/src/main/java/com/cj/jshintmojo/cache/Cache.java b/src/main/java/com/cj/jshintmojo/cache/Cache.java index 6e52d2b..9efc948 100644 --- a/src/main/java/com/cj/jshintmojo/cache/Cache.java +++ b/src/main/java/com/cj/jshintmojo/cache/Cache.java @@ -16,8 +16,9 @@ public static class Hash implements Serializable { public final String configFile; public final List directories; public final List excludes; + public final List includes; - public Hash(String options, String globals, String jsHintVersion, String configFile, List directories, List excludes) { + public Hash(String options, String globals, String jsHintVersion, String configFile, List directories, List excludes, List includes) { super(); this.options = options; this.globals = globals; @@ -25,6 +26,7 @@ public Hash(String options, String globals, String jsHintVersion, String configF this.configFile = configFile; this.directories = directories; this.excludes = excludes; + this.includes = includes; } } diff --git a/src/test/java/com/cj/jshintmojo/MojoTest.java b/src/test/java/com/cj/jshintmojo/MojoTest.java index b5b4b5c..ca47da3 100644 --- a/src/test/java/com/cj/jshintmojo/MojoTest.java +++ b/src/test/java/com/cj/jshintmojo/MojoTest.java @@ -35,10 +35,10 @@ public void walksTheDirectoryTreeToFindAndUseJshintFiles() throws Exception { FileUtils.writeStringToFile(fileToIgnore, "whatever, this should be ignored"); LogStub log = new LogStub(); - Mojo mojo = new Mojo("", "", + Mojo mojo = new Mojo("", "", projectDirectory, Collections.singletonList("src/main/resources"), - Collections.emptyList(),true, null, null, null, null); + Collections.emptyList(), Collections.emptyList(), true, null, null, null, null); mojo.setLog(log); // when @@ -64,7 +64,7 @@ public void warnsUsersWhenConfiguredToWorkWithNonexistentDirectories() throws Ex Mojo mojo = new Mojo("", "", directory, Collections.singletonList("src/main/resources/nonexistentDirectory"), - Collections.emptyList(),true, null, null, null, null); + Collections.emptyList(), Collections.emptyList(), true, null, null, null, null); mojo.setLog(log); // when @@ -99,7 +99,7 @@ public void resolvesConfigFileRelativeToMavenBasedirProperty() throws Exception Mojo mojo = new Mojo(null, "", directory, Collections.singletonList("src/main/resources/"), - Collections.emptyList(),true, "foo/bar/my-config-file.js", null, null, null); + Collections.emptyList(), Collections.emptyList(), true, "foo/bar/my-config-file.js", null, null, null); LogStub log = new LogStub(); mojo.setLog(log); From 019c390928c4ebf63e3f1cdd6128ed963381e54e Mon Sep 17 00:00:00 2001 From: bvarner Date: Fri, 30 Oct 2015 14:34:28 -0400 Subject: [PATCH 2/3] Resolve issue #58, log exclusion details from ignore files as debug. --- src/main/java/com/cj/jshintmojo/Mojo.java | 2 +- src/test/java/com/cj/jshintmojo/MojoTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cj/jshintmojo/Mojo.java b/src/main/java/com/cj/jshintmojo/Mojo.java index ffb62b4..819aa50 100644 --- a/src/main/java/com/cj/jshintmojo/Mojo.java +++ b/src/main/java/com/cj/jshintmojo/Mojo.java @@ -246,7 +246,7 @@ private List findFilesToCheck() throws MojoExecutionException { // And we have to do this instead. for (File ignoredFile : readIgnore(this.ignoreFile, this.basedir, getLog()).files) { if (javascriptFiles.remove(ignoredFile)) { - getLog().warn("Excluding " + ignoredFile.getAbsolutePath()); + getLog().debug("Excluding " + ignoredFile.getAbsolutePath()); } } diff --git a/src/test/java/com/cj/jshintmojo/MojoTest.java b/src/test/java/com/cj/jshintmojo/MojoTest.java index ca47da3..3eac558 100644 --- a/src/test/java/com/cj/jshintmojo/MojoTest.java +++ b/src/test/java/com/cj/jshintmojo/MojoTest.java @@ -46,7 +46,7 @@ public void walksTheDirectoryTreeToFindAndUseJshintFiles() throws Exception { // then assertTrue("Sees ignore files", log.hasMessage("info", "Using ignore file: " + ignoreFile.getAbsolutePath())); - assertTrue("Uses ignore files", log.hasMessage("warn", "Excluding " + fileToIgnore.getAbsolutePath())); + assertTrue("Uses ignore files", log.hasMessage("debug", "Excluding " + fileToIgnore.getAbsolutePath())); }finally{ deleteDirectory(directory); From 24619e50c066689abebebacc1c13d2651b2c4b27 Mon Sep 17 00:00:00 2001 From: bvarner Date: Fri, 30 Oct 2015 15:36:50 -0400 Subject: [PATCH 3/3] Fixes for whitespace and markdown formatting. --- README.md | 2 +- src/main/java/com/cj/jshintmojo/Mojo.java | 586 +++++++++++----------- 2 files changed, 294 insertions(+), 294 deletions(-) diff --git a/README.md b/README.md index 82b5cec..a0d019c 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ It's real simple and it runs [JSHint](http://www.jshint.com/) on your *.js files | configFile | | Path to a JSHint JSON config file. Its contents will override values set in `options` and `globals`, if present. Please note that block and line comments will be stripped prior to processing so it's OK to include them. | | directories | `src` | Locations in which the plugin will search for *.js files | | excludes | | Excludes are resolved relative to the source directories. Standard maven semantics apply. | -| includes | | Includes are resolved relative to the source directories. Standard maven semantics apply. Default inclusion rule is: "**/*.js" | +| includes | "\*\*/\*.js" | Includes are resolved relative to the source directories. Standard maven semantics apply. | | reporter | | If present, JSHint will generate a reporting file which can be used for some CI tools. Currently, `jslint`, `html`, and `checkstyle` formats are supported. | | reportFile | target/jshint.xml | Path to an output reporting file | | failOnError | `true` | Controls whether the plugin fails the build when JSHint is unhappy. Setting this to `false` is discouraged, as it removes most of the benefit of using this plugin. Instead, if you have problem files that you can't fix [disable/override JSHint on a per-file basis](http://www.jshint.com/docs/#config), or tell the plugin to specifically exclude them in the `excludes` section | diff --git a/src/main/java/com/cj/jshintmojo/Mojo.java b/src/main/java/com/cj/jshintmojo/Mojo.java index 819aa50..02146fa 100644 --- a/src/main/java/com/cj/jshintmojo/Mojo.java +++ b/src/main/java/com/cj/jshintmojo/Mojo.java @@ -50,10 +50,10 @@ public class Mojo extends AbstractMojo { */ private final List directories = new ArrayList(); - /** - * @parameter property="includes" - */ - private final List includes = new ArrayList(); + /** + * @parameter property="includes" + */ + private final List includes = new ArrayList(); /** * @parameter property="excludes" @@ -90,10 +90,10 @@ public class Mojo extends AbstractMojo { */ private String ignoreFile = ""; - /** - * @parameter property="jshint.version" - */ - private String version = "2.5.6"; + /** + * @parameter property="jshint.version" + */ + private String version = "2.5.6"; /** * @parameter @@ -115,7 +115,7 @@ public Mojo(String options, String globals, File basedir, List directori this.globals = globals; this.basedir = basedir; this.directories.addAll(directories); - this.includes.addAll(includes); + this.includes.addAll(includes); this.excludes.addAll(excludes); this.failOnError = failOnError; this.configFile = configFile; @@ -125,21 +125,21 @@ public Mojo(String options, String globals, File basedir, List directori } public void execute() throws MojoExecutionException, MojoFailureException { - getLog().info("using jshint version " + version); + getLog().info("using jshint version " + version); - final String jshintCode = getEmbeddedJshintCode(version); - - final JSHint jshint = new JSHint(jshintCode); + final String jshintCode = getEmbeddedJshintCode(version); + + final JSHint jshint = new JSHint(jshintCode); - final Config config = readConfig(this.options, this.globals, this.configFile, this.basedir, getLog()); - if (includes.isEmpty()) { - includes.add("**/*.js"); - } - if(directories.isEmpty()){ - directories.add("src"); - } + final Config config = readConfig(this.options, this.globals, this.configFile, this.basedir, getLog()); + if (includes.isEmpty()) { + includes.add("**/*.js"); + } + if(directories.isEmpty()){ + directories.add("src"); + } - final Cache.Hash cacheHash = new Cache.Hash(config.options, config.globals, this.version, this.configFile, this.directories, this.excludes, this.includes); + final Cache.Hash cacheHash = new Cache.Hash(config.options, config.globals, this.version, this.configFile, this.directories, this.excludes, this.includes); try { final File targetPath = new File(basedir, "target"); @@ -153,271 +153,271 @@ public void execute() throws MojoExecutionException, MojoFailureException { Util.writeObject(new Cache(cacheHash, currentResults), cachePath); - handleResults(currentResults, this.reporter, this.reportFile); - + handleResults(currentResults, this.reporter, this.reportFile); + } catch (FileNotFoundException e) { throw new MojoExecutionException("Something bad happened", e); } } static class Config { - final String options, globals; - - public Config(String options, String globals) { - super(); - this.options = options; - this.globals = globals; - } - + final String options, globals; + + public Config(String options, String globals) { + super(); + this.options = options; + this.globals = globals; + } + + } + + private static Config readConfig(String options, String globals, String configFileParam, File basedir, Log log) throws MojoExecutionException { + final File jshintRc = findJshintrc(basedir); + final File configFile = StringUtils.isNotBlank(configFileParam)?new File(basedir, configFileParam):null; + + final Config config; + if(options==null){ + if(configFile!=null){ + log.info("Using configuration file: " + configFile.getAbsolutePath()); + config = processConfigFile(configFile); + }else if(jshintRc!=null){ + log.info("Using configuration file: " + jshintRc.getAbsolutePath()); + config = processConfigFile(jshintRc); + }else{ + config = new Config("", globals); + } + }else{ + config = new Config(options, globals); + } + + return config; + } + + static class Ignore { + + final List files; + + public Ignore(List files) { + this.files = files; + } + + } + + private static Ignore readIgnore(String ignoreFileParam, File basedir, Log log) throws MojoExecutionException { + final File jshintignore = findJshintignore(basedir); + final File ignoreFile = StringUtils.isNotBlank(ignoreFileParam) ? new File(basedir, ignoreFileParam) : null; + + final Ignore ignore; + if (ignoreFile != null) { + log.info("Using ignore file: " + ignoreFile.getAbsolutePath()); + ignore = processIgnoreFile(basedir, ignoreFile); + } else if (jshintignore != null) { + log.info("Using ignore file: " + jshintignore.getAbsolutePath()); + ignore = processIgnoreFile(basedir, jshintignore); + } else { + ignore = new Ignore(Collections.emptyList()); + } + + return ignore; + } + + private List findFilesToCheck() throws MojoExecutionException { + List javascriptFiles = new ArrayList(); + + String includesStr = StringUtils.join(includes.iterator(), ","); + String excludesStr = StringUtils.join(excludes.iterator(), ","); + + for(String next: directories) { + File path = new File(basedir, next); + if (!path.exists() || !path.isDirectory()) { + getLog().warn("You told me to find tests in " + next + ", but there is nothing there (" + path.getAbsolutePath() + ")"); + } else { + try { + javascriptFiles.addAll(FileUtils.getFiles(path, includesStr, excludesStr)); + } catch (IOException ioe) { + getLog().warn("Error while processing inclusion / exclusion files for directory: " + path.getAbsolutePath()); + } + } + } + + // Support the ignore file definitions, by removing any contents of the ignore list from the list of javascriptFiles. + // Because the MojoTest expects to see WARN level output for each file excluded, we can't do this. + // javascriptFiles.removeAll(readIgnore(this.ignoreFile, this.basedir, getLog()).files); + // And we have to do this instead. + for (File ignoredFile : readIgnore(this.ignoreFile, this.basedir, getLog()).files) { + if (javascriptFiles.remove(ignoredFile)) { + getLog().debug("Excluding " + ignoredFile.getAbsolutePath()); + } + } + + return javascriptFiles; + } + + private static Map lintTheFiles(final JSHint jshint, final Cache cache, List filesToCheck, final Config config, final Log log) throws FileNotFoundException { + final Map currentResults = new HashMap(); + for(File file : filesToCheck){ + Result previousResult = cache.previousResults.get(file.getAbsolutePath()); + Result theResult; + if(previousResult==null || (previousResult.lastModified.longValue()!=file.lastModified())){ + log.info(" " + file ); + List errors = jshint.run(new FileInputStream(file), config.options, config.globals); + theResult = new Result(file.getAbsolutePath(), file.lastModified(), errors); + }else{ + log.info(" " + file + " [no change]"); + theResult = previousResult; + } + + if(theResult!=null){ + currentResults.put(theResult.path, theResult); + Result r = theResult; + currentResults.put(r.path, r); + for(Error error: r.errors){ + log.error(" " + error.line.intValue() + "," + error.character.intValue() + ": " + error.reason); + } + } + } + return currentResults; + } + + private void handleResults(final Map currentResults, + final String reporter, final String reportFile) throws MojoExecutionException + { + char NEWLINE = '\n'; + StringBuilder errorRecap = new StringBuilder(NEWLINE); + + int numProblematicFiles = 0; + for(Result r : currentResults.values()){ + if(!r.errors.isEmpty()){ + numProblematicFiles ++; + + errorRecap + .append(NEWLINE) + .append(r.path) + .append(NEWLINE); + + for(Error error: r.errors){ + errorRecap + .append(" ") + .append(error.line.intValue()) + .append(",") + .append(error.character.intValue()) + .append(": ") + .append(error.reason) + .append(NEWLINE); + } + } + } + + if(numProblematicFiles > 0) { + saveReportFile(currentResults, reporter, reportFile); + + String errorMessage = "\nJSHint found problems with " + numProblematicFiles + " file"; + + // pluralise + if (numProblematicFiles > 1) { + errorMessage += "s"; + } + + errorMessage += errorRecap.toString(); + + if (failOnError) { + throw new MojoExecutionException(errorMessage); + } else { + getLog().info(errorMessage); + } + } + } + + private void saveReportFile(Map results, String reportType, String reportFile) { + JSHintReporter reporter = null; + if(JSLintReporter.FORMAT.equalsIgnoreCase(reportType)){ + reporter = new JSLintReporter(); + }else if(HTMLReporter.FORMAT.equalsIgnoreCase(reportType)){ + reporter = new HTMLReporter(); + }else if(CheckStyleReporter.FORMAT.equalsIgnoreCase(reportType)){ + reporter = new CheckStyleReporter(); + }else if(StringUtils.isNotBlank(reportType)){ + getLog().warn("Unknown reporter \"" + reportType + "\". Skip reporting."); + return; + }else{ + return; + } + File file = StringUtils.isNotBlank(reportFile) ? + new File(reportFile) : new File("target/jshint.xml"); + getLog().info(String.format("Generating \"JSHint\" report. reporter=%s, reportFile=%s.", + reportType, file.getAbsolutePath())); + + String report = reporter.report(results); + Writer writer = null; + try{ + writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8")); + writer.write(report); + }catch (IOException e){ + getLog().error(e); + }finally{ + if(writer != null){ + try { + writer.close(); + } catch (IOException e) { + getLog().error(e); + } + } + } + } + + @SuppressWarnings("serial") + private static String getEmbeddedJshintCode(String version) throws MojoFailureException { + + final String resource = EmbeddedJshintCode.EMBEDDED_VERSIONS.get(version); + if(resource==null){ + StringBuffer knownVersions = new StringBuffer(); + for(String v : EmbeddedJshintCode.EMBEDDED_VERSIONS.keySet()){ + knownVersions.append("\n " + v); + } + throw new MojoFailureException("I don't know about the \"" + version + "\" version of jshint. Here are the versions I /do/ know about: " + knownVersions); + } + return resource; } - private static Config readConfig(String options, String globals, String configFileParam, File basedir, Log log) throws MojoExecutionException { - final File jshintRc = findJshintrc(basedir); - final File configFile = StringUtils.isNotBlank(configFileParam)?new File(basedir, configFileParam):null; - - final Config config; - if(options==null){ - if(configFile!=null){ - log.info("Using configuration file: " + configFile.getAbsolutePath()); - config = processConfigFile(configFile); - }else if(jshintRc!=null){ - log.info("Using configuration file: " + jshintRc.getAbsolutePath()); - config = processConfigFile(jshintRc); - }else{ - config = new Config("", globals); - } - }else{ - config = new Config(options, globals); - } - - return config; - } - - static class Ignore { - - final List files; - - public Ignore(List files) { - this.files = files; - } - - } - - private static Ignore readIgnore(String ignoreFileParam, File basedir, Log log) throws MojoExecutionException { - final File jshintignore = findJshintignore(basedir); - final File ignoreFile = StringUtils.isNotBlank(ignoreFileParam) ? new File(basedir, ignoreFileParam) : null; - - final Ignore ignore; - if (ignoreFile != null) { - log.info("Using ignore file: " + ignoreFile.getAbsolutePath()); - ignore = processIgnoreFile(basedir, ignoreFile); - } else if (jshintignore != null) { - log.info("Using ignore file: " + jshintignore.getAbsolutePath()); - ignore = processIgnoreFile(basedir, jshintignore); - } else { - ignore = new Ignore(Collections.emptyList()); - } - - return ignore; - } - - private List findFilesToCheck() throws MojoExecutionException { - List javascriptFiles = new ArrayList(); - - String includesStr = StringUtils.join(includes.iterator(), ","); - String excludesStr = StringUtils.join(excludes.iterator(), ","); - - for(String next: directories) { - File path = new File(basedir, next); - if (!path.exists() || !path.isDirectory()) { - getLog().warn("You told me to find tests in " + next + ", but there is nothing there (" + path.getAbsolutePath() + ")"); - } else { - try { - javascriptFiles.addAll(FileUtils.getFiles(path, includesStr, excludesStr)); - } catch (IOException ioe) { - getLog().warn("Error while processing inclusion / exclusion files for directory: " + path.getAbsolutePath()); - } - } - } - - // Support the ignore file definitions, by removing any contents of the ignore list from the list of javascriptFiles. - // Because the MojoTest expects to see WARN level output for each file excluded, we can't do this. - // javascriptFiles.removeAll(readIgnore(this.ignoreFile, this.basedir, getLog()).files); - // And we have to do this instead. - for (File ignoredFile : readIgnore(this.ignoreFile, this.basedir, getLog()).files) { - if (javascriptFiles.remove(ignoredFile)) { - getLog().debug("Excluding " + ignoredFile.getAbsolutePath()); - } - } - - return javascriptFiles; - } - - private static Map lintTheFiles(final JSHint jshint, final Cache cache, List filesToCheck, final Config config, final Log log) throws FileNotFoundException { - final Map currentResults = new HashMap(); - for(File file : filesToCheck){ - Result previousResult = cache.previousResults.get(file.getAbsolutePath()); - Result theResult; - if(previousResult==null || (previousResult.lastModified.longValue()!=file.lastModified())){ - log.info(" " + file ); - List errors = jshint.run(new FileInputStream(file), config.options, config.globals); - theResult = new Result(file.getAbsolutePath(), file.lastModified(), errors); - }else{ - log.info(" " + file + " [no change]"); - theResult = previousResult; - } - - if(theResult!=null){ - currentResults.put(theResult.path, theResult); - Result r = theResult; - currentResults.put(r.path, r); - for(Error error: r.errors){ - log.error(" " + error.line.intValue() + "," + error.character.intValue() + ": " + error.reason); - } - } - } - return currentResults; - } - - private void handleResults(final Map currentResults, - final String reporter, final String reportFile) throws MojoExecutionException - { - char NEWLINE = '\n'; - StringBuilder errorRecap = new StringBuilder(NEWLINE); - - int numProblematicFiles = 0; - for(Result r : currentResults.values()){ - if(!r.errors.isEmpty()){ - numProblematicFiles ++; - - errorRecap - .append(NEWLINE) - .append(r.path) - .append(NEWLINE); - - for(Error error: r.errors){ - errorRecap - .append(" ") - .append(error.line.intValue()) - .append(",") - .append(error.character.intValue()) - .append(": ") - .append(error.reason) - .append(NEWLINE); - } - } - } - - if(numProblematicFiles > 0) { - saveReportFile(currentResults, reporter, reportFile); - - String errorMessage = "\nJSHint found problems with " + numProblematicFiles + " file"; - - // pluralise - if (numProblematicFiles > 1) { - errorMessage += "s"; - } - - errorMessage += errorRecap.toString(); - - if (failOnError) { - throw new MojoExecutionException(errorMessage); - } else { - getLog().info(errorMessage); - } - } - } - - private void saveReportFile(Map results, String reportType, String reportFile) { - JSHintReporter reporter = null; - if(JSLintReporter.FORMAT.equalsIgnoreCase(reportType)){ - reporter = new JSLintReporter(); - }else if(HTMLReporter.FORMAT.equalsIgnoreCase(reportType)){ - reporter = new HTMLReporter(); - }else if(CheckStyleReporter.FORMAT.equalsIgnoreCase(reportType)){ - reporter = new CheckStyleReporter(); - }else if(StringUtils.isNotBlank(reportType)){ - getLog().warn("Unknown reporter \"" + reportType + "\". Skip reporting."); - return; - }else{ - return; - } - File file = StringUtils.isNotBlank(reportFile) ? - new File(reportFile) : new File("target/jshint.xml"); - getLog().info(String.format("Generating \"JSHint\" report. reporter=%s, reportFile=%s.", - reportType, file.getAbsolutePath())); - - String report = reporter.report(results); - Writer writer = null; - try{ - writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8")); - writer.write(report); - }catch (IOException e){ - getLog().error(e); - }finally{ - if(writer != null){ - try { - writer.close(); - } catch (IOException e) { - getLog().error(e); - } - } - } - } - - @SuppressWarnings("serial") - private static String getEmbeddedJshintCode(String version) throws MojoFailureException { - - final String resource = EmbeddedJshintCode.EMBEDDED_VERSIONS.get(version); - if(resource==null){ - StringBuffer knownVersions = new StringBuffer(); - for(String v : EmbeddedJshintCode.EMBEDDED_VERSIONS.keySet()){ - knownVersions.append("\n " + v); - } - throw new MojoFailureException("I don't know about the \"" + version + "\" version of jshint. Here are the versions I /do/ know about: " + knownVersions); - } - return resource; - } - - private static File findJshintrc(File cwd) { - File placeToLook = cwd; - while(placeToLook.getParentFile()!=null){ - File rcFile = new File(placeToLook, ".jshintrc"); - if(rcFile.exists()){ - return rcFile; - }else{ - placeToLook = placeToLook.getParentFile(); - } - } - - return null; - } - - private static File findJshintignore(File cwd) { - File placeToLook = cwd; - while (placeToLook.getParentFile() != null) { - File ignoreFile = new File(placeToLook, ".jshintignore"); - if (ignoreFile.exists()) { - return ignoreFile; - } else { - placeToLook = placeToLook.getParentFile(); - } - } - - return null; - } + private static File findJshintrc(File cwd) { + File placeToLook = cwd; + while(placeToLook.getParentFile()!=null){ + File rcFile = new File(placeToLook, ".jshintrc"); + if(rcFile.exists()){ + return rcFile; + }else{ + placeToLook = placeToLook.getParentFile(); + } + } + + return null; + } + + private static File findJshintignore(File cwd) { + File placeToLook = cwd; + while (placeToLook.getParentFile() != null) { + File ignoreFile = new File(placeToLook, ".jshintignore"); + if (ignoreFile.exists()) { + return ignoreFile; + } else { + placeToLook = placeToLook.getParentFile(); + } + } + + return null; + } private Cache readCache(File path, Cache.Hash hash){ try { if(path.exists()){ Cache cache = Util.readObject(path); - if(EqualsBuilder.reflectionEquals(cache.hash, hash)){ - return cache; - }else{ - getLog().warn("Something changed ... clearing cache"); - return new Cache(hash); - } - + if(EqualsBuilder.reflectionEquals(cache.hash, hash)){ + return cache; + }else{ + getLog().warn("Something changed ... clearing cache"); + return new Cache(hash); + } + } } catch (Throwable e) { super.getLog().warn("I was unable to read the cache. This may be because of an upgrade to the plugin."); @@ -447,34 +447,34 @@ private static Config processConfigFile(File configFile) throws MojoExecutionExc if (globalsSet.size() > 0) { globals = StringUtils.join(globalsSet.iterator(), ","); }else{ - globals = ""; + globals = ""; } if (optionsSet.size() > 0) { options = StringUtils.join(optionsSet.iterator(), ","); }else{ - options = ""; + options = ""; } return new Config(options, globals); } - /** - * Read contents of the specified ignore file and use the values defined - * there instead of the ones defined directly in pom.xml config. - * - * @throws MojoExecutionException if the specified file cannot be processed - */ - private static Ignore processIgnoreFile(File basedir, File ignoreFile) throws MojoExecutionException { - try { - List lines = org.apache.commons.io.FileUtils.readLines(ignoreFile, "UTF-8"); - List files = new ArrayList(lines.size()); - for (String line : lines) { - files.add(new File(basedir, line)); - } - return new Ignore(files); - } catch (IOException e) { - throw new MojoExecutionException("Unable to read ignore file located in " + ignoreFile, e); - } - } + /** + * Read contents of the specified ignore file and use the values defined + * there instead of the ones defined directly in pom.xml config. + * + * @throws MojoExecutionException if the specified file cannot be processed + */ + private static Ignore processIgnoreFile(File basedir, File ignoreFile) throws MojoExecutionException { + try { + List lines = org.apache.commons.io.FileUtils.readLines(ignoreFile, "UTF-8"); + List files = new ArrayList(lines.size()); + for (String line : lines) { + files.add(new File(basedir, line)); + } + return new Ignore(files); + } catch (IOException e) { + throw new MojoExecutionException("Unable to read ignore file located in " + ignoreFile, e); + } + } }