All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.googlecode.jslint4java.ant.JSLintTask Maven / Gradle / Ivy
package com.googlecode.jslint4java.ant;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.LogOutputStream;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.Union;
import com.googlecode.jslint4java.JSLint;
import com.googlecode.jslint4java.JSLintBuilder;
import com.googlecode.jslint4java.JSLintResult;
import com.googlecode.jslint4java.Option;
import com.googlecode.jslint4java.UnicodeBomInputStream;
/**
* Run {@link JSLint} over a tree of files in order to pick holes in your
* JavaScript.
*
*
* Example build.xml usage:
*
*
* <project name="build-test" xmlns:jsl="antlib:com.googlecode.jslint4java">
* <target name="jslint">
* <jsl:jslint options="undef">
* <formatter type="plain" />
* <fileset dir="." includes="*.js" excludes="*.pack.js" />
* </jsl:jslint>
* </target>
* </project
*
*
*
* You have to specify one or more nested fileset elements. You may
* optionally specify a formatter element in order to generate output (as
* opposed to just a build failed message). Usually, you will want the plain
* formatter, but in case you want to generate a report, the xml formatter
* mighht be useful.
*
*
Attributes
*
*
* encoding
* Optional. The encoding of the JavaScript files. Defaults to system
* encoding.
* haltOnFailure
* Optional. Specify if the build should fail if there are files which do
* not pass JSLint. Defaults to true.
* options
* Optional. A comma separated list of {@link Option} names. No default.
* timeout
* Optional. The maximum amount of time that JSLint can run.
*
*
* @author dom
* @see jslint.com
* @see FormatterElement
*/
public class JSLintTask extends Task {
private static final String NO_FILES_TO_LINT = "no files to lint!";
private final Union resources = new Union();
private final List formatters = new ArrayList();
private boolean haltOnFailure = true;
private String encoding = System.getProperty("file.encoding", "UTF-8");
private String failureProperty = null;
private File jslintSource = null;
private final Map options = new HashMap ();
private PredefElement predef = null;
private long timeout = 0;
/**
* Check the contents of this {@link ResourceCollection}.
*
* @param rc
* Any kind of resource collection, e.g. fileset.
*/
public void add(ResourceCollection rc) {
resources.add(rc);
}
/**
* Add in a {@link ResultFormatter} through the medium of a
* {@link FormatterElement}.
*
* @param fe
*/
public void addConfiguredFormatter(FormatterElement fe) {
fe.setDefaultOutputStream(getDefaultOutput());
formatters.add(fe.getResultFormatter());
}
/**
* Capture a predef element.
*/
public void addPredef(PredefElement predef) {
this.predef = predef;
}
public void applyOptions(JSLint lint) {
for (Entry entry : options.entrySet()) {
String value = entry.getValue();
try {
if (value == null) {
lint.addOption(entry.getKey());
} else {
lint.addOption(entry.getKey(), value);
}
} catch (IllegalArgumentException e) {
String optName = entry.getKey().getLowerName();
String className = e.getClass().getName();
throw new BuildException(optName + ": " + className + ": " + e.getMessage());
}
}
// Handle predefs separately. They don't work too well in the options
// string.
if (predef != null) {
lint.addOption(Option.PREDEF, predef.getText());
}
}
/**
* Scan the specified directories for JavaScript files and lint them.
*/
@Override
public void execute() throws BuildException {
if (resources.size() == 0) {
// issue 53: this isn't a fail, just a notice.
log(NO_FILES_TO_LINT);
}
JSLint lint = makeLint();
applyOptions(lint);
for (ResultFormatter rf : formatters) {
rf.begin();
}
int failedCount = 0;
int totalErrorCount = 0;
for (Resource resource : resources.listResources()) {
try {
int errorCount = lintStream(lint, resource);
if (errorCount > 0) {
totalErrorCount += errorCount;
failedCount++;
}
} catch (IOException e) {
throw new BuildException(e);
}
}
for (ResultFormatter rf : formatters) {
rf.end();
}
if (failedCount != 0) {
String msg = failureMessage(failedCount, totalErrorCount);
if (haltOnFailure) {
throw new BuildException(msg);
} else {
log(msg);
if (failureProperty != null) {
getProject().setProperty(failureProperty, msg);
}
}
}
}
private String failureMessage(int failedCount, int totalErrorCount) {
return "JSLint: " + totalErrorCount + " " + plural(totalErrorCount, "error") + " in "
+ failedCount + " " + plural(failedCount, "file");
}
/**
* Return a logging {@link OutputStream} that can be passed to formatters.
*/
private OutputStream getDefaultOutput() {
return new LogOutputStream(this, Project.MSG_INFO);
}
/**
* Lint a given stream. Closes the stream after use.
*
* @param lint
*
* @throws IOException
*/
private int lintStream(JSLint lint, Resource resource) throws UnsupportedEncodingException,
IOException {
BufferedReader reader = null;
try {
UnicodeBomInputStream stream = new UnicodeBomInputStream(resource.getInputStream());
stream.skipBOM();
reader = new BufferedReader(new InputStreamReader(stream, encoding));
String name = resource.toString();
JSLintResult result = lint.lint(name, reader);
log("Found " + result.getIssues().size() + " issues in " + name, Project.MSG_VERBOSE);
for (ResultFormatter rf : formatters) {
rf.output(result);
}
return result.getIssues().size();
} finally {
if (reader != null) {
reader.close();
}
}
}
/**
* Create a new {@link JSLint} object.
*/
public JSLint makeLint() throws BuildException {
try {
JSLintBuilder builder = new JSLintBuilder();
if (timeout > 0) {
builder.timeout(timeout);
}
if (jslintSource == null) {
return builder.fromDefault();
} else {
return builder.fromFile(jslintSource);
}
} catch (IOException e) {
throw new BuildException(e);
}
}
/**
* Quick and nasty hack to pluralise words. Works enough for my needs.
*/
private String plural(int count, String word) {
return count == 1 ? word : word + "s";
}
/**
* Set the encoding of the source files that JSLint will read. If not
* specified, the default is the system encoding (via the
* file.encoding
property). If that isn't present, default to
* UTF-8
.
*
* @param encoding
* a valid charset identifier.
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
/**
* The name of a property to set upon failure. This property will contain
* the log message.
*/
public void setFailureProperty(String failureProperty) {
this.failureProperty = failureProperty;
}
/**
* Specify an alternative version of jslint.
*/
public void setJslint(File jslint) {
jslintSource = jslint;
}
/**
* Should the build stop if JSLint fails? Defaults to true.
*
* @param haltOnFailure
*/
public void setHaltOnFailure(boolean haltOnFailure) {
this.haltOnFailure = haltOnFailure;
}
/**
* Set the options for running JSLint. This is a comma separated list of
* {@link Option} names. The names are case-insensitive.
*
*
* NB: If you want to put an {@link Option#PREDEF} in here, you should use a
* {@code } child element instead. Otherwise, it could be difficult
* to specify a comma separated list as an element of a comma separated
* list…
*/
public void setOptions(String optionList) throws BuildException {
for (String name : optionList.split("\\s*,\\s*")) {
String[] parts = name.split("=", 2);
String optName = parts[0];
try {
// The Option constants are upper case…
Option o = Option.valueOf(optName.toUpperCase(Locale.getDefault()));
// If an argument has been specified, use it.
String value = parts.length == 2 ? parts[1] : null;
options.put(o, value);
} catch (IllegalArgumentException e) {
throw new BuildException("Unknown option " + optName);
}
}
}
/** Set the maximum time JSLint can run for in seconds. */
public void setTimeout(long timeout) {
this.timeout = timeout;
}
}