<commit_before>package com.googlecode.jslint4java.ant;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

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.Issue;
import com.googlecode.jslint4java.JSLint;
import com.googlecode.jslint4java.Option;

/**
 * Run {@link JSLint} over a tree of files in order to pick holes in your
 * JavaScript.
 *
 * <p>
 * Example build.xml usage:
 *
 * <pre>
 * &lt;project name=&quot;build-test&quot; xmlns:jsl=&quot;antlib:com.googlecode.jslint4java&quot;&gt;
 *   &lt;target name=&quot;jslint&quot;&gt;
 *     &lt;jsl:jslint options=&quot;undef&quot;&gt;
 *       &lt;formatter type=&quot;plain&quot; /&gt;
 *       &lt;fileset dir=&quot;.&quot; includes=&quot;*.js&quot; excludes=&quot;*.pack.js&quot; /&gt;
 *     &lt;/jsl:jslint&gt;
 *   &lt;/target&gt;
 * &lt;/project
 * </pre>
 *
 * <p>
 * You have to specify one or more nested <i>fileset</i> elements. You may
 * optionally specify a <i>formatter</i> 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.
 *
 * <h3>Attributes</h3>
 *
 * <dl>
 * <dt><code>encoding</code></dt>
 * <dd>Optional. The encoding of the JavaScript files. Defaults to system
 * encoding.</dd>
 * <dt><code>haltOnFailure</code></dt>
 * <dd>Optional. Specify if the build should fail if there are files which do
 * not pass JSLint. Defaults to true.</dd>
 * <dt><code>options</code></dt>
 * <dd>Optional. A comma separated list of {@link Option} names. No default.</dd>
 * </dl>
 *
 * @author dom
 * @version $Id$
 * @see <a href="http://jslint.com/">jslint.com< /a>
 * @see FormatterElement
 */
public class JSLintTask extends Task {

    private final Union resources = new Union();

    private JSLint lint;

    private final List<ResultFormatter> formatters = new ArrayList<ResultFormatter>();

    private boolean haltOnFailure = true;

    private String encoding = System.getProperty("file.encoding", "UTF-8");

    /**
     * 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());
    }

    /**
     * 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);
    }

    /**
     * Scan the specified directories for JavaScript files and lint them.
     */
    @Override
    public void execute() throws BuildException {
        if (resources.size() == 0)
            throw new BuildException("no resources specified");

        for (ResultFormatter rf : formatters) {
            rf.begin();
        }

        int failedCount = 0;
        for (Resource resource : resources.listResources()) {
            try {
                if (!lintStream(resource.getName(), resource.toString(), resource.getInputStream())) {
                    failedCount++;
                }
            } catch (IOException e) {
                throw new BuildException(e);
            }
        }

        for (ResultFormatter rf : formatters) {
            rf.end();
        }

        if (failedCount != 0) {
            String files = failedCount == 1 ? "file" : "files";
            String msg = failedCount + " " + files + " did not pass JSLint";
            if (haltOnFailure)
                throw new BuildException(msg);
            else {
                log(msg);
            }
        }
    }

    /**
     * Return a logging {@link OutputStream} that can be passed to formatters.
     *
     * @return
     */
    private OutputStream getDefaultOutput() {
        return new LogOutputStream(this, Project.MSG_INFO);
    }

    /**
     * Create a new {@link JSLint} object.
     */
    @Override
    public void init() throws BuildException {
        try {
            lint = new JSLint();
        } catch (IOException e) {
            throw new BuildException(e);
        }
    }

    /**
     * Lint a given stream. Closes the stream after use.
     *
     * @throws IOException
     */
    private boolean lintStream(String name, String fullPath, InputStream stream)
            throws UnsupportedEncodingException, IOException {
        try {
            List<Issue> issues = lint.lint(name, new BufferedReader(
                    new InputStreamReader(stream, encoding)));
            log("Found " + issues.size() + " issues in " + name,
                    Project.MSG_VERBOSE);
            for (ResultFormatter rf : formatters) {
                rf.output(name, fullPath, issues);
            }
            return issues.size() == 0;
        } finally {
            if (stream != null) {
                stream.close();
            }
        }
    }

    /**
     * Should the build stop if JSLint fails? Defaults to true.
     *
     * @param haltOnFailure
     */
    public void setHaltOnFailure(boolean haltOnFailure) {
        this.haltOnFailure = haltOnFailure;
    }

    /**
     * Set the encoding of the source files that JSLint will read. If not<commit_msg>Pass the resource directly to lintStream().<commit_after>package com.googlecode.jslint4java.ant;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

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.Issue;
import com.googlecode.jslint4java.JSLint;
import com.googlecode.jslint4java.Option;

/**
 * Run {@link JSLint} over a tree of files in order to pick holes in your
 * JavaScript.
 *
 * <p>
 * Example build.xml usage:
 *
 * <pre>
 * &lt;project name=&quot;build-test&quot; xmlns:jsl=&quot;antlib:com.googlecode.jslint4java&quot;&gt;
 *   &lt;target name=&quot;jslint&quot;&gt;
 *     &lt;jsl:jslint options=&quot;undef&quot;&gt;
 *       &lt;formatter type=&quot;plain&quot; /&gt;
 *       &lt;fileset dir=&quot;.&quot; includes=&quot;*.js&quot; excludes=&quot;*.pack.js&quot; /&gt;
 *     &lt;/jsl:jslint&gt;
 *   &lt;/target&gt;
 * &lt;/project
 * </pre>
 *
 * <p>
 * You have to specify one or more nested <i>fileset</i> elements. You may
 * optionally specify a <i>formatter</i> 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.
 *
 * <h3>Attributes</h3>
 *
 * <dl>
 * <dt><code>encoding</code></dt>
 * <dd>Optional. The encoding of the JavaScript files. Defaults to system
 * encoding.</dd>
 * <dt><code>haltOnFailure</code></dt>
 * <dd>Optional. Specify if the build should fail if there are files which do
 * not pass JSLint. Defaults to true.</dd>
 * <dt><code>options</code></dt>
 * <dd>Optional. A comma separated list of {@link Option} names. No default.</dd>
 * </dl>
 *
 * @author dom
 * @version $Id$
 * @see <a href="http://jslint.com/">jslint.com< /a>
 * @see FormatterElement
 */
public class JSLintTask extends Task {

    private final Union resources = new Union();

    private JSLint lint;

    private final List<ResultFormatter> formatters = new ArrayList<ResultFormatter>();

    private boolean haltOnFailure = true;

    private String encoding = System.getProperty("file.encoding", "UTF-8");

    /**
     * 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());
    }

    /**
     * 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);
    }

    /**
     * Scan the specified directories for JavaScript files and lint them.
     */
    @Override
    public void execute() throws BuildException {
        if (resources.size() == 0) {
            throw new BuildException("no resources specified");
        }

        for (ResultFormatter rf : formatters) {
            rf.begin();
        }

        int failedCount = 0;
        for (Resource resource : resources.listResources()) {
            try {
                if (!lintStream(resource)) {
                    failedCount++;
                }
            } catch (IOException e) {
                throw new BuildException(e);
            }
        }

        for (ResultFormatter rf : formatters) {
            rf.end();
        }

        if (failedCount != 0) {
            String files = failedCount == 1 ? "file" : "files";
            String msg = failedCount + " " + files + " did not pass JSLint";
            if (haltOnFailure) {
                throw new BuildException(msg);
            } else {
                log(msg);
            }
        }
    }

    /**
     * Return a logging {@link OutputStream} that can be passed to formatters.
     *
     * @return
     */
    private OutputStream getDefaultOutput() {
        return new LogOutputStream(this, Project.MSG_INFO);
    }

    /**
     * Create a new {@link JSLint} object.
     */
    @Override
    public void init() throws BuildException {
        try {
            lint = new JSLint();
        } catch (IOException e) {
            throw new BuildException(e);
        }
    }

    /**
     * Lint a given stream. Closes the stream after use.
     *
     * @throws IOException
     */
    private boolean lintStream(Resource resource)
            throws UnsupportedEncodingException, IOException {
        InputStream stream = null;
        try {
            stream = resource.getInputStream();
            String name = resource.getName();
            List<Issue> issues = lint.lint(name, new BufferedReader(
                    new InputStreamReader(resource.getInputStream(), encoding)));
            log("Found " + issues.size() + " issues in " + name,
                    Project.MSG_VERBOSE);
            for (ResultFormatter rf : formatters) {
                rf.output(resource.getName(), resource.toString(), issues);
            }
            return issues.size() == 0;
        } finally {
            if (stream != null) {
                stream.close();
            }
        }
    }

    /**
     * Should the build stop if JSLint fails? Defaults to true.
     *
     * @param haltOnFailure
     */
    public void setHaltOnFailure(boolean haltOnFailure) {
        this.haltOnFailure = haltOnFailure;
    }

    /**
     * Set the encoding of the source files that JSLint will read. If not
{'fraction_non_alphanumeric': 0.11922946367956551, 'fraction_numerical': 0.0022063815342837747, 'mean_word_length': 2.3787270642201834, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3230874', 'n_tokens_mistral': 3466, 'n_tokens_neox': 3358, 'n_words': 928}