Skip to content

Commit

Permalink
Merged pull request #126 from benblank/master.
Browse files Browse the repository at this point in the history
Add WSH support to JSHint
  • Loading branch information
valueof committed Apr 28, 2011
2 parents 36465a5 + 051acc9 commit 94e186d
Show file tree
Hide file tree
Showing 4 changed files with 263 additions and 57 deletions.
4 changes: 4 additions & 0 deletions README.markdown
Expand Up @@ -49,6 +49,10 @@ If you use Rhino, we have a special wrapper script for that:


java -jar /path/to/js.jar env/rhino.js myscript.js java -jar /path/to/js.jar env/rhino.js myscript.js


Also included is a Windows Scripting Host wrapper:

cscript env/wsh.js myscript.js

Tests Tests
----- -----


Expand Down
168 changes: 168 additions & 0 deletions env/wsh.js
@@ -0,0 +1,168 @@
/*jshint evil: true, shadow: true, wsh: true */
/*global JSHINT: false */

(function() {
function readFile(path) {
try {
return new ActiveXObject("Scripting.FileSystemObject").OpenTextFile(path, 1).ReadAll();
} catch (ex) {
return null;
}
}

var formatters = {
errors: function(errors, lines) {
for (var i = 0; i < errors.length; i++) {
var error = errors[i];

if (!error) continue;

if (i) lines.push("");

lines.push("Line " + error.line + " character " + error.character + ": " + error.reason);

if (error.evidence) lines.push(" " + error.evidence.replace(/^\s*((?:[\S\s]*\S)?)\s*$/, "$1"));
}
},

implieds: function(implieds, lines) {
lines.push("Implied globals:");

var globals = {};

for (var i = 0; i < implieds.length; i++) {
var item = implieds[i];

if (!(item.name in globals)) globals[item.name] = [];

globals[item.name].push(item.line);
}

for (var name in globals) {
lines.push(" " + name + ": " + globals[name].join(", "));
}
},

unused: function(unused, lines) {
lines.push("Unused variables:");

var func, names = {};

for (var i = 0; i < unused.length; i++) {
var item = unused[i];

func = item["function"];

if (!(func in names)) names[func] = [];

names[func].push(item.name + " (" + item.line + ")");
}

for (func in names) {
lines.push(" " + func + ": " + names[func].join(", "));
}
}
};

var scriptName = WScript.ScriptName;
var scriptPath = WScript.ScriptFullName;

scriptPath = scriptPath.substr(0, scriptPath.length - scriptName.length);

// load JSHint if the two scripts have not been concatenated
if (typeof JSHINT === "undefined") {
eval(readFile(scriptPath + "..\\jshint.js"));

if (typeof JSHINT === "undefined") {
WScript.StdOut.WriteLine("ERROR: Could not find 'jshint.js'.");

WScript.Quit(-2);
}
}

var globals = {};
var options = {};
var named = WScript.Arguments.Named;
var unnamed = WScript.Arguments.Unnamed;

if (unnamed.length !== 1) {
WScript.StdOut.WriteLine(" usage: cscript " + scriptName + " [options] <script>");
WScript.StdOut.WriteLine("");
WScript.StdOut.WriteLine("Scans the specified script with JSHint and reports any errors encountered. If");
WScript.StdOut.WriteLine("the script name is \"-\", it will be read from standard input instead.");
WScript.StdOut.WriteLine("");
WScript.StdOut.WriteLine("JSHint configuration options can be passed in via optional, Windows-style");
WScript.StdOut.WriteLine("arguments. For example:");
WScript.StdOut.WriteLine(" cscript " + scriptName + " /jquery:true myscript.js");
WScript.StdOut.WriteLine(" cscript " + scriptName + " /globals:QUnit:false,_:false,foo:true foo.js");

WScript.Quit(-1);
}

var script = unnamed(0);

if (script === "-") {
try {
script = WScript.StdIn.ReadAll();
} catch (ex) {
script = null;
}
} else {
script = readFile(script);
}

if (script === null) {
WScript.StdOut.WriteLine("ERROR: Could not read target script.");

WScript.Quit(2);
}

for (var etor = new Enumerator(named); !etor.atEnd(); etor.moveNext()) {
var option = etor.item();
var value = named(option);

if (option === "global") {
value = value.split(",");

for (var i = 0; i < value.length; i++) {
var name = value[i].split(":");

if (name.length === 1 || name[1] === "false") {
globals[name[0]] = false;
} else if (name[1] === "true") {
globals[name[0]] = true;
} else {
WScript.StdOut.WriteLine("Unrecognized value for global: " + name[0]);
WScript.StdOut.WriteLine("Must be \"true\", \"false\", or omitted.");

WScript.Quit(-1);
}
}
} else {
options[option] = value === "true" ? true : value === "false" ? false : value;
}
}

JSHINT(script, options, globals);

var data = JSHINT.data();
var lines = [];

for (var formatter in formatters) {
if (data[formatter]) {
if (lines.length) lines.push("");

formatters[formatter](data[formatter], lines);
}
}

if (lines.length) {
for (var i = 0; i < lines.length; i++) {
WScript.StdOut.WriteLine(lines[i]);
}

WScript.Quit(1);
} else {
WScript.Quit(0);
}
}());
130 changes: 73 additions & 57 deletions jshint.js
Expand Up @@ -154,62 +154,61 @@
evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true
*/ */


/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", /*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)",
"(begin)", "(breakage)", "(context)", "(error)", "(global)", "(breakage)", "(context)", "(error)", "(global)", "(identifier)", "(last)",
"(identifier)", "(last)", "(line)", "(loopage)", "(name)", "(onevar)", "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)",
"(params)", "(scope)", "(statement)", "(verb)", "*", "+", "++", "-", "(statement)", "(verb)", "*", "+", "++", "-", "--", "\/", "<", "<=", "==",
"--", "\/", "<", "<=", "==", "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax,
$continue, $w, Abstract, Ajax, __filename, __dirname, ActiveXObject, Array, __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView,
ArrayBuffer, ArrayBufferView, Autocompleter, Assets, Boolean, Builder, Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas,
Buffer, Browser, COM, CScript, Canvas, CustomAnimation, Class, Control, CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date,
Chain, Color, Cookie, Core, DataView, Date, Debug, Draggable, Draggables, Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, Drag,
Droppables, Document, DomReady, DOMReady, Drag, E, Enumerator, Enumerable, E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event,
Element, Elements, Error, Effect, EvalError, Event, Events, FadeAnimation, Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form,
Field, Flash, Float32Array, Float64Array, Form, FormField, Frame, Function, FormField, Frame, Function, Fx, GetObject, Group, Hash, HotKey, HTMLElement,
Fx, Group, Hash, HotKey, HTMLElement, HtmlTable, Iframe, IframeShim, Image, HtmlTable, Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array,
Int16Array, Int32Array, Int8Array, Insertion, InputValidator, JSON, Keyboard, Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E,
Locale, LN10, LN2, LOG10E, LOG2E, MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MoveAnimation, MooTools, Native,
MoveAnimation, MooTools, Native, NEGATIVE_INFINITY, Number, Object, NEGATIVE_INFINITY, Number, Object, ObjectRange, Option, Options, OverText, PI,
ObjectRange, Option, Options, OverText, PI, POSITIVE_INFINITY, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, RangeError,
PeriodicalExecuter, Point, Position, Prototype, RangeError, Rectangle, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation,
ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, SQRT1_2, SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion,
SQRT2, ScrollBar, Scriptaculous, Scroller, Slick, Slider, Selector, String, ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller,
Style, SyntaxError, Sortable, Sortables, SortableObserver, Sound, Spinner, Slick, Slider, Selector, String, Style, SyntaxError, Sortable, Sortables,
System, Swiff, Text, TextArea, Template, Timer, Tips, Type, TypeError, SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template,
Toggle, Try, URI, URIError, URL, VBArray, WScript, Web, Window, XMLDOM, Timer, Tips, Type, TypeError, Toggle, Try, URI, URIError, URL, VBArray, WSH,
XMLHttpRequest, XPathEvaluator, XPathException, XPathExpression, WScript, Web, Window, XMLDOM, XMLHttpRequest, XPathEvaluator, XPathException,
XPathNamespace, XPathNSResolver, XPathResult, "\\", a, addEventListener, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, "\\", a,
address, alert, apply, applicationCache, arguments, arity, asi, b, bitwise, addEventListener, address, alert, apply, applicationCache, arguments, arity,
block, blur, boolOptions, boss, browser, c, call, callee, caller, cases, asi, b, bitwise, block, blur, boolOptions, boss, browser, c, call, callee,
charAt, charCodeAt, character, clearInterval, clearTimeout, close, closed, caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout,
closure, comment, condition, confirm, console, constructor, content, couch, close, closed, closure, comment, condition, confirm, console, constructor,
create, css, curly, d, data, datalist, dd, debug, decodeURI, content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI,
decodeURIComponent, defaultStatus, defineClass, deserialize, devel, decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document,
document, edition, else, emit, encodeURI, encodeURIComponent, entityify, edition, else, emit, encodeURI, encodeURIComponent, entityify, eqeqeq, eqnull,
eqeqeq, eqnull, errors, es5, escape, eval, event, evidence, evil, ex, errors, es5, escape, eval, event, evidence, evil, ex, exception, exec, exps,
exception, exec, exps, expr, exports, FileReader, first, floor, focus, expr, exports, FileReader, first, floor, focus, forin, fragment, frames, from,
forin, fragment, frames, from, fromCharCode, fud, funct, function, functions, fromCharCode, fud, funct, function, functions, g, gc, getComputedStyle, getRow,
g, gc, getComputedStyle, getRow, GLOBAL, global, globals, globalstrict, GLOBAL, global, globals, globalstrict, hasOwnProperty, help, history, i, id,
hasOwnProperty, help, history, i, id, identifier, immed, implieds, identifier, immed, implieds, include, indent, indexOf, init, ins, instanceOf,
include, indent, indexOf, init, ins, instanceOf, isAlpha, isAlpha, isApplicationRunning, isArray, isDigit, isFinite, isNaN, join, jshint,
isApplicationRunning, isArray, isDigit, isFinite, isNaN, join, jshint, JSHINT, json, jquery, jQuery, keys, label, labelled, last, laxbreak, latedef,
JSHINT, json, jquery, jQuery, keys, label, labelled, last, laxbreak, lbp, led, left, length, line, load, loadClass, localStorage, location, log,
latedef, lbp, led, left, length, line, load, loadClass, localStorage, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy,
location, log, loopfunc, m, match, maxerr, maxlen, member,message, meta, moveTo, mootools, name, navigator, new, newcap, noarg, node, noempty, nomen,
module, moveBy, moveTo, mootools, name, navigator, new, newcap, noarg, nonew, nud, onbeforeunload, onblur, onerror, onevar, onfocus, onload, onresize,
node, noempty, nomen, nonew, nud, onbeforeunload, onblur, onerror, onevar, onunload, open, openDatabase, openURL, opener, opera, outer, param, parent,
onfocus, onload, onresize, onunload, open, openDatabase, openURL, opener, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt,
opera, outer, param, parent, parseFloat, parseInt, passfail, plusplus, prototype, prototypejs, push, quit, range, raw, reach, reason, regexp,
predef, print, process, prompt, prototype, prototypejs, push, quit, range, readFile, readUrl, removeEventListener, replace, report, require, reserved,
raw, reach, reason, regexp, readFile, readUrl, removeEventListener, replace, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right,
report, require, reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, runCommand, scroll, screen, scrollBy, scrollTo, scrollbar, search, seal, send,
respond, rhino, right, runCommand, scroll, screen, scrollBy, scrollTo, serialize, setInterval, setTimeout, shift, slice, sort,spawn, split, stack,
scrollbar, search, seal, send, serialize, setInterval, setTimeout, shift, status, start, strict, sub, substr, supernew, shadow, supplant, sum, sync,
slice, sort,spawn, split, stack, status, start, strict, sub, substr, supernew, test, toLowerCase, toString, toUpperCase, toint32, token, top, type, typeOf,
shadow, supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, Uint16Array, Uint32Array, Uint8Array, undef, unused, urls, value, valueOf, var,
token, top, type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef, version, WebSocket, white, window, Worker,
unused, urls, value, valueOf, var, version, WebSocket, white, window, Worker wsh*/
*/


/*global exports: false */ /*global exports: false */


Expand Down Expand Up @@ -281,7 +280,8 @@ var JSHINT = (function () {
strict : true, // require the "use strict"; pragma strict : true, // require the "use strict"; pragma
sub : true, // if all forms of subscript notation are tolerated sub : true, // if all forms of subscript notation are tolerated
supernew : true, // if `new function () { ... };` and `new Object;` should be tolerated supernew : true, // if `new function () { ... };` and `new Object;` should be tolerated
white : true // if strict whitespace rules apply white : true, // if strict whitespace rules apply
wsh : true // if the Windows Scripting Host environment globals should be predefined
}, },


// browser contains a set of global names which are commonly provided by a // browser contains a set of global names which are commonly provided by a
Expand Down Expand Up @@ -604,6 +604,19 @@ var JSHINT = (function () {
urls, urls,
warnings, warnings,


wsh = {
ActiveXObject : true,
Enumerator : true,
GetObject : true,
ScriptEngine : true,
ScriptEngineBuildVersion : true,
ScriptEngineMajorVersion : true,
ScriptEngineMinorVersion : true,
VBArray : true,
WSH : true,
WScript : true
},

// Regular expressions. Some of these are stupidly long. // Regular expressions. Some of these are stupidly long.


// unsafe comment or string // unsafe comment or string
Expand Down Expand Up @@ -754,6 +767,9 @@ var JSHINT = (function () {
if (option.mootools) if (option.mootools)
combine(predefined, mootools); combine(predefined, mootools);


if (option.wsh)
combine(predefined, wsh);

if (option.globalstrict) if (option.globalstrict)
option.strict = true; option.strict = true;
} }
Expand Down
18 changes: 18 additions & 0 deletions tests/envs.js
Expand Up @@ -264,6 +264,24 @@ exports.rhino = function () {
assert.globalsKnown(globals, { rhino: true }); assert.globalsKnown(globals, { rhino: true });
}; };


exports.wsh = function () {
var globals = [
'ActiveXObject'
, 'Enumerator'
, 'GetObject'
, 'ScriptEngine'
, 'ScriptEngineBuildVersion'
, 'ScriptEngineMajorVersion'
, 'ScriptEngineMinorVersion'
, 'VBArray'
, 'WSH'
, 'WScript'
];

assert.globalsImplied(globals);
assert.globalsKnown(globals, { wsh: true });
};

exports.es5 = function () { exports.es5 = function () {
var src = fs.readFileSync(__dirname + "/fixtures/es5.js", "utf8"); var src = fs.readFileSync(__dirname + "/fixtures/es5.js", "utf8");


Expand Down

0 comments on commit 94e186d

Please sign in to comment.