Commit | Line | Data |
---|---|---|
758a629f DV |
1 | /*jshint evil: true, shadow: true, wsh: true */ |
2 | /*global JSHINT: false */ | |
3 | ||
4 | (function() { | |
5 | function readFile(path, charset) { | |
6 | try { | |
7 | var stream = WScript.CreateObject("ADODB.Stream"); | |
8 | ||
9 | stream.Charset = charset; | |
10 | stream.Open(); | |
11 | stream.LoadFromFile(path); | |
12 | ||
13 | var result = stream.ReadText(); | |
14 | stream.close(); | |
15 | ||
16 | return result; | |
17 | } catch (ex) { | |
18 | return null; | |
19 | } | |
20 | } | |
21 | ||
22 | var formatters = { | |
23 | errors: function(errors, lines) { | |
24 | for (var i = 0; i < errors.length; i++) { | |
25 | var error = errors[i]; | |
26 | ||
27 | if (!error) continue; | |
28 | ||
29 | if (i) lines.push(""); | |
30 | ||
31 | lines.push("Line " + error.line + " character " + error.character + ": " + error.reason); | |
32 | ||
33 | if (error.evidence) lines.push(" " + error.evidence.replace(/^\s*((?:[\S\s]*\S)?)\s*$/, "$1")); | |
34 | } | |
35 | }, | |
36 | ||
37 | implieds: function(implieds, lines) { | |
38 | lines.push("Implied globals:"); | |
39 | ||
40 | var globals = {}; | |
41 | ||
42 | for (var i = 0; i < implieds.length; i++) { | |
43 | var item = implieds[i]; | |
44 | ||
45 | if (!(item.name in globals)) globals[item.name] = []; | |
46 | ||
47 | globals[item.name].push(item.line); | |
48 | } | |
49 | ||
50 | for (var name in globals) { | |
51 | lines.push(" " + name + ": " + globals[name].join(", ")); | |
52 | } | |
53 | }, | |
54 | ||
55 | unused: function(unused, lines) { | |
56 | lines.push("Unused variables:"); | |
57 | ||
58 | var func, names = {}; | |
59 | ||
60 | for (var i = 0; i < unused.length; i++) { | |
61 | var item = unused[i]; | |
62 | ||
63 | func = item["function"]; | |
64 | ||
65 | if (!(func in names)) names[func] = []; | |
66 | ||
67 | names[func].push(item.name + " (" + item.line + ")"); | |
68 | } | |
69 | ||
70 | for (func in names) { | |
71 | lines.push(" " + func + ": " + names[func].join(", ")); | |
72 | } | |
73 | } | |
74 | }; | |
75 | ||
76 | var scriptName = WScript.ScriptName; | |
77 | var scriptPath = WScript.ScriptFullName; | |
78 | ||
79 | scriptPath = scriptPath.substr(0, scriptPath.length - scriptName.length); | |
80 | ||
81 | // load JSHint if the two scripts have not been concatenated | |
82 | if (typeof JSHINT === "undefined") { | |
83 | eval(readFile(scriptPath + "..\\jshint.js", 'utf-8')); | |
84 | ||
85 | if (typeof JSHINT === "undefined") { | |
86 | WScript.StdOut.WriteLine("ERROR: Could not find 'jshint.js'."); | |
87 | ||
88 | WScript.Quit(-2); | |
89 | } | |
90 | } | |
91 | ||
92 | var globals = {}; | |
93 | var options = {}; | |
94 | var named = WScript.Arguments.Named; | |
95 | var unnamed = WScript.Arguments.Unnamed; | |
96 | ||
97 | if (unnamed.length !== 1) { | |
98 | WScript.StdOut.WriteLine(" usage: cscript " + scriptName + " [options] <script>"); | |
99 | WScript.StdOut.WriteLine(""); | |
100 | WScript.StdOut.WriteLine("Scans the specified script with JSHint and reports any errors encountered. If"); | |
101 | WScript.StdOut.WriteLine("the script name is \"-\", it will be read from standard input instead."); | |
102 | WScript.StdOut.WriteLine(""); | |
103 | WScript.StdOut.WriteLine("JSHint configuration options can be passed in via optional, Windows-style"); | |
104 | WScript.StdOut.WriteLine("arguments. For example:"); | |
105 | WScript.StdOut.WriteLine(" cscript " + scriptName + " /jquery:true myscript.js"); | |
106 | WScript.StdOut.WriteLine(" cscript " + scriptName + " /global:QUnit:false,_:false,foo:true foo.js"); | |
107 | WScript.StdOut.WriteLine(""); | |
108 | WScript.StdOut.WriteLine("By default, we assume that your file is encoded if UTF-8. You can change that"); | |
109 | WScript.StdOut.WriteLine("by providing a custom charset option:"); | |
110 | WScript.StdOut.WriteLine(" cscript " + scriptName + " /charset:ascii myscript.js"); | |
111 | ||
112 | WScript.Quit(-1); | |
113 | } | |
114 | ||
115 | var script = unnamed(0); | |
116 | ||
117 | if (script === "-") { | |
118 | try { | |
119 | script = WScript.StdIn.ReadAll(); | |
120 | } catch (ex) { | |
121 | script = null; | |
122 | } | |
123 | } else { | |
124 | script = readFile(script, named('charset') || 'utf-8'); | |
125 | } | |
126 | ||
127 | if (script === null) { | |
128 | WScript.StdOut.WriteLine("ERROR: Could not read target script."); | |
129 | ||
130 | WScript.Quit(2); | |
131 | } | |
132 | ||
133 | for (var etor = new Enumerator(named); !etor.atEnd(); etor.moveNext()) { | |
134 | var option = etor.item(); | |
135 | var value = named(option); | |
136 | ||
137 | if (option === "global") { | |
138 | value = value.split(","); | |
139 | ||
140 | for (var i = 0; i < value.length; i++) { | |
141 | var name = value[i].split(":"); | |
142 | ||
143 | if (name.length === 1 || name[1] === "false") { | |
144 | globals[name[0]] = false; | |
145 | } else if (name[1] === "true") { | |
146 | globals[name[0]] = true; | |
147 | } else { | |
148 | WScript.StdOut.WriteLine("Unrecognized value for global: " + name[0]); | |
149 | WScript.StdOut.WriteLine("Must be \"true\", \"false\", or omitted."); | |
150 | ||
151 | WScript.Quit(-1); | |
152 | } | |
153 | } | |
154 | } else { | |
155 | options[option] = value === "true" ? true : value === "false" ? false : value; | |
156 | } | |
157 | } | |
158 | ||
159 | JSHINT(script, options, globals); | |
160 | ||
161 | var data = JSHINT.data(); | |
162 | var lines = []; | |
163 | ||
164 | for (var formatter in formatters) { | |
165 | if (data[formatter]) { | |
166 | if (lines.length) lines.push(""); | |
167 | ||
168 | formatters[formatter](data[formatter], lines); | |
169 | } | |
170 | } | |
171 | ||
172 | if (lines.length) { | |
173 | for (var i = 0; i < lines.length; i++) { | |
174 | WScript.StdOut.WriteLine(lines[i]); | |
175 | } | |
176 | ||
177 | WScript.Quit(1); | |
178 | } else { | |
179 | WScript.Quit(0); | |
180 | } | |
181 | }()); |