jshintrb 0.1.6 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -0
- data/README.md +2 -2
- data/Rakefile +3 -4
- data/jshintrb.gemspec +1 -1
- data/lib/js/jshint.js +1358 -1127
- data/lib/jshintrb.rb +2 -2
- data/lib/jshintrb/lint.rb +8 -3
- data/lib/jshintrb/version.rb +2 -2
- data/spec/jshintrb_spec.rb +6 -0
- metadata +58 -88
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -36,9 +36,9 @@ end
|
|
36
36
|
When initializing `Jshintrb`, you can pass options
|
37
37
|
|
38
38
|
```ruby
|
39
|
-
Jshintrb.new(:undef => true).
|
39
|
+
Jshintrb::Lint.new(:undef => true).lint(source)
|
40
40
|
# Or
|
41
|
-
Jshintrb.
|
41
|
+
Jshintrb.lint(source, :undef => true)
|
42
42
|
```
|
43
43
|
|
44
44
|
[List of all available options](http://www.jshint.com/options/)
|
data/Rakefile
CHANGED
@@ -5,8 +5,8 @@ require "bundler/gem_tasks"
|
|
5
5
|
end
|
6
6
|
|
7
7
|
require 'submodule'
|
8
|
-
|
9
|
-
|
8
|
+
Submodule::Task.new do |t|
|
9
|
+
t.test do
|
10
10
|
# sudo apt-get update
|
11
11
|
# sudo apt-get install npm
|
12
12
|
# sudo npm -g install expresso
|
@@ -15,12 +15,11 @@ class JshintSubmodule < Submodule::Task
|
|
15
15
|
sh "#{expresso} tests/regression/*.js"
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
t.after_pull do
|
19
19
|
cp "vendor/jshint/jshint.js", "lib/js/jshint.js"
|
20
20
|
sh "git add lib/js/jshint.js"
|
21
21
|
end
|
22
22
|
end
|
23
|
-
JshintSubmodule.new
|
24
23
|
|
25
24
|
require "rspec/core/rake_task"
|
26
25
|
RSpec::Core::RakeTask.new
|
data/jshintrb.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
|
19
19
|
# specify any dependencies here; for example:
|
20
20
|
s.add_development_dependency "rspec"
|
21
|
-
s.add_development_dependency "submodule"
|
21
|
+
s.add_development_dependency "submodule", ">=0.0.3"
|
22
22
|
s.add_runtime_dependency "rake"
|
23
23
|
|
24
24
|
s.add_dependency "multi_json", ">= 1.3"
|
data/lib/js/jshint.js
CHANGED
@@ -28,7 +28,7 @@
|
|
28
28
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
29
29
|
* DEALINGS IN THE SOFTWARE.
|
30
30
|
*
|
31
|
-
* JSHint was forked from 2010-12-16 edition of JSLint.
|
31
|
+
* JSHint was forked from the 2010-12-16 edition of JSLint.
|
32
32
|
*
|
33
33
|
*/
|
34
34
|
|
@@ -55,8 +55,8 @@
|
|
55
55
|
JSHINT.errors is an array of objects containing these members:
|
56
56
|
|
57
57
|
{
|
58
|
-
line : The line (relative to
|
59
|
-
character : The character (relative to
|
58
|
+
line : The line (relative to 1) at which the lint was found
|
59
|
+
character : The character (relative to 1) at which the lint was found
|
60
60
|
reason : The problem
|
61
61
|
evidence : The text line in which the problem occurred
|
62
62
|
raw : The raw message before the details were inserted
|
@@ -69,15 +69,6 @@
|
|
69
69
|
If a fatal error was found, a null will be the last element of the
|
70
70
|
JSHINT.errors array.
|
71
71
|
|
72
|
-
You can request a Function Report, which shows all of the functions
|
73
|
-
and the parameters and vars that they use. This can be used to find
|
74
|
-
implied global variables and other problems. The report is in HTML and
|
75
|
-
can be inserted in an HTML <body>.
|
76
|
-
|
77
|
-
var myReport = JSHINT.report(limited);
|
78
|
-
|
79
|
-
If limited is true, then the report will be limited to only errors.
|
80
|
-
|
81
72
|
You can request a data structure which contains JSHint's results.
|
82
73
|
|
83
74
|
var myData = JSHINT.data();
|
@@ -96,7 +87,9 @@
|
|
96
87
|
functions: [
|
97
88
|
name: STRING,
|
98
89
|
line: NUMBER,
|
90
|
+
character: NUMBER,
|
99
91
|
last: NUMBER,
|
92
|
+
lastcharacter: NUMBER,
|
100
93
|
param: [
|
101
94
|
STRING
|
102
95
|
],
|
@@ -152,19 +145,20 @@
|
|
152
145
|
|
153
146
|
/*jshint
|
154
147
|
evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true,
|
155
|
-
undef: true, maxlen: 100, indent:4
|
148
|
+
undef: true, maxlen: 100, indent: 4, quotmark: double, unused: true
|
156
149
|
*/
|
157
150
|
|
158
151
|
/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)",
|
159
|
-
"(breakage)", "(
|
160
|
-
"(
|
161
|
-
"(
|
152
|
+
"(breakage)", "(character)", "(context)", "(error)", "(explicitNewcap)", "(global)",
|
153
|
+
"(identifier)", "(last)", "(lastcharacter)", "(line)", "(loopage)", "(metrics)",
|
154
|
+
"(name)", "(onevar)", "(params)", "(scope)", "(statement)", "(verb)", "(tokens)",
|
155
|
+
"*", "+", "++", "-", "--", "\/", "<", "<=", "==",
|
162
156
|
"===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax,
|
163
157
|
__filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio,
|
164
|
-
Autocompleter,
|
165
|
-
CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date,
|
166
|
-
Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, DOMParser,
|
167
|
-
E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event,
|
158
|
+
Autocompleter, Asset, Boolean, Builder, Buffer, Browser, Blob, COM, CScript, Canvas,
|
159
|
+
CustomAnimation, Class, Control, ComplexityCount, Chain, Color, Cookie, Core, DataView, Date,
|
160
|
+
Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMEvent, DOMReady, DOMParser,
|
161
|
+
Drag, E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event,
|
168
162
|
Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form,
|
169
163
|
FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey,
|
170
164
|
HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement,
|
@@ -181,49 +175,53 @@
|
|
181
175
|
HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement,
|
182
176
|
HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement,
|
183
177
|
HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement,
|
184
|
-
Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array,
|
178
|
+
Iframe, IframeShim, Image, importScripts, Int16Array, Int32Array, Int8Array,
|
185
179
|
Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E,
|
186
|
-
MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort,
|
187
|
-
MoveAnimation, MooTools,
|
188
|
-
|
189
|
-
|
180
|
+
MAX_VALUE, MIN_VALUE, Map, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort,
|
181
|
+
MoveAnimation, MooTools, MutationObserver, NaN, Native, NEGATIVE_INFINITY, Node, NodeFilter,
|
182
|
+
Number, Object, ObjectRange,
|
183
|
+
Option, Options, OverText, PI, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype,
|
184
|
+
RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, Set,
|
190
185
|
SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion,
|
191
186
|
ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller,
|
192
187
|
Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables,
|
193
188
|
SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template,
|
194
189
|
Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL,
|
195
|
-
VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer,
|
190
|
+
VBArray, WeakMap, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer,
|
196
191
|
XPathEvaluator, XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult,
|
197
|
-
"\\", a, addEventListener, address, alert, apply, applicationCache, arguments, arity,
|
198
|
-
b, basic, basicToken, bitwise, block, blur, boolOptions, boss,
|
199
|
-
caller, cases, charAt, charCodeAt, character,
|
200
|
-
close, closed, closure, comment,
|
201
|
-
content, couch, create, css, curly, d, data, datalist, dd, debug,
|
202
|
-
decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document,
|
203
|
-
dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent,
|
204
|
-
|
205
|
-
ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus,
|
192
|
+
"\\", a, abs, addEventListener, address, alert, apply, applicationCache, arguments, arity,
|
193
|
+
asi, atob, b, basic, basicToken, bitwise, blacklist, block, blur, boolOptions, boss,
|
194
|
+
browser, btoa, c, call, callee, caller, camelcase, cases, charAt, charCodeAt, character,
|
195
|
+
clearInterval, clearTimeout, close, closed, closure, comment, complexityCount, condition,
|
196
|
+
confirm, console, constructor, content, couch, create, css, curly, d, data, datalist, dd, debug,
|
197
|
+
decodeURI, decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document,
|
198
|
+
dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent, elem,
|
199
|
+
eqeq, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil,
|
200
|
+
ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, forEach,
|
206
201
|
forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions,
|
207
202
|
g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict,
|
208
203
|
hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include,
|
209
|
-
indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray,
|
204
|
+
indent, indexOf, init, ins, internals, instanceOf, isAlpha, isApplicationRunning, isArray,
|
210
205
|
isDigit, isFinite, isNaN, iterator, java, join, jshint,
|
211
|
-
JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak,
|
212
|
-
latedef, lbp, led, left, length, line, load, loadClass, localStorage, location,
|
213
|
-
log, loopfunc, m, match,
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
206
|
+
JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastcharacter, lastsemic, laxbreak,
|
207
|
+
laxcomma, latedef, lbp, led, left, length, line, load, loadClass, localStorage, location,
|
208
|
+
log, loopfunc, m, match, max, maxcomplexity, maxdepth, maxerr, maxlen, maxstatements, maxparams,
|
209
|
+
member, message, meta, module, moveBy, moveTo, mootools, multistr, name, navigator, new, newcap,
|
210
|
+
nestedBlockDepth, noarg, node, noempty, nomen, nonew, nonstandard, nud, onbeforeunload, onblur,
|
211
|
+
onerror, onevar, onecase, onfocus, onload, onresize, onunload, open, openDatabase, openURL,
|
212
|
+
opener, opera, options, outer, param, parent, parseFloat, parseInt, passfail, plusplus,
|
213
|
+
postMessage, pop, predef, print, process, prompt, proto, prototype, prototypejs, provides, push,
|
214
|
+
quit, quotmark, range, raw, reach, reason, regexp, readFile, readUrl, regexdash,
|
215
|
+
removeEventListener, replace, report, require, reserved, resizeBy, resizeTo, resolvePath,
|
216
|
+
resumeUpdates, respond, rhino, right, runCommand, scroll, scope, screen, scripturl, scrollBy,
|
217
|
+
scrollTo, scrollbar, search, seal, self, send, serialize, sessionStorage, setInterval, setTimeout,
|
218
|
+
setter, setterToken, shift, slice, smarttabs, sort, spawn, split, statementCount, stack, status,
|
219
|
+
start, strict, sub, substr, supernew, shadow, supplant, sum, sync, test, toLowerCase, toString,
|
220
|
+
toUpperCase, toint32, token, tokens, top, trailing, type, typeOf, Uint16Array, Uint32Array,
|
221
|
+
Uint8Array, undef, undefs, unused, urls, validthis, value, valueOf, var, vars, version,
|
222
|
+
verifyMaxParametersPerFunction, verifyMaxStatementsPerFunction, verifyMaxComplexityPerFunction,
|
223
|
+
verifyMaxNestedBlockDepthPerFunction, WebSocket, withstmt, white, window, windows, Worker, worker,
|
224
|
+
wsh*/
|
227
225
|
|
228
226
|
/*global exports: false */
|
229
227
|
|
@@ -239,19 +237,19 @@ var JSHINT = (function () {
|
|
239
237
|
// These are operators that should not be used with the ! operator.
|
240
238
|
|
241
239
|
bang = {
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
240
|
+
"<" : true,
|
241
|
+
"<=" : true,
|
242
|
+
"==" : true,
|
243
|
+
"===": true,
|
244
|
+
"!==": true,
|
245
|
+
"!=" : true,
|
246
|
+
">" : true,
|
247
|
+
">=" : true,
|
248
|
+
"+" : true,
|
249
|
+
"-" : true,
|
250
|
+
"*" : true,
|
251
|
+
"/" : true,
|
252
|
+
"%" : true
|
255
253
|
},
|
256
254
|
|
257
255
|
// These are the JSHint boolean options.
|
@@ -260,6 +258,7 @@ var JSHINT = (function () {
|
|
260
258
|
bitwise : true, // if bitwise operators should not be allowed
|
261
259
|
boss : true, // if advanced usage of assignments should be allowed
|
262
260
|
browser : true, // if the standard browser globals should be predefined
|
261
|
+
camelcase : true, // if identifiers should be required in camel case
|
263
262
|
couch : true, // if CouchDB globals should be predefined
|
264
263
|
curly : true, // if curly braces around all blocks should be required
|
265
264
|
debug : true, // if debugger statements should be allowed
|
@@ -311,6 +310,7 @@ var JSHINT = (function () {
|
|
311
310
|
regexp : true, // if the . should not be allowed in regexp literals
|
312
311
|
rhino : true, // if the Rhino environment globals should be predefined
|
313
312
|
undef : true, // if variables should be declared before used
|
313
|
+
unused : true, // if variables should be always used
|
314
314
|
scripturl : true, // if script-targeted URLs should be tolerated
|
315
315
|
shadow : true, // if variable shadowing should be tolerated
|
316
316
|
smarttabs : true, // if smarttabs should be tolerated
|
@@ -324,6 +324,7 @@ var JSHINT = (function () {
|
|
324
324
|
// This is a function scoped option only.
|
325
325
|
withstmt : true, // if with statements should be allowed
|
326
326
|
white : true, // if strict whitespace rules apply
|
327
|
+
worker : true, // if Web Worker script symbols should be allowed
|
327
328
|
wsh : true // if the Windows Scripting Host environment globals
|
328
329
|
// should be predefined
|
329
330
|
},
|
@@ -331,10 +332,16 @@ var JSHINT = (function () {
|
|
331
332
|
// These are the JSHint options that can take any value
|
332
333
|
// (we use this object to detect invalid options)
|
333
334
|
valOptions = {
|
334
|
-
maxlen: false,
|
335
|
-
indent: false,
|
336
|
-
maxerr: false,
|
337
|
-
predef: false
|
335
|
+
maxlen : false,
|
336
|
+
indent : false,
|
337
|
+
maxerr : false,
|
338
|
+
predef : false,
|
339
|
+
quotmark : false, //'single'|'double'|true
|
340
|
+
scope : false,
|
341
|
+
maxstatements: false, // {int} max statements per function
|
342
|
+
maxdepth : false, // {int} max nested block depth per function
|
343
|
+
maxparams : false, // {int} max params per function
|
344
|
+
maxcomplexity: false // {int} max cyclomatic complexity per function
|
338
345
|
},
|
339
346
|
|
340
347
|
// These are JSHint boolean options which are shared with JSLint
|
@@ -369,6 +376,7 @@ var JSHINT = (function () {
|
|
369
376
|
ArrayBuffer : false,
|
370
377
|
ArrayBufferView : false,
|
371
378
|
Audio : false,
|
379
|
+
Blob : false,
|
372
380
|
addEventListener : false,
|
373
381
|
applicationCache : false,
|
374
382
|
atob : false,
|
@@ -457,7 +465,10 @@ var JSHINT = (function () {
|
|
457
465
|
MessagePort : false,
|
458
466
|
moveBy : false,
|
459
467
|
moveTo : false,
|
468
|
+
MutationObserver : false,
|
460
469
|
name : false,
|
470
|
+
Node : false,
|
471
|
+
NodeFilter : false,
|
461
472
|
navigator : false,
|
462
473
|
onbeforeunload : true,
|
463
474
|
onblur : true,
|
@@ -515,6 +526,8 @@ var JSHINT = (function () {
|
|
515
526
|
provides : false
|
516
527
|
},
|
517
528
|
|
529
|
+
declared, // Globals that were declared using /*global ... */ syntax.
|
530
|
+
|
518
531
|
devel = {
|
519
532
|
alert : false,
|
520
533
|
confirm : false,
|
@@ -532,22 +545,11 @@ var JSHINT = (function () {
|
|
532
545
|
"require" : false
|
533
546
|
},
|
534
547
|
|
535
|
-
escapes = {
|
536
|
-
'\b': '\\b',
|
537
|
-
'\t': '\\t',
|
538
|
-
'\n': '\\n',
|
539
|
-
'\f': '\\f',
|
540
|
-
'\r': '\\r',
|
541
|
-
'"' : '\\"',
|
542
|
-
'/' : '\\/',
|
543
|
-
'\\': '\\\\'
|
544
|
-
},
|
545
|
-
|
546
548
|
funct, // The current function
|
547
549
|
|
548
550
|
functionicity = [
|
549
|
-
|
550
|
-
|
551
|
+
"closure", "exception", "global", "label",
|
552
|
+
"outer", "unused", "var"
|
551
553
|
],
|
552
554
|
|
553
555
|
functions, // All of the functions
|
@@ -559,7 +561,7 @@ var JSHINT = (function () {
|
|
559
561
|
jsonmode,
|
560
562
|
|
561
563
|
jquery = {
|
562
|
-
|
564
|
+
"$" : false,
|
563
565
|
jQuery : false
|
564
566
|
},
|
565
567
|
|
@@ -569,9 +571,9 @@ var JSHINT = (function () {
|
|
569
571
|
membersOnly,
|
570
572
|
|
571
573
|
mootools = {
|
572
|
-
|
573
|
-
|
574
|
-
|
574
|
+
"$" : false,
|
575
|
+
"$$" : false,
|
576
|
+
Asset : false,
|
575
577
|
Browser : false,
|
576
578
|
Chain : false,
|
577
579
|
Class : false,
|
@@ -580,6 +582,7 @@ var JSHINT = (function () {
|
|
580
582
|
Core : false,
|
581
583
|
Document : false,
|
582
584
|
DomReady : false,
|
585
|
+
DOMEvent : false,
|
583
586
|
DOMReady : false,
|
584
587
|
Drag : false,
|
585
588
|
Element : false,
|
@@ -622,7 +625,7 @@ var JSHINT = (function () {
|
|
622
625
|
__dirname : false,
|
623
626
|
Buffer : false,
|
624
627
|
console : false,
|
625
|
-
exports :
|
628
|
+
exports : true, // In Node it is ok to exports = module.exports = foo();
|
626
629
|
GLOBAL : false,
|
627
630
|
global : false,
|
628
631
|
module : false,
|
@@ -641,15 +644,15 @@ var JSHINT = (function () {
|
|
641
644
|
prevtoken,
|
642
645
|
|
643
646
|
prototypejs = {
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
647
|
+
"$" : false,
|
648
|
+
"$$" : false,
|
649
|
+
"$A" : false,
|
650
|
+
"$F" : false,
|
651
|
+
"$H" : false,
|
652
|
+
"$R" : false,
|
653
|
+
"$break" : false,
|
654
|
+
"$continue" : false,
|
655
|
+
"$w" : false,
|
653
656
|
Abstract : false,
|
654
657
|
Ajax : false,
|
655
658
|
Class : false,
|
@@ -681,6 +684,8 @@ var JSHINT = (function () {
|
|
681
684
|
Scriptaculous : false
|
682
685
|
},
|
683
686
|
|
687
|
+
quotmark,
|
688
|
+
|
684
689
|
rhino = {
|
685
690
|
defineClass : false,
|
686
691
|
deserialize : false,
|
@@ -717,14 +722,16 @@ var JSHINT = (function () {
|
|
717
722
|
encodeURI : false,
|
718
723
|
encodeURIComponent : false,
|
719
724
|
Error : false,
|
720
|
-
|
725
|
+
"eval" : false,
|
721
726
|
EvalError : false,
|
722
727
|
Function : false,
|
723
728
|
hasOwnProperty : false,
|
724
729
|
isFinite : false,
|
725
730
|
isNaN : false,
|
726
731
|
JSON : false,
|
732
|
+
Map : false,
|
727
733
|
Math : false,
|
734
|
+
NaN : false,
|
728
735
|
Number : false,
|
729
736
|
Object : false,
|
730
737
|
parseInt : false,
|
@@ -732,10 +739,12 @@ var JSHINT = (function () {
|
|
732
739
|
RangeError : false,
|
733
740
|
ReferenceError : false,
|
734
741
|
RegExp : false,
|
742
|
+
Set : false,
|
735
743
|
String : false,
|
736
744
|
SyntaxError : false,
|
737
745
|
TypeError : false,
|
738
|
-
URIError : false
|
746
|
+
URIError : false,
|
747
|
+
WeakMap : false
|
739
748
|
},
|
740
749
|
|
741
750
|
// widely adopted global names that are not part of ECMAScript standard
|
@@ -744,29 +753,21 @@ var JSHINT = (function () {
|
|
744
753
|
unescape : false
|
745
754
|
},
|
746
755
|
|
747
|
-
standard_member = {
|
748
|
-
E : true,
|
749
|
-
LN2 : true,
|
750
|
-
LN10 : true,
|
751
|
-
LOG2E : true,
|
752
|
-
LOG10E : true,
|
753
|
-
MAX_VALUE : true,
|
754
|
-
MIN_VALUE : true,
|
755
|
-
NEGATIVE_INFINITY : true,
|
756
|
-
PI : true,
|
757
|
-
POSITIVE_INFINITY : true,
|
758
|
-
SQRT1_2 : true,
|
759
|
-
SQRT2 : true
|
760
|
-
},
|
761
|
-
|
762
756
|
directive,
|
763
757
|
syntax = {},
|
764
758
|
tab,
|
765
759
|
token,
|
760
|
+
unuseds,
|
766
761
|
urls,
|
767
762
|
useESNextSyntax,
|
768
763
|
warnings,
|
769
764
|
|
765
|
+
worker = {
|
766
|
+
importScripts : true,
|
767
|
+
postMessage : true,
|
768
|
+
self : true
|
769
|
+
},
|
770
|
+
|
770
771
|
wsh = {
|
771
772
|
ActiveXObject : true,
|
772
773
|
Enumerator : true,
|
@@ -800,7 +801,7 @@ var JSHINT = (function () {
|
|
800
801
|
nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
|
801
802
|
|
802
803
|
// star slash
|
803
|
-
lx =
|
804
|
+
lx = /\*\//;
|
804
805
|
|
805
806
|
// identifier
|
806
807
|
ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
|
@@ -815,10 +816,8 @@ var JSHINT = (function () {
|
|
815
816
|
function F() {} // Used by Object.create
|
816
817
|
|
817
818
|
function is_own(object, name) {
|
818
|
-
|
819
|
-
//
|
820
|
-
// is named 'hasOwnProperty'. So we have to use this more convoluted form.
|
821
|
-
|
819
|
+
// The object.hasOwnProperty method fails when the property under consideration
|
820
|
+
// is named 'hasOwnProperty'. So we have to use this more convoluted form.
|
822
821
|
return Object.prototype.hasOwnProperty.call(object, name);
|
823
822
|
}
|
824
823
|
|
@@ -828,22 +827,74 @@ var JSHINT = (function () {
|
|
828
827
|
}
|
829
828
|
}
|
830
829
|
|
831
|
-
|
830
|
+
function isString(obj) {
|
831
|
+
return Object.prototype.toString.call(obj) === "[object String]";
|
832
|
+
}
|
832
833
|
|
833
|
-
|
834
|
+
// Provide critical ES5 functions to ES3.
|
835
|
+
|
836
|
+
if (typeof Array.isArray !== "function") {
|
834
837
|
Array.isArray = function (o) {
|
835
|
-
return Object.prototype.toString.apply(o) ===
|
838
|
+
return Object.prototype.toString.apply(o) === "[object Array]";
|
839
|
+
};
|
840
|
+
}
|
841
|
+
|
842
|
+
if (!Array.prototype.forEach) {
|
843
|
+
Array.prototype.forEach = function (fn, scope) {
|
844
|
+
var len = this.length;
|
845
|
+
|
846
|
+
for (var i = 0; i < len; i++) {
|
847
|
+
fn.call(scope || this, this[i], i, this);
|
848
|
+
}
|
849
|
+
};
|
850
|
+
}
|
851
|
+
|
852
|
+
if (!Array.prototype.indexOf) {
|
853
|
+
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
|
854
|
+
if (this === null || this === undefined) {
|
855
|
+
throw new TypeError();
|
856
|
+
}
|
857
|
+
|
858
|
+
var t = new Object(this);
|
859
|
+
var len = t.length >>> 0;
|
860
|
+
|
861
|
+
if (len === 0) {
|
862
|
+
return -1;
|
863
|
+
}
|
864
|
+
|
865
|
+
var n = 0;
|
866
|
+
if (arguments.length > 0) {
|
867
|
+
n = Number(arguments[1]);
|
868
|
+
if (n != n) { // shortcut for verifying if it's NaN
|
869
|
+
n = 0;
|
870
|
+
} else if (n !== 0 && n != Infinity && n != -Infinity) {
|
871
|
+
n = (n > 0 || -1) * Math.floor(Math.abs(n));
|
872
|
+
}
|
873
|
+
}
|
874
|
+
|
875
|
+
if (n >= len) {
|
876
|
+
return -1;
|
877
|
+
}
|
878
|
+
|
879
|
+
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
|
880
|
+
for (; k < len; k++) {
|
881
|
+
if (k in t && t[k] === searchElement) {
|
882
|
+
return k;
|
883
|
+
}
|
884
|
+
}
|
885
|
+
|
886
|
+
return -1;
|
836
887
|
};
|
837
888
|
}
|
838
889
|
|
839
|
-
if (typeof Object.create !==
|
890
|
+
if (typeof Object.create !== "function") {
|
840
891
|
Object.create = function (o) {
|
841
892
|
F.prototype = o;
|
842
893
|
return new F();
|
843
894
|
};
|
844
895
|
}
|
845
896
|
|
846
|
-
if (typeof Object.keys !==
|
897
|
+
if (typeof Object.keys !== "function") {
|
847
898
|
Object.keys = function (o) {
|
848
899
|
var a = [], k;
|
849
900
|
for (k in o) {
|
@@ -855,74 +906,49 @@ var JSHINT = (function () {
|
|
855
906
|
};
|
856
907
|
}
|
857
908
|
|
858
|
-
// Non standard methods
|
909
|
+
// Non standard methods
|
859
910
|
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
.replace(/&/g, '&')
|
864
|
-
.replace(/</g, '<')
|
865
|
-
.replace(/>/g, '>');
|
866
|
-
};
|
911
|
+
function isAlpha(str) {
|
912
|
+
return (str >= "a" && str <= "z\uffff") ||
|
913
|
+
(str >= "A" && str <= "Z\uffff");
|
867
914
|
}
|
868
915
|
|
869
|
-
|
870
|
-
|
871
|
-
return (this >= 'a' && this <= 'z\uffff') ||
|
872
|
-
(this >= 'A' && this <= 'Z\uffff');
|
873
|
-
};
|
874
|
-
}
|
875
|
-
|
876
|
-
if (typeof String.prototype.isDigit !== 'function') {
|
877
|
-
String.prototype.isDigit = function () {
|
878
|
-
return (this >= '0' && this <= '9');
|
879
|
-
};
|
880
|
-
}
|
881
|
-
|
882
|
-
if (typeof String.prototype.supplant !== 'function') {
|
883
|
-
String.prototype.supplant = function (o) {
|
884
|
-
return this.replace(/\{([^{}]*)\}/g, function (a, b) {
|
885
|
-
var r = o[b];
|
886
|
-
return typeof r === 'string' || typeof r === 'number' ? r : a;
|
887
|
-
});
|
888
|
-
};
|
916
|
+
function isDigit(str) {
|
917
|
+
return (str >= "0" && str <= "9");
|
889
918
|
}
|
890
919
|
|
891
|
-
|
892
|
-
|
920
|
+
function isIdentifier(token, value) {
|
921
|
+
if (!token)
|
922
|
+
return false;
|
893
923
|
|
894
|
-
|
895
|
-
|
896
|
-
// backslash characters, then we can simply slap some quotes around it.
|
897
|
-
// Otherwise we must also replace the offending characters with safe
|
898
|
-
// sequences.
|
924
|
+
if (!token.identifier || token.value !== value)
|
925
|
+
return false;
|
899
926
|
|
900
|
-
|
901
|
-
return this;
|
902
|
-
}
|
903
|
-
if (nx.test(this)) {
|
904
|
-
return '"' + this.replace(nxg, function (a) {
|
905
|
-
var c = escapes[a];
|
906
|
-
if (c) {
|
907
|
-
return c;
|
908
|
-
}
|
909
|
-
return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);
|
910
|
-
}) + '"';
|
911
|
-
}
|
912
|
-
return '"' + this + '"';
|
913
|
-
};
|
927
|
+
return true;
|
914
928
|
}
|
915
929
|
|
930
|
+
function supplant(str, data) {
|
931
|
+
return str.replace(/\{([^{}]*)\}/g, function (a, b) {
|
932
|
+
var r = data[b];
|
933
|
+
return typeof r === "string" || typeof r === "number" ? r : a;
|
934
|
+
});
|
935
|
+
}
|
916
936
|
|
917
937
|
function combine(t, o) {
|
918
938
|
var n;
|
919
939
|
for (n in o) {
|
920
|
-
if (is_own(o, n)) {
|
940
|
+
if (is_own(o, n) && !is_own(JSHINT.blacklist, n)) {
|
921
941
|
t[n] = o[n];
|
922
942
|
}
|
923
943
|
}
|
924
944
|
}
|
925
945
|
|
946
|
+
function updatePredefined() {
|
947
|
+
Object.keys(JSHINT.blacklist).forEach(function (key) {
|
948
|
+
delete predefined[key];
|
949
|
+
});
|
950
|
+
}
|
951
|
+
|
926
952
|
function assume() {
|
927
953
|
if (option.couch) {
|
928
954
|
combine(predefined, couch);
|
@@ -965,6 +991,10 @@ var JSHINT = (function () {
|
|
965
991
|
combine(predefined, mootools);
|
966
992
|
}
|
967
993
|
|
994
|
+
if (option.worker) {
|
995
|
+
combine(predefined, worker);
|
996
|
+
}
|
997
|
+
|
968
998
|
if (option.wsh) {
|
969
999
|
combine(predefined, wsh);
|
970
1000
|
}
|
@@ -984,7 +1014,7 @@ var JSHINT = (function () {
|
|
984
1014
|
var percentage = Math.floor((line / lines.length) * 100);
|
985
1015
|
|
986
1016
|
throw {
|
987
|
-
name:
|
1017
|
+
name: "JSHintError",
|
988
1018
|
line: line,
|
989
1019
|
character: chr,
|
990
1020
|
message: message + " (" + percentage + "% scanned).",
|
@@ -999,26 +1029,27 @@ var JSHINT = (function () {
|
|
999
1029
|
function warning(m, t, a, b, c, d) {
|
1000
1030
|
var ch, l, w;
|
1001
1031
|
t = t || nexttoken;
|
1002
|
-
if (t.id ===
|
1032
|
+
if (t.id === "(end)") { // `~
|
1003
1033
|
t = token;
|
1004
1034
|
}
|
1005
1035
|
l = t.line || 0;
|
1006
1036
|
ch = t.from || 0;
|
1007
1037
|
w = {
|
1008
|
-
id:
|
1038
|
+
id: "(error)",
|
1009
1039
|
raw: m,
|
1010
|
-
evidence: lines[l - 1] ||
|
1040
|
+
evidence: lines[l - 1] || "",
|
1011
1041
|
line: l,
|
1012
1042
|
character: ch,
|
1043
|
+
scope: JSHINT.scope,
|
1013
1044
|
a: a,
|
1014
1045
|
b: b,
|
1015
1046
|
c: c,
|
1016
1047
|
d: d
|
1017
1048
|
};
|
1018
|
-
w.reason =
|
1049
|
+
w.reason = supplant(m, w);
|
1019
1050
|
JSHINT.errors.push(w);
|
1020
1051
|
if (option.passfail) {
|
1021
|
-
quit(
|
1052
|
+
quit("Stopping. ", l, ch);
|
1022
1053
|
}
|
1023
1054
|
warnings += 1;
|
1024
1055
|
if (warnings >= option.maxerr) {
|
@@ -1035,7 +1066,7 @@ var JSHINT = (function () {
|
|
1035
1066
|
}
|
1036
1067
|
|
1037
1068
|
function error(m, t, a, b, c, d) {
|
1038
|
-
|
1069
|
+
warning(m, t, a, b, c, d);
|
1039
1070
|
}
|
1040
1071
|
|
1041
1072
|
function errorAt(m, l, ch, a, b, c, d) {
|
@@ -1045,6 +1076,17 @@ var JSHINT = (function () {
|
|
1045
1076
|
}, a, b, c, d);
|
1046
1077
|
}
|
1047
1078
|
|
1079
|
+
// Tracking of "internal" scripts, like eval containing a static string
|
1080
|
+
function addInternalSrc(elem, src) {
|
1081
|
+
var i;
|
1082
|
+
i = {
|
1083
|
+
id: "(internal)",
|
1084
|
+
elem: elem,
|
1085
|
+
value: src
|
1086
|
+
};
|
1087
|
+
JSHINT.internals.push(i);
|
1088
|
+
return i;
|
1089
|
+
}
|
1048
1090
|
|
1049
1091
|
|
1050
1092
|
// lexical analysis and token construction
|
@@ -1067,10 +1109,11 @@ var JSHINT = (function () {
|
|
1067
1109
|
|
1068
1110
|
// If smarttabs option is used check for spaces followed by tabs only.
|
1069
1111
|
// Otherwise check for any occurence of mixed tabs and spaces.
|
1112
|
+
// Tabs and one space followed by block comment is allowed.
|
1070
1113
|
if (option.smarttabs)
|
1071
1114
|
at = s.search(/ \t/);
|
1072
1115
|
else
|
1073
|
-
at = s.search(/ \t|\t /);
|
1116
|
+
at = s.search(/ \t|\t [^\*]/);
|
1074
1117
|
|
1075
1118
|
if (at >= 0)
|
1076
1119
|
warningAt("Mixed spaces and tabs.", line, at + 1);
|
@@ -1096,46 +1139,74 @@ var JSHINT = (function () {
|
|
1096
1139
|
|
1097
1140
|
function it(type, value) {
|
1098
1141
|
var i, t;
|
1099
|
-
|
1142
|
+
|
1143
|
+
function checkName(name) {
|
1144
|
+
if (!option.proto && name === "__proto__") {
|
1145
|
+
warningAt("The '{a}' property is deprecated.", line, from, name);
|
1146
|
+
return;
|
1147
|
+
}
|
1148
|
+
|
1149
|
+
if (!option.iterator && name === "__iterator__") {
|
1150
|
+
warningAt("'{a}' is only available in JavaScript 1.7.", line, from, name);
|
1151
|
+
return;
|
1152
|
+
}
|
1153
|
+
|
1154
|
+
// Check for dangling underscores unless we're in Node
|
1155
|
+
// environment and this identifier represents built-in
|
1156
|
+
// Node globals with underscores.
|
1157
|
+
|
1158
|
+
var hasDangling = /^(_+.*|.*_+)$/.test(name);
|
1159
|
+
|
1160
|
+
if (option.nomen && hasDangling && name !== "_") {
|
1161
|
+
if (option.node && token.id !== "." && /^(__dirname|__filename)$/.test(name))
|
1162
|
+
return;
|
1163
|
+
|
1164
|
+
warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", name);
|
1165
|
+
return;
|
1166
|
+
}
|
1167
|
+
|
1168
|
+
// Check for non-camelcase names. Names like MY_VAR and
|
1169
|
+
// _myVar are okay though.
|
1170
|
+
|
1171
|
+
if (option.camelcase) {
|
1172
|
+
if (name.replace(/^_+/, "").indexOf("_") > -1 && !name.match(/^[A-Z0-9_]*$/)) {
|
1173
|
+
warningAt("Identifier '{a}' is not in camel case.", line, from, value);
|
1174
|
+
}
|
1175
|
+
}
|
1176
|
+
}
|
1177
|
+
|
1178
|
+
if (type === "(color)" || type === "(range)") {
|
1100
1179
|
t = {type: type};
|
1101
|
-
} else if (type ===
|
1102
|
-
(type ===
|
1103
|
-
t = syntax[value] || syntax[
|
1180
|
+
} else if (type === "(punctuator)" ||
|
1181
|
+
(type === "(identifier)" && is_own(syntax, value))) {
|
1182
|
+
t = syntax[value] || syntax["(error)"];
|
1104
1183
|
} else {
|
1105
1184
|
t = syntax[type];
|
1106
1185
|
}
|
1186
|
+
|
1107
1187
|
t = Object.create(t);
|
1108
|
-
|
1188
|
+
|
1189
|
+
if (type === "(string)" || type === "(range)") {
|
1109
1190
|
if (!option.scripturl && jx.test(value)) {
|
1110
1191
|
warningAt("Script URL.", line, from);
|
1111
1192
|
}
|
1112
1193
|
}
|
1113
|
-
|
1194
|
+
|
1195
|
+
if (type === "(identifier)") {
|
1114
1196
|
t.identifier = true;
|
1115
|
-
|
1116
|
-
warningAt("The '{a}' property is deprecated.",
|
1117
|
-
line, from, value);
|
1118
|
-
} else if (value === '__iterator__' && !option.iterator) {
|
1119
|
-
warningAt("'{a}' is only available in JavaScript 1.7.",
|
1120
|
-
line, from, value);
|
1121
|
-
} else if (option.nomen && (value.charAt(0) === '_' ||
|
1122
|
-
value.charAt(value.length - 1) === '_')) {
|
1123
|
-
if (!option.node || token.id === '.' ||
|
1124
|
-
(value !== '__dirname' && value !== '__filename')) {
|
1125
|
-
warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", value);
|
1126
|
-
}
|
1127
|
-
}
|
1197
|
+
checkName(value);
|
1128
1198
|
}
|
1199
|
+
|
1129
1200
|
t.value = value;
|
1130
1201
|
t.line = line;
|
1131
1202
|
t.character = character;
|
1132
1203
|
t.from = from;
|
1133
1204
|
i = t.id;
|
1134
|
-
if (i !==
|
1205
|
+
if (i !== "(endline)") {
|
1135
1206
|
prereg = i &&
|
1136
|
-
((
|
1137
|
-
i ===
|
1138
|
-
i ===
|
1207
|
+
(("(,=:[!&|?{};".indexOf(i.charAt(i.length - 1)) >= 0) ||
|
1208
|
+
i === "return" ||
|
1209
|
+
i === "case");
|
1139
1210
|
}
|
1140
1211
|
return t;
|
1141
1212
|
}
|
@@ -1143,19 +1214,19 @@ var JSHINT = (function () {
|
|
1143
1214
|
// Public lex methods
|
1144
1215
|
return {
|
1145
1216
|
init: function (source) {
|
1146
|
-
if (typeof source ===
|
1217
|
+
if (typeof source === "string") {
|
1147
1218
|
lines = source
|
1148
|
-
.replace(/\r\n/g,
|
1149
|
-
.replace(/\r/g,
|
1150
|
-
.split(
|
1219
|
+
.replace(/\r\n/g, "\n")
|
1220
|
+
.replace(/\r/g, "\n")
|
1221
|
+
.split("\n");
|
1151
1222
|
} else {
|
1152
1223
|
lines = source;
|
1153
1224
|
}
|
1154
1225
|
|
1155
1226
|
// If the first line is a shebang (#!), make it a blank and move on.
|
1156
1227
|
// Shebangs are used by Node scripts.
|
1157
|
-
if (lines[0] && lines[0].substr(0, 2) ===
|
1158
|
-
lines[0] =
|
1228
|
+
if (lines[0] && lines[0].substr(0, 2) === "#!")
|
1229
|
+
lines[0] = "";
|
1159
1230
|
|
1160
1231
|
line = 0;
|
1161
1232
|
nextLine();
|
@@ -1163,7 +1234,7 @@ var JSHINT = (function () {
|
|
1163
1234
|
},
|
1164
1235
|
|
1165
1236
|
range: function (begin, end) {
|
1166
|
-
var c, value =
|
1237
|
+
var c, value = "";
|
1167
1238
|
from = character;
|
1168
1239
|
if (s.charAt(0) !== begin) {
|
1169
1240
|
errorAt("Expected '{a}' and instead saw '{b}'.",
|
@@ -1174,14 +1245,14 @@ var JSHINT = (function () {
|
|
1174
1245
|
character += 1;
|
1175
1246
|
c = s.charAt(0);
|
1176
1247
|
switch (c) {
|
1177
|
-
case
|
1248
|
+
case "":
|
1178
1249
|
errorAt("Missing '{a}'.", line, character, c);
|
1179
1250
|
break;
|
1180
1251
|
case end:
|
1181
1252
|
s = s.slice(1);
|
1182
1253
|
character += 1;
|
1183
|
-
return it(
|
1184
|
-
case
|
1254
|
+
return it("(range)", value);
|
1255
|
+
case "\\":
|
1185
1256
|
warningAt("Unexpected '{a}'.", line, character, c);
|
1186
1257
|
}
|
1187
1258
|
value += c;
|
@@ -1208,13 +1279,29 @@ var JSHINT = (function () {
|
|
1208
1279
|
}
|
1209
1280
|
|
1210
1281
|
function string(x) {
|
1211
|
-
var c, j, r =
|
1282
|
+
var c, j, r = "", allowNewLine = false;
|
1212
1283
|
|
1213
|
-
if (jsonmode && x !==
|
1284
|
+
if (jsonmode && x !== "\"") {
|
1214
1285
|
warningAt("Strings must use doublequote.",
|
1215
1286
|
line, character);
|
1216
1287
|
}
|
1217
1288
|
|
1289
|
+
if (option.quotmark) {
|
1290
|
+
if (option.quotmark === "single" && x !== "'") {
|
1291
|
+
warningAt("Strings must use singlequote.",
|
1292
|
+
line, character);
|
1293
|
+
} else if (option.quotmark === "double" && x !== "\"") {
|
1294
|
+
warningAt("Strings must use doublequote.",
|
1295
|
+
line, character);
|
1296
|
+
} else if (option.quotmark === true) {
|
1297
|
+
quotmark = quotmark || x;
|
1298
|
+
if (quotmark !== x) {
|
1299
|
+
warningAt("Mixed double and single quotes.",
|
1300
|
+
line, character);
|
1301
|
+
}
|
1302
|
+
}
|
1303
|
+
}
|
1304
|
+
|
1218
1305
|
function esc(n) {
|
1219
1306
|
var i = parseInt(s.substr(j + 1, n), 16);
|
1220
1307
|
j += n;
|
@@ -1246,46 +1333,46 @@ unclosedString: for (;;) {
|
|
1246
1333
|
if (c === x) {
|
1247
1334
|
character += 1;
|
1248
1335
|
s = s.substr(j + 1);
|
1249
|
-
return it(
|
1336
|
+
return it("(string)", r, x);
|
1250
1337
|
}
|
1251
|
-
if (c <
|
1252
|
-
if (c ===
|
1338
|
+
if (c < " ") {
|
1339
|
+
if (c === "\n" || c === "\r") {
|
1253
1340
|
break;
|
1254
1341
|
}
|
1255
1342
|
warningAt("Control character in string: {a}.",
|
1256
1343
|
line, character + j, s.slice(0, j));
|
1257
|
-
} else if (c ===
|
1344
|
+
} else if (c === "\\") {
|
1258
1345
|
j += 1;
|
1259
1346
|
character += 1;
|
1260
1347
|
c = s.charAt(j);
|
1261
1348
|
n = s.charAt(j + 1);
|
1262
1349
|
switch (c) {
|
1263
|
-
case
|
1264
|
-
case
|
1265
|
-
case
|
1350
|
+
case "\\":
|
1351
|
+
case "\"":
|
1352
|
+
case "/":
|
1266
1353
|
break;
|
1267
|
-
case
|
1354
|
+
case "\'":
|
1268
1355
|
if (jsonmode) {
|
1269
1356
|
warningAt("Avoid \\'.", line, character);
|
1270
1357
|
}
|
1271
1358
|
break;
|
1272
|
-
case
|
1273
|
-
c =
|
1359
|
+
case "b":
|
1360
|
+
c = "\b";
|
1274
1361
|
break;
|
1275
|
-
case
|
1276
|
-
c =
|
1362
|
+
case "f":
|
1363
|
+
c = "\f";
|
1277
1364
|
break;
|
1278
|
-
case
|
1279
|
-
c =
|
1365
|
+
case "n":
|
1366
|
+
c = "\n";
|
1280
1367
|
break;
|
1281
|
-
case
|
1282
|
-
c =
|
1368
|
+
case "r":
|
1369
|
+
c = "\r";
|
1283
1370
|
break;
|
1284
|
-
case
|
1285
|
-
c =
|
1371
|
+
case "t":
|
1372
|
+
c = "\t";
|
1286
1373
|
break;
|
1287
|
-
case
|
1288
|
-
c =
|
1374
|
+
case "0":
|
1375
|
+
c = "\0";
|
1289
1376
|
// Octal literals fail in strict mode
|
1290
1377
|
// check if the number is between 00 and 07
|
1291
1378
|
// where 'n' is the token next to 'c'
|
@@ -1295,22 +1382,22 @@ unclosedString: for (;;) {
|
|
1295
1382
|
line, character);
|
1296
1383
|
}
|
1297
1384
|
break;
|
1298
|
-
case
|
1385
|
+
case "u":
|
1299
1386
|
esc(4);
|
1300
1387
|
break;
|
1301
|
-
case
|
1388
|
+
case "v":
|
1302
1389
|
if (jsonmode) {
|
1303
1390
|
warningAt("Avoid \\v.", line, character);
|
1304
1391
|
}
|
1305
|
-
c =
|
1392
|
+
c = "\v";
|
1306
1393
|
break;
|
1307
|
-
case
|
1394
|
+
case "x":
|
1308
1395
|
if (jsonmode) {
|
1309
1396
|
warningAt("Avoid \\x-.", line, character);
|
1310
1397
|
}
|
1311
1398
|
esc(2);
|
1312
1399
|
break;
|
1313
|
-
case
|
1400
|
+
case "":
|
1314
1401
|
// last character is escape character
|
1315
1402
|
// always allow new line if escaped, but show
|
1316
1403
|
// warning if option is not set
|
@@ -1319,13 +1406,17 @@ unclosedString: for (;;) {
|
|
1319
1406
|
if (jsonmode) {
|
1320
1407
|
warningAt("Avoid EOL escapement.", line, character);
|
1321
1408
|
}
|
1322
|
-
c =
|
1409
|
+
c = "";
|
1323
1410
|
character -= 1;
|
1324
1411
|
break;
|
1325
1412
|
}
|
1326
1413
|
warningAt("Bad escapement of EOL. Use option multistr if needed.",
|
1327
1414
|
line, character);
|
1328
1415
|
break;
|
1416
|
+
case "!":
|
1417
|
+
if (s.charAt(j - 2) === "<")
|
1418
|
+
break;
|
1419
|
+
/*falls through*/
|
1329
1420
|
default:
|
1330
1421
|
warningAt("Bad escapement.", line, character);
|
1331
1422
|
}
|
@@ -1338,74 +1429,74 @@ unclosedString: for (;;) {
|
|
1338
1429
|
|
1339
1430
|
for (;;) {
|
1340
1431
|
if (!s) {
|
1341
|
-
return it(nextLine() ?
|
1432
|
+
return it(nextLine() ? "(endline)" : "(end)", "");
|
1342
1433
|
}
|
1343
1434
|
t = match(tx);
|
1344
1435
|
if (!t) {
|
1345
|
-
t =
|
1346
|
-
c =
|
1347
|
-
while (s && s <
|
1436
|
+
t = "";
|
1437
|
+
c = "";
|
1438
|
+
while (s && s < "!") {
|
1348
1439
|
s = s.substr(1);
|
1349
1440
|
}
|
1350
1441
|
if (s) {
|
1351
1442
|
errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1));
|
1352
|
-
s =
|
1443
|
+
s = "";
|
1353
1444
|
}
|
1354
1445
|
} else {
|
1355
1446
|
|
1356
1447
|
// identifier
|
1357
1448
|
|
1358
|
-
if (
|
1359
|
-
return it(
|
1449
|
+
if (isAlpha(c) || c === "_" || c === "$") {
|
1450
|
+
return it("(identifier)", t);
|
1360
1451
|
}
|
1361
1452
|
|
1362
1453
|
// number
|
1363
1454
|
|
1364
|
-
if (
|
1455
|
+
if (isDigit(c)) {
|
1365
1456
|
if (!isFinite(Number(t))) {
|
1366
1457
|
warningAt("Bad number '{a}'.",
|
1367
1458
|
line, character, t);
|
1368
1459
|
}
|
1369
|
-
if (s.substr(0, 1)
|
1460
|
+
if (isAlpha(s.substr(0, 1))) {
|
1370
1461
|
warningAt("Missing space after '{a}'.",
|
1371
1462
|
line, character, t);
|
1372
1463
|
}
|
1373
|
-
if (c ===
|
1464
|
+
if (c === "0") {
|
1374
1465
|
d = t.substr(1, 1);
|
1375
|
-
if (
|
1376
|
-
if (token.id !==
|
1466
|
+
if (isDigit(d)) {
|
1467
|
+
if (token.id !== ".") {
|
1377
1468
|
warningAt("Don't use extra leading zeros '{a}'.",
|
1378
1469
|
line, character, t);
|
1379
1470
|
}
|
1380
|
-
} else if (jsonmode && (d ===
|
1471
|
+
} else if (jsonmode && (d === "x" || d === "X")) {
|
1381
1472
|
warningAt("Avoid 0x-. '{a}'.",
|
1382
1473
|
line, character, t);
|
1383
1474
|
}
|
1384
1475
|
}
|
1385
|
-
if (t.substr(t.length - 1) ===
|
1476
|
+
if (t.substr(t.length - 1) === ".") {
|
1386
1477
|
warningAt(
|
1387
1478
|
"A trailing decimal point can be confused with a dot '{a}'.", line, character, t);
|
1388
1479
|
}
|
1389
|
-
return it(
|
1480
|
+
return it("(number)", t);
|
1390
1481
|
}
|
1391
1482
|
switch (t) {
|
1392
1483
|
|
1393
1484
|
// string
|
1394
1485
|
|
1395
|
-
case
|
1486
|
+
case "\"":
|
1396
1487
|
case "'":
|
1397
1488
|
return string(t);
|
1398
1489
|
|
1399
1490
|
// // comment
|
1400
1491
|
|
1401
|
-
case
|
1402
|
-
s =
|
1492
|
+
case "//":
|
1493
|
+
s = "";
|
1403
1494
|
token.comment = true;
|
1404
1495
|
break;
|
1405
1496
|
|
1406
1497
|
// /* comment
|
1407
1498
|
|
1408
|
-
case
|
1499
|
+
case "/*":
|
1409
1500
|
for (;;) {
|
1410
1501
|
i = s.search(lx);
|
1411
1502
|
if (i >= 0) {
|
@@ -1415,35 +1506,31 @@ unclosedString: for (;;) {
|
|
1415
1506
|
errorAt("Unclosed comment.", line, character);
|
1416
1507
|
}
|
1417
1508
|
}
|
1418
|
-
character += i + 2;
|
1419
|
-
if (s.substr(i, 1) === '/') {
|
1420
|
-
errorAt("Nested comment.", line, character);
|
1421
|
-
}
|
1422
1509
|
s = s.substr(i + 2);
|
1423
1510
|
token.comment = true;
|
1424
1511
|
break;
|
1425
1512
|
|
1426
1513
|
// /*members /*jshint /*global
|
1427
1514
|
|
1428
|
-
case
|
1429
|
-
case
|
1430
|
-
case
|
1431
|
-
case
|
1432
|
-
case
|
1433
|
-
case
|
1515
|
+
case "/*members":
|
1516
|
+
case "/*member":
|
1517
|
+
case "/*jshint":
|
1518
|
+
case "/*jslint":
|
1519
|
+
case "/*global":
|
1520
|
+
case "*/":
|
1434
1521
|
return {
|
1435
1522
|
value: t,
|
1436
|
-
type:
|
1523
|
+
type: "special",
|
1437
1524
|
line: line,
|
1438
1525
|
character: character,
|
1439
1526
|
from: from
|
1440
1527
|
};
|
1441
1528
|
|
1442
|
-
case
|
1529
|
+
case "":
|
1443
1530
|
break;
|
1444
1531
|
// /
|
1445
|
-
case
|
1446
|
-
if (token.id ===
|
1532
|
+
case "/":
|
1533
|
+
if (token.id === "/=") {
|
1447
1534
|
errorAt("A regular expression literal can be confused with '/='.",
|
1448
1535
|
line, from);
|
1449
1536
|
}
|
@@ -1456,10 +1543,10 @@ unclosedString: for (;;) {
|
|
1456
1543
|
c = s.charAt(l);
|
1457
1544
|
l += 1;
|
1458
1545
|
switch (c) {
|
1459
|
-
case
|
1546
|
+
case "":
|
1460
1547
|
errorAt("Unclosed regular expression.", line, from);
|
1461
|
-
return quit(
|
1462
|
-
case
|
1548
|
+
return quit("Stopping.", line, from);
|
1549
|
+
case "/":
|
1463
1550
|
if (depth > 0) {
|
1464
1551
|
warningAt("{a} unterminated regular expression " +
|
1465
1552
|
"group(s).", line, from + l, depth);
|
@@ -1477,55 +1564,55 @@ unclosedString: for (;;) {
|
|
1477
1564
|
character += l;
|
1478
1565
|
s = s.substr(l);
|
1479
1566
|
q = s.charAt(0);
|
1480
|
-
if (q ===
|
1567
|
+
if (q === "/" || q === "*") {
|
1481
1568
|
errorAt("Confusing regular expression.",
|
1482
1569
|
line, from);
|
1483
1570
|
}
|
1484
|
-
return it(
|
1485
|
-
case
|
1571
|
+
return it("(regexp)", c);
|
1572
|
+
case "\\":
|
1486
1573
|
c = s.charAt(l);
|
1487
|
-
if (c <
|
1574
|
+
if (c < " ") {
|
1488
1575
|
warningAt(
|
1489
1576
|
"Unexpected control character in regular expression.", line, from + l);
|
1490
|
-
} else if (c ===
|
1577
|
+
} else if (c === "<") {
|
1491
1578
|
warningAt(
|
1492
1579
|
"Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
|
1493
1580
|
}
|
1494
1581
|
l += 1;
|
1495
1582
|
break;
|
1496
|
-
case
|
1583
|
+
case "(":
|
1497
1584
|
depth += 1;
|
1498
1585
|
b = false;
|
1499
|
-
if (s.charAt(l) ===
|
1586
|
+
if (s.charAt(l) === "?") {
|
1500
1587
|
l += 1;
|
1501
1588
|
switch (s.charAt(l)) {
|
1502
|
-
case
|
1503
|
-
case
|
1504
|
-
case
|
1589
|
+
case ":":
|
1590
|
+
case "=":
|
1591
|
+
case "!":
|
1505
1592
|
l += 1;
|
1506
1593
|
break;
|
1507
1594
|
default:
|
1508
1595
|
warningAt(
|
1509
|
-
"Expected '{a}' and instead saw '{b}'.", line, from + l,
|
1596
|
+
"Expected '{a}' and instead saw '{b}'.", line, from + l, ":", s.charAt(l));
|
1510
1597
|
}
|
1511
1598
|
} else {
|
1512
1599
|
captures += 1;
|
1513
1600
|
}
|
1514
1601
|
break;
|
1515
|
-
case
|
1602
|
+
case "|":
|
1516
1603
|
b = false;
|
1517
1604
|
break;
|
1518
|
-
case
|
1605
|
+
case ")":
|
1519
1606
|
if (depth === 0) {
|
1520
1607
|
warningAt("Unescaped '{a}'.",
|
1521
|
-
line, from + l,
|
1608
|
+
line, from + l, ")");
|
1522
1609
|
} else {
|
1523
1610
|
depth -= 1;
|
1524
1611
|
}
|
1525
1612
|
break;
|
1526
|
-
case
|
1613
|
+
case " ":
|
1527
1614
|
q = 1;
|
1528
|
-
while (s.charAt(l) ===
|
1615
|
+
while (s.charAt(l) === " ") {
|
1529
1616
|
l += 1;
|
1530
1617
|
q += 1;
|
1531
1618
|
}
|
@@ -1534,19 +1621,16 @@ unclosedString: for (;;) {
|
|
1534
1621
|
"Spaces are hard to count. Use {{a}}.", line, from + l, q);
|
1535
1622
|
}
|
1536
1623
|
break;
|
1537
|
-
case
|
1624
|
+
case "[":
|
1538
1625
|
c = s.charAt(l);
|
1539
|
-
if (c ===
|
1626
|
+
if (c === "^") {
|
1540
1627
|
l += 1;
|
1541
|
-
if (
|
1542
|
-
warningAt("Insecure '{a}'.",
|
1543
|
-
line, from + l, c);
|
1544
|
-
} else if (s.charAt(l) === ']') {
|
1628
|
+
if (s.charAt(l) === "]") {
|
1545
1629
|
errorAt("Unescaped '{a}'.",
|
1546
|
-
line, from + l,
|
1630
|
+
line, from + l, "^");
|
1547
1631
|
}
|
1548
1632
|
}
|
1549
|
-
if (c ===
|
1633
|
+
if (c === "]") {
|
1550
1634
|
warningAt("Empty class.", line,
|
1551
1635
|
from + l - 1);
|
1552
1636
|
}
|
@@ -1556,8 +1640,8 @@ klass: do {
|
|
1556
1640
|
c = s.charAt(l);
|
1557
1641
|
l += 1;
|
1558
1642
|
switch (c) {
|
1559
|
-
case
|
1560
|
-
case
|
1643
|
+
case "[":
|
1644
|
+
case "^":
|
1561
1645
|
warningAt("Unescaped '{a}'.",
|
1562
1646
|
line, from + l, c);
|
1563
1647
|
if (isInRange) {
|
@@ -1566,35 +1650,35 @@ klass: do {
|
|
1566
1650
|
isLiteral = true;
|
1567
1651
|
}
|
1568
1652
|
break;
|
1569
|
-
case
|
1653
|
+
case "-":
|
1570
1654
|
if (isLiteral && !isInRange) {
|
1571
1655
|
isLiteral = false;
|
1572
1656
|
isInRange = true;
|
1573
1657
|
} else if (isInRange) {
|
1574
1658
|
isInRange = false;
|
1575
|
-
} else if (s.charAt(l) ===
|
1659
|
+
} else if (s.charAt(l) === "]") {
|
1576
1660
|
isInRange = true;
|
1577
1661
|
} else {
|
1578
1662
|
if (option.regexdash !== (l === 2 || (l === 3 &&
|
1579
|
-
s.charAt(1) ===
|
1663
|
+
s.charAt(1) === "^"))) {
|
1580
1664
|
warningAt("Unescaped '{a}'.",
|
1581
|
-
line, from + l - 1,
|
1665
|
+
line, from + l - 1, "-");
|
1582
1666
|
}
|
1583
1667
|
isLiteral = true;
|
1584
1668
|
}
|
1585
1669
|
break;
|
1586
|
-
case
|
1670
|
+
case "]":
|
1587
1671
|
if (isInRange && !option.regexdash) {
|
1588
1672
|
warningAt("Unescaped '{a}'.",
|
1589
|
-
line, from + l - 1,
|
1673
|
+
line, from + l - 1, "-");
|
1590
1674
|
}
|
1591
1675
|
break klass;
|
1592
|
-
case
|
1676
|
+
case "\\":
|
1593
1677
|
c = s.charAt(l);
|
1594
|
-
if (c <
|
1678
|
+
if (c < " ") {
|
1595
1679
|
warningAt(
|
1596
1680
|
"Unexpected control character in regular expression.", line, from + l);
|
1597
|
-
} else if (c ===
|
1681
|
+
} else if (c === "<") {
|
1598
1682
|
warningAt(
|
1599
1683
|
"Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
|
1600
1684
|
}
|
@@ -1604,7 +1688,7 @@ klass: do {
|
|
1604
1688
|
if (/[wsd]/i.test(c)) {
|
1605
1689
|
if (isInRange) {
|
1606
1690
|
warningAt("Unescaped '{a}'.",
|
1607
|
-
line, from + l,
|
1691
|
+
line, from + l, "-");
|
1608
1692
|
isInRange = false;
|
1609
1693
|
}
|
1610
1694
|
isLiteral = false;
|
@@ -1614,9 +1698,9 @@ klass: do {
|
|
1614
1698
|
isLiteral = true;
|
1615
1699
|
}
|
1616
1700
|
break;
|
1617
|
-
case
|
1701
|
+
case "/":
|
1618
1702
|
warningAt("Unescaped '{a}'.",
|
1619
|
-
line, from + l - 1,
|
1703
|
+
line, from + l - 1, "/");
|
1620
1704
|
|
1621
1705
|
if (isInRange) {
|
1622
1706
|
isInRange = false;
|
@@ -1624,7 +1708,7 @@ klass: do {
|
|
1624
1708
|
isLiteral = true;
|
1625
1709
|
}
|
1626
1710
|
break;
|
1627
|
-
case
|
1711
|
+
case "<":
|
1628
1712
|
if (isInRange) {
|
1629
1713
|
isInRange = false;
|
1630
1714
|
} else {
|
@@ -1640,35 +1724,35 @@ klass: do {
|
|
1640
1724
|
}
|
1641
1725
|
} while (c);
|
1642
1726
|
break;
|
1643
|
-
case
|
1727
|
+
case ".":
|
1644
1728
|
if (option.regexp) {
|
1645
1729
|
warningAt("Insecure '{a}'.", line,
|
1646
1730
|
from + l, c);
|
1647
1731
|
}
|
1648
1732
|
break;
|
1649
|
-
case
|
1650
|
-
case
|
1651
|
-
case
|
1652
|
-
case
|
1653
|
-
case
|
1654
|
-
case
|
1733
|
+
case "]":
|
1734
|
+
case "?":
|
1735
|
+
case "{":
|
1736
|
+
case "}":
|
1737
|
+
case "+":
|
1738
|
+
case "*":
|
1655
1739
|
warningAt("Unescaped '{a}'.", line,
|
1656
1740
|
from + l, c);
|
1657
1741
|
}
|
1658
1742
|
if (b) {
|
1659
1743
|
switch (s.charAt(l)) {
|
1660
|
-
case
|
1661
|
-
case
|
1662
|
-
case
|
1744
|
+
case "?":
|
1745
|
+
case "+":
|
1746
|
+
case "*":
|
1663
1747
|
l += 1;
|
1664
|
-
if (s.charAt(l) ===
|
1748
|
+
if (s.charAt(l) === "?") {
|
1665
1749
|
l += 1;
|
1666
1750
|
}
|
1667
1751
|
break;
|
1668
|
-
case
|
1752
|
+
case "{":
|
1669
1753
|
l += 1;
|
1670
1754
|
c = s.charAt(l);
|
1671
|
-
if (c <
|
1755
|
+
if (c < "0" || c > "9") {
|
1672
1756
|
warningAt(
|
1673
1757
|
"Expected a number and instead saw '{a}'.", line, from + l, c);
|
1674
1758
|
}
|
@@ -1676,23 +1760,23 @@ klass: do {
|
|
1676
1760
|
low = +c;
|
1677
1761
|
for (;;) {
|
1678
1762
|
c = s.charAt(l);
|
1679
|
-
if (c <
|
1763
|
+
if (c < "0" || c > "9") {
|
1680
1764
|
break;
|
1681
1765
|
}
|
1682
1766
|
l += 1;
|
1683
1767
|
low = +c + (low * 10);
|
1684
1768
|
}
|
1685
1769
|
high = low;
|
1686
|
-
if (c ===
|
1770
|
+
if (c === ",") {
|
1687
1771
|
l += 1;
|
1688
1772
|
high = Infinity;
|
1689
1773
|
c = s.charAt(l);
|
1690
|
-
if (c >=
|
1774
|
+
if (c >= "0" && c <= "9") {
|
1691
1775
|
l += 1;
|
1692
1776
|
high = +c;
|
1693
1777
|
for (;;) {
|
1694
1778
|
c = s.charAt(l);
|
1695
|
-
if (c <
|
1779
|
+
if (c < "0" || c > "9") {
|
1696
1780
|
break;
|
1697
1781
|
}
|
1698
1782
|
l += 1;
|
@@ -1700,13 +1784,13 @@ klass: do {
|
|
1700
1784
|
}
|
1701
1785
|
}
|
1702
1786
|
}
|
1703
|
-
if (s.charAt(l) !==
|
1787
|
+
if (s.charAt(l) !== "}") {
|
1704
1788
|
warningAt(
|
1705
|
-
"Expected '{a}' and instead saw '{b}'.", line, from + l,
|
1789
|
+
"Expected '{a}' and instead saw '{b}'.", line, from + l, "}", c);
|
1706
1790
|
} else {
|
1707
1791
|
l += 1;
|
1708
1792
|
}
|
1709
|
-
if (s.charAt(l) ===
|
1793
|
+
if (s.charAt(l) === "?") {
|
1710
1794
|
l += 1;
|
1711
1795
|
}
|
1712
1796
|
if (low > high) {
|
@@ -1719,16 +1803,16 @@ klass: do {
|
|
1719
1803
|
c = s.substr(0, l - 1);
|
1720
1804
|
character += l;
|
1721
1805
|
s = s.substr(l);
|
1722
|
-
return it(
|
1806
|
+
return it("(regexp)", c);
|
1723
1807
|
}
|
1724
|
-
return it(
|
1808
|
+
return it("(punctuator)", t);
|
1725
1809
|
|
1726
1810
|
// punctuator
|
1727
1811
|
|
1728
|
-
case
|
1729
|
-
return it(
|
1812
|
+
case "#":
|
1813
|
+
return it("(punctuator)", t);
|
1730
1814
|
default:
|
1731
|
-
return it(
|
1815
|
+
return it("(punctuator)", t);
|
1732
1816
|
}
|
1733
1817
|
}
|
1734
1818
|
}
|
@@ -1737,14 +1821,13 @@ klass: do {
|
|
1737
1821
|
}());
|
1738
1822
|
|
1739
1823
|
|
1740
|
-
function addlabel(t, type) {
|
1741
|
-
|
1742
|
-
if (t === 'hasOwnProperty') {
|
1824
|
+
function addlabel(t, type, token) {
|
1825
|
+
if (t === "hasOwnProperty") {
|
1743
1826
|
warning("'hasOwnProperty' is a really bad name.");
|
1744
1827
|
}
|
1745
1828
|
|
1746
|
-
// Define t in the current function in the current scope.
|
1747
|
-
if (is_own(funct, t) && !funct[
|
1829
|
+
// Define t in the current function in the current scope.
|
1830
|
+
if (is_own(funct, t) && !funct["(global)"]) {
|
1748
1831
|
if (funct[t] === true) {
|
1749
1832
|
if (option.latedef)
|
1750
1833
|
warning("'{a}' was used before it was defined.", nexttoken, t);
|
@@ -1755,7 +1838,12 @@ klass: do {
|
|
1755
1838
|
}
|
1756
1839
|
|
1757
1840
|
funct[t] = type;
|
1758
|
-
|
1841
|
+
|
1842
|
+
if (token) {
|
1843
|
+
funct["(tokens)"][t] = token;
|
1844
|
+
}
|
1845
|
+
|
1846
|
+
if (funct["(global)"]) {
|
1759
1847
|
global[t] = funct;
|
1760
1848
|
if (is_own(implied, t)) {
|
1761
1849
|
if (option.latedef)
|
@@ -1769,27 +1857,32 @@ klass: do {
|
|
1769
1857
|
|
1770
1858
|
|
1771
1859
|
function doOption() {
|
1772
|
-
var
|
1860
|
+
var nt = nexttoken;
|
1861
|
+
var o = nt.value;
|
1862
|
+
var quotmarkValue = option.quotmark;
|
1863
|
+
var predef = {};
|
1864
|
+
var b, obj, filter, t, tn, v, minus;
|
1773
1865
|
|
1774
1866
|
switch (o) {
|
1775
|
-
case
|
1867
|
+
case "*/":
|
1776
1868
|
error("Unbegun comment.");
|
1777
1869
|
break;
|
1778
|
-
case
|
1779
|
-
case
|
1780
|
-
o =
|
1870
|
+
case "/*members":
|
1871
|
+
case "/*member":
|
1872
|
+
o = "/*members";
|
1781
1873
|
if (!membersOnly) {
|
1782
1874
|
membersOnly = {};
|
1783
1875
|
}
|
1784
1876
|
obj = membersOnly;
|
1877
|
+
option.quotmark = false;
|
1785
1878
|
break;
|
1786
|
-
case
|
1787
|
-
case
|
1879
|
+
case "/*jshint":
|
1880
|
+
case "/*jslint":
|
1788
1881
|
obj = option;
|
1789
1882
|
filter = boolOptions;
|
1790
1883
|
break;
|
1791
|
-
case
|
1792
|
-
obj =
|
1884
|
+
case "/*global":
|
1885
|
+
obj = predef;
|
1793
1886
|
break;
|
1794
1887
|
default:
|
1795
1888
|
error("What?");
|
@@ -1797,89 +1890,132 @@ klass: do {
|
|
1797
1890
|
|
1798
1891
|
t = lex.token();
|
1799
1892
|
loop: for (;;) {
|
1893
|
+
minus = false;
|
1800
1894
|
for (;;) {
|
1801
|
-
if (t.type ===
|
1895
|
+
if (t.type === "special" && t.value === "*/") {
|
1802
1896
|
break loop;
|
1803
1897
|
}
|
1804
|
-
if (t.id !==
|
1898
|
+
if (t.id !== "(endline)" && t.id !== ",") {
|
1805
1899
|
break;
|
1806
1900
|
}
|
1807
1901
|
t = lex.token();
|
1808
1902
|
}
|
1809
|
-
|
1810
|
-
|
1903
|
+
|
1904
|
+
if (o === "/*global" && t.value === "-") {
|
1905
|
+
minus = true;
|
1906
|
+
t = lex.token();
|
1907
|
+
}
|
1908
|
+
|
1909
|
+
if (t.type !== "(string)" && t.type !== "(identifier)" && o !== "/*members") {
|
1811
1910
|
error("Bad option.", t);
|
1812
1911
|
}
|
1813
1912
|
|
1814
1913
|
v = lex.token();
|
1815
|
-
if (v.id ===
|
1914
|
+
if (v.id === ":") {
|
1816
1915
|
v = lex.token();
|
1817
1916
|
|
1818
1917
|
if (obj === membersOnly) {
|
1819
|
-
error("Expected '{a}' and instead saw '{b}'.",
|
1820
|
-
t, '*/', ':');
|
1918
|
+
error("Expected '{a}' and instead saw '{b}'.", t, "*/", ":");
|
1821
1919
|
}
|
1822
1920
|
|
1823
|
-
if (o ===
|
1921
|
+
if (o === "/*jshint") {
|
1824
1922
|
checkOption(t.value, t);
|
1825
1923
|
}
|
1826
1924
|
|
1827
|
-
if (t.value ===
|
1925
|
+
if (t.value === "indent" && (o === "/*jshint" || o === "/*jslint")) {
|
1828
1926
|
b = +v.value;
|
1829
|
-
if (typeof b !==
|
1927
|
+
if (typeof b !== "number" || !isFinite(b) || b <= 0 ||
|
1830
1928
|
Math.floor(b) !== b) {
|
1831
1929
|
error("Expected a small integer and instead saw '{a}'.",
|
1832
1930
|
v, v.value);
|
1833
1931
|
}
|
1834
1932
|
obj.white = true;
|
1835
1933
|
obj.indent = b;
|
1836
|
-
} else if (t.value ===
|
1934
|
+
} else if (t.value === "maxerr" && (o === "/*jshint" || o === "/*jslint")) {
|
1837
1935
|
b = +v.value;
|
1838
|
-
if (typeof b !==
|
1936
|
+
if (typeof b !== "number" || !isFinite(b) || b <= 0 ||
|
1839
1937
|
Math.floor(b) !== b) {
|
1840
1938
|
error("Expected a small integer and instead saw '{a}'.",
|
1841
1939
|
v, v.value);
|
1842
1940
|
}
|
1843
1941
|
obj.maxerr = b;
|
1844
|
-
} else if (t.value ===
|
1942
|
+
} else if (t.value === "maxlen" && (o === "/*jshint" || o === "/*jslint")) {
|
1845
1943
|
b = +v.value;
|
1846
|
-
if (typeof b !==
|
1944
|
+
if (typeof b !== "number" || !isFinite(b) || b <= 0 ||
|
1847
1945
|
Math.floor(b) !== b) {
|
1848
1946
|
error("Expected a small integer and instead saw '{a}'.",
|
1849
1947
|
v, v.value);
|
1850
1948
|
}
|
1851
1949
|
obj.maxlen = b;
|
1852
|
-
} else if (t.value ===
|
1853
|
-
if (funct[
|
1950
|
+
} else if (t.value === "validthis") {
|
1951
|
+
if (funct["(global)"]) {
|
1854
1952
|
error("Option 'validthis' can't be used in a global scope.");
|
1855
1953
|
} else {
|
1856
|
-
if (v.value ===
|
1857
|
-
obj[t.value] = v.value ===
|
1954
|
+
if (v.value === "true" || v.value === "false")
|
1955
|
+
obj[t.value] = v.value === "true";
|
1858
1956
|
else
|
1859
1957
|
error("Bad option value.", v);
|
1860
1958
|
}
|
1861
|
-
} else if (
|
1862
|
-
|
1959
|
+
} else if (t.value === "quotmark" && (o === "/*jshint")) {
|
1960
|
+
switch (v.value) {
|
1961
|
+
case "true":
|
1962
|
+
obj.quotmark = true;
|
1963
|
+
break;
|
1964
|
+
case "false":
|
1965
|
+
obj.quotmark = false;
|
1966
|
+
break;
|
1967
|
+
case "double":
|
1968
|
+
case "single":
|
1969
|
+
obj.quotmark = v.value;
|
1970
|
+
break;
|
1971
|
+
default:
|
1972
|
+
error("Bad option value.", v);
|
1973
|
+
}
|
1974
|
+
} else if (v.value === "true" || v.value === "false") {
|
1975
|
+
if (o === "/*jslint") {
|
1863
1976
|
tn = renamedOptions[t.value] || t.value;
|
1864
|
-
obj[tn] = v.value ===
|
1977
|
+
obj[tn] = v.value === "true";
|
1865
1978
|
if (invertedOptions[tn] !== undefined) {
|
1866
1979
|
obj[tn] = !obj[tn];
|
1867
1980
|
}
|
1868
1981
|
} else {
|
1869
|
-
obj[t.value] = v.value ===
|
1982
|
+
obj[t.value] = v.value === "true";
|
1870
1983
|
}
|
1984
|
+
|
1985
|
+
if (t.value === "newcap")
|
1986
|
+
obj["(explicitNewcap)"] = true;
|
1871
1987
|
} else {
|
1872
1988
|
error("Bad option value.", v);
|
1873
1989
|
}
|
1874
1990
|
t = lex.token();
|
1875
1991
|
} else {
|
1876
|
-
if (o ===
|
1992
|
+
if (o === "/*jshint" || o === "/*jslint") {
|
1877
1993
|
error("Missing option value.", t);
|
1878
1994
|
}
|
1995
|
+
|
1879
1996
|
obj[t.value] = false;
|
1997
|
+
|
1998
|
+
if (o === "/*global" && minus === true) {
|
1999
|
+
JSHINT.blacklist[t.value] = t.value;
|
2000
|
+
updatePredefined();
|
2001
|
+
}
|
2002
|
+
|
1880
2003
|
t = v;
|
1881
2004
|
}
|
1882
2005
|
}
|
2006
|
+
|
2007
|
+
if (o === "/*members") {
|
2008
|
+
option.quotmark = quotmarkValue;
|
2009
|
+
}
|
2010
|
+
|
2011
|
+
combine(predefined, predef);
|
2012
|
+
|
2013
|
+
for (var key in predef) {
|
2014
|
+
if (is_own(predef, key)) {
|
2015
|
+
declared[key] = nt;
|
2016
|
+
}
|
2017
|
+
}
|
2018
|
+
|
1883
2019
|
if (filter) {
|
1884
2020
|
assume();
|
1885
2021
|
}
|
@@ -1911,36 +2047,36 @@ loop: for (;;) {
|
|
1911
2047
|
|
1912
2048
|
function advance(id, t) {
|
1913
2049
|
switch (token.id) {
|
1914
|
-
case
|
1915
|
-
if (nexttoken.id ===
|
2050
|
+
case "(number)":
|
2051
|
+
if (nexttoken.id === ".") {
|
1916
2052
|
warning("A dot following a number can be confused with a decimal point.", token);
|
1917
2053
|
}
|
1918
2054
|
break;
|
1919
|
-
case
|
1920
|
-
if (nexttoken.id ===
|
2055
|
+
case "-":
|
2056
|
+
if (nexttoken.id === "-" || nexttoken.id === "--") {
|
1921
2057
|
warning("Confusing minusses.");
|
1922
2058
|
}
|
1923
2059
|
break;
|
1924
|
-
case
|
1925
|
-
if (nexttoken.id ===
|
2060
|
+
case "+":
|
2061
|
+
if (nexttoken.id === "+" || nexttoken.id === "++") {
|
1926
2062
|
warning("Confusing plusses.");
|
1927
2063
|
}
|
1928
2064
|
break;
|
1929
2065
|
}
|
1930
2066
|
|
1931
|
-
if (token.type ===
|
2067
|
+
if (token.type === "(string)" || token.identifier) {
|
1932
2068
|
anonname = token.value;
|
1933
2069
|
}
|
1934
2070
|
|
1935
2071
|
if (id && nexttoken.id !== id) {
|
1936
2072
|
if (t) {
|
1937
|
-
if (nexttoken.id ===
|
2073
|
+
if (nexttoken.id === "(end)") {
|
1938
2074
|
warning("Unmatched '{a}'.", t, t.id);
|
1939
2075
|
} else {
|
1940
2076
|
warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
|
1941
2077
|
nexttoken, id, t.id, t.line, nexttoken.value);
|
1942
2078
|
}
|
1943
|
-
} else if (nexttoken.type !==
|
2079
|
+
} else if (nexttoken.type !== "(identifier)" ||
|
1944
2080
|
nexttoken.value !== id) {
|
1945
2081
|
warning("Expected '{a}' and instead saw '{b}'.",
|
1946
2082
|
nexttoken, id, nexttoken.value);
|
@@ -1951,13 +2087,13 @@ loop: for (;;) {
|
|
1951
2087
|
token = nexttoken;
|
1952
2088
|
for (;;) {
|
1953
2089
|
nexttoken = lookahead.shift() || lex.token();
|
1954
|
-
if (nexttoken.id ===
|
2090
|
+
if (nexttoken.id === "(end)" || nexttoken.id === "(error)") {
|
1955
2091
|
return;
|
1956
2092
|
}
|
1957
|
-
if (nexttoken.type ===
|
2093
|
+
if (nexttoken.type === "special") {
|
1958
2094
|
doOption();
|
1959
2095
|
} else {
|
1960
|
-
if (nexttoken.id !==
|
2096
|
+
if (nexttoken.id !== "(endline)") {
|
1961
2097
|
break;
|
1962
2098
|
}
|
1963
2099
|
}
|
@@ -1982,13 +2118,13 @@ loop: for (;;) {
|
|
1982
2118
|
function expression(rbp, initial) {
|
1983
2119
|
var left, isArray = false, isObject = false;
|
1984
2120
|
|
1985
|
-
if (nexttoken.id ===
|
2121
|
+
if (nexttoken.id === "(end)")
|
1986
2122
|
error("Unexpected early end of program.", token);
|
1987
2123
|
|
1988
2124
|
advance();
|
1989
2125
|
if (initial) {
|
1990
|
-
anonname =
|
1991
|
-
funct[
|
2126
|
+
anonname = "anonymous";
|
2127
|
+
funct["(verb)"] = token.value;
|
1992
2128
|
}
|
1993
2129
|
if (initial === true && token.fud) {
|
1994
2130
|
left = token.fud();
|
@@ -1996,7 +2132,7 @@ loop: for (;;) {
|
|
1996
2132
|
if (token.nud) {
|
1997
2133
|
left = token.nud();
|
1998
2134
|
} else {
|
1999
|
-
if (nexttoken.type ===
|
2135
|
+
if (nexttoken.type === "(number)" && token.id === ".") {
|
2000
2136
|
warning("A leading decimal point can be confused with a dot: '.{a}'.",
|
2001
2137
|
token, nexttoken.value);
|
2002
2138
|
advance();
|
@@ -2007,8 +2143,8 @@ loop: for (;;) {
|
|
2007
2143
|
}
|
2008
2144
|
}
|
2009
2145
|
while (rbp < nexttoken.lbp) {
|
2010
|
-
isArray = token.value ===
|
2011
|
-
isObject = token.value ===
|
2146
|
+
isArray = token.value === "Array";
|
2147
|
+
isObject = token.value === "Object";
|
2012
2148
|
|
2013
2149
|
// #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
|
2014
2150
|
// Line breaks in IfStatement heads exist to satisfy the checkJSHint
|
@@ -2017,8 +2153,8 @@ loop: for (;;) {
|
|
2017
2153
|
// If the left.value is not "new", or the left.first.value is a "."
|
2018
2154
|
// then safely assume that this is not "new Array()" and possibly
|
2019
2155
|
// not "new Object()"...
|
2020
|
-
if (left.value !==
|
2021
|
-
(left.first && left.first.value && left.first.value ===
|
2156
|
+
if (left.value !== "new" ||
|
2157
|
+
(left.first && left.first.value && left.first.value === ".")) {
|
2022
2158
|
isArray = false;
|
2023
2159
|
// ...In the case of Object, if the left.value and token.value
|
2024
2160
|
// are not equal, then safely assume that this not "new Object()"
|
@@ -2029,9 +2165,9 @@ loop: for (;;) {
|
|
2029
2165
|
}
|
2030
2166
|
|
2031
2167
|
advance();
|
2032
|
-
if (isArray && token.id ===
|
2168
|
+
if (isArray && token.id === "(" && nexttoken.id === ")")
|
2033
2169
|
warning("Use the array literal notation [].", token);
|
2034
|
-
if (isObject && token.id ===
|
2170
|
+
if (isObject && token.id === "(" && nexttoken.id === ")")
|
2035
2171
|
warning("Use the object literal notation {}.", token);
|
2036
2172
|
if (token.led) {
|
2037
2173
|
left = token.led(left);
|
@@ -2080,6 +2216,9 @@ loop: for (;;) {
|
|
2080
2216
|
if (option.white) {
|
2081
2217
|
left = left || token;
|
2082
2218
|
right = right || nexttoken;
|
2219
|
+
if (left.value === ";" && right.value === ";") {
|
2220
|
+
return;
|
2221
|
+
}
|
2083
2222
|
if (left.line === right.line && left.character === right.from) {
|
2084
2223
|
left.from += (left.character - left.from);
|
2085
2224
|
warning("Missing space after '{a}'.",
|
@@ -2106,7 +2245,7 @@ loop: for (;;) {
|
|
2106
2245
|
|
2107
2246
|
function indentation(bias) {
|
2108
2247
|
var i;
|
2109
|
-
if (option.white && nexttoken.id !==
|
2248
|
+
if (option.white && nexttoken.id !== "(end)") {
|
2110
2249
|
i = indent + (bias || 0);
|
2111
2250
|
if (nexttoken.from !== i) {
|
2112
2251
|
warning(
|
@@ -2137,7 +2276,7 @@ loop: for (;;) {
|
|
2137
2276
|
token.from += (token.character - token.from);
|
2138
2277
|
warning("Unexpected space after '{a}'.", token, token.value);
|
2139
2278
|
}
|
2140
|
-
advance(
|
2279
|
+
advance(",");
|
2141
2280
|
nonadjacent(token, nexttoken);
|
2142
2281
|
}
|
2143
2282
|
|
@@ -2147,7 +2286,7 @@ loop: for (;;) {
|
|
2147
2286
|
|
2148
2287
|
function symbol(s, p) {
|
2149
2288
|
var x = syntax[s];
|
2150
|
-
if (!x || typeof x !==
|
2289
|
+
if (!x || typeof x !== "object") {
|
2151
2290
|
syntax[s] = x = {
|
2152
2291
|
id: s,
|
2153
2292
|
lbp: p,
|
@@ -2180,7 +2319,7 @@ loop: for (;;) {
|
|
2180
2319
|
|
2181
2320
|
function reserveName(x) {
|
2182
2321
|
var c = x.id.charAt(0);
|
2183
|
-
if ((c >=
|
2322
|
+
if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
|
2184
2323
|
x.identifier = x.reserved = true;
|
2185
2324
|
}
|
2186
2325
|
return x;
|
@@ -2190,14 +2329,14 @@ loop: for (;;) {
|
|
2190
2329
|
function prefix(s, f) {
|
2191
2330
|
var x = symbol(s, 150);
|
2192
2331
|
reserveName(x);
|
2193
|
-
x.nud = (typeof f ===
|
2332
|
+
x.nud = (typeof f === "function") ? f : function () {
|
2194
2333
|
this.right = expression(150);
|
2195
|
-
this.arity =
|
2196
|
-
if (this.id ===
|
2334
|
+
this.arity = "unary";
|
2335
|
+
if (this.id === "++" || this.id === "--") {
|
2197
2336
|
if (option.plusplus) {
|
2198
2337
|
warning("Unexpected use of '{a}'.", this, this.id);
|
2199
2338
|
} else if ((!this.right.identifier || this.right.reserved) &&
|
2200
|
-
this.right.id !==
|
2339
|
+
this.right.id !== "." && this.right.id !== "[") {
|
2201
2340
|
warning("Bad operand.", this);
|
2202
2341
|
}
|
2203
2342
|
}
|
@@ -2224,7 +2363,7 @@ loop: for (;;) {
|
|
2224
2363
|
|
2225
2364
|
function reservevar(s, v) {
|
2226
2365
|
return reserve(s, function () {
|
2227
|
-
if (typeof v ===
|
2366
|
+
if (typeof v === "function") {
|
2228
2367
|
v(this);
|
2229
2368
|
}
|
2230
2369
|
return this;
|
@@ -2241,9 +2380,9 @@ loop: for (;;) {
|
|
2241
2380
|
nonadjacent(token, nexttoken);
|
2242
2381
|
}
|
2243
2382
|
if (s === "in" && left.id === "!") {
|
2244
|
-
warning("Confusing use of '{a}'.", left,
|
2383
|
+
warning("Confusing use of '{a}'.", left, "!");
|
2245
2384
|
}
|
2246
|
-
if (typeof f ===
|
2385
|
+
if (typeof f === "function") {
|
2247
2386
|
return f(left, this);
|
2248
2387
|
} else {
|
2249
2388
|
this.left = left;
|
@@ -2261,16 +2400,17 @@ loop: for (;;) {
|
|
2261
2400
|
nobreaknonadjacent(prevtoken, token);
|
2262
2401
|
nonadjacent(token, nexttoken);
|
2263
2402
|
var right = expression(100);
|
2264
|
-
|
2403
|
+
|
2404
|
+
if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
|
2265
2405
|
warning("Use the isNaN function to compare with NaN.", this);
|
2266
2406
|
} else if (f) {
|
2267
2407
|
f.apply(this, [left, right]);
|
2268
2408
|
}
|
2269
|
-
if (left.id ===
|
2270
|
-
warning("Confusing use of '{a}'.", left,
|
2409
|
+
if (left.id === "!") {
|
2410
|
+
warning("Confusing use of '{a}'.", left, "!");
|
2271
2411
|
}
|
2272
|
-
if (right.id ===
|
2273
|
-
warning("Confusing use of '{a}'.", right,
|
2412
|
+
if (right.id === "!") {
|
2413
|
+
warning("Confusing use of '{a}'.", right, "!");
|
2274
2414
|
}
|
2275
2415
|
this.left = left;
|
2276
2416
|
this.right = right;
|
@@ -2282,49 +2422,54 @@ loop: for (;;) {
|
|
2282
2422
|
|
2283
2423
|
function isPoorRelation(node) {
|
2284
2424
|
return node &&
|
2285
|
-
((node.type ===
|
2286
|
-
(node.type ===
|
2287
|
-
(node.type ===
|
2288
|
-
node.type ===
|
2289
|
-
node.type ===
|
2290
|
-
node.type ===
|
2425
|
+
((node.type === "(number)" && +node.value === 0) ||
|
2426
|
+
(node.type === "(string)" && node.value === "") ||
|
2427
|
+
(node.type === "null" && !option.eqnull) ||
|
2428
|
+
node.type === "true" ||
|
2429
|
+
node.type === "false" ||
|
2430
|
+
node.type === "undefined");
|
2291
2431
|
}
|
2292
2432
|
|
2293
2433
|
|
2294
|
-
function assignop(s
|
2434
|
+
function assignop(s) {
|
2295
2435
|
symbol(s, 20).exps = true;
|
2436
|
+
|
2296
2437
|
return infix(s, function (left, that) {
|
2297
|
-
var l;
|
2298
2438
|
that.left = left;
|
2439
|
+
|
2299
2440
|
if (predefined[left.value] === false &&
|
2300
|
-
scope[left.value][
|
2441
|
+
scope[left.value]["(global)"] === true) {
|
2301
2442
|
warning("Read only.", left);
|
2302
|
-
} else if (left[
|
2443
|
+
} else if (left["function"]) {
|
2303
2444
|
warning("'{a}' is a function.", left, left.value);
|
2304
2445
|
}
|
2446
|
+
|
2305
2447
|
if (left) {
|
2306
|
-
if (option.esnext && funct[left.value] ===
|
2448
|
+
if (option.esnext && funct[left.value] === "const") {
|
2307
2449
|
warning("Attempting to override '{a}' which is a constant", left, left.value);
|
2308
2450
|
}
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2451
|
+
|
2452
|
+
if (left.id === "." || left.id === "[") {
|
2453
|
+
if (!left.left || left.left.value === "arguments") {
|
2454
|
+
warning("Bad assignment.", that);
|
2312
2455
|
}
|
2313
2456
|
that.right = expression(19);
|
2314
2457
|
return that;
|
2315
2458
|
} else if (left.identifier && !left.reserved) {
|
2316
|
-
if (funct[left.value] ===
|
2459
|
+
if (funct[left.value] === "exception") {
|
2317
2460
|
warning("Do not assign to the exception parameter.", left);
|
2318
2461
|
}
|
2319
2462
|
that.right = expression(19);
|
2320
2463
|
return that;
|
2321
2464
|
}
|
2322
|
-
|
2465
|
+
|
2466
|
+
if (left === syntax["function"]) {
|
2323
2467
|
warning(
|
2324
2468
|
"Expected an identifier in an assignment and instead saw a function invocation.",
|
2325
2469
|
token);
|
2326
2470
|
}
|
2327
2471
|
}
|
2472
|
+
|
2328
2473
|
error("Bad assignment.", that);
|
2329
2474
|
}, 20);
|
2330
2475
|
}
|
@@ -2333,7 +2478,7 @@ loop: for (;;) {
|
|
2333
2478
|
function bitwise(s, f, p) {
|
2334
2479
|
var x = symbol(s, p);
|
2335
2480
|
reserveName(x);
|
2336
|
-
x.led = (typeof f ===
|
2481
|
+
x.led = (typeof f === "function") ? f : function (left) {
|
2337
2482
|
if (option.bitwise) {
|
2338
2483
|
warning("Unexpected use of '{a}'.", this, this.id);
|
2339
2484
|
}
|
@@ -2354,12 +2499,12 @@ loop: for (;;) {
|
|
2354
2499
|
nonadjacent(prevtoken, token);
|
2355
2500
|
nonadjacent(token, nexttoken);
|
2356
2501
|
if (left) {
|
2357
|
-
if (left.id ===
|
2502
|
+
if (left.id === "." || left.id === "[" ||
|
2358
2503
|
(left.identifier && !left.reserved)) {
|
2359
2504
|
expression(19);
|
2360
2505
|
return that;
|
2361
2506
|
}
|
2362
|
-
if (left === syntax[
|
2507
|
+
if (left === syntax["function"]) {
|
2363
2508
|
warning(
|
2364
2509
|
"Expected an identifier in an assignment, and instead saw a function invocation.",
|
2365
2510
|
token);
|
@@ -2371,13 +2516,13 @@ loop: for (;;) {
|
|
2371
2516
|
}
|
2372
2517
|
|
2373
2518
|
|
2374
|
-
function suffix(s
|
2519
|
+
function suffix(s) {
|
2375
2520
|
var x = symbol(s, 150);
|
2376
2521
|
x.led = function (left) {
|
2377
2522
|
if (option.plusplus) {
|
2378
2523
|
warning("Unexpected use of '{a}'.", this, this.id);
|
2379
2524
|
} else if ((!left.identifier || left.reserved) &&
|
2380
|
-
left.id !==
|
2525
|
+
left.id !== "." && left.id !== "[") {
|
2381
2526
|
warning("Bad operand.", this);
|
2382
2527
|
}
|
2383
2528
|
this.left = left;
|
@@ -2396,7 +2541,7 @@ loop: for (;;) {
|
|
2396
2541
|
// `undefined` as a function param is a common pattern to protect
|
2397
2542
|
// against the case when somebody does `undefined = true` and
|
2398
2543
|
// help with minification. More info: https://gist.github.com/315916
|
2399
|
-
if (!fnparam || token.value !==
|
2544
|
+
if (!fnparam || token.value !== "undefined") {
|
2400
2545
|
warning("Expected an identifier and instead saw '{a}' (a reserved word).",
|
2401
2546
|
token, token.id);
|
2402
2547
|
}
|
@@ -2412,7 +2557,7 @@ loop: for (;;) {
|
|
2412
2557
|
if (i) {
|
2413
2558
|
return i;
|
2414
2559
|
}
|
2415
|
-
if (token.id ===
|
2560
|
+
if (token.id === "function" && nexttoken.id === "(") {
|
2416
2561
|
warning("Missing name in function declaration.");
|
2417
2562
|
} else {
|
2418
2563
|
error("Expected an identifier and instead saw '{a}'.",
|
@@ -2423,7 +2568,7 @@ loop: for (;;) {
|
|
2423
2568
|
|
2424
2569
|
function reachable(s) {
|
2425
2570
|
var i = 0, t;
|
2426
|
-
if (nexttoken.id !==
|
2571
|
+
if (nexttoken.id !== ";" || noreach) {
|
2427
2572
|
return;
|
2428
2573
|
}
|
2429
2574
|
for (;;) {
|
@@ -2431,8 +2576,8 @@ loop: for (;;) {
|
|
2431
2576
|
if (t.reach) {
|
2432
2577
|
return;
|
2433
2578
|
}
|
2434
|
-
if (t.id !==
|
2435
|
-
if (t.id ===
|
2579
|
+
if (t.id !== "(endline)") {
|
2580
|
+
if (t.id === "function") {
|
2436
2581
|
if (!option.latedef) {
|
2437
2582
|
break;
|
2438
2583
|
}
|
@@ -2456,26 +2601,34 @@ loop: for (;;) {
|
|
2456
2601
|
return;
|
2457
2602
|
}
|
2458
2603
|
|
2459
|
-
// Is this a labelled statement?
|
2604
|
+
// Is this a labelled statement?
|
2460
2605
|
|
2461
|
-
if (t.identifier && !t.reserved && peek().id ===
|
2606
|
+
if (t.identifier && !t.reserved && peek().id === ":") {
|
2462
2607
|
advance();
|
2463
|
-
advance(
|
2608
|
+
advance(":");
|
2464
2609
|
scope = Object.create(s);
|
2465
|
-
addlabel(t.value,
|
2466
|
-
|
2467
|
-
|
2468
|
-
|
2610
|
+
addlabel(t.value, "label");
|
2611
|
+
|
2612
|
+
if (!nexttoken.labelled && nexttoken.value !== "{") {
|
2613
|
+
warning("Label '{a}' on {b} statement.", nexttoken, t.value, nexttoken.value);
|
2469
2614
|
}
|
2470
|
-
|
2471
|
-
|
2472
|
-
|
2615
|
+
|
2616
|
+
if (jx.test(t.value + ":")) {
|
2617
|
+
warning("Label '{a}' looks like a javascript url.", t, t.value);
|
2473
2618
|
}
|
2619
|
+
|
2474
2620
|
nexttoken.label = t.value;
|
2475
2621
|
t = nexttoken;
|
2476
2622
|
}
|
2477
2623
|
|
2478
|
-
//
|
2624
|
+
// Is it a lonely block?
|
2625
|
+
|
2626
|
+
if (t.id === "{") {
|
2627
|
+
block(true, true);
|
2628
|
+
return;
|
2629
|
+
}
|
2630
|
+
|
2631
|
+
// Parse the statement.
|
2479
2632
|
|
2480
2633
|
if (!noindent) {
|
2481
2634
|
indentation();
|
@@ -2483,31 +2636,32 @@ loop: for (;;) {
|
|
2483
2636
|
r = expression(0, true);
|
2484
2637
|
|
2485
2638
|
// Look for the final semicolon.
|
2639
|
+
|
2486
2640
|
if (!t.block) {
|
2487
2641
|
if (!option.expr && (!r || !r.exps)) {
|
2488
2642
|
warning("Expected an assignment or function call and instead saw an expression.",
|
2489
2643
|
token);
|
2490
|
-
} else if (option.nonew && r.id ===
|
2491
|
-
warning("Do not use 'new' for side effects.");
|
2644
|
+
} else if (option.nonew && r.id === "(" && r.left.id === "new") {
|
2645
|
+
warning("Do not use 'new' for side effects.", t);
|
2492
2646
|
}
|
2493
2647
|
|
2494
|
-
if (nexttoken.id ===
|
2648
|
+
if (nexttoken.id === ",") {
|
2495
2649
|
return comma();
|
2496
2650
|
}
|
2497
2651
|
|
2498
|
-
if (nexttoken.id !==
|
2652
|
+
if (nexttoken.id !== ";") {
|
2499
2653
|
if (!option.asi) {
|
2500
2654
|
// If this is the last statement in a block that ends on
|
2501
2655
|
// the same line *and* option lastsemic is on, ignore the warning.
|
2502
2656
|
// Otherwise, complain about missing semicolon.
|
2503
|
-
if (!option.lastsemic || nexttoken.id !==
|
2657
|
+
if (!option.lastsemic || nexttoken.id !== "}" ||
|
2504
2658
|
nexttoken.line !== token.line) {
|
2505
2659
|
warningAt("Missing semicolon.", token.line, token.character);
|
2506
2660
|
}
|
2507
2661
|
}
|
2508
2662
|
} else {
|
2509
2663
|
adjacent(token, nexttoken);
|
2510
|
-
advance(
|
2664
|
+
advance(";");
|
2511
2665
|
nonadjacent(token, nexttoken);
|
2512
2666
|
}
|
2513
2667
|
}
|
@@ -2521,15 +2675,15 @@ loop: for (;;) {
|
|
2521
2675
|
|
2522
2676
|
|
2523
2677
|
function statements(startLine) {
|
2524
|
-
var a = [],
|
2678
|
+
var a = [], p;
|
2525
2679
|
|
2526
|
-
while (!nexttoken.reach && nexttoken.id !==
|
2527
|
-
if (nexttoken.id ===
|
2680
|
+
while (!nexttoken.reach && nexttoken.id !== "(end)") {
|
2681
|
+
if (nexttoken.id === ";") {
|
2528
2682
|
p = peek();
|
2529
2683
|
if (!p || p.id !== "(") {
|
2530
2684
|
warning("Unnecessary semicolon.");
|
2531
2685
|
}
|
2532
|
-
advance(
|
2686
|
+
advance(";");
|
2533
2687
|
} else {
|
2534
2688
|
a.push(statement(startLine === nexttoken.line));
|
2535
2689
|
}
|
@@ -2580,7 +2734,8 @@ loop: for (;;) {
|
|
2580
2734
|
}
|
2581
2735
|
|
2582
2736
|
if (token.value === "use strict") {
|
2583
|
-
option
|
2737
|
+
if (!option["(explicitNewcap)"])
|
2738
|
+
option.newcap = true;
|
2584
2739
|
option.undef = true;
|
2585
2740
|
}
|
2586
2741
|
|
@@ -2620,10 +2775,14 @@ loop: for (;;) {
|
|
2620
2775
|
nonadjacent(token, nexttoken);
|
2621
2776
|
t = nexttoken;
|
2622
2777
|
|
2623
|
-
|
2624
|
-
|
2778
|
+
var metrics = funct["(metrics)"];
|
2779
|
+
metrics.nestedBlockDepth += 1;
|
2780
|
+
metrics.verifyMaxNestedBlockDepthPerFunction();
|
2781
|
+
|
2782
|
+
if (nexttoken.id === "{") {
|
2783
|
+
advance("{");
|
2625
2784
|
line = token.line;
|
2626
|
-
if (nexttoken.id !==
|
2785
|
+
if (nexttoken.id !== "}") {
|
2627
2786
|
indent += option.indent;
|
2628
2787
|
while (!ordinary && nexttoken.from > indent) {
|
2629
2788
|
indent += option.indent;
|
@@ -2638,7 +2797,7 @@ loop: for (;;) {
|
|
2638
2797
|
}
|
2639
2798
|
directives();
|
2640
2799
|
|
2641
|
-
if (option.strict && funct[
|
2800
|
+
if (option.strict && funct["(context)"]["(global)"]) {
|
2642
2801
|
if (!m["use strict"] && !directive["use strict"]) {
|
2643
2802
|
warning("Missing \"use strict\" statement.");
|
2644
2803
|
}
|
@@ -2647,6 +2806,8 @@ loop: for (;;) {
|
|
2647
2806
|
|
2648
2807
|
a = statements(line);
|
2649
2808
|
|
2809
|
+
metrics.statementCount += a.length;
|
2810
|
+
|
2650
2811
|
if (isfunc) {
|
2651
2812
|
directive = m;
|
2652
2813
|
}
|
@@ -2658,15 +2819,15 @@ loop: for (;;) {
|
|
2658
2819
|
} else if (line !== nexttoken.line) {
|
2659
2820
|
indentation();
|
2660
2821
|
}
|
2661
|
-
advance(
|
2822
|
+
advance("}", t);
|
2662
2823
|
indent = old_indent;
|
2663
2824
|
} else if (!ordinary) {
|
2664
2825
|
error("Expected '{a}' and instead saw '{b}'.",
|
2665
|
-
nexttoken,
|
2826
|
+
nexttoken, "{", nexttoken.value);
|
2666
2827
|
} else {
|
2667
2828
|
if (!stmt || option.curly)
|
2668
2829
|
warning("Expected '{a}' and instead saw '{b}'.",
|
2669
|
-
nexttoken,
|
2830
|
+
nexttoken, "{", nexttoken.value);
|
2670
2831
|
|
2671
2832
|
noreach = true;
|
2672
2833
|
indent += option.indent;
|
@@ -2675,21 +2836,22 @@ loop: for (;;) {
|
|
2675
2836
|
indent -= option.indent;
|
2676
2837
|
noreach = false;
|
2677
2838
|
}
|
2678
|
-
funct[
|
2839
|
+
funct["(verb)"] = null;
|
2679
2840
|
if (!ordinary || !option.funcscope) scope = s;
|
2680
2841
|
inblock = b;
|
2681
2842
|
if (ordinary && option.noempty && (!a || a.length === 0)) {
|
2682
2843
|
warning("Empty block.");
|
2683
2844
|
}
|
2845
|
+
metrics.nestedBlockDepth -= 1;
|
2684
2846
|
return a;
|
2685
2847
|
}
|
2686
2848
|
|
2687
2849
|
|
2688
2850
|
function countMember(m) {
|
2689
|
-
if (membersOnly && typeof membersOnly[m] !==
|
2851
|
+
if (membersOnly && typeof membersOnly[m] !== "boolean") {
|
2690
2852
|
warning("Unexpected /*member '{a}'.", token, m);
|
2691
2853
|
}
|
2692
|
-
if (typeof member[m] ===
|
2854
|
+
if (typeof member[m] === "number") {
|
2693
2855
|
member[m] += 1;
|
2694
2856
|
} else {
|
2695
2857
|
member[m] = 1;
|
@@ -2699,7 +2861,7 @@ loop: for (;;) {
|
|
2699
2861
|
|
2700
2862
|
function note_implied(token) {
|
2701
2863
|
var name = token.value, line = token.line, a = implied[name];
|
2702
|
-
if (typeof a ===
|
2864
|
+
if (typeof a === "function") {
|
2703
2865
|
a = false;
|
2704
2866
|
}
|
2705
2867
|
|
@@ -2714,16 +2876,16 @@ loop: for (;;) {
|
|
2714
2876
|
|
2715
2877
|
// Build the syntax table by declaring the syntactic elements of the language.
|
2716
2878
|
|
2717
|
-
type(
|
2879
|
+
type("(number)", function () {
|
2718
2880
|
return this;
|
2719
2881
|
});
|
2720
2882
|
|
2721
|
-
type(
|
2883
|
+
type("(string)", function () {
|
2722
2884
|
return this;
|
2723
2885
|
});
|
2724
2886
|
|
2725
|
-
syntax[
|
2726
|
-
type:
|
2887
|
+
syntax["(identifier)"] = {
|
2888
|
+
type: "(identifier)",
|
2727
2889
|
lbp: 0,
|
2728
2890
|
identifier: true,
|
2729
2891
|
nud: function () {
|
@@ -2731,13 +2893,13 @@ loop: for (;;) {
|
|
2731
2893
|
s = scope[v],
|
2732
2894
|
f;
|
2733
2895
|
|
2734
|
-
if (typeof s ===
|
2896
|
+
if (typeof s === "function") {
|
2735
2897
|
// Protection against accidental inheritance.
|
2736
2898
|
s = undefined;
|
2737
|
-
} else if (typeof s ===
|
2899
|
+
} else if (typeof s === "boolean") {
|
2738
2900
|
f = funct;
|
2739
2901
|
funct = functions[0];
|
2740
|
-
addlabel(v,
|
2902
|
+
addlabel(v, "var");
|
2741
2903
|
s = funct;
|
2742
2904
|
funct = f;
|
2743
2905
|
}
|
@@ -2746,21 +2908,21 @@ loop: for (;;) {
|
|
2746
2908
|
if (funct === s) {
|
2747
2909
|
// Change 'unused' to 'var', and reject labels.
|
2748
2910
|
switch (funct[v]) {
|
2749
|
-
case
|
2750
|
-
funct[v] =
|
2911
|
+
case "unused":
|
2912
|
+
funct[v] = "var";
|
2751
2913
|
break;
|
2752
|
-
case
|
2753
|
-
funct[v] =
|
2754
|
-
this[
|
2914
|
+
case "unction":
|
2915
|
+
funct[v] = "function";
|
2916
|
+
this["function"] = true;
|
2755
2917
|
break;
|
2756
|
-
case
|
2757
|
-
this[
|
2918
|
+
case "function":
|
2919
|
+
this["function"] = true;
|
2758
2920
|
break;
|
2759
|
-
case
|
2921
|
+
case "label":
|
2760
2922
|
warning("'{a}' is a statement label.", token, v);
|
2761
2923
|
break;
|
2762
2924
|
}
|
2763
|
-
} else if (funct[
|
2925
|
+
} else if (funct["(global)"]) {
|
2764
2926
|
// The name is not defined in the function. If we are in the global
|
2765
2927
|
// scope, then we have an undefined variable.
|
2766
2928
|
//
|
@@ -2768,32 +2930,33 @@ loop: for (;;) {
|
|
2768
2930
|
// the base object of a reference is null so no need to display warning
|
2769
2931
|
// if we're inside of typeof or delete.
|
2770
2932
|
|
2771
|
-
if (option.undef && typeof predefined[v] !==
|
2933
|
+
if (option.undef && typeof predefined[v] !== "boolean") {
|
2772
2934
|
// Attempting to subscript a null reference will throw an
|
2773
2935
|
// error, even within the typeof and delete operators
|
2774
|
-
if (!(anonname ===
|
2775
|
-
(nexttoken && (nexttoken.value ===
|
2936
|
+
if (!(anonname === "typeof" || anonname === "delete") ||
|
2937
|
+
(nexttoken && (nexttoken.value === "." || nexttoken.value === "["))) {
|
2776
2938
|
|
2777
2939
|
isundef(funct, "'{a}' is not defined.", token, v);
|
2778
2940
|
}
|
2779
2941
|
}
|
2942
|
+
|
2780
2943
|
note_implied(token);
|
2781
2944
|
} else {
|
2782
2945
|
// If the name is already defined in the current
|
2783
2946
|
// function, but not as outer, then there is a scope error.
|
2784
2947
|
|
2785
2948
|
switch (funct[v]) {
|
2786
|
-
case
|
2787
|
-
case
|
2788
|
-
case
|
2789
|
-
case
|
2949
|
+
case "closure":
|
2950
|
+
case "function":
|
2951
|
+
case "var":
|
2952
|
+
case "unused":
|
2790
2953
|
warning("'{a}' used out of scope.", token, v);
|
2791
2954
|
break;
|
2792
|
-
case
|
2955
|
+
case "label":
|
2793
2956
|
warning("'{a}' is a statement label.", token, v);
|
2794
2957
|
break;
|
2795
|
-
case
|
2796
|
-
case
|
2958
|
+
case "outer":
|
2959
|
+
case "global":
|
2797
2960
|
break;
|
2798
2961
|
default:
|
2799
2962
|
// If the name is defined in an outer function, make an outer entry,
|
@@ -2803,16 +2966,16 @@ loop: for (;;) {
|
|
2803
2966
|
} else if (s === null) {
|
2804
2967
|
warning("'{a}' is not allowed.", token, v);
|
2805
2968
|
note_implied(token);
|
2806
|
-
} else if (typeof s !==
|
2969
|
+
} else if (typeof s !== "object") {
|
2807
2970
|
// Operators typeof and delete do not raise runtime errors even
|
2808
2971
|
// if the base object of a reference is null so no need to
|
2809
2972
|
// display warning if we're inside of typeof or delete.
|
2810
2973
|
if (option.undef) {
|
2811
2974
|
// Attempting to subscript a null reference will throw an
|
2812
2975
|
// error, even within the typeof and delete operators
|
2813
|
-
if (!(anonname ===
|
2976
|
+
if (!(anonname === "typeof" || anonname === "delete") ||
|
2814
2977
|
(nexttoken &&
|
2815
|
-
(nexttoken.value ===
|
2978
|
+
(nexttoken.value === "." || nexttoken.value === "["))) {
|
2816
2979
|
|
2817
2980
|
isundef(funct, "'{a}' is not defined.", token, v);
|
2818
2981
|
}
|
@@ -2821,22 +2984,21 @@ loop: for (;;) {
|
|
2821
2984
|
note_implied(token);
|
2822
2985
|
} else {
|
2823
2986
|
switch (s[v]) {
|
2824
|
-
case
|
2825
|
-
case
|
2826
|
-
this[
|
2827
|
-
s[v] =
|
2828
|
-
funct[v] = s[
|
2987
|
+
case "function":
|
2988
|
+
case "unction":
|
2989
|
+
this["function"] = true;
|
2990
|
+
s[v] = "closure";
|
2991
|
+
funct[v] = s["(global)"] ? "global" : "outer";
|
2829
2992
|
break;
|
2830
|
-
case
|
2831
|
-
case
|
2832
|
-
s[v] =
|
2833
|
-
funct[v] = s[
|
2993
|
+
case "var":
|
2994
|
+
case "unused":
|
2995
|
+
s[v] = "closure";
|
2996
|
+
funct[v] = s["(global)"] ? "global" : "outer";
|
2834
2997
|
break;
|
2835
|
-
case
|
2836
|
-
|
2837
|
-
funct[v] = s['(global)'] ? 'global' : 'outer';
|
2998
|
+
case "closure":
|
2999
|
+
funct[v] = s["(global)"] ? "global" : "outer";
|
2838
3000
|
break;
|
2839
|
-
case
|
3001
|
+
case "label":
|
2840
3002
|
warning("'{a}' is a statement label.", token, v);
|
2841
3003
|
}
|
2842
3004
|
}
|
@@ -2850,123 +3012,122 @@ loop: for (;;) {
|
|
2850
3012
|
}
|
2851
3013
|
};
|
2852
3014
|
|
2853
|
-
type(
|
3015
|
+
type("(regexp)", function () {
|
2854
3016
|
return this;
|
2855
3017
|
});
|
2856
3018
|
|
2857
3019
|
|
2858
3020
|
// ECMAScript parser
|
2859
3021
|
|
2860
|
-
delim(
|
2861
|
-
delim(
|
2862
|
-
delim(
|
2863
|
-
delim(
|
2864
|
-
delim(
|
2865
|
-
delim(
|
2866
|
-
delim(
|
2867
|
-
delim(
|
2868
|
-
delim(
|
2869
|
-
delim(
|
2870
|
-
delim(
|
2871
|
-
delim(
|
3022
|
+
delim("(endline)");
|
3023
|
+
delim("(begin)");
|
3024
|
+
delim("(end)").reach = true;
|
3025
|
+
delim("</").reach = true;
|
3026
|
+
delim("<!");
|
3027
|
+
delim("<!--");
|
3028
|
+
delim("-->");
|
3029
|
+
delim("(error)").reach = true;
|
3030
|
+
delim("}").reach = true;
|
3031
|
+
delim(")");
|
3032
|
+
delim("]");
|
3033
|
+
delim("\"").reach = true;
|
2872
3034
|
delim("'").reach = true;
|
2873
|
-
delim(
|
2874
|
-
delim(
|
2875
|
-
delim(
|
2876
|
-
delim(
|
2877
|
-
delim(
|
2878
|
-
reserve(
|
2879
|
-
reserve(
|
2880
|
-
reserve(
|
2881
|
-
reserve(
|
2882
|
-
reserve(
|
2883
|
-
reservevar(
|
2884
|
-
if (directive[
|
3035
|
+
delim(";");
|
3036
|
+
delim(":").reach = true;
|
3037
|
+
delim(",");
|
3038
|
+
delim("#");
|
3039
|
+
delim("@");
|
3040
|
+
reserve("else");
|
3041
|
+
reserve("case").reach = true;
|
3042
|
+
reserve("catch");
|
3043
|
+
reserve("default").reach = true;
|
3044
|
+
reserve("finally");
|
3045
|
+
reservevar("arguments", function (x) {
|
3046
|
+
if (directive["use strict"] && funct["(global)"]) {
|
2885
3047
|
warning("Strict violation.", x);
|
2886
3048
|
}
|
2887
3049
|
});
|
2888
|
-
reservevar(
|
2889
|
-
reservevar(
|
2890
|
-
reservevar(
|
2891
|
-
reservevar(
|
2892
|
-
reservevar(
|
2893
|
-
|
2894
|
-
|
2895
|
-
funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) {
|
3050
|
+
reservevar("eval");
|
3051
|
+
reservevar("false");
|
3052
|
+
reservevar("Infinity");
|
3053
|
+
reservevar("null");
|
3054
|
+
reservevar("this", function (x) {
|
3055
|
+
if (directive["use strict"] && !option.validthis && ((funct["(statement)"] &&
|
3056
|
+
funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
|
2896
3057
|
warning("Possible strict violation.", x);
|
2897
3058
|
}
|
2898
3059
|
});
|
2899
|
-
reservevar(
|
2900
|
-
reservevar(
|
2901
|
-
assignop(
|
2902
|
-
assignop(
|
2903
|
-
assignop(
|
2904
|
-
assignop(
|
2905
|
-
assignop(
|
3060
|
+
reservevar("true");
|
3061
|
+
reservevar("undefined");
|
3062
|
+
assignop("=", "assign", 20);
|
3063
|
+
assignop("+=", "assignadd", 20);
|
3064
|
+
assignop("-=", "assignsub", 20);
|
3065
|
+
assignop("*=", "assignmult", 20);
|
3066
|
+
assignop("/=", "assigndiv", 20).nud = function () {
|
2906
3067
|
error("A regular expression literal can be confused with '/='.");
|
2907
3068
|
};
|
2908
|
-
assignop(
|
2909
|
-
bitwiseassignop(
|
2910
|
-
bitwiseassignop(
|
2911
|
-
bitwiseassignop(
|
2912
|
-
bitwiseassignop(
|
2913
|
-
bitwiseassignop(
|
2914
|
-
bitwiseassignop(
|
2915
|
-
infix(
|
3069
|
+
assignop("%=", "assignmod", 20);
|
3070
|
+
bitwiseassignop("&=", "assignbitand", 20);
|
3071
|
+
bitwiseassignop("|=", "assignbitor", 20);
|
3072
|
+
bitwiseassignop("^=", "assignbitxor", 20);
|
3073
|
+
bitwiseassignop("<<=", "assignshiftleft", 20);
|
3074
|
+
bitwiseassignop(">>=", "assignshiftright", 20);
|
3075
|
+
bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
|
3076
|
+
infix("?", function (left, that) {
|
2916
3077
|
that.left = left;
|
2917
3078
|
that.right = expression(10);
|
2918
|
-
advance(
|
2919
|
-
that[
|
3079
|
+
advance(":");
|
3080
|
+
that["else"] = expression(10);
|
2920
3081
|
return that;
|
2921
3082
|
}, 30);
|
2922
3083
|
|
2923
|
-
infix(
|
2924
|
-
infix(
|
2925
|
-
bitwise(
|
2926
|
-
bitwise(
|
2927
|
-
bitwise(
|
2928
|
-
relation(
|
2929
|
-
var eqnull = option.eqnull && (left.value ===
|
3084
|
+
infix("||", "or", 40);
|
3085
|
+
infix("&&", "and", 50);
|
3086
|
+
bitwise("|", "bitor", 70);
|
3087
|
+
bitwise("^", "bitxor", 80);
|
3088
|
+
bitwise("&", "bitand", 90);
|
3089
|
+
relation("==", function (left, right) {
|
3090
|
+
var eqnull = option.eqnull && (left.value === "null" || right.value === "null");
|
2930
3091
|
|
2931
3092
|
if (!eqnull && option.eqeqeq)
|
2932
|
-
warning("Expected '{a}' and instead saw '{b}'.", this,
|
3093
|
+
warning("Expected '{a}' and instead saw '{b}'.", this, "===", "==");
|
2933
3094
|
else if (isPoorRelation(left))
|
2934
|
-
warning("Use '{a}' to compare with '{b}'.", this,
|
3095
|
+
warning("Use '{a}' to compare with '{b}'.", this, "===", left.value);
|
2935
3096
|
else if (isPoorRelation(right))
|
2936
|
-
warning("Use '{a}' to compare with '{b}'.", this,
|
3097
|
+
warning("Use '{a}' to compare with '{b}'.", this, "===", right.value);
|
2937
3098
|
|
2938
3099
|
return this;
|
2939
3100
|
});
|
2940
|
-
relation(
|
2941
|
-
relation(
|
3101
|
+
relation("===");
|
3102
|
+
relation("!=", function (left, right) {
|
2942
3103
|
var eqnull = option.eqnull &&
|
2943
|
-
(left.value ===
|
3104
|
+
(left.value === "null" || right.value === "null");
|
2944
3105
|
|
2945
3106
|
if (!eqnull && option.eqeqeq) {
|
2946
3107
|
warning("Expected '{a}' and instead saw '{b}'.",
|
2947
|
-
this,
|
3108
|
+
this, "!==", "!=");
|
2948
3109
|
} else if (isPoorRelation(left)) {
|
2949
3110
|
warning("Use '{a}' to compare with '{b}'.",
|
2950
|
-
this,
|
3111
|
+
this, "!==", left.value);
|
2951
3112
|
} else if (isPoorRelation(right)) {
|
2952
3113
|
warning("Use '{a}' to compare with '{b}'.",
|
2953
|
-
this,
|
3114
|
+
this, "!==", right.value);
|
2954
3115
|
}
|
2955
3116
|
return this;
|
2956
3117
|
});
|
2957
|
-
relation(
|
2958
|
-
relation(
|
2959
|
-
relation(
|
2960
|
-
relation(
|
2961
|
-
relation(
|
2962
|
-
bitwise(
|
2963
|
-
bitwise(
|
2964
|
-
bitwise(
|
2965
|
-
infix(
|
2966
|
-
infix(
|
2967
|
-
infix(
|
3118
|
+
relation("!==");
|
3119
|
+
relation("<");
|
3120
|
+
relation(">");
|
3121
|
+
relation("<=");
|
3122
|
+
relation(">=");
|
3123
|
+
bitwise("<<", "shiftleft", 120);
|
3124
|
+
bitwise(">>", "shiftright", 120);
|
3125
|
+
bitwise(">>>", "shiftrightunsigned", 120);
|
3126
|
+
infix("in", "in", 120);
|
3127
|
+
infix("instanceof", "instanceof", 120);
|
3128
|
+
infix("+", function (left, that) {
|
2968
3129
|
var right = expression(130);
|
2969
|
-
if (left && right && left.id ===
|
3130
|
+
if (left && right && left.id === "(string)" && right.id === "(string)") {
|
2970
3131
|
left.value += right.value;
|
2971
3132
|
left.character = right.character;
|
2972
3133
|
if (!option.scripturl && jx.test(left.value)) {
|
@@ -2978,102 +3139,102 @@ loop: for (;;) {
|
|
2978
3139
|
that.right = right;
|
2979
3140
|
return that;
|
2980
3141
|
}, 130);
|
2981
|
-
prefix(
|
2982
|
-
prefix(
|
3142
|
+
prefix("+", "num");
|
3143
|
+
prefix("+++", function () {
|
2983
3144
|
warning("Confusing pluses.");
|
2984
3145
|
this.right = expression(150);
|
2985
|
-
this.arity =
|
3146
|
+
this.arity = "unary";
|
2986
3147
|
return this;
|
2987
3148
|
});
|
2988
|
-
infix(
|
3149
|
+
infix("+++", function (left) {
|
2989
3150
|
warning("Confusing pluses.");
|
2990
3151
|
this.left = left;
|
2991
3152
|
this.right = expression(130);
|
2992
3153
|
return this;
|
2993
3154
|
}, 130);
|
2994
|
-
infix(
|
2995
|
-
prefix(
|
2996
|
-
prefix(
|
3155
|
+
infix("-", "sub", 130);
|
3156
|
+
prefix("-", "neg");
|
3157
|
+
prefix("---", function () {
|
2997
3158
|
warning("Confusing minuses.");
|
2998
3159
|
this.right = expression(150);
|
2999
|
-
this.arity =
|
3160
|
+
this.arity = "unary";
|
3000
3161
|
return this;
|
3001
3162
|
});
|
3002
|
-
infix(
|
3163
|
+
infix("---", function (left) {
|
3003
3164
|
warning("Confusing minuses.");
|
3004
3165
|
this.left = left;
|
3005
3166
|
this.right = expression(130);
|
3006
3167
|
return this;
|
3007
3168
|
}, 130);
|
3008
|
-
infix(
|
3009
|
-
infix(
|
3010
|
-
infix(
|
3011
|
-
|
3012
|
-
suffix(
|
3013
|
-
prefix(
|
3014
|
-
syntax[
|
3015
|
-
|
3016
|
-
suffix(
|
3017
|
-
prefix(
|
3018
|
-
syntax[
|
3019
|
-
prefix(
|
3169
|
+
infix("*", "mult", 140);
|
3170
|
+
infix("/", "div", 140);
|
3171
|
+
infix("%", "mod", 140);
|
3172
|
+
|
3173
|
+
suffix("++", "postinc");
|
3174
|
+
prefix("++", "preinc");
|
3175
|
+
syntax["++"].exps = true;
|
3176
|
+
|
3177
|
+
suffix("--", "postdec");
|
3178
|
+
prefix("--", "predec");
|
3179
|
+
syntax["--"].exps = true;
|
3180
|
+
prefix("delete", function () {
|
3020
3181
|
var p = expression(0);
|
3021
|
-
if (!p || (p.id !==
|
3182
|
+
if (!p || (p.id !== "." && p.id !== "[")) {
|
3022
3183
|
warning("Variables should not be deleted.");
|
3023
3184
|
}
|
3024
3185
|
this.first = p;
|
3025
3186
|
return this;
|
3026
3187
|
}).exps = true;
|
3027
3188
|
|
3028
|
-
prefix(
|
3189
|
+
prefix("~", function () {
|
3029
3190
|
if (option.bitwise) {
|
3030
|
-
warning("Unexpected '{a}'.", this,
|
3191
|
+
warning("Unexpected '{a}'.", this, "~");
|
3031
3192
|
}
|
3032
3193
|
expression(150);
|
3033
3194
|
return this;
|
3034
3195
|
});
|
3035
3196
|
|
3036
|
-
prefix(
|
3197
|
+
prefix("!", function () {
|
3037
3198
|
this.right = expression(150);
|
3038
|
-
this.arity =
|
3199
|
+
this.arity = "unary";
|
3039
3200
|
if (bang[this.right.id] === true) {
|
3040
|
-
warning("Confusing use of '{a}'.", this,
|
3201
|
+
warning("Confusing use of '{a}'.", this, "!");
|
3041
3202
|
}
|
3042
3203
|
return this;
|
3043
3204
|
});
|
3044
|
-
prefix(
|
3045
|
-
prefix(
|
3205
|
+
prefix("typeof", "typeof");
|
3206
|
+
prefix("new", function () {
|
3046
3207
|
var c = expression(155), i;
|
3047
|
-
if (c && c.id !==
|
3208
|
+
if (c && c.id !== "function") {
|
3048
3209
|
if (c.identifier) {
|
3049
|
-
c[
|
3210
|
+
c["new"] = true;
|
3050
3211
|
switch (c.value) {
|
3051
|
-
case
|
3052
|
-
case
|
3053
|
-
case
|
3054
|
-
case
|
3055
|
-
case
|
3056
|
-
warning("Do not use {a} as a constructor.",
|
3212
|
+
case "Number":
|
3213
|
+
case "String":
|
3214
|
+
case "Boolean":
|
3215
|
+
case "Math":
|
3216
|
+
case "JSON":
|
3217
|
+
warning("Do not use {a} as a constructor.", prevtoken, c.value);
|
3057
3218
|
break;
|
3058
|
-
case
|
3219
|
+
case "Function":
|
3059
3220
|
if (!option.evil) {
|
3060
3221
|
warning("The Function constructor is eval.");
|
3061
3222
|
}
|
3062
3223
|
break;
|
3063
|
-
case
|
3064
|
-
case
|
3224
|
+
case "Date":
|
3225
|
+
case "RegExp":
|
3065
3226
|
break;
|
3066
3227
|
default:
|
3067
|
-
if (c.id !==
|
3228
|
+
if (c.id !== "function") {
|
3068
3229
|
i = c.value.substr(0, 1);
|
3069
|
-
if (option.newcap && (i <
|
3230
|
+
if (option.newcap && (i < "A" || i > "Z") && !is_own(global, c.value)) {
|
3070
3231
|
warning("A constructor name should start with an uppercase letter.",
|
3071
3232
|
token);
|
3072
3233
|
}
|
3073
3234
|
}
|
3074
3235
|
}
|
3075
3236
|
} else {
|
3076
|
-
if (c.id !==
|
3237
|
+
if (c.id !== "." && c.id !== "[" && c.id !== "(") {
|
3077
3238
|
warning("Bad constructor.", token);
|
3078
3239
|
}
|
3079
3240
|
}
|
@@ -3082,46 +3243,47 @@ loop: for (;;) {
|
|
3082
3243
|
warning("Weird construction. Delete 'new'.", this);
|
3083
3244
|
}
|
3084
3245
|
adjacent(token, nexttoken);
|
3085
|
-
if (nexttoken.id !==
|
3086
|
-
warning("Missing '()' invoking a constructor."
|
3246
|
+
if (nexttoken.id !== "(" && !option.supernew) {
|
3247
|
+
warning("Missing '()' invoking a constructor.",
|
3248
|
+
token, token.value);
|
3087
3249
|
}
|
3088
3250
|
this.first = c;
|
3089
3251
|
return this;
|
3090
3252
|
});
|
3091
|
-
syntax[
|
3253
|
+
syntax["new"].exps = true;
|
3092
3254
|
|
3093
|
-
prefix(
|
3255
|
+
prefix("void").exps = true;
|
3094
3256
|
|
3095
|
-
infix(
|
3257
|
+
infix(".", function (left, that) {
|
3096
3258
|
adjacent(prevtoken, token);
|
3097
3259
|
nobreak();
|
3098
3260
|
var m = identifier();
|
3099
|
-
if (typeof m ===
|
3261
|
+
if (typeof m === "string") {
|
3100
3262
|
countMember(m);
|
3101
3263
|
}
|
3102
3264
|
that.left = left;
|
3103
3265
|
that.right = m;
|
3104
|
-
if (left && left.value ===
|
3266
|
+
if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
|
3105
3267
|
if (option.noarg)
|
3106
3268
|
warning("Avoid arguments.{a}.", left, m);
|
3107
|
-
else if (directive[
|
3108
|
-
error(
|
3109
|
-
} else if (!option.evil && left && left.value ===
|
3110
|
-
(m ===
|
3269
|
+
else if (directive["use strict"])
|
3270
|
+
error("Strict violation.");
|
3271
|
+
} else if (!option.evil && left && left.value === "document" &&
|
3272
|
+
(m === "write" || m === "writeln")) {
|
3111
3273
|
warning("document.write can be a form of eval.", left);
|
3112
3274
|
}
|
3113
|
-
if (!option.evil && (m ===
|
3114
|
-
warning(
|
3275
|
+
if (!option.evil && (m === "eval" || m === "execScript")) {
|
3276
|
+
warning("eval is evil.");
|
3115
3277
|
}
|
3116
3278
|
return that;
|
3117
3279
|
}, 160, true);
|
3118
3280
|
|
3119
|
-
infix(
|
3120
|
-
if (prevtoken.id !==
|
3281
|
+
infix("(", function (left, that) {
|
3282
|
+
if (prevtoken.id !== "}" && prevtoken.id !== ")") {
|
3121
3283
|
nobreak(prevtoken, token);
|
3122
3284
|
}
|
3123
3285
|
nospace();
|
3124
|
-
if (option.immed && !left.immed && left.id ===
|
3286
|
+
if (option.immed && !left.immed && left.id === "function") {
|
3125
3287
|
warning("Wrap an immediate function invocation in parentheses " +
|
3126
3288
|
"to assist the reader in understanding that the expression " +
|
3127
3289
|
"is the result of a function, and not the function itself.");
|
@@ -3129,51 +3291,63 @@ loop: for (;;) {
|
|
3129
3291
|
var n = 0,
|
3130
3292
|
p = [];
|
3131
3293
|
if (left) {
|
3132
|
-
if (left.type ===
|
3294
|
+
if (left.type === "(identifier)") {
|
3133
3295
|
if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
|
3134
|
-
if (
|
3135
|
-
|
3136
|
-
left.value !== 'Date') {
|
3137
|
-
if (left.value === 'Math') {
|
3296
|
+
if ("Number String Boolean Date Object".indexOf(left.value) === -1) {
|
3297
|
+
if (left.value === "Math") {
|
3138
3298
|
warning("Math is not a function.", left);
|
3139
3299
|
} else if (option.newcap) {
|
3140
|
-
warning(
|
3141
|
-
"Missing 'new' prefix when invoking a constructor.", left);
|
3300
|
+
warning("Missing 'new' prefix when invoking a constructor.", left);
|
3142
3301
|
}
|
3143
3302
|
}
|
3144
3303
|
}
|
3145
3304
|
}
|
3146
3305
|
}
|
3147
|
-
if (nexttoken.id !==
|
3306
|
+
if (nexttoken.id !== ")") {
|
3148
3307
|
for (;;) {
|
3149
3308
|
p[p.length] = expression(10);
|
3150
3309
|
n += 1;
|
3151
|
-
if (nexttoken.id !==
|
3310
|
+
if (nexttoken.id !== ",") {
|
3152
3311
|
break;
|
3153
3312
|
}
|
3154
3313
|
comma();
|
3155
3314
|
}
|
3156
3315
|
}
|
3157
|
-
advance(
|
3316
|
+
advance(")");
|
3158
3317
|
nospace(prevtoken, token);
|
3159
|
-
if (typeof left ===
|
3160
|
-
if (left.value ===
|
3161
|
-
warning("Missing radix parameter.",
|
3318
|
+
if (typeof left === "object") {
|
3319
|
+
if (left.value === "parseInt" && n === 1) {
|
3320
|
+
warning("Missing radix parameter.", token);
|
3162
3321
|
}
|
3163
3322
|
if (!option.evil) {
|
3164
|
-
if (left.value ===
|
3165
|
-
left.value ===
|
3323
|
+
if (left.value === "eval" || left.value === "Function" ||
|
3324
|
+
left.value === "execScript") {
|
3166
3325
|
warning("eval is evil.", left);
|
3167
|
-
|
3168
|
-
|
3169
|
-
left.value
|
3326
|
+
|
3327
|
+
if (p[0] && [0].id === "(string)") {
|
3328
|
+
addInternalSrc(left, p[0].value);
|
3329
|
+
}
|
3330
|
+
} else if (p[0] && p[0].id === "(string)" &&
|
3331
|
+
(left.value === "setTimeout" ||
|
3332
|
+
left.value === "setInterval")) {
|
3170
3333
|
warning(
|
3171
3334
|
"Implied eval is evil. Pass a function instead of a string.", left);
|
3335
|
+
addInternalSrc(left, p[0].value);
|
3336
|
+
|
3337
|
+
// window.setTimeout/setInterval
|
3338
|
+
} else if (p[0] && p[0].id === "(string)" &&
|
3339
|
+
left.value === "." &&
|
3340
|
+
left.left.value === "window" &&
|
3341
|
+
(left.right === "setTimeout" ||
|
3342
|
+
left.right === "setInterval")) {
|
3343
|
+
warning(
|
3344
|
+
"Implied eval is evil. Pass a function instead of a string.", left);
|
3345
|
+
addInternalSrc(left, p[0].value);
|
3172
3346
|
}
|
3173
3347
|
}
|
3174
|
-
if (!left.identifier && left.id !==
|
3175
|
-
left.id !==
|
3176
|
-
left.id !==
|
3348
|
+
if (!left.identifier && left.id !== "." && left.id !== "[" &&
|
3349
|
+
left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
|
3350
|
+
left.id !== "?") {
|
3177
3351
|
warning("Bad invocation.", left);
|
3178
3352
|
}
|
3179
3353
|
}
|
@@ -3181,34 +3355,32 @@ loop: for (;;) {
|
|
3181
3355
|
return that;
|
3182
3356
|
}, 155, true).exps = true;
|
3183
3357
|
|
3184
|
-
prefix(
|
3358
|
+
prefix("(", function () {
|
3185
3359
|
nospace();
|
3186
|
-
if (nexttoken.id ===
|
3360
|
+
if (nexttoken.id === "function") {
|
3187
3361
|
nexttoken.immed = true;
|
3188
3362
|
}
|
3189
3363
|
var v = expression(0);
|
3190
|
-
advance(
|
3364
|
+
advance(")", this);
|
3191
3365
|
nospace(prevtoken, token);
|
3192
|
-
if (option.immed && v.id ===
|
3193
|
-
if (nexttoken.id
|
3194
|
-
(nexttoken.id
|
3195
|
-
warning(
|
3196
|
-
"Move the invocation into the parens that contain the function.", nexttoken);
|
3197
|
-
} else {
|
3366
|
+
if (option.immed && v.id === "function") {
|
3367
|
+
if (nexttoken.id !== "(" &&
|
3368
|
+
(nexttoken.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
|
3198
3369
|
warning(
|
3199
3370
|
"Do not wrap function literals in parens unless they are to be immediately invoked.",
|
3200
3371
|
this);
|
3201
3372
|
}
|
3202
3373
|
}
|
3374
|
+
|
3203
3375
|
return v;
|
3204
3376
|
});
|
3205
3377
|
|
3206
|
-
infix(
|
3378
|
+
infix("[", function (left, that) {
|
3207
3379
|
nobreak(prevtoken, token);
|
3208
3380
|
nospace();
|
3209
3381
|
var e = expression(0), s;
|
3210
|
-
if (e && e.type ===
|
3211
|
-
if (!option.evil && (e.value ===
|
3382
|
+
if (e && e.type === "(string)") {
|
3383
|
+
if (!option.evil && (e.value === "eval" || e.value === "execScript")) {
|
3212
3384
|
warning("eval is evil.", that);
|
3213
3385
|
}
|
3214
3386
|
countMember(e.value);
|
@@ -3216,18 +3388,18 @@ loop: for (;;) {
|
|
3216
3388
|
s = syntax[e.value];
|
3217
3389
|
if (!s || !s.reserved) {
|
3218
3390
|
warning("['{a}'] is better written in dot notation.",
|
3219
|
-
|
3391
|
+
prevtoken, e.value);
|
3220
3392
|
}
|
3221
3393
|
}
|
3222
3394
|
}
|
3223
|
-
advance(
|
3395
|
+
advance("]", that);
|
3224
3396
|
nospace(prevtoken, token);
|
3225
3397
|
that.left = left;
|
3226
3398
|
that.right = e;
|
3227
3399
|
return that;
|
3228
3400
|
}, 160, true);
|
3229
3401
|
|
3230
|
-
prefix(
|
3402
|
+
prefix("[", function () {
|
3231
3403
|
var b = token.line !== nexttoken.line;
|
3232
3404
|
this.first = [];
|
3233
3405
|
if (b) {
|
@@ -3236,21 +3408,21 @@ loop: for (;;) {
|
|
3236
3408
|
indent += option.indent;
|
3237
3409
|
}
|
3238
3410
|
}
|
3239
|
-
while (nexttoken.id !==
|
3240
|
-
while (nexttoken.id ===
|
3411
|
+
while (nexttoken.id !== "(end)") {
|
3412
|
+
while (nexttoken.id === ",") {
|
3241
3413
|
warning("Extra comma.");
|
3242
|
-
advance(
|
3414
|
+
advance(",");
|
3243
3415
|
}
|
3244
|
-
if (nexttoken.id ===
|
3416
|
+
if (nexttoken.id === "]") {
|
3245
3417
|
break;
|
3246
3418
|
}
|
3247
3419
|
if (b && token.line !== nexttoken.line) {
|
3248
3420
|
indentation();
|
3249
3421
|
}
|
3250
3422
|
this.first.push(expression(10));
|
3251
|
-
if (nexttoken.id ===
|
3423
|
+
if (nexttoken.id === ",") {
|
3252
3424
|
comma();
|
3253
|
-
if (nexttoken.id ===
|
3425
|
+
if (nexttoken.id === "]" && !option.es5) {
|
3254
3426
|
warning("Extra comma.", token);
|
3255
3427
|
break;
|
3256
3428
|
}
|
@@ -3262,7 +3434,7 @@ loop: for (;;) {
|
|
3262
3434
|
indent -= option.indent;
|
3263
3435
|
indentation();
|
3264
3436
|
}
|
3265
|
-
advance(
|
3437
|
+
advance("]", this);
|
3266
3438
|
return this;
|
3267
3439
|
}, 160);
|
3268
3440
|
|
@@ -3270,10 +3442,10 @@ loop: for (;;) {
|
|
3270
3442
|
function property_name() {
|
3271
3443
|
var id = optionalidentifier(true);
|
3272
3444
|
if (!id) {
|
3273
|
-
if (nexttoken.id ===
|
3445
|
+
if (nexttoken.id === "(string)") {
|
3274
3446
|
id = nexttoken.value;
|
3275
3447
|
advance();
|
3276
|
-
} else if (nexttoken.id ===
|
3448
|
+
} else if (nexttoken.id === "(number)") {
|
3277
3449
|
id = nexttoken.value.toString();
|
3278
3450
|
advance();
|
3279
3451
|
}
|
@@ -3283,23 +3455,28 @@ loop: for (;;) {
|
|
3283
3455
|
|
3284
3456
|
|
3285
3457
|
function functionparams() {
|
3286
|
-
var
|
3287
|
-
|
3458
|
+
var next = nexttoken;
|
3459
|
+
var params = [];
|
3460
|
+
var ident;
|
3461
|
+
|
3462
|
+
advance("(");
|
3288
3463
|
nospace();
|
3289
|
-
|
3290
|
-
|
3464
|
+
|
3465
|
+
if (nexttoken.id === ")") {
|
3466
|
+
advance(")");
|
3291
3467
|
return;
|
3292
3468
|
}
|
3469
|
+
|
3293
3470
|
for (;;) {
|
3294
|
-
|
3295
|
-
|
3296
|
-
addlabel(
|
3297
|
-
if (nexttoken.id ===
|
3471
|
+
ident = identifier(true);
|
3472
|
+
params.push(ident);
|
3473
|
+
addlabel(ident, "unused", token);
|
3474
|
+
if (nexttoken.id === ",") {
|
3298
3475
|
comma();
|
3299
3476
|
} else {
|
3300
|
-
advance(
|
3477
|
+
advance(")", next);
|
3301
3478
|
nospace(prevtoken, token);
|
3302
|
-
return
|
3479
|
+
return params;
|
3303
3480
|
}
|
3304
3481
|
}
|
3305
3482
|
}
|
@@ -3314,34 +3491,88 @@ loop: for (;;) {
|
|
3314
3491
|
scope = Object.create(scope);
|
3315
3492
|
|
3316
3493
|
funct = {
|
3317
|
-
|
3318
|
-
|
3319
|
-
|
3320
|
-
|
3321
|
-
|
3322
|
-
|
3323
|
-
|
3494
|
+
"(name)" : i || "\"" + anonname + "\"",
|
3495
|
+
"(line)" : nexttoken.line,
|
3496
|
+
"(character)": nexttoken.character,
|
3497
|
+
"(context)" : funct,
|
3498
|
+
"(breakage)" : 0,
|
3499
|
+
"(loopage)" : 0,
|
3500
|
+
"(metrics)" : createMetrics(nexttoken),
|
3501
|
+
"(scope)" : scope,
|
3502
|
+
"(statement)": statement,
|
3503
|
+
"(tokens)" : {}
|
3324
3504
|
};
|
3325
3505
|
f = funct;
|
3326
3506
|
token.funct = funct;
|
3327
3507
|
functions.push(funct);
|
3328
3508
|
if (i) {
|
3329
|
-
addlabel(i,
|
3509
|
+
addlabel(i, "function");
|
3330
3510
|
}
|
3331
|
-
funct[
|
3511
|
+
funct["(params)"] = functionparams();
|
3512
|
+
funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
|
3332
3513
|
|
3333
3514
|
block(false, false, true);
|
3515
|
+
|
3516
|
+
funct["(metrics)"].verifyMaxStatementsPerFunction();
|
3517
|
+
funct["(metrics)"].verifyMaxComplexityPerFunction();
|
3518
|
+
|
3334
3519
|
scope = oldScope;
|
3335
3520
|
option = oldOption;
|
3336
|
-
funct[
|
3337
|
-
funct
|
3521
|
+
funct["(last)"] = token.line;
|
3522
|
+
funct["(lastcharacter)"] = token.character;
|
3523
|
+
funct = funct["(context)"];
|
3338
3524
|
return f;
|
3339
3525
|
}
|
3340
3526
|
|
3527
|
+
function createMetrics(functionStartToken) {
|
3528
|
+
return {
|
3529
|
+
statementCount: 0,
|
3530
|
+
nestedBlockDepth: -1,
|
3531
|
+
ComplexityCount: 1,
|
3532
|
+
verifyMaxStatementsPerFunction: function () {
|
3533
|
+
if (option.maxstatements &&
|
3534
|
+
this.statementCount > option.maxstatements) {
|
3535
|
+
var message = "Too many statements per function (" + this.statementCount + ").";
|
3536
|
+
warning(message, functionStartToken);
|
3537
|
+
}
|
3538
|
+
},
|
3539
|
+
|
3540
|
+
verifyMaxParametersPerFunction: function (parameters) {
|
3541
|
+
if (option.maxparams &&
|
3542
|
+
parameters.length > option.maxparams) {
|
3543
|
+
var message = "Too many parameters per function (" + parameters.length + ").";
|
3544
|
+
warning(message, functionStartToken);
|
3545
|
+
}
|
3546
|
+
},
|
3547
|
+
|
3548
|
+
verifyMaxNestedBlockDepthPerFunction: function () {
|
3549
|
+
if (option.maxdepth &&
|
3550
|
+
this.nestedBlockDepth > 0 &&
|
3551
|
+
this.nestedBlockDepth === option.maxdepth + 1) {
|
3552
|
+
var message = "Blocks are nested too deeply (" + this.nestedBlockDepth + ").";
|
3553
|
+
warning(message);
|
3554
|
+
}
|
3555
|
+
},
|
3556
|
+
|
3557
|
+
verifyMaxComplexityPerFunction: function () {
|
3558
|
+
var max = option.maxcomplexity;
|
3559
|
+
var cc = this.ComplexityCount;
|
3560
|
+
if (max && cc > max) {
|
3561
|
+
var message = "Cyclomatic complexity is too high per function (" + cc + ").";
|
3562
|
+
warning(message, functionStartToken);
|
3563
|
+
}
|
3564
|
+
}
|
3565
|
+
};
|
3566
|
+
}
|
3567
|
+
|
3568
|
+
function increaseComplexityCount() {
|
3569
|
+
funct["(metrics)"].ComplexityCount += 1;
|
3570
|
+
}
|
3571
|
+
|
3341
3572
|
|
3342
3573
|
(function (x) {
|
3343
3574
|
x.nud = function () {
|
3344
|
-
var b, f, i,
|
3575
|
+
var b, f, i, p, t;
|
3345
3576
|
var props = {}; // All properties, including accessors
|
3346
3577
|
|
3347
3578
|
function saveProperty(name, token) {
|
@@ -3386,14 +3617,14 @@ loop: for (;;) {
|
|
3386
3617
|
}
|
3387
3618
|
}
|
3388
3619
|
for (;;) {
|
3389
|
-
if (nexttoken.id ===
|
3620
|
+
if (nexttoken.id === "}") {
|
3390
3621
|
break;
|
3391
3622
|
}
|
3392
3623
|
if (b) {
|
3393
3624
|
indentation();
|
3394
3625
|
}
|
3395
|
-
if (nexttoken.value ===
|
3396
|
-
advance(
|
3626
|
+
if (nexttoken.value === "get" && peek().id !== ":") {
|
3627
|
+
advance("get");
|
3397
3628
|
if (!option.es5) {
|
3398
3629
|
error("get/set are ES5 features.");
|
3399
3630
|
}
|
@@ -3405,13 +3636,13 @@ loop: for (;;) {
|
|
3405
3636
|
t = nexttoken;
|
3406
3637
|
adjacent(token, nexttoken);
|
3407
3638
|
f = doFunction();
|
3408
|
-
p = f[
|
3639
|
+
p = f["(params)"];
|
3409
3640
|
if (p) {
|
3410
3641
|
warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i);
|
3411
3642
|
}
|
3412
3643
|
adjacent(token, nexttoken);
|
3413
|
-
} else if (nexttoken.value ===
|
3414
|
-
advance(
|
3644
|
+
} else if (nexttoken.value === "set" && peek().id !== ":") {
|
3645
|
+
advance("set");
|
3415
3646
|
if (!option.es5) {
|
3416
3647
|
error("get/set are ES5 features.");
|
3417
3648
|
}
|
@@ -3423,27 +3654,27 @@ loop: for (;;) {
|
|
3423
3654
|
t = nexttoken;
|
3424
3655
|
adjacent(token, nexttoken);
|
3425
3656
|
f = doFunction();
|
3426
|
-
p = f[
|
3657
|
+
p = f["(params)"];
|
3427
3658
|
if (!p || p.length !== 1) {
|
3428
3659
|
warning("Expected a single parameter in set {a} function.", t, i);
|
3429
3660
|
}
|
3430
3661
|
} else {
|
3431
3662
|
i = property_name();
|
3432
3663
|
saveProperty(i, nexttoken);
|
3433
|
-
if (typeof i !==
|
3664
|
+
if (typeof i !== "string") {
|
3434
3665
|
break;
|
3435
3666
|
}
|
3436
|
-
advance(
|
3667
|
+
advance(":");
|
3437
3668
|
nonadjacent(token, nexttoken);
|
3438
3669
|
expression(10);
|
3439
3670
|
}
|
3440
3671
|
|
3441
3672
|
countMember(i);
|
3442
|
-
if (nexttoken.id ===
|
3673
|
+
if (nexttoken.id === ",") {
|
3443
3674
|
comma();
|
3444
|
-
if (nexttoken.id ===
|
3675
|
+
if (nexttoken.id === ",") {
|
3445
3676
|
warning("Extra comma.", token);
|
3446
|
-
} else if (nexttoken.id ===
|
3677
|
+
} else if (nexttoken.id === "}" && !option.es5) {
|
3447
3678
|
warning("Extra comma.", token);
|
3448
3679
|
}
|
3449
3680
|
} else {
|
@@ -3454,7 +3685,7 @@ loop: for (;;) {
|
|
3454
3685
|
indent -= option.indent;
|
3455
3686
|
indentation();
|
3456
3687
|
}
|
3457
|
-
advance(
|
3688
|
+
advance("}", this);
|
3458
3689
|
|
3459
3690
|
// Check for lonely setters if in the ES5 mode.
|
3460
3691
|
if (option.es5) {
|
@@ -3469,13 +3700,13 @@ loop: for (;;) {
|
|
3469
3700
|
x.fud = function () {
|
3470
3701
|
error("Expected to see a statement and instead saw a block.", token);
|
3471
3702
|
};
|
3472
|
-
}(delim(
|
3703
|
+
}(delim("{")));
|
3473
3704
|
|
3474
3705
|
// This Function is called when esnext option is set to true
|
3475
3706
|
// it adds the `const` statement to JSHINT
|
3476
3707
|
|
3477
3708
|
useESNextSyntax = function () {
|
3478
|
-
var conststatement = stmt(
|
3709
|
+
var conststatement = stmt("const", function (prefix) {
|
3479
3710
|
var id, name, value;
|
3480
3711
|
|
3481
3712
|
this.first = [];
|
@@ -3485,10 +3716,10 @@ loop: for (;;) {
|
|
3485
3716
|
if (funct[id] === "const") {
|
3486
3717
|
warning("const '" + id + "' has already been declared");
|
3487
3718
|
}
|
3488
|
-
if (funct[
|
3719
|
+
if (funct["(global)"] && predefined[id] === false) {
|
3489
3720
|
warning("Redefinition of '{a}'.", token, id);
|
3490
3721
|
}
|
3491
|
-
addlabel(id,
|
3722
|
+
addlabel(id, "const");
|
3492
3723
|
if (prefix) {
|
3493
3724
|
break;
|
3494
3725
|
}
|
@@ -3500,15 +3731,15 @@ loop: for (;;) {
|
|
3500
3731
|
"'{a}' is initialized to 'undefined'.", token, id);
|
3501
3732
|
}
|
3502
3733
|
|
3503
|
-
if (nexttoken.id ===
|
3734
|
+
if (nexttoken.id === "=") {
|
3504
3735
|
nonadjacent(token, nexttoken);
|
3505
|
-
advance(
|
3736
|
+
advance("=");
|
3506
3737
|
nonadjacent(token, nexttoken);
|
3507
|
-
if (nexttoken.id ===
|
3738
|
+
if (nexttoken.id === "undefined") {
|
3508
3739
|
warning("It is not necessary to initialize " +
|
3509
3740
|
"'{a}' to 'undefined'.", token, id);
|
3510
3741
|
}
|
3511
|
-
if (peek(0).id ===
|
3742
|
+
if (peek(0).id === "=" && nexttoken.identifier) {
|
3512
3743
|
error("Constant {a} was not declared correctly.",
|
3513
3744
|
nexttoken, nexttoken.value);
|
3514
3745
|
}
|
@@ -3516,7 +3747,7 @@ loop: for (;;) {
|
|
3516
3747
|
name.first = value;
|
3517
3748
|
}
|
3518
3749
|
|
3519
|
-
if (nexttoken.id !==
|
3750
|
+
if (nexttoken.id !== ",") {
|
3520
3751
|
break;
|
3521
3752
|
}
|
3522
3753
|
comma();
|
@@ -3526,47 +3757,55 @@ loop: for (;;) {
|
|
3526
3757
|
conststatement.exps = true;
|
3527
3758
|
};
|
3528
3759
|
|
3529
|
-
var varstatement = stmt(
|
3760
|
+
var varstatement = stmt("var", function (prefix) {
|
3530
3761
|
// JavaScript does not have block scope. It only has function scope. So,
|
3531
3762
|
// declaring a variable in a block can have unexpected consequences.
|
3532
3763
|
var id, name, value;
|
3533
3764
|
|
3534
|
-
if (funct[
|
3765
|
+
if (funct["(onevar)"] && option.onevar) {
|
3535
3766
|
warning("Too many var statements.");
|
3536
|
-
} else if (!funct[
|
3537
|
-
funct[
|
3767
|
+
} else if (!funct["(global)"]) {
|
3768
|
+
funct["(onevar)"] = true;
|
3538
3769
|
}
|
3770
|
+
|
3539
3771
|
this.first = [];
|
3772
|
+
|
3540
3773
|
for (;;) {
|
3541
3774
|
nonadjacent(token, nexttoken);
|
3542
3775
|
id = identifier();
|
3776
|
+
|
3543
3777
|
if (option.esnext && funct[id] === "const") {
|
3544
3778
|
warning("const '" + id + "' has already been declared");
|
3545
3779
|
}
|
3546
|
-
|
3780
|
+
|
3781
|
+
if (funct["(global)"] && predefined[id] === false) {
|
3547
3782
|
warning("Redefinition of '{a}'.", token, id);
|
3548
3783
|
}
|
3549
|
-
|
3784
|
+
|
3785
|
+
addlabel(id, "unused", token);
|
3786
|
+
|
3550
3787
|
if (prefix) {
|
3551
3788
|
break;
|
3552
3789
|
}
|
3790
|
+
|
3553
3791
|
name = token;
|
3554
3792
|
this.first.push(token);
|
3555
|
-
|
3793
|
+
|
3794
|
+
if (nexttoken.id === "=") {
|
3556
3795
|
nonadjacent(token, nexttoken);
|
3557
|
-
advance(
|
3796
|
+
advance("=");
|
3558
3797
|
nonadjacent(token, nexttoken);
|
3559
|
-
if (nexttoken.id ===
|
3798
|
+
if (nexttoken.id === "undefined") {
|
3560
3799
|
warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id);
|
3561
3800
|
}
|
3562
|
-
if (peek(0).id ===
|
3801
|
+
if (peek(0).id === "=" && nexttoken.identifier) {
|
3563
3802
|
error("Variable {a} was not declared correctly.",
|
3564
3803
|
nexttoken, nexttoken.value);
|
3565
3804
|
}
|
3566
3805
|
value = expression(0);
|
3567
3806
|
name.first = value;
|
3568
3807
|
}
|
3569
|
-
if (nexttoken.id !==
|
3808
|
+
if (nexttoken.id !== ",") {
|
3570
3809
|
break;
|
3571
3810
|
}
|
3572
3811
|
comma();
|
@@ -3575,7 +3814,7 @@ loop: for (;;) {
|
|
3575
3814
|
});
|
3576
3815
|
varstatement.exps = true;
|
3577
3816
|
|
3578
|
-
blockstmt(
|
3817
|
+
blockstmt("function", function () {
|
3579
3818
|
if (inblock) {
|
3580
3819
|
warning("Function declarations should not be placed in blocks. " +
|
3581
3820
|
"Use a function expression or move the statement to the top of " +
|
@@ -3587,16 +3826,17 @@ loop: for (;;) {
|
|
3587
3826
|
warning("const '" + i + "' has already been declared");
|
3588
3827
|
}
|
3589
3828
|
adjacent(token, nexttoken);
|
3590
|
-
addlabel(i,
|
3829
|
+
addlabel(i, "unction", token);
|
3830
|
+
|
3591
3831
|
doFunction(i, true);
|
3592
|
-
if (nexttoken.id ===
|
3832
|
+
if (nexttoken.id === "(" && nexttoken.line === token.line) {
|
3593
3833
|
error(
|
3594
3834
|
"Function declarations are not invocable. Wrap the whole function invocation in parens.");
|
3595
3835
|
}
|
3596
3836
|
return this;
|
3597
3837
|
});
|
3598
3838
|
|
3599
|
-
prefix(
|
3839
|
+
prefix("function", function () {
|
3600
3840
|
var i = optionalidentifier();
|
3601
3841
|
if (i) {
|
3602
3842
|
adjacent(token, nexttoken);
|
@@ -3604,31 +3844,32 @@ loop: for (;;) {
|
|
3604
3844
|
nonadjacent(token, nexttoken);
|
3605
3845
|
}
|
3606
3846
|
doFunction(i);
|
3607
|
-
if (!option.loopfunc && funct[
|
3847
|
+
if (!option.loopfunc && funct["(loopage)"]) {
|
3608
3848
|
warning("Don't make functions within a loop.");
|
3609
3849
|
}
|
3610
3850
|
return this;
|
3611
3851
|
});
|
3612
3852
|
|
3613
|
-
blockstmt(
|
3853
|
+
blockstmt("if", function () {
|
3614
3854
|
var t = nexttoken;
|
3615
|
-
|
3855
|
+
increaseComplexityCount();
|
3856
|
+
advance("(");
|
3616
3857
|
nonadjacent(this, t);
|
3617
3858
|
nospace();
|
3618
3859
|
expression(20);
|
3619
|
-
if (nexttoken.id ===
|
3860
|
+
if (nexttoken.id === "=") {
|
3620
3861
|
if (!option.boss)
|
3621
3862
|
warning("Expected a conditional expression and instead saw an assignment.");
|
3622
|
-
advance(
|
3863
|
+
advance("=");
|
3623
3864
|
expression(20);
|
3624
3865
|
}
|
3625
|
-
advance(
|
3866
|
+
advance(")", t);
|
3626
3867
|
nospace(prevtoken, token);
|
3627
3868
|
block(true, true);
|
3628
|
-
if (nexttoken.id ===
|
3869
|
+
if (nexttoken.id === "else") {
|
3629
3870
|
nonadjacent(token, nexttoken);
|
3630
|
-
advance(
|
3631
|
-
if (nexttoken.id ===
|
3871
|
+
advance("else");
|
3872
|
+
if (nexttoken.id === "if" || nexttoken.id === "switch") {
|
3632
3873
|
statement(true);
|
3633
3874
|
} else {
|
3634
3875
|
block(true, true);
|
@@ -3637,107 +3878,109 @@ loop: for (;;) {
|
|
3637
3878
|
return this;
|
3638
3879
|
});
|
3639
3880
|
|
3640
|
-
blockstmt(
|
3881
|
+
blockstmt("try", function () {
|
3641
3882
|
var b, e, s;
|
3642
3883
|
|
3643
3884
|
block(false);
|
3644
|
-
if (nexttoken.id ===
|
3645
|
-
|
3885
|
+
if (nexttoken.id === "catch") {
|
3886
|
+
increaseComplexityCount();
|
3887
|
+
advance("catch");
|
3646
3888
|
nonadjacent(token, nexttoken);
|
3647
|
-
advance(
|
3889
|
+
advance("(");
|
3648
3890
|
s = scope;
|
3649
3891
|
scope = Object.create(s);
|
3650
3892
|
e = nexttoken.value;
|
3651
|
-
if (nexttoken.type !==
|
3893
|
+
if (nexttoken.type !== "(identifier)") {
|
3652
3894
|
warning("Expected an identifier and instead saw '{a}'.",
|
3653
3895
|
nexttoken, e);
|
3654
3896
|
} else {
|
3655
|
-
addlabel(e,
|
3897
|
+
addlabel(e, "exception");
|
3656
3898
|
}
|
3657
3899
|
advance();
|
3658
|
-
advance(
|
3900
|
+
advance(")");
|
3659
3901
|
block(false);
|
3660
3902
|
b = true;
|
3661
3903
|
scope = s;
|
3662
3904
|
}
|
3663
|
-
if (nexttoken.id ===
|
3664
|
-
advance(
|
3905
|
+
if (nexttoken.id === "finally") {
|
3906
|
+
advance("finally");
|
3665
3907
|
block(false);
|
3666
3908
|
return;
|
3667
3909
|
} else if (!b) {
|
3668
3910
|
error("Expected '{a}' and instead saw '{b}'.",
|
3669
|
-
nexttoken,
|
3911
|
+
nexttoken, "catch", nexttoken.value);
|
3670
3912
|
}
|
3671
3913
|
return this;
|
3672
3914
|
});
|
3673
3915
|
|
3674
|
-
blockstmt(
|
3916
|
+
blockstmt("while", function () {
|
3675
3917
|
var t = nexttoken;
|
3676
|
-
funct[
|
3677
|
-
funct[
|
3678
|
-
|
3918
|
+
funct["(breakage)"] += 1;
|
3919
|
+
funct["(loopage)"] += 1;
|
3920
|
+
increaseComplexityCount();
|
3921
|
+
advance("(");
|
3679
3922
|
nonadjacent(this, t);
|
3680
3923
|
nospace();
|
3681
3924
|
expression(20);
|
3682
|
-
if (nexttoken.id ===
|
3925
|
+
if (nexttoken.id === "=") {
|
3683
3926
|
if (!option.boss)
|
3684
3927
|
warning("Expected a conditional expression and instead saw an assignment.");
|
3685
|
-
advance(
|
3928
|
+
advance("=");
|
3686
3929
|
expression(20);
|
3687
3930
|
}
|
3688
|
-
advance(
|
3931
|
+
advance(")", t);
|
3689
3932
|
nospace(prevtoken, token);
|
3690
3933
|
block(true, true);
|
3691
|
-
funct[
|
3692
|
-
funct[
|
3934
|
+
funct["(breakage)"] -= 1;
|
3935
|
+
funct["(loopage)"] -= 1;
|
3693
3936
|
return this;
|
3694
3937
|
}).labelled = true;
|
3695
3938
|
|
3696
|
-
blockstmt(
|
3939
|
+
blockstmt("with", function () {
|
3697
3940
|
var t = nexttoken;
|
3698
|
-
if (directive[
|
3941
|
+
if (directive["use strict"]) {
|
3699
3942
|
error("'with' is not allowed in strict mode.", token);
|
3700
3943
|
} else if (!option.withstmt) {
|
3701
3944
|
warning("Don't use 'with'.", token);
|
3702
3945
|
}
|
3703
3946
|
|
3704
|
-
advance(
|
3947
|
+
advance("(");
|
3705
3948
|
nonadjacent(this, t);
|
3706
3949
|
nospace();
|
3707
3950
|
expression(0);
|
3708
|
-
advance(
|
3951
|
+
advance(")", t);
|
3709
3952
|
nospace(prevtoken, token);
|
3710
3953
|
block(true, true);
|
3711
3954
|
|
3712
3955
|
return this;
|
3713
3956
|
});
|
3714
3957
|
|
3715
|
-
blockstmt(
|
3958
|
+
blockstmt("switch", function () {
|
3716
3959
|
var t = nexttoken,
|
3717
3960
|
g = false;
|
3718
|
-
funct[
|
3719
|
-
advance(
|
3961
|
+
funct["(breakage)"] += 1;
|
3962
|
+
advance("(");
|
3720
3963
|
nonadjacent(this, t);
|
3721
3964
|
nospace();
|
3722
3965
|
this.condition = expression(20);
|
3723
|
-
advance(
|
3966
|
+
advance(")", t);
|
3724
3967
|
nospace(prevtoken, token);
|
3725
3968
|
nonadjacent(token, nexttoken);
|
3726
3969
|
t = nexttoken;
|
3727
|
-
advance(
|
3970
|
+
advance("{");
|
3728
3971
|
nonadjacent(token, nexttoken);
|
3729
3972
|
indent += option.indent;
|
3730
3973
|
this.cases = [];
|
3731
3974
|
for (;;) {
|
3732
3975
|
switch (nexttoken.id) {
|
3733
|
-
case
|
3734
|
-
switch (funct[
|
3735
|
-
case
|
3736
|
-
case
|
3737
|
-
case
|
3738
|
-
case
|
3739
|
-
case
|
3740
|
-
case
|
3976
|
+
case "case":
|
3977
|
+
switch (funct["(verb)"]) {
|
3978
|
+
case "break":
|
3979
|
+
case "case":
|
3980
|
+
case "continue":
|
3981
|
+
case "return":
|
3982
|
+
case "switch":
|
3983
|
+
case "throw":
|
3741
3984
|
break;
|
3742
3985
|
default:
|
3743
3986
|
// You can tell JSHint that you don't use break intentionally by
|
@@ -3750,18 +3993,19 @@ loop: for (;;) {
|
|
3750
3993
|
}
|
3751
3994
|
}
|
3752
3995
|
indentation(-option.indent);
|
3753
|
-
advance(
|
3996
|
+
advance("case");
|
3754
3997
|
this.cases.push(expression(20));
|
3998
|
+
increaseComplexityCount();
|
3755
3999
|
g = true;
|
3756
|
-
advance(
|
3757
|
-
funct[
|
4000
|
+
advance(":");
|
4001
|
+
funct["(verb)"] = "case";
|
3758
4002
|
break;
|
3759
|
-
case
|
3760
|
-
switch (funct[
|
3761
|
-
case
|
3762
|
-
case
|
3763
|
-
case
|
3764
|
-
case
|
4003
|
+
case "default":
|
4004
|
+
switch (funct["(verb)"]) {
|
4005
|
+
case "break":
|
4006
|
+
case "continue":
|
4007
|
+
case "return":
|
4008
|
+
case "throw":
|
3765
4009
|
break;
|
3766
4010
|
default:
|
3767
4011
|
if (!ft.test(lines[nexttoken.line - 2])) {
|
@@ -3771,32 +4015,32 @@ loop: for (;;) {
|
|
3771
4015
|
}
|
3772
4016
|
}
|
3773
4017
|
indentation(-option.indent);
|
3774
|
-
advance(
|
4018
|
+
advance("default");
|
3775
4019
|
g = true;
|
3776
|
-
advance(
|
4020
|
+
advance(":");
|
3777
4021
|
break;
|
3778
|
-
case
|
4022
|
+
case "}":
|
3779
4023
|
indent -= option.indent;
|
3780
4024
|
indentation();
|
3781
|
-
advance(
|
3782
|
-
if (this.cases.length === 1 || this.condition.id ===
|
3783
|
-
this.condition.id ===
|
4025
|
+
advance("}", t);
|
4026
|
+
if (this.cases.length === 1 || this.condition.id === "true" ||
|
4027
|
+
this.condition.id === "false") {
|
3784
4028
|
if (!option.onecase)
|
3785
4029
|
warning("This 'switch' should be an 'if'.", this);
|
3786
4030
|
}
|
3787
|
-
funct[
|
3788
|
-
funct[
|
4031
|
+
funct["(breakage)"] -= 1;
|
4032
|
+
funct["(verb)"] = undefined;
|
3789
4033
|
return;
|
3790
|
-
case
|
3791
|
-
error("Missing '{a}'.", nexttoken,
|
4034
|
+
case "(end)":
|
4035
|
+
error("Missing '{a}'.", nexttoken, "}");
|
3792
4036
|
return;
|
3793
4037
|
default:
|
3794
4038
|
if (g) {
|
3795
4039
|
switch (token.id) {
|
3796
|
-
case
|
4040
|
+
case ",":
|
3797
4041
|
error("Each value should have its own case label.");
|
3798
4042
|
return;
|
3799
|
-
case
|
4043
|
+
case ":":
|
3800
4044
|
g = false;
|
3801
4045
|
statements();
|
3802
4046
|
break;
|
@@ -3805,13 +4049,13 @@ loop: for (;;) {
|
|
3805
4049
|
return;
|
3806
4050
|
}
|
3807
4051
|
} else {
|
3808
|
-
if (token.id ===
|
3809
|
-
advance(
|
3810
|
-
error("Unexpected '{a}'.", token,
|
4052
|
+
if (token.id === ":") {
|
4053
|
+
advance(":");
|
4054
|
+
error("Unexpected '{a}'.", token, ":");
|
3811
4055
|
statements();
|
3812
4056
|
} else {
|
3813
4057
|
error("Expected '{a}' and instead saw '{b}'.",
|
3814
|
-
nexttoken,
|
4058
|
+
nexttoken, "case", nexttoken.value);
|
3815
4059
|
return;
|
3816
4060
|
}
|
3817
4061
|
}
|
@@ -3819,7 +4063,7 @@ loop: for (;;) {
|
|
3819
4063
|
}
|
3820
4064
|
}).labelled = true;
|
3821
4065
|
|
3822
|
-
stmt(
|
4066
|
+
stmt("debugger", function () {
|
3823
4067
|
if (!option.debug) {
|
3824
4068
|
warning("All 'debugger' statements should be removed.");
|
3825
4069
|
}
|
@@ -3827,49 +4071,52 @@ loop: for (;;) {
|
|
3827
4071
|
}).exps = true;
|
3828
4072
|
|
3829
4073
|
(function () {
|
3830
|
-
var x = stmt(
|
3831
|
-
funct[
|
3832
|
-
funct[
|
4074
|
+
var x = stmt("do", function () {
|
4075
|
+
funct["(breakage)"] += 1;
|
4076
|
+
funct["(loopage)"] += 1;
|
4077
|
+
increaseComplexityCount();
|
4078
|
+
|
3833
4079
|
this.first = block(true);
|
3834
|
-
advance(
|
4080
|
+
advance("while");
|
3835
4081
|
var t = nexttoken;
|
3836
4082
|
nonadjacent(token, t);
|
3837
|
-
advance(
|
4083
|
+
advance("(");
|
3838
4084
|
nospace();
|
3839
4085
|
expression(20);
|
3840
|
-
if (nexttoken.id ===
|
4086
|
+
if (nexttoken.id === "=") {
|
3841
4087
|
if (!option.boss)
|
3842
4088
|
warning("Expected a conditional expression and instead saw an assignment.");
|
3843
|
-
advance(
|
4089
|
+
advance("=");
|
3844
4090
|
expression(20);
|
3845
4091
|
}
|
3846
|
-
advance(
|
4092
|
+
advance(")", t);
|
3847
4093
|
nospace(prevtoken, token);
|
3848
|
-
funct[
|
3849
|
-
funct[
|
4094
|
+
funct["(breakage)"] -= 1;
|
4095
|
+
funct["(loopage)"] -= 1;
|
3850
4096
|
return this;
|
3851
4097
|
});
|
3852
4098
|
x.labelled = true;
|
3853
4099
|
x.exps = true;
|
3854
4100
|
}());
|
3855
4101
|
|
3856
|
-
blockstmt(
|
4102
|
+
blockstmt("for", function () {
|
3857
4103
|
var s, t = nexttoken;
|
3858
|
-
funct[
|
3859
|
-
funct[
|
3860
|
-
|
4104
|
+
funct["(breakage)"] += 1;
|
4105
|
+
funct["(loopage)"] += 1;
|
4106
|
+
increaseComplexityCount();
|
4107
|
+
advance("(");
|
3861
4108
|
nonadjacent(this, t);
|
3862
4109
|
nospace();
|
3863
|
-
if (peek(nexttoken.id ===
|
3864
|
-
if (nexttoken.id ===
|
3865
|
-
advance(
|
4110
|
+
if (peek(nexttoken.id === "var" ? 1 : 0).id === "in") {
|
4111
|
+
if (nexttoken.id === "var") {
|
4112
|
+
advance("var");
|
3866
4113
|
varstatement.fud.call(varstatement, true);
|
3867
4114
|
} else {
|
3868
4115
|
switch (funct[nexttoken.value]) {
|
3869
|
-
case
|
3870
|
-
funct[nexttoken.value] =
|
4116
|
+
case "unused":
|
4117
|
+
funct[nexttoken.value] = "var";
|
3871
4118
|
break;
|
3872
|
-
case
|
4119
|
+
case "var":
|
3873
4120
|
break;
|
3874
4121
|
default:
|
3875
4122
|
warning("Bad for in variable '{a}'.",
|
@@ -3877,27 +4124,27 @@ loop: for (;;) {
|
|
3877
4124
|
}
|
3878
4125
|
advance();
|
3879
4126
|
}
|
3880
|
-
advance(
|
4127
|
+
advance("in");
|
3881
4128
|
expression(20);
|
3882
|
-
advance(
|
4129
|
+
advance(")", t);
|
3883
4130
|
s = block(true, true);
|
3884
|
-
if (option.forin && s && (s.length > 1 || typeof s[0] !==
|
3885
|
-
s[0].value !==
|
4131
|
+
if (option.forin && s && (s.length > 1 || typeof s[0] !== "object" ||
|
4132
|
+
s[0].value !== "if")) {
|
3886
4133
|
warning("The body of a for in should be wrapped in an if statement to filter " +
|
3887
4134
|
"unwanted properties from the prototype.", this);
|
3888
4135
|
}
|
3889
|
-
funct[
|
3890
|
-
funct[
|
4136
|
+
funct["(breakage)"] -= 1;
|
4137
|
+
funct["(loopage)"] -= 1;
|
3891
4138
|
return this;
|
3892
4139
|
} else {
|
3893
|
-
if (nexttoken.id !==
|
3894
|
-
if (nexttoken.id ===
|
3895
|
-
advance(
|
4140
|
+
if (nexttoken.id !== ";") {
|
4141
|
+
if (nexttoken.id === "var") {
|
4142
|
+
advance("var");
|
3896
4143
|
varstatement.fud.call(varstatement);
|
3897
4144
|
} else {
|
3898
4145
|
for (;;) {
|
3899
|
-
expression(0,
|
3900
|
-
if (nexttoken.id !==
|
4146
|
+
expression(0, "for");
|
4147
|
+
if (nexttoken.id !== ",") {
|
3901
4148
|
break;
|
3902
4149
|
}
|
3903
4150
|
comma();
|
@@ -3905,53 +4152,53 @@ loop: for (;;) {
|
|
3905
4152
|
}
|
3906
4153
|
}
|
3907
4154
|
nolinebreak(token);
|
3908
|
-
advance(
|
3909
|
-
if (nexttoken.id !==
|
4155
|
+
advance(";");
|
4156
|
+
if (nexttoken.id !== ";") {
|
3910
4157
|
expression(20);
|
3911
|
-
if (nexttoken.id ===
|
4158
|
+
if (nexttoken.id === "=") {
|
3912
4159
|
if (!option.boss)
|
3913
4160
|
warning("Expected a conditional expression and instead saw an assignment.");
|
3914
|
-
advance(
|
4161
|
+
advance("=");
|
3915
4162
|
expression(20);
|
3916
4163
|
}
|
3917
4164
|
}
|
3918
4165
|
nolinebreak(token);
|
3919
|
-
advance(
|
3920
|
-
if (nexttoken.id ===
|
4166
|
+
advance(";");
|
4167
|
+
if (nexttoken.id === ";") {
|
3921
4168
|
error("Expected '{a}' and instead saw '{b}'.",
|
3922
|
-
nexttoken,
|
4169
|
+
nexttoken, ")", ";");
|
3923
4170
|
}
|
3924
|
-
if (nexttoken.id !==
|
4171
|
+
if (nexttoken.id !== ")") {
|
3925
4172
|
for (;;) {
|
3926
|
-
expression(0,
|
3927
|
-
if (nexttoken.id !==
|
4173
|
+
expression(0, "for");
|
4174
|
+
if (nexttoken.id !== ",") {
|
3928
4175
|
break;
|
3929
4176
|
}
|
3930
4177
|
comma();
|
3931
4178
|
}
|
3932
4179
|
}
|
3933
|
-
advance(
|
4180
|
+
advance(")", t);
|
3934
4181
|
nospace(prevtoken, token);
|
3935
4182
|
block(true, true);
|
3936
|
-
funct[
|
3937
|
-
funct[
|
4183
|
+
funct["(breakage)"] -= 1;
|
4184
|
+
funct["(loopage)"] -= 1;
|
3938
4185
|
return this;
|
3939
4186
|
}
|
3940
4187
|
}).labelled = true;
|
3941
4188
|
|
3942
4189
|
|
3943
|
-
stmt(
|
4190
|
+
stmt("break", function () {
|
3944
4191
|
var v = nexttoken.value;
|
3945
4192
|
|
3946
|
-
if (funct[
|
4193
|
+
if (funct["(breakage)"] === 0)
|
3947
4194
|
warning("Unexpected '{a}'.", nexttoken, this.value);
|
3948
4195
|
|
3949
4196
|
if (!option.asi)
|
3950
4197
|
nolinebreak(this);
|
3951
4198
|
|
3952
|
-
if (nexttoken.id !==
|
4199
|
+
if (nexttoken.id !== ";") {
|
3953
4200
|
if (token.line === nexttoken.line) {
|
3954
|
-
if (funct[v] !==
|
4201
|
+
if (funct[v] !== "label") {
|
3955
4202
|
warning("'{a}' is not a statement label.", nexttoken, v);
|
3956
4203
|
} else if (scope[v] !== funct) {
|
3957
4204
|
warning("'{a}' is out of scope.", nexttoken, v);
|
@@ -3960,23 +4207,23 @@ loop: for (;;) {
|
|
3960
4207
|
advance();
|
3961
4208
|
}
|
3962
4209
|
}
|
3963
|
-
reachable(
|
4210
|
+
reachable("break");
|
3964
4211
|
return this;
|
3965
4212
|
}).exps = true;
|
3966
4213
|
|
3967
4214
|
|
3968
|
-
stmt(
|
4215
|
+
stmt("continue", function () {
|
3969
4216
|
var v = nexttoken.value;
|
3970
4217
|
|
3971
|
-
if (funct[
|
4218
|
+
if (funct["(breakage)"] === 0)
|
3972
4219
|
warning("Unexpected '{a}'.", nexttoken, this.value);
|
3973
4220
|
|
3974
4221
|
if (!option.asi)
|
3975
4222
|
nolinebreak(this);
|
3976
4223
|
|
3977
|
-
if (nexttoken.id !==
|
4224
|
+
if (nexttoken.id !== ";") {
|
3978
4225
|
if (token.line === nexttoken.line) {
|
3979
|
-
if (funct[v] !==
|
4226
|
+
if (funct[v] !== "label") {
|
3980
4227
|
warning("'{a}' is not a statement label.", nexttoken, v);
|
3981
4228
|
} else if (scope[v] !== funct) {
|
3982
4229
|
warning("'{a}' is out of scope.", nexttoken, v);
|
@@ -3984,20 +4231,20 @@ loop: for (;;) {
|
|
3984
4231
|
this.first = nexttoken;
|
3985
4232
|
advance();
|
3986
4233
|
}
|
3987
|
-
} else if (!funct[
|
4234
|
+
} else if (!funct["(loopage)"]) {
|
3988
4235
|
warning("Unexpected '{a}'.", nexttoken, this.value);
|
3989
4236
|
}
|
3990
|
-
reachable(
|
4237
|
+
reachable("continue");
|
3991
4238
|
return this;
|
3992
4239
|
}).exps = true;
|
3993
4240
|
|
3994
4241
|
|
3995
|
-
stmt(
|
4242
|
+
stmt("return", function () {
|
3996
4243
|
if (this.line === nexttoken.line) {
|
3997
|
-
if (nexttoken.id ===
|
4244
|
+
if (nexttoken.id === "(regexp)")
|
3998
4245
|
warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");
|
3999
4246
|
|
4000
|
-
if (nexttoken.id !==
|
4247
|
+
if (nexttoken.id !== ";" && !nexttoken.reach) {
|
4001
4248
|
nonadjacent(token, nexttoken);
|
4002
4249
|
if (peek().value === "=" && !option.boss) {
|
4003
4250
|
warningAt("Did you mean to return a conditional instead of an assignment?",
|
@@ -4008,38 +4255,38 @@ loop: for (;;) {
|
|
4008
4255
|
} else if (!option.asi) {
|
4009
4256
|
nolinebreak(this); // always warn (Line breaking error)
|
4010
4257
|
}
|
4011
|
-
reachable(
|
4258
|
+
reachable("return");
|
4012
4259
|
return this;
|
4013
4260
|
}).exps = true;
|
4014
4261
|
|
4015
4262
|
|
4016
|
-
stmt(
|
4263
|
+
stmt("throw", function () {
|
4017
4264
|
nolinebreak(this);
|
4018
4265
|
nonadjacent(token, nexttoken);
|
4019
4266
|
this.first = expression(20);
|
4020
|
-
reachable(
|
4267
|
+
reachable("throw");
|
4021
4268
|
return this;
|
4022
4269
|
}).exps = true;
|
4023
4270
|
|
4024
4271
|
// Superfluous reserved words
|
4025
4272
|
|
4026
|
-
reserve(
|
4027
|
-
reserve(
|
4028
|
-
reserve(
|
4029
|
-
reserve(
|
4030
|
-
reserve(
|
4031
|
-
reserve(
|
4032
|
-
reserve(
|
4033
|
-
|
4034
|
-
reserve(
|
4035
|
-
reserve(
|
4036
|
-
reserve(
|
4037
|
-
reserve(
|
4038
|
-
reserve(
|
4039
|
-
reserve(
|
4040
|
-
reserve(
|
4041
|
-
reserve(
|
4042
|
-
reserve(
|
4273
|
+
reserve("class");
|
4274
|
+
reserve("const");
|
4275
|
+
reserve("enum");
|
4276
|
+
reserve("export");
|
4277
|
+
reserve("extends");
|
4278
|
+
reserve("import");
|
4279
|
+
reserve("super");
|
4280
|
+
|
4281
|
+
reserve("let");
|
4282
|
+
reserve("yield");
|
4283
|
+
reserve("implements");
|
4284
|
+
reserve("interface");
|
4285
|
+
reserve("package");
|
4286
|
+
reserve("private");
|
4287
|
+
reserve("protected");
|
4288
|
+
reserve("public");
|
4289
|
+
reserve("static");
|
4043
4290
|
|
4044
4291
|
|
4045
4292
|
// Parse JSON
|
@@ -4048,26 +4295,26 @@ loop: for (;;) {
|
|
4048
4295
|
|
4049
4296
|
function jsonObject() {
|
4050
4297
|
var o = {}, t = nexttoken;
|
4051
|
-
advance(
|
4052
|
-
if (nexttoken.id !==
|
4298
|
+
advance("{");
|
4299
|
+
if (nexttoken.id !== "}") {
|
4053
4300
|
for (;;) {
|
4054
|
-
if (nexttoken.id ===
|
4301
|
+
if (nexttoken.id === "(end)") {
|
4055
4302
|
error("Missing '}' to match '{' from line {a}.",
|
4056
4303
|
nexttoken, t.line);
|
4057
|
-
} else if (nexttoken.id ===
|
4304
|
+
} else if (nexttoken.id === "}") {
|
4058
4305
|
warning("Unexpected comma.", token);
|
4059
4306
|
break;
|
4060
|
-
} else if (nexttoken.id ===
|
4307
|
+
} else if (nexttoken.id === ",") {
|
4061
4308
|
error("Unexpected comma.", nexttoken);
|
4062
|
-
} else if (nexttoken.id !==
|
4309
|
+
} else if (nexttoken.id !== "(string)") {
|
4063
4310
|
warning("Expected a string and instead saw {a}.",
|
4064
4311
|
nexttoken, nexttoken.value);
|
4065
4312
|
}
|
4066
4313
|
if (o[nexttoken.value] === true) {
|
4067
4314
|
warning("Duplicate key '{a}'.",
|
4068
4315
|
nexttoken, nexttoken.value);
|
4069
|
-
} else if ((nexttoken.value ===
|
4070
|
-
!option.proto) || (nexttoken.value ===
|
4316
|
+
} else if ((nexttoken.value === "__proto__" &&
|
4317
|
+
!option.proto) || (nexttoken.value === "__iterator__" &&
|
4071
4318
|
!option.iterator)) {
|
4072
4319
|
warning("The '{a}' key may produce unexpected results.",
|
4073
4320
|
nexttoken, nexttoken.value);
|
@@ -4075,62 +4322,62 @@ loop: for (;;) {
|
|
4075
4322
|
o[nexttoken.value] = true;
|
4076
4323
|
}
|
4077
4324
|
advance();
|
4078
|
-
advance(
|
4325
|
+
advance(":");
|
4079
4326
|
jsonValue();
|
4080
|
-
if (nexttoken.id !==
|
4327
|
+
if (nexttoken.id !== ",") {
|
4081
4328
|
break;
|
4082
4329
|
}
|
4083
|
-
advance(
|
4330
|
+
advance(",");
|
4084
4331
|
}
|
4085
4332
|
}
|
4086
|
-
advance(
|
4333
|
+
advance("}");
|
4087
4334
|
}
|
4088
4335
|
|
4089
4336
|
function jsonArray() {
|
4090
4337
|
var t = nexttoken;
|
4091
|
-
advance(
|
4092
|
-
if (nexttoken.id !==
|
4338
|
+
advance("[");
|
4339
|
+
if (nexttoken.id !== "]") {
|
4093
4340
|
for (;;) {
|
4094
|
-
if (nexttoken.id ===
|
4341
|
+
if (nexttoken.id === "(end)") {
|
4095
4342
|
error("Missing ']' to match '[' from line {a}.",
|
4096
4343
|
nexttoken, t.line);
|
4097
|
-
} else if (nexttoken.id ===
|
4344
|
+
} else if (nexttoken.id === "]") {
|
4098
4345
|
warning("Unexpected comma.", token);
|
4099
4346
|
break;
|
4100
|
-
} else if (nexttoken.id ===
|
4347
|
+
} else if (nexttoken.id === ",") {
|
4101
4348
|
error("Unexpected comma.", nexttoken);
|
4102
4349
|
}
|
4103
4350
|
jsonValue();
|
4104
|
-
if (nexttoken.id !==
|
4351
|
+
if (nexttoken.id !== ",") {
|
4105
4352
|
break;
|
4106
4353
|
}
|
4107
|
-
advance(
|
4354
|
+
advance(",");
|
4108
4355
|
}
|
4109
4356
|
}
|
4110
|
-
advance(
|
4357
|
+
advance("]");
|
4111
4358
|
}
|
4112
4359
|
|
4113
4360
|
switch (nexttoken.id) {
|
4114
|
-
case
|
4361
|
+
case "{":
|
4115
4362
|
jsonObject();
|
4116
4363
|
break;
|
4117
|
-
case
|
4364
|
+
case "[":
|
4118
4365
|
jsonArray();
|
4119
4366
|
break;
|
4120
|
-
case
|
4121
|
-
case
|
4122
|
-
case
|
4123
|
-
case
|
4124
|
-
case
|
4367
|
+
case "true":
|
4368
|
+
case "false":
|
4369
|
+
case "null":
|
4370
|
+
case "(number)":
|
4371
|
+
case "(string)":
|
4125
4372
|
advance();
|
4126
4373
|
break;
|
4127
|
-
case
|
4128
|
-
advance(
|
4374
|
+
case "-":
|
4375
|
+
advance("-");
|
4129
4376
|
if (token.character !== nexttoken.from) {
|
4130
4377
|
warning("Unexpected space after '-'.", token);
|
4131
4378
|
}
|
4132
4379
|
adjacent(token, nexttoken);
|
4133
|
-
advance(
|
4380
|
+
advance("(number)");
|
4134
4381
|
break;
|
4135
4382
|
default:
|
4136
4383
|
error("Expected a JSON value.", nexttoken);
|
@@ -4138,34 +4385,48 @@ loop: for (;;) {
|
|
4138
4385
|
}
|
4139
4386
|
|
4140
4387
|
|
4141
|
-
// The actual JSHINT function itself.
|
4142
|
-
|
4388
|
+
// The actual JSHINT function itself.
|
4143
4389
|
var itself = function (s, o, g) {
|
4144
|
-
var a, i, k, x
|
4145
|
-
|
4146
|
-
|
4390
|
+
var a, i, k, x;
|
4391
|
+
var optionKeys;
|
4392
|
+
var newOptionObj = {};
|
4393
|
+
|
4394
|
+
if (o && o.scope) {
|
4395
|
+
JSHINT.scope = o.scope;
|
4396
|
+
} else {
|
4397
|
+
JSHINT.errors = [];
|
4398
|
+
JSHINT.undefs = [];
|
4399
|
+
JSHINT.internals = [];
|
4400
|
+
JSHINT.blacklist = {};
|
4401
|
+
JSHINT.scope = "(main)";
|
4402
|
+
}
|
4147
4403
|
|
4148
|
-
JSHINT.errors = [];
|
4149
|
-
JSHINT.undefs = [];
|
4150
4404
|
predefined = Object.create(standard);
|
4405
|
+
declared = Object.create(null);
|
4151
4406
|
combine(predefined, g || {});
|
4407
|
+
|
4152
4408
|
if (o) {
|
4153
4409
|
a = o.predef;
|
4154
4410
|
if (a) {
|
4155
|
-
if (Array.isArray(a)) {
|
4156
|
-
|
4157
|
-
predefined[a[i]] = true;
|
4158
|
-
}
|
4159
|
-
} else if (typeof a === 'object') {
|
4160
|
-
k = Object.keys(a);
|
4161
|
-
for (i = 0; i < k.length; i += 1) {
|
4162
|
-
predefined[k[i]] = !!a[k[i]];
|
4163
|
-
}
|
4411
|
+
if (!Array.isArray(a) && typeof a === "object") {
|
4412
|
+
a = Object.keys(a);
|
4164
4413
|
}
|
4414
|
+
a.forEach(function (item) {
|
4415
|
+
var slice;
|
4416
|
+
if (item[0] === "-") {
|
4417
|
+
slice = item.slice(1);
|
4418
|
+
JSHINT.blacklist[slice] = slice;
|
4419
|
+
} else {
|
4420
|
+
predefined[item] = true;
|
4421
|
+
}
|
4422
|
+
});
|
4165
4423
|
}
|
4166
4424
|
optionKeys = Object.keys(o);
|
4167
4425
|
for (x = 0; x < optionKeys.length; x++) {
|
4168
4426
|
newOptionObj[optionKeys[x]] = o[optionKeys[x]];
|
4427
|
+
|
4428
|
+
if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
|
4429
|
+
newOptionObj["(explicitNewcap)"] = true;
|
4169
4430
|
}
|
4170
4431
|
}
|
4171
4432
|
|
@@ -4174,19 +4435,21 @@ loop: for (;;) {
|
|
4174
4435
|
option.indent = option.indent || 4;
|
4175
4436
|
option.maxerr = option.maxerr || 50;
|
4176
4437
|
|
4177
|
-
tab =
|
4438
|
+
tab = "";
|
4178
4439
|
for (i = 0; i < option.indent; i += 1) {
|
4179
|
-
tab +=
|
4440
|
+
tab += " ";
|
4180
4441
|
}
|
4181
4442
|
indent = 1;
|
4182
4443
|
global = Object.create(predefined);
|
4183
4444
|
scope = global;
|
4184
4445
|
funct = {
|
4185
|
-
|
4186
|
-
|
4187
|
-
|
4188
|
-
|
4189
|
-
|
4446
|
+
"(global)": true,
|
4447
|
+
"(name)": "(global)",
|
4448
|
+
"(scope)": scope,
|
4449
|
+
"(breakage)": 0,
|
4450
|
+
"(loopage)": 0,
|
4451
|
+
"(tokens)": {},
|
4452
|
+
"(metrics)": createMetrics(nexttoken)
|
4190
4453
|
};
|
4191
4454
|
functions = [funct];
|
4192
4455
|
urls = [];
|
@@ -4198,11 +4461,30 @@ loop: for (;;) {
|
|
4198
4461
|
lookahead = [];
|
4199
4462
|
jsonmode = false;
|
4200
4463
|
warnings = 0;
|
4464
|
+
lines = [];
|
4465
|
+
unuseds = [];
|
4466
|
+
|
4467
|
+
if (!isString(s) && !Array.isArray(s)) {
|
4468
|
+
errorAt("Input is neither a string nor an array of strings.", 0);
|
4469
|
+
return false;
|
4470
|
+
}
|
4471
|
+
|
4472
|
+
if (isString(s) && /^\s*$/g.test(s)) {
|
4473
|
+
errorAt("Input is an empty string.", 0);
|
4474
|
+
return false;
|
4475
|
+
}
|
4476
|
+
|
4477
|
+
if (s.length === 0) {
|
4478
|
+
errorAt("Input is an empty array.", 0);
|
4479
|
+
return false;
|
4480
|
+
}
|
4481
|
+
|
4201
4482
|
lex.init(s);
|
4483
|
+
|
4202
4484
|
prereg = true;
|
4203
4485
|
directive = {};
|
4204
4486
|
|
4205
|
-
prevtoken = token = nexttoken = syntax[
|
4487
|
+
prevtoken = token = nexttoken = syntax["(begin)"];
|
4206
4488
|
|
4207
4489
|
// Check options
|
4208
4490
|
for (var name in o) {
|
@@ -4218,12 +4500,13 @@ loop: for (;;) {
|
|
4218
4500
|
|
4219
4501
|
//reset values
|
4220
4502
|
comma.first = true;
|
4503
|
+
quotmark = undefined;
|
4221
4504
|
|
4222
4505
|
try {
|
4223
4506
|
advance();
|
4224
4507
|
switch (nexttoken.id) {
|
4225
|
-
case
|
4226
|
-
case
|
4508
|
+
case "{":
|
4509
|
+
case "[":
|
4227
4510
|
option.laxbreak = true;
|
4228
4511
|
jsonmode = true;
|
4229
4512
|
jsonValue();
|
@@ -4236,26 +4519,26 @@ loop: for (;;) {
|
|
4236
4519
|
|
4237
4520
|
statements();
|
4238
4521
|
}
|
4239
|
-
advance((nexttoken && nexttoken.value !==
|
4522
|
+
advance((nexttoken && nexttoken.value !== ".") ? "(end)" : undefined);
|
4240
4523
|
|
4241
4524
|
var markDefined = function (name, context) {
|
4242
4525
|
do {
|
4243
|
-
if (typeof context[name] ===
|
4526
|
+
if (typeof context[name] === "string") {
|
4244
4527
|
// JSHINT marks unused variables as 'unused' and
|
4245
4528
|
// unused function declaration as 'unction'. This
|
4246
4529
|
// code changes such instances back 'var' and
|
4247
4530
|
// 'closure' so that the code in JSHINT.data()
|
4248
4531
|
// doesn't think they're unused.
|
4249
4532
|
|
4250
|
-
if (context[name] ===
|
4251
|
-
context[name] =
|
4252
|
-
else if (context[name] ===
|
4253
|
-
context[name] =
|
4533
|
+
if (context[name] === "unused")
|
4534
|
+
context[name] = "var";
|
4535
|
+
else if (context[name] === "unction")
|
4536
|
+
context[name] = "closure";
|
4254
4537
|
|
4255
4538
|
return true;
|
4256
4539
|
}
|
4257
4540
|
|
4258
|
-
context = context[
|
4541
|
+
context = context["(context)"];
|
4259
4542
|
} while (context);
|
4260
4543
|
|
4261
4544
|
return false;
|
@@ -4277,6 +4560,37 @@ loop: for (;;) {
|
|
4277
4560
|
implied[name] = newImplied;
|
4278
4561
|
};
|
4279
4562
|
|
4563
|
+
var warnUnused = function (name, token) {
|
4564
|
+
var line = token.line;
|
4565
|
+
var chr = token.character;
|
4566
|
+
|
4567
|
+
if (option.unused)
|
4568
|
+
warningAt("'{a}' is defined but never used.", line, chr, name);
|
4569
|
+
|
4570
|
+
unuseds.push({
|
4571
|
+
name: name,
|
4572
|
+
line: line,
|
4573
|
+
character: chr
|
4574
|
+
});
|
4575
|
+
};
|
4576
|
+
|
4577
|
+
var checkUnused = function (func, key) {
|
4578
|
+
var type = func[key];
|
4579
|
+
var token = func["(tokens)"][key];
|
4580
|
+
|
4581
|
+
if (key.charAt(0) === "(")
|
4582
|
+
return;
|
4583
|
+
|
4584
|
+
if (type !== "unused" && type !== "unction")
|
4585
|
+
return;
|
4586
|
+
|
4587
|
+
// Params are checked separately from other variables.
|
4588
|
+
if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
|
4589
|
+
return;
|
4590
|
+
|
4591
|
+
warnUnused(key, token);
|
4592
|
+
};
|
4593
|
+
|
4280
4594
|
// Check queued 'x is not defined' instances to see if they're still undefined.
|
4281
4595
|
for (i = 0; i < JSHINT.undefs.length; i += 1) {
|
4282
4596
|
k = JSHINT.undefs[i].slice(0);
|
@@ -4287,6 +4601,43 @@ loop: for (;;) {
|
|
4287
4601
|
warning.apply(warning, k.slice(1));
|
4288
4602
|
}
|
4289
4603
|
}
|
4604
|
+
|
4605
|
+
functions.forEach(function (func) {
|
4606
|
+
for (var key in func) {
|
4607
|
+
if (is_own(func, key)) {
|
4608
|
+
checkUnused(func, key);
|
4609
|
+
}
|
4610
|
+
}
|
4611
|
+
|
4612
|
+
if (!func["(params)"])
|
4613
|
+
return;
|
4614
|
+
|
4615
|
+
var params = func["(params)"].slice();
|
4616
|
+
var param = params.pop();
|
4617
|
+
var type;
|
4618
|
+
|
4619
|
+
while (param) {
|
4620
|
+
type = func[param];
|
4621
|
+
|
4622
|
+
// 'undefined' is a special case for (function (window, undefined) { ... })();
|
4623
|
+
// patterns.
|
4624
|
+
|
4625
|
+
if (param === "undefined")
|
4626
|
+
return;
|
4627
|
+
|
4628
|
+
if (type !== "unused" && type !== "unction")
|
4629
|
+
return;
|
4630
|
+
|
4631
|
+
warnUnused(param, func["(tokens)"][param]);
|
4632
|
+
param = params.pop();
|
4633
|
+
}
|
4634
|
+
});
|
4635
|
+
|
4636
|
+
for (var key in declared) {
|
4637
|
+
if (is_own(declared, key) && !is_own(global, key)) {
|
4638
|
+
warnUnused(key, declared[key]);
|
4639
|
+
}
|
4640
|
+
}
|
4290
4641
|
} catch (e) {
|
4291
4642
|
if (e) {
|
4292
4643
|
var nt = nexttoken || {};
|
@@ -4299,14 +4650,31 @@ loop: for (;;) {
|
|
4299
4650
|
}
|
4300
4651
|
}
|
4301
4652
|
|
4653
|
+
// Loop over the listed "internals", and check them as well.
|
4654
|
+
|
4655
|
+
if (JSHINT.scope === "(main)") {
|
4656
|
+
o = o || {};
|
4657
|
+
|
4658
|
+
for (i = 0; i < JSHINT.internals.length; i += 1) {
|
4659
|
+
k = JSHINT.internals[i];
|
4660
|
+
o.scope = k.elem;
|
4661
|
+
itself(k.value, o, g);
|
4662
|
+
}
|
4663
|
+
}
|
4664
|
+
|
4302
4665
|
return JSHINT.errors.length === 0;
|
4303
4666
|
};
|
4304
4667
|
|
4305
4668
|
// Data summary.
|
4306
4669
|
itself.data = function () {
|
4670
|
+
var data = {
|
4671
|
+
functions: [],
|
4672
|
+
options: option
|
4673
|
+
};
|
4674
|
+
var implieds = [];
|
4675
|
+
var members = [];
|
4676
|
+
var fu, f, i, j, n, globals;
|
4307
4677
|
|
4308
|
-
var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j,
|
4309
|
-
members = [], n, unused = [], v;
|
4310
4678
|
if (itself.errors.length) {
|
4311
4679
|
data.errors = itself.errors;
|
4312
4680
|
}
|
@@ -4323,6 +4691,7 @@ loop: for (;;) {
|
|
4323
4691
|
});
|
4324
4692
|
}
|
4325
4693
|
}
|
4694
|
+
|
4326
4695
|
if (implieds.length > 0) {
|
4327
4696
|
data.implieds = implieds;
|
4328
4697
|
}
|
@@ -4335,49 +4704,37 @@ loop: for (;;) {
|
|
4335
4704
|
if (globals.length > 0) {
|
4336
4705
|
data.globals = globals;
|
4337
4706
|
}
|
4707
|
+
|
4338
4708
|
for (i = 1; i < functions.length; i += 1) {
|
4339
4709
|
f = functions[i];
|
4340
4710
|
fu = {};
|
4711
|
+
|
4341
4712
|
for (j = 0; j < functionicity.length; j += 1) {
|
4342
4713
|
fu[functionicity[j]] = [];
|
4343
4714
|
}
|
4344
|
-
|
4345
|
-
if (is_own(f, n) && n.charAt(0) !== '(') {
|
4346
|
-
v = f[n];
|
4347
|
-
if (v === 'unction') {
|
4348
|
-
v = 'unused';
|
4349
|
-
}
|
4350
|
-
if (Array.isArray(fu[v])) {
|
4351
|
-
fu[v].push(n);
|
4352
|
-
if (v === 'unused') {
|
4353
|
-
unused.push({
|
4354
|
-
name: n,
|
4355
|
-
line: f['(line)'],
|
4356
|
-
'function': f['(name)']
|
4357
|
-
});
|
4358
|
-
}
|
4359
|
-
}
|
4360
|
-
}
|
4361
|
-
}
|
4715
|
+
|
4362
4716
|
for (j = 0; j < functionicity.length; j += 1) {
|
4363
4717
|
if (fu[functionicity[j]].length === 0) {
|
4364
4718
|
delete fu[functionicity[j]];
|
4365
4719
|
}
|
4366
4720
|
}
|
4367
|
-
|
4368
|
-
fu.
|
4369
|
-
fu.
|
4370
|
-
fu.
|
4721
|
+
|
4722
|
+
fu.name = f["(name)"];
|
4723
|
+
fu.param = f["(params)"];
|
4724
|
+
fu.line = f["(line)"];
|
4725
|
+
fu.character = f["(character)"];
|
4726
|
+
fu.last = f["(last)"];
|
4727
|
+
fu.lastcharacter = f["(lastcharacter)"];
|
4371
4728
|
data.functions.push(fu);
|
4372
4729
|
}
|
4373
4730
|
|
4374
|
-
if (
|
4375
|
-
data.unused =
|
4731
|
+
if (unuseds.length > 0) {
|
4732
|
+
data.unused = unuseds;
|
4376
4733
|
}
|
4377
4734
|
|
4378
4735
|
members = [];
|
4379
4736
|
for (n in member) {
|
4380
|
-
if (typeof member[n] ===
|
4737
|
+
if (typeof member[n] === "number") {
|
4381
4738
|
data.member = member;
|
4382
4739
|
break;
|
4383
4740
|
}
|
@@ -4386,138 +4743,12 @@ loop: for (;;) {
|
|
4386
4743
|
return data;
|
4387
4744
|
};
|
4388
4745
|
|
4389
|
-
itself.report = function (option) {
|
4390
|
-
var data = itself.data();
|
4391
|
-
|
4392
|
-
var a = [], c, e, err, f, i, k, l, m = '', n, o = [], s;
|
4393
|
-
|
4394
|
-
function detail(h, array) {
|
4395
|
-
var b, i, singularity;
|
4396
|
-
if (array) {
|
4397
|
-
o.push('<div><i>' + h + '</i> ');
|
4398
|
-
array = array.sort();
|
4399
|
-
for (i = 0; i < array.length; i += 1) {
|
4400
|
-
if (array[i] !== singularity) {
|
4401
|
-
singularity = array[i];
|
4402
|
-
o.push((b ? ', ' : '') + singularity);
|
4403
|
-
b = true;
|
4404
|
-
}
|
4405
|
-
}
|
4406
|
-
o.push('</div>');
|
4407
|
-
}
|
4408
|
-
}
|
4409
|
-
|
4410
|
-
|
4411
|
-
if (data.errors || data.implieds || data.unused) {
|
4412
|
-
err = true;
|
4413
|
-
o.push('<div id=errors><i>Error:</i>');
|
4414
|
-
if (data.errors) {
|
4415
|
-
for (i = 0; i < data.errors.length; i += 1) {
|
4416
|
-
c = data.errors[i];
|
4417
|
-
if (c) {
|
4418
|
-
e = c.evidence || '';
|
4419
|
-
o.push('<p>Problem' + (isFinite(c.line) ? ' at line ' +
|
4420
|
-
c.line + ' character ' + c.character : '') +
|
4421
|
-
': ' + c.reason.entityify() +
|
4422
|
-
'</p><p class=evidence>' +
|
4423
|
-
(e && (e.length > 80 ? e.slice(0, 77) + '...' :
|
4424
|
-
e).entityify()) + '</p>');
|
4425
|
-
}
|
4426
|
-
}
|
4427
|
-
}
|
4428
|
-
|
4429
|
-
if (data.implieds) {
|
4430
|
-
s = [];
|
4431
|
-
for (i = 0; i < data.implieds.length; i += 1) {
|
4432
|
-
s[i] = '<code>' + data.implieds[i].name + '</code> <i>' +
|
4433
|
-
data.implieds[i].line + '</i>';
|
4434
|
-
}
|
4435
|
-
o.push('<p><i>Implied global:</i> ' + s.join(', ') + '</p>');
|
4436
|
-
}
|
4437
|
-
|
4438
|
-
if (data.unused) {
|
4439
|
-
s = [];
|
4440
|
-
for (i = 0; i < data.unused.length; i += 1) {
|
4441
|
-
s[i] = '<code><u>' + data.unused[i].name + '</u></code> <i>' +
|
4442
|
-
data.unused[i].line + '</i> <code>' +
|
4443
|
-
data.unused[i]['function'] + '</code>';
|
4444
|
-
}
|
4445
|
-
o.push('<p><i>Unused variable:</i> ' + s.join(', ') + '</p>');
|
4446
|
-
}
|
4447
|
-
if (data.json) {
|
4448
|
-
o.push('<p>JSON: bad.</p>');
|
4449
|
-
}
|
4450
|
-
o.push('</div>');
|
4451
|
-
}
|
4452
|
-
|
4453
|
-
if (!option) {
|
4454
|
-
|
4455
|
-
o.push('<br><div id=functions>');
|
4456
|
-
|
4457
|
-
if (data.urls) {
|
4458
|
-
detail("URLs<br>", data.urls, '<br>');
|
4459
|
-
}
|
4460
|
-
|
4461
|
-
if (data.json && !err) {
|
4462
|
-
o.push('<p>JSON: good.</p>');
|
4463
|
-
} else if (data.globals) {
|
4464
|
-
o.push('<div><i>Global</i> ' +
|
4465
|
-
data.globals.sort().join(', ') + '</div>');
|
4466
|
-
} else {
|
4467
|
-
o.push('<div><i>No new global variables introduced.</i></div>');
|
4468
|
-
}
|
4469
|
-
|
4470
|
-
for (i = 0; i < data.functions.length; i += 1) {
|
4471
|
-
f = data.functions[i];
|
4472
|
-
|
4473
|
-
o.push('<br><div class=function><i>' + f.line + '-' +
|
4474
|
-
f.last + '</i> ' + (f.name || '') + '(' +
|
4475
|
-
(f.param ? f.param.join(', ') : '') + ')</div>');
|
4476
|
-
detail('<big><b>Unused</b></big>', f.unused);
|
4477
|
-
detail('Closure', f.closure);
|
4478
|
-
detail('Variable', f['var']);
|
4479
|
-
detail('Exception', f.exception);
|
4480
|
-
detail('Outer', f.outer);
|
4481
|
-
detail('Global', f.global);
|
4482
|
-
detail('Label', f.label);
|
4483
|
-
}
|
4484
|
-
|
4485
|
-
if (data.member) {
|
4486
|
-
a = Object.keys(data.member);
|
4487
|
-
if (a.length) {
|
4488
|
-
a = a.sort();
|
4489
|
-
m = '<br><pre id=members>/*members ';
|
4490
|
-
l = 10;
|
4491
|
-
for (i = 0; i < a.length; i += 1) {
|
4492
|
-
k = a[i];
|
4493
|
-
n = k.name();
|
4494
|
-
if (l + n.length > 72) {
|
4495
|
-
o.push(m + '<br>');
|
4496
|
-
m = ' ';
|
4497
|
-
l = 1;
|
4498
|
-
}
|
4499
|
-
l += n.length + 2;
|
4500
|
-
if (data.member[k] === 1) {
|
4501
|
-
n = '<i>' + n + '</i>';
|
4502
|
-
}
|
4503
|
-
if (i < a.length - 1) {
|
4504
|
-
n += ', ';
|
4505
|
-
}
|
4506
|
-
m += n;
|
4507
|
-
}
|
4508
|
-
o.push(m + '<br>*/</pre>');
|
4509
|
-
}
|
4510
|
-
o.push('</div>');
|
4511
|
-
}
|
4512
|
-
}
|
4513
|
-
return o.join('');
|
4514
|
-
};
|
4515
|
-
|
4516
4746
|
itself.jshint = itself;
|
4517
4747
|
|
4518
4748
|
return itself;
|
4519
4749
|
}());
|
4520
4750
|
|
4521
4751
|
// Make JSHINT a Node module, if possible.
|
4522
|
-
if (typeof exports ===
|
4752
|
+
if (typeof exports === "object" && exports) {
|
4523
4753
|
exports.JSHINT = JSHINT;
|
4754
|
+
}
|