Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80556 views
1
#!/usr/bin/env node
2
/*
3
Copyright (C) 2012 Ariya Hidayat <[email protected]>
4
5
Redistribution and use in source and binary forms, with or without
6
modification, are permitted provided that the following conditions are met:
7
8
* Redistributions of source code must retain the above copyright
9
notice, this list of conditions and the following disclaimer.
10
* Redistributions in binary form must reproduce the above copyright
11
notice, this list of conditions and the following disclaimer in the
12
documentation and/or other materials provided with the distribution.
13
14
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
18
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
*/
25
26
/*jslint sloppy:true plusplus:true node:true rhino:true */
27
/*global phantom:true */
28
29
var fs, system, esprima, options, fnames, count;
30
31
if (typeof esprima === 'undefined') {
32
// PhantomJS can only require() relative files
33
if (typeof phantom === 'object') {
34
fs = require('fs');
35
system = require('system');
36
esprima = require('./esprima');
37
} else if (typeof require === 'function') {
38
fs = require('fs');
39
esprima = require('esprima');
40
} else if (typeof load === 'function') {
41
try {
42
load('esprima.js');
43
} catch (e) {
44
load('../esprima.js');
45
}
46
}
47
}
48
49
// Shims to Node.js objects when running under PhantomJS 1.7+.
50
if (typeof phantom === 'object') {
51
fs.readFileSync = fs.read;
52
process = {
53
argv: [].slice.call(system.args),
54
exit: phantom.exit
55
};
56
process.argv.unshift('phantomjs');
57
}
58
59
// Shims to Node.js objects when running under Rhino.
60
if (typeof console === 'undefined' && typeof process === 'undefined') {
61
console = { log: print };
62
fs = { readFileSync: readFile };
63
process = { argv: arguments, exit: quit };
64
process.argv.unshift('esvalidate.js');
65
process.argv.unshift('rhino');
66
}
67
68
function showUsage() {
69
console.log('Usage:');
70
console.log(' esvalidate [options] file.js');
71
console.log();
72
console.log('Available options:');
73
console.log();
74
console.log(' --format=type Set the report format, plain (default) or junit');
75
console.log(' -v, --version Print program version');
76
console.log();
77
process.exit(1);
78
}
79
80
if (process.argv.length <= 2) {
81
showUsage();
82
}
83
84
options = {
85
format: 'plain'
86
};
87
88
fnames = [];
89
90
process.argv.splice(2).forEach(function (entry) {
91
92
if (entry === '-h' || entry === '--help') {
93
showUsage();
94
} else if (entry === '-v' || entry === '--version') {
95
console.log('ECMAScript Validator (using Esprima version', esprima.version, ')');
96
console.log();
97
process.exit(0);
98
} else if (entry.slice(0, 9) === '--format=') {
99
options.format = entry.slice(9);
100
if (options.format !== 'plain' && options.format !== 'junit') {
101
console.log('Error: unknown report format ' + options.format + '.');
102
process.exit(1);
103
}
104
} else if (entry.slice(0, 2) === '--') {
105
console.log('Error: unknown option ' + entry + '.');
106
process.exit(1);
107
} else {
108
fnames.push(entry);
109
}
110
});
111
112
if (fnames.length === 0) {
113
console.log('Error: no input file.');
114
process.exit(1);
115
}
116
117
if (options.format === 'junit') {
118
console.log('<?xml version="1.0" encoding="UTF-8"?>');
119
console.log('<testsuites>');
120
}
121
122
count = 0;
123
fnames.forEach(function (fname) {
124
var content, timestamp, syntax, name;
125
try {
126
content = fs.readFileSync(fname, 'utf-8');
127
128
if (content[0] === '#' && content[1] === '!') {
129
content = '//' + content.substr(2, content.length);
130
}
131
132
timestamp = Date.now();
133
syntax = esprima.parse(content, { tolerant: true });
134
135
if (options.format === 'junit') {
136
137
name = fname;
138
if (name.lastIndexOf('/') >= 0) {
139
name = name.slice(name.lastIndexOf('/') + 1);
140
}
141
142
console.log('<testsuite name="' + fname + '" errors="0" ' +
143
' failures="' + syntax.errors.length + '" ' +
144
' tests="' + syntax.errors.length + '" ' +
145
' time="' + Math.round((Date.now() - timestamp) / 1000) +
146
'">');
147
148
syntax.errors.forEach(function (error) {
149
var msg = error.message;
150
msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
151
console.log(' <testcase name="Line ' + error.lineNumber + ': ' + msg + '" ' +
152
' time="0">');
153
console.log(' <error type="SyntaxError" message="' + error.message + '">' +
154
error.message + '(' + name + ':' + error.lineNumber + ')' +
155
'</error>');
156
console.log(' </testcase>');
157
});
158
159
console.log('</testsuite>');
160
161
} else if (options.format === 'plain') {
162
163
syntax.errors.forEach(function (error) {
164
var msg = error.message;
165
msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
166
msg = fname + ':' + error.lineNumber + ': ' + msg;
167
console.log(msg);
168
++count;
169
});
170
171
}
172
} catch (e) {
173
++count;
174
if (options.format === 'junit') {
175
console.log('<testsuite name="' + fname + '" errors="1" failures="0" tests="1" ' +
176
' time="' + Math.round((Date.now() - timestamp) / 1000) + '">');
177
console.log(' <testcase name="' + e.message + '" ' + ' time="0">');
178
console.log(' <error type="ParseError" message="' + e.message + '">' +
179
e.message + '(' + fname + ((e.lineNumber) ? ':' + e.lineNumber : '') +
180
')</error>');
181
console.log(' </testcase>');
182
console.log('</testsuite>');
183
} else {
184
console.log('Error: ' + e.message);
185
}
186
}
187
});
188
189
if (options.format === 'junit') {
190
console.log('</testsuites>');
191
}
192
193
if (count > 0) {
194
process.exit(1);
195
}
196
197
if (count === 0 && typeof phantom === 'object') {
198
process.exit(0);
199
}
200
201