From 6dfe5cb1ba2223de4cf876cfab6c5468b76bff20 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Fri, 22 Jul 2011 13:53:14 +0200 Subject: [PATCH] update jshint. fix #322 --- lib/ace/worker/jshint.js | 156 +++++++++++++++++++++++++-------------- 1 file changed, 99 insertions(+), 57 deletions(-) diff --git a/lib/ace/worker/jshint.js b/lib/ace/worker/jshint.js index 0f408db9..1a099f18 100644 --- a/lib/ace/worker/jshint.js +++ b/lib/ace/worker/jshint.js @@ -1,5 +1,5 @@ define(function(require, exports, module) { -/* +/*! * JSHint, by JSHint Community. * * Licensed under the same slightly modified MIT license that JSLint is. @@ -152,7 +152,8 @@ define(function(require, exports, module) { */ /*jshint - evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true + evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true, + undef: true, maxlen: 100 */ /*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)", @@ -186,13 +187,14 @@ define(function(require, exports, module) { close, closed, closure, comment, condition, confirm, console, constructor, content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI, decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document, - edition, else, emit, encodeURI, encodeURIComponent, entityify, eqeqeq, eqnull, - errors, es5, escape, eval, event, evidence, evil, ex, exception, exec, exps, - expr, exports, FileReader, first, floor, focus, forin, fragment, frames, from, - fromCharCode, fud, funct, function, functions, g, gc, getComputedStyle, getRow, - GLOBAL, global, globals, globalstrict, hasOwnProperty, help, history, i, id, - identifier, immed, implieds, include, indent, indexOf, init, ins, instanceOf, - isAlpha, isApplicationRunning, isArray, isDigit, isFinite, isNaN, join, jshint, + dojo, dijit, dojox, define, edition, else, emit, encodeURI, encodeURIComponent, + entityify, eqeqeq, eqnull, errors, es5, escape, eval, event, evidence, evil, + ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, + forin, fragment, frames, from, fromCharCode, fud, funct, function, functions, + g, gc, getComputedStyle, getRow, GLOBAL, global, globals, globalstrict, + hasOwnProperty, help, history, i, id, identifier, immed, implieds, include, + indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray, + isDigit, isFinite, isNaN, iterator, join, jshint, JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, latedef, lbp, led, left, length, line, load, loadClass, localStorage, location, log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy, @@ -200,10 +202,10 @@ define(function(require, exports, module) { nonew, nud, onbeforeunload, onblur, onerror, onevar, onfocus, onload, onresize, onunload, open, openDatabase, openURL, opener, opera, outer, param, parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt, - prototype, prototypejs, push, quit, range, raw, reach, reason, regexp, + proto, prototype, prototypejs, push, quit, range, raw, reach, reason, regexp, readFile, readUrl, regexdash, removeEventListener, replace, report, require, reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right, - runCommand, scroll, screen, scrollBy, scrollTo, scrollbar, search, seal, send, + runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal, send, serialize, setInterval, setTimeout, shift, slice, sort,spawn, split, stack, status, start, strict, sub, substr, supernew, shadow, supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing, type, @@ -247,9 +249,10 @@ var JSHINT = (function () { boss : true, // if advanced usage of assignments should be allowed browser : true, // if the standard browser globals should be predefined couch : true, // if CouchDB globals should be predefined - curly : true, // if curly braces around blocks should be required (even in if/for/while) + curly : true, // if curly braces around all blocks should be required debug : true, // if debugger statements should be allowed devel : true, // if logging globals should be predefined (console, alert, etc.) + dojo : true, // if Dojo Toolkit globals should be predefined eqeqeq : true, // if === should be required eqnull : true, // if == null comparisons should be tolerated es5 : true, // if ES5 syntax should be allowed @@ -258,6 +261,7 @@ var JSHINT = (function () { forin : true, // if for in statements must filter globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict') immed : true, // if immediate invocations must be wrapped in parens + iterator : true, // if the `__iterator__` property should be disallowed jquery : true, // if jQuery globals should be predefined latedef : true, // if the use before definition should not be tolerated laxbreak : true, // if line breaks should not be checked @@ -272,18 +276,22 @@ var JSHINT = (function () { onevar : true, // if only one var statement per function should be allowed passfail : true, // if the scan should stop on first error plusplus : true, // if increment/decrement should not be allowed + proto : true, // if the `__proto__` property should be disallowed prototypejs : true, // if Prototype and Scriptaculous globals should be predefined regexdash : true, // if unescaped last dash (-) inside brackets should be tolerated regexp : true, // if the . should not be allowed in regexp literals rhino : true, // if the Rhino environment globals should be predefined undef : true, // if variables should be declared before used + scripturl : true, // if script-targeted URLs should be tolerated shadow : true, // if variable shadowing should be tolerated strict : true, // require the "use strict"; pragma 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 trailing : true, // if trailing whitespace rules apply white : true, // if strict whitespace rules apply - wsh : true // if the Windows Scripting Host environment globals should be predefined + 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 @@ -375,12 +383,20 @@ var JSHINT = (function () { }, devel = { - alert : false, - confirm : false, - console : false, - Debug : false, - opera : false, - prompt : false + alert : false, + confirm : false, + console : false, + Debug : false, + opera : false, + prompt : false + }, + + dojo = { + dojo : false, + dijit : false, + dojox : false, + define : false, + "require" : false }, escapes = { @@ -617,27 +633,38 @@ var JSHINT = (function () { VBArray : true, WSH : true, WScript : true - }, + }; -// Regular expressions. Some of these are stupidly long. + // Regular expressions. Some of these are stupidly long. + var ax, cx, tx, nx, nxg, lx, ix, jx, ft; + (function () { + /*jshint maxlen:300 */ -// unsafe comment or string - ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i, -// unsafe characters that are silently deleted by one or more browsers - cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/, -// token - tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/, -// characters in strings that need escapement - nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/, - nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, -// star slash - lx = /\*\/|\/\*/, -// identifier - ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/, -// javascript url - jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i, -// catches /* falls through */ comments - ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/; + // unsafe comment or string + ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i; + + // unsafe characters that are silently deleted by one or more browsers + cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + + // token + tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/; + + // characters in strings that need escapement + nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + + // star slash + lx = /\*\/|\/\*/; + + // identifier + ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/; + + // javascript url + jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i; + + // catches /* falls through */ comments + ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/; + }()); function F() {} // Used by Object.create @@ -760,6 +787,9 @@ var JSHINT = (function () { if (option.devel) combine(predefined, devel); + if (option.dojo) + combine(predefined, dojo); + if (option.browser) combine(predefined, browser); @@ -875,7 +905,7 @@ var JSHINT = (function () { // Check for trailing whitespaces tw = s.search(/\s+$/); - if (option.trailing && ~tw) + if (option.trailing && ~tw && !~s.search(/^\s+$/)) warningAt("Trailing whitespace.", line, tw); return true; @@ -895,17 +925,19 @@ var JSHINT = (function () { } t = Object.create(t); if (type === '(string)' || type === '(range)') { - if (jx.test(value)) { + if (!option.scripturl && jx.test(value)) { warningAt("Script URL.", line, from); } } if (type === '(identifier)') { t.identifier = true; - if (value === '__iterator__' || value === '__proto__') { - errorAt("Reserved name '{a}'.", + if (value === '__proto__' && !option.proto) { + warningAt("The '{a}' property is deprecated.", line, from, value); - } else if (option.nomen && - (value.charAt(0) === '_' || + } else if (value === '__iterator__' && !option.iterator) { + warningAt("'{a}' is only available in JavaScript 1.7.", + line, from, value); + } else if (option.nomen && (value.charAt(0) === '_' || value.charAt(value.length - 1) === '_')) { warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", value); @@ -2141,12 +2173,14 @@ loop: for (;;) { if (!t.block) { if (!option.expr && (!r || !r.exps)) { - warning("Expected an assignment or function call and instead saw an expression.", token); + warning("Expected an assignment or function call and instead saw an expression.", + token); } else if (option.nonew && r.id === '(' && r.left.id === 'new') { warning("Do not use 'new' for side effects."); } if (nexttoken.id !== ';') { - if (!option.asi && !(option.lastsemic && nexttoken.id == '}' && nexttoken.line == token.line)) { + if (!option.asi && !(option.lastsemic && nexttoken.id == '}' && + nexttoken.line == token.line)) { warningAt("Missing semicolon.", token.line, token.from + token.value.length); } } else { @@ -2509,7 +2543,10 @@ loop: for (;;) { }); relation('==='); relation('!=', function (left, right) { - if (option.eqeqeq) { + var eqnull = option.eqnull && + (left.value == 'null' || right.value == 'null'); + + if (!eqnull && option.eqeqeq) { warning("Expected '{a}' and instead saw '{b}'.", this, '!==', '!='); } else if (isPoorRelation(left)) { @@ -2536,7 +2573,7 @@ loop: for (;;) { if (left && right && left.id === '(string)' && right.id === '(string)') { left.value += right.value; left.character = right.character; - if (jx.test(left.value)) { + if (!option.scripturl && jx.test(left.value)) { warning("JavaScript URL.", left); } return left; @@ -2637,7 +2674,8 @@ loop: for (;;) { if (c.id !== 'function') { i = c.value.substr(0, 1); if (option.newcap && (i < 'A' || i > 'Z')) { - warning("A constructor name should start with an uppercase letter.", token); + warning("A constructor name should start with "+ + "an uppercase letter.", token); } } } @@ -3043,8 +3081,9 @@ loop: for (;;) { blockstmt('function', function () { if (inblock) { - warning( -"Function declarations should not be placed in blocks. Use a function expression or move the statement to the top of the outer function.", token); + warning("Function declarations should not be placed in blocks. " + + "Use a function expression or move the statement to the top of " + + "the outer function.", token); } var i = identifier(); @@ -3318,7 +3357,8 @@ loop: for (;;) { s = block(true, true); if (option.forin && (s.length > 1 || typeof s[0] !== 'object' || s[0].value !== 'if')) { - warning("The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.", this); + warning("The body of a for in should be wrapped in an if statement to filter " + + "unwanted properties from the prototype.", this); } funct['(breakage)'] -= 1; funct['(loopage)'] -= 1; @@ -3487,8 +3527,10 @@ loop: for (;;) { if (o[nexttoken.value] === true) { warning("Duplicate key '{a}'.", nexttoken, nexttoken.value); - } else if (nexttoken.value === '__proto__') { - warning("Stupid key '{a}'.", + } else if ((nexttoken.value === '__proto__' && + !option.proto) || (nexttoken.value === '__iterator__' && + !option.iterator)) { + warning("The '{a}' key may produce unexpected results.", nexttoken, nexttoken.value); } else { o[nexttoken.value] = true; @@ -3574,7 +3616,7 @@ loop: for (;;) { } else if (typeof a === 'object') { k = Object.keys(a); for (i = 0; i < k.length; i += 1) { - predefined[k[i]] = !!a[k]; + predefined[k[i]] = !!a[k[i]]; } } } @@ -3871,5 +3913,5 @@ loop: for (;;) { // Make JSHINT a Node module, if possible. if (typeof exports == 'object' && exports) exports.JSHINT = JSHINT; - + }); \ No newline at end of file