From 31d94d64a510b50023729370d45959b5540b5d9c Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Sun, 8 Dec 2013 16:59:21 -0500 Subject: [PATCH] use the 2.x (stable) branch of jshint also commit the updated jshint modules themselves --- Support/jshint-tm.js | 6 +-- Support/jshint.js | 93 ++++++++++++++++++++++++-------------------- Support/lex.js | 25 ++++++++---- Support/messages.js | 4 +- Support/package.json | 14 ++++--- Support/reg.js | 4 ++ Support/vars.js | 3 ++ 7 files changed, 88 insertions(+), 61 deletions(-) diff --git a/Support/jshint-tm.js b/Support/jshint-tm.js index 574fffb..20a0bc3 100755 --- a/Support/jshint-tm.js +++ b/Support/jshint-tm.js @@ -18,8 +18,8 @@ function html(s) { } /** - * Downloads the latest JSHint version from GitHub and invokes the callback when done. - * https://raw.github.com/jshint/jshint/master/src/jshint.js + * Downloads the latest JSHint from the 2.x branch from GitHub and invokes the callback when done. + * https://raw.github.com/jshint/jshint/2.x/src/jshint.js */ function download_jshint_resources(ready) { var req, @@ -27,7 +27,7 @@ function download_jshint_resources(ready) { jshint_data_resources = ["ascii-identifier-data.js", "non-ascii-identifier-part-only.js", "non-ascii-identifier-start.js"]; jshint_resources.forEach(function(resource) { - req = https.get({host: 'raw.github.com', port: 443, path: '/jshint/jshint/master/src/' + resource}, function(res) { + req = https.get({host: 'raw.github.com', port: 443, path: '/jshint/jshint/2.x/src/' + resource}, function(res) { if (res.statusCode === 200) { res.setEncoding('utf8'); var data = ''; diff --git a/Support/jshint.js b/Support/jshint.js index 6e11ff0..07f9b10 100644 --- a/Support/jshint.js +++ b/Support/jshint.js @@ -311,18 +311,10 @@ var JSHINT = (function () { }); } - function combine(t, o) { - var n; - for (n in o) { - if (_.has(o, n) && !_.has(JSHINT.blacklist, n)) { - t[n] = o[n]; - } - } - } - - function updatePredefined() { - Object.keys(JSHINT.blacklist).forEach(function (key) { - delete predefined[key]; + function combine(dest, src) { + Object.keys(src).forEach(function (name) { + if (JSHINT.blacklist.hasOwnProperty(name)) return; + dest[name] = src[name]; }); } @@ -547,8 +539,7 @@ var JSHINT = (function () { } } } else { - if (!state.option.shadow && type !== "exception" || - (funct["(blockscope)"].getlabel(t))) { + if (!state.option.shadow && type !== "exception" || (funct["(blockscope)"].getlabel(t))) { warning("W004", state.tokens.next, t); } } @@ -604,7 +595,7 @@ var JSHINT = (function () { val = false; JSHINT.blacklist[key] = key; - updatePredefined(); + delete predefined[key]; } else { predef[key] = (val === "true"); } @@ -697,15 +688,14 @@ var JSHINT = (function () { if (key === "validthis") { // `validthis` is valid only within a function scope. - if (funct["(global)"]) { - error("E009"); - } else { - if (val === "true" || val === "false") { - state.option.validthis = (val === "true"); - } else { - error("E002", nt); - } - } + + if (funct["(global)"]) + return void error("E009"); + + if (val !== "true" && val !== "false") + return void error("E002", nt); + + state.option.validthis = (val === "true"); return; } @@ -1948,17 +1938,13 @@ var JSHINT = (function () { function note_implied(tkn) { - var name = tkn.value, line = tkn.line, a = implied[name]; - if (typeof a === "function") { - a = false; - } + var name = tkn.value; + var desc = Object.getOwnPropertyDescriptor(implied, name); - if (!a) { - a = [line]; - implied[name] = a; - } else if (a[a.length - 1] !== line) { - a.push(line); - } + if (!desc) + implied[name] = [tkn.line]; + else + desc.value.push(tkn.line); } @@ -3045,7 +3031,11 @@ var JSHINT = (function () { } i = property_name(); - if (!i) { + + // ES6 allows for get() {...} and set() {...} method + // definition shorthand syntax, so we don't produce an error + // if the esnext option is enabled. + if (!i && !state.option.inESNext()) { error("E035"); } @@ -3055,13 +3045,19 @@ var JSHINT = (function () { error("E049", state.tokens.next, "class getter method", i); } - saveGetter(tag + i); + // We don't want to save this getter unless it's an actual getter + // and not an ES6 concise method + if (i) { + saveGetter(tag + i); + } + t = state.tokens.next; adjacent(state.tokens.curr, state.tokens.next); f = doFunction(); p = f["(params)"]; - if (p) { + // Don't warn about getter/setter pairs if this is an ES6 concise method + if (i && p) { warning("W076", t, p[0], i); } @@ -3074,7 +3070,11 @@ var JSHINT = (function () { } i = property_name(); - if (!i) { + + // ES6 allows for get() {...} and set() {...} method + // definition shorthand syntax, so we don't produce an error + // if the esnext option is enabled. + if (!i && !state.option.inESNext()) { error("E035"); } @@ -3084,13 +3084,19 @@ var JSHINT = (function () { error("E049", state.tokens.next, "class setter method", i); } - saveSetter(tag + i, state.tokens.next); + // We don't want to save this getter unless it's an actual getter + // and not an ES6 concise method + if (i) { + saveSetter(tag + i, state.tokens.next); + } + t = state.tokens.next; adjacent(state.tokens.curr, state.tokens.next); f = doFunction(); p = f["(params)"]; - if (!p || p.length !== 1) { + // Don't warn about getter/setter pairs if this is an ES6 concise method + if (i && (!p || p.length !== 1)) { warning("W077", t, i); } } else { @@ -4023,7 +4029,8 @@ var JSHINT = (function () { this.first = expression(0); if (this.first && - this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) { + this.first.type === "(punctuator)" && this.first.value === "=" && + !this.first.paren && !state.option.boss) { warningAt("W093", this.first.line, this.first.character); } } @@ -4056,7 +4063,8 @@ var JSHINT = (function () { nobreaknonadjacent(state.tokens.curr, state.tokens.next); this.first = expression(10); - if (this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) { + if (this.first.type === "(punctuator)" && this.first.value === "=" && + !this.first.paren && !state.option.boss) { warningAt("W093", this.first.line, this.first.character); } } @@ -4517,6 +4525,7 @@ var JSHINT = (function () { var newOptionObj = {}; var newIgnoredObj = {}; + o = _.clone(o); state.reset(); if (o && o.scope) { diff --git a/Support/lex.js b/Support/lex.js index 4f49961..e857614 100644 --- a/Support/lex.js +++ b/Support/lex.js @@ -1314,16 +1314,17 @@ Lexer.prototype = { this.char = 1; this.from = 1; + var startsWith = function (prefix) { + return this.indexOf(prefix) === 0; + }; + var endsWith = function (suffix) { + return this.indexOf(suffix, this.length - suffix.length) !== -1; + }; + var inputTrimmed = this.input.trim(); + // If we are ignoring linter errors, replace the input with empty string // if it doesn't already at least start or end a multi-line comment if (state.ignoreLinterErrors === true) { - var startsWith = function (prefix) { - return this.indexOf(prefix) === 0; - }; - var endsWith = function (suffix) { - return this.indexOf(suffix, this.length - suffix.length) !== -1; - }; - var inputTrimmed = this.input.trim(); if (! (startsWith.call(inputTrimmed, "/*") || endsWith.call(inputTrimmed, "*/"))) { this.input = ""; } @@ -1345,7 +1346,15 @@ Lexer.prototype = { // long. if (state.option.maxlen && state.option.maxlen < this.input.length) { - this.trigger("warning", { code: "W101", line: this.line, character: this.input.length }); + var inComment = state.tokens.curr.comment || + startsWith.call(inputTrimmed, "//") || + startsWith.call(inputTrimmed, "/*"); + + var shouldTriggerError = !inComment || !reg.maxlenException.test(inputTrimmed); + + if (shouldTriggerError) { + this.trigger("warning", { code: "W101", line: this.line, character: this.input.length }); + } } return true; diff --git a/Support/messages.js b/Support/messages.js index cabbe4c..ff2862a 100644 --- a/Support/messages.js +++ b/Support/messages.js @@ -40,7 +40,7 @@ var errors = { E024: "Unexpected '{a}'.", E025: "Missing ':' on a case clause.", E026: "Missing '}' to match '{' from line {a}.", - E027: "Missing ']' to match '[' form line {a}.", + E027: "Missing ']' to match '[' from line {a}.", E028: "Illegal comma.", E029: "Unclosed string.", @@ -125,7 +125,7 @@ var warnings = { W054: "The Function constructor is a form of eval.", W055: "A constructor name should start with an uppercase letter.", W056: "Bad constructor.", - W057: "Weird construction. Is 'new' unnecessary?", + W057: "Weird construction. Is 'new' necessary?", W058: "Missing '()' invoking a constructor.", W059: "Avoid arguments.{a}.", W060: "document.write can be a form of eval.", diff --git a/Support/package.json b/Support/package.json index 2e012da..5aacb77 100644 --- a/Support/package.json +++ b/Support/package.json @@ -33,10 +33,11 @@ "main": "./src/jshint.js", "dependencies": { - "shelljs": "0.1.x", - "underscore": "1.4.x", - "cli": "0.4.x", - "minimatch": "0.x.x", + "shelljs": "0.1.x", + "underscore": "1.4.x", + "cli": "0.4.x", + "minimatch": "0.x.x", + "htmlparser2": "3.3.x", "console-browserify": "0.1.x" }, @@ -57,11 +58,12 @@ "strict": true, "white": true, "smarttabs": true, - "maxlen": 100, - "newcap": false, "undef": true, "unused": true, "onecase": true, + "lastsemic": true, + "newcap": false, + "maxlen": 100, "indent": 2 }, diff --git a/Support/reg.js b/Support/reg.js index 5a54a31..6c43b7e 100644 --- a/Support/reg.js +++ b/Support/reg.js @@ -32,3 +32,7 @@ exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livesc // Catches /* falls through */ comments (ft) exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/; + +// very conservative rule (eg: only one space between the start of the comment and the first character) +// to relax the maxlen option +exports.maxlenException = /^(?:(?:\/\/|\/\*|\*) ?)?[^ ]+$/; diff --git a/Support/vars.js b/Support/vars.js index 930e055..a3589b1 100644 --- a/Support/vars.js +++ b/Support/vars.js @@ -52,6 +52,9 @@ exports.browser = { atob : false, blur : false, btoa : false, + CanvasGradient : false, + CanvasPattern : false, + CanvasRenderingContext2D: false, clearInterval : false, clearTimeout : false, close : false,