UNPKG

6.16 kBJavaScriptView Raw
1var vowFs = require('vow-fs');
2var Vow = require('vow');
3var StringChecker = require('./string-checker');
4var extractJs = require('./extract-js');
5var utils = require('util');
6
7var NodeConfiguration = require('./config/node-configuration');
8
9/**
10 * Starts Code Style checking process.
11 *
12 * @name Checker
13 * @see StringChecker constructor
14 */
15var Checker = function() {
16 StringChecker.apply(this, arguments);
17};
18
19utils.inherits(Checker, StringChecker);
20
21/**
22 * Loads configuration from JS Object. Activates and configures required rules.
23 *
24 * @param {Object} config
25 */
26Checker.prototype.configure = function(config) {
27 StringChecker.prototype.configure.call(this, config);
28};
29
30/**
31 * Execute checker depending on config value either checks or checks and fixes
32 *
33 * @see Checker#checkPath/Checker#fixPath
34 */
35Checker.prototype.execute = function() {
36 var method = this._configuration.getFix() === true ? this.fixPath : this.checkPath;
37
38 return method.apply(this, arguments);
39};
40
41/**
42 * Checks single file.
43 *
44 * @param {String} path
45 * @returns {Promise.<Errors>}
46 */
47Checker.prototype.checkFile = function(path) {
48 if (this._configuration.isFileExcluded(path)) {
49 return Vow.resolve(null);
50 }
51
52 return vowFs.read(path, 'utf8').then(function(data) {
53 return this.checkString(data, path);
54 }, this);
55};
56
57/**
58 * Fixes single file.
59 *
60 * @param {String} path
61 * @returns {Promise.<Errors>}
62 */
63Checker.prototype.fixFile = function(path) {
64 if (this._configuration.isFileExcluded(path)) {
65 return Vow.resolve(null);
66 }
67
68 return vowFs.read(path, 'utf8').then(function(data) {
69 var result = this.fixString(data, path);
70 return vowFs.write(path, result.output).then(function() {
71 return result.errors;
72 });
73 }, this);
74};
75
76/**
77 * Extract JavaScript from file.
78 *
79 * @param {String} path
80 * @returns {Promise.<Errors>}
81 */
82Checker.prototype.extractFile = function(path) {
83 if (this._configuration.isFileExcluded(path)) {
84 return Vow.resolve(null);
85 }
86
87 if (!this._configuration.shouldExtractFile(path)) {
88 return Vow.resolve(null);
89 }
90
91 return vowFs.read(path, 'utf8').then(function(data) {
92 var result = extractJs(path, data);
93
94 result.sources.forEach(function(script) {
95 this.checkString(script.source, path).getErrorList().forEach(function(error) {
96 error.line += script.line;
97 error.column += script.offset;
98 result.addError(error);
99 });
100 }, this);
101
102 return result.errors;
103 }, this);
104};
105
106/**
107 * Checks directory recursively.
108 *
109 * @param {String} path
110 * @returns {Promise.<Error[]>}
111 */
112Checker.prototype.checkDirectory = function(path) {
113 return this._processDirectory(path, this.checkFile.bind(this));
114};
115
116/**
117 * Checks directory or file.
118 *
119 * @param {String} path
120 * @returns {Promise.<Error[]>}
121 */
122Checker.prototype.checkPath = function(path) {
123 return this._processPath(path, this.checkFile.bind(this));
124};
125
126/**
127 * Fixes directory or file.
128 *
129 * @param {String} path
130 * @returns {Promise.<Error[]>}
131 */
132Checker.prototype.fixPath = function(path) {
133 return this._processPath(path, this.fixFile.bind(this));
134};
135
136/**
137 * Processes directory recursively.
138 *
139 * @param {String} path
140 * @param {Function} fileHandler
141 * @returns {Promise.<Error[]>}
142 */
143Checker.prototype._processDirectory = function(path, fileHandler) {
144 return vowFs.listDir(path).then(function(filenames) {
145 return Vow.all(filenames.map(function(filename) {
146 var fullname = path + '/' + filename;
147
148 if (this._configuration.isFileExcluded(fullname)) {
149 return [];
150 }
151
152 return vowFs.stat(fullname).then(function(stat) {
153 if (stat.isDirectory()) {
154 return this._processDirectory(fullname, fileHandler);
155 }
156
157 if (!this._configuration.hasCorrectExtension(fullname)) {
158 if (!this._configuration.shouldExtractFile(fullname)) {
159 return [];
160 }
161
162 return this.extractFile(fullname);
163 }
164
165 return fileHandler(fullname);
166 }, this);
167 }, this)).then(function(results) {
168 return [].concat.apply([], results);
169 });
170 }, this);
171};
172
173/**
174 * Processes directory or file.
175 *
176 * @param {String} path
177 * @param {Function} fileHandler
178 * @returns {Promise.<Error[]>}
179 */
180Checker.prototype._processPath = function(path, fileHandler) {
181 path = path.replace(/\/$/, '');
182
183 return vowFs.exists(path).then(function(exists) {
184 if (!exists) {
185 throw new Error('Path ' + path + ' was not found.');
186 }
187
188 return vowFs.stat(path).then(function(stat) {
189 if (stat.isDirectory()) {
190 return this._processDirectory(path, fileHandler);
191 }
192
193 return fileHandler(path).then(function(errors) {
194 if (errors) {
195 return [errors];
196 }
197
198 return [];
199 });
200 }, this);
201 }, this);
202};
203
204/**
205 * Checks stdin for input
206 *
207 * @returns {Promise}
208 */
209Checker.prototype.checkStdin = function() {
210 return this._processStdin(this.checkString.bind(this));
211};
212
213/**
214 * Fixes stdin input
215 *
216 * @returns {Promise}
217 */
218Checker.prototype.fixStdin = function() {
219 return this._processStdin(this.fixString.bind(this));
220};
221
222/**
223 *
224 * @param {Function} stdinHandler
225 * @returns {Promise}
226 */
227Checker.prototype._processStdin = function(stdinHandler) {
228 var stdInput = [];
229 var deferred = Vow.defer();
230
231 process.stdin.setEncoding('utf8');
232
233 process.stdin.on('data', function(chunk) {
234 stdInput.push(chunk);
235 });
236
237 process.stdin.on('end', function() {
238 deferred.resolve(stdinHandler(stdInput.join('')));
239 });
240
241 return deferred.promise();
242};
243
244/**
245 * Returns new configuration instance.
246 *
247 * @protected
248 * @returns {NodeConfiguration}
249 */
250Checker.prototype._createConfiguration = function() {
251 return new NodeConfiguration();
252};
253
254module.exports = Checker;