1 | "use strict";
|
2 | const path = require("path");
|
3 | const process = require("process");
|
4 | const childProcess = require("child_process");
|
5 | const worker_rpc_1 = require("worker-rpc");
|
6 | const semver = require("semver");
|
7 | const chalk_1 = require("chalk");
|
8 | const micromatch = require("micromatch");
|
9 | const os = require("os");
|
10 | const CancellationToken_1 = require("./CancellationToken");
|
11 | const NormalizedMessage_1 = require("./NormalizedMessage");
|
12 | const defaultFormatter_1 = require("./formatter/defaultFormatter");
|
13 | const codeframeFormatter_1 = require("./formatter/codeframeFormatter");
|
14 | const FsHelper_1 = require("./FsHelper");
|
15 | const hooks_1 = require("./hooks");
|
16 | const RpcTypes_1 = require("./RpcTypes");
|
17 | const checkerPluginName = 'fork-ts-checker-webpack-plugin';
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | class ForkTsCheckerWebpackPlugin {
|
26 | constructor(options) {
|
27 | this.tslint = false;
|
28 | this.eslint = false;
|
29 | this.eslintOptions = {};
|
30 | this.tslintAutoFix = false;
|
31 | this.tsconfigPath = undefined;
|
32 | this.tslintPath = undefined;
|
33 | this.watchPaths = [];
|
34 | this.compiler = undefined;
|
35 | this.started = undefined;
|
36 | this.elapsed = undefined;
|
37 | this.cancellationToken = undefined;
|
38 | this.isWatching = false;
|
39 | this.checkDone = false;
|
40 | this.compilationDone = false;
|
41 | this.diagnostics = [];
|
42 | this.lints = [];
|
43 | this.eslintVersion = undefined;
|
44 | this.startAt = 0;
|
45 | this.nodeArgs = [];
|
46 | options = options || {};
|
47 | this.options = Object.assign({}, options);
|
48 | this.watch =
|
49 | typeof options.watch === 'string' ? [options.watch] : options.watch || [];
|
50 | this.ignoreDiagnostics = options.ignoreDiagnostics || [];
|
51 | this.ignoreLints = options.ignoreLints || [];
|
52 | this.ignoreLintWarnings = options.ignoreLintWarnings === true;
|
53 | this.reportFiles = options.reportFiles || [];
|
54 | this.logger = options.logger || console;
|
55 | this.silent = options.silent === true;
|
56 | this.async = options.async !== false;
|
57 | this.checkSyntacticErrors = options.checkSyntacticErrors === true;
|
58 | this.resolveModuleNameModule = options.resolveModuleNameModule;
|
59 | this.resolveTypeReferenceDirectiveModule =
|
60 | options.resolveTypeReferenceDirectiveModule;
|
61 | this.workersNumber = options.workers || ForkTsCheckerWebpackPlugin.ONE_CPU;
|
62 | this.memoryLimit =
|
63 | options.memoryLimit || ForkTsCheckerWebpackPlugin.DEFAULT_MEMORY_LIMIT;
|
64 | this.useColors = options.colors !== false;
|
65 | this.colors = new chalk_1.default.constructor({ enabled: this.useColors });
|
66 | this.formatter =
|
67 | options.formatter && typeof options.formatter === 'function'
|
68 | ? options.formatter
|
69 | : ForkTsCheckerWebpackPlugin.createFormatter(options.formatter || 'default', options.formatterOptions || {});
|
70 | this.emitCallback = this.createNoopEmitCallback();
|
71 | this.doneCallback = this.createDoneCallback();
|
72 | const { typescript, typescriptPath, typescriptVersion, tsconfig, compilerOptions } = this.validateTypeScript(options);
|
73 | this.typescript = typescript;
|
74 | this.typescriptPath = typescriptPath;
|
75 | this.typescriptVersion = typescriptVersion;
|
76 | this.tsconfig = tsconfig;
|
77 | this.compilerOptions = compilerOptions;
|
78 | if (options.eslint === true) {
|
79 | const { eslintVersion, eslintOptions } = this.validateEslint(options);
|
80 | this.eslint = true;
|
81 | this.eslintVersion = eslintVersion;
|
82 | this.eslintOptions = eslintOptions;
|
83 | }
|
84 | else {
|
85 | const { tslint, tslintVersion, tslintAutoFix } = this.validateTslint(options);
|
86 | this.tslint = tslint;
|
87 | this.tslintVersion = tslintVersion;
|
88 | this.tslintAutoFix = tslintAutoFix;
|
89 | }
|
90 | this.vue = options.vue === true;
|
91 | this.useTypescriptIncrementalApi =
|
92 | options.useTypescriptIncrementalApi === undefined
|
93 | ? semver.gte(this.typescriptVersion, '3.0.0') && !this.vue
|
94 | : options.useTypescriptIncrementalApi;
|
95 | this.measureTime = options.measureCompilationTime === true;
|
96 | if (this.measureTime) {
|
97 |
|
98 | this.performance = require('perf_hooks').performance;
|
99 | }
|
100 | }
|
101 | static getCompilerHooks(compiler) {
|
102 | return hooks_1.getForkTsCheckerWebpackPluginHooks(compiler);
|
103 | }
|
104 | validateTypeScript(options) {
|
105 | const typescriptPath = options.typescript || require.resolve('typescript');
|
106 | const tsconfig = options.tsconfig || './tsconfig.json';
|
107 | const compilerOptions = typeof options.compilerOptions === 'object'
|
108 | ? options.compilerOptions
|
109 | : {};
|
110 | let typescript, typescriptVersion;
|
111 | try {
|
112 | typescript = require(typescriptPath);
|
113 | typescriptVersion = typescript.version;
|
114 | }
|
115 | catch (_ignored) {
|
116 | throw new Error('When you use this plugin you must install `typescript`.');
|
117 | }
|
118 | if (semver.lt(typescriptVersion, '2.1.0')) {
|
119 | throw new Error(`Cannot use current typescript version of ${typescriptVersion}, the minimum required version is 2.1.0`);
|
120 | }
|
121 | return {
|
122 | typescriptPath,
|
123 | typescript,
|
124 | typescriptVersion,
|
125 | tsconfig,
|
126 | compilerOptions
|
127 | };
|
128 | }
|
129 | validateTslint(options) {
|
130 | const tslint = options.tslint
|
131 | ? options.tslint === true
|
132 | ? true
|
133 | : options.tslint
|
134 | : undefined;
|
135 | let tslintAutoFix, tslintVersion;
|
136 | try {
|
137 | tslintAutoFix = options.tslintAutoFix || false;
|
138 | tslintVersion = tslint
|
139 | ?
|
140 | require('tslint').Linter.VERSION
|
141 | : undefined;
|
142 | }
|
143 | catch (_ignored) {
|
144 | throw new Error('When you use `tslint` option, make sure to install `tslint`.');
|
145 | }
|
146 | if (tslintVersion && semver.lt(tslintVersion, '4.0.0')) {
|
147 | throw new Error(`Cannot use current tslint version of ${tslintVersion}, the minimum required version is 4.0.0`);
|
148 | }
|
149 | return { tslint, tslintAutoFix, tslintVersion };
|
150 | }
|
151 | validateEslint(options) {
|
152 | let eslintVersion;
|
153 | const eslintOptions = typeof options.eslintOptions === 'object' ? options.eslintOptions : {};
|
154 | try {
|
155 | eslintVersion = require('eslint').Linter.version;
|
156 | }
|
157 | catch (_ignored) {
|
158 | throw new Error('When you use `eslint` option, make sure to install `eslint`.');
|
159 | }
|
160 | return { eslintVersion, eslintOptions };
|
161 | }
|
162 | static createFormatter(type, options) {
|
163 | switch (type) {
|
164 | case 'default':
|
165 | return defaultFormatter_1.createDefaultFormatter();
|
166 | case 'codeframe':
|
167 | return codeframeFormatter_1.createCodeframeFormatter(options);
|
168 | default:
|
169 | throw new Error('Unknown "' + type + '" formatter. Available are: default, codeframe.');
|
170 | }
|
171 | }
|
172 | apply(compiler) {
|
173 | this.compiler = compiler;
|
174 | this.tsconfigPath = this.computeContextPath(this.tsconfig);
|
175 | this.tslintPath =
|
176 | typeof this.tslint === 'string'
|
177 | ? this.computeContextPath(this.tslint)
|
178 | : undefined;
|
179 | this.watchPaths = this.watch.map(this.computeContextPath.bind(this));
|
180 |
|
181 | const tsconfigOk = FsHelper_1.fileExistsSync(this.tsconfigPath);
|
182 | const tslintOk = !this.tslintPath || FsHelper_1.fileExistsSync(this.tslintPath);
|
183 | if (this.useTypescriptIncrementalApi && this.workersNumber !== 1) {
|
184 | throw new Error('Using typescript incremental compilation API ' +
|
185 | 'is currently only allowed with a single worker.');
|
186 | }
|
187 |
|
188 | if (this.logger) {
|
189 | if (!this.logger.error || !this.logger.warn || !this.logger.info) {
|
190 | throw new Error("Invalid logger object - doesn't provide `error`, `warn` or `info` method.");
|
191 | }
|
192 | }
|
193 | if (tsconfigOk && tslintOk) {
|
194 | this.pluginStart();
|
195 | this.pluginStop();
|
196 | this.pluginCompile();
|
197 | this.pluginEmit();
|
198 | this.pluginDone();
|
199 | }
|
200 | else {
|
201 | if (!tsconfigOk) {
|
202 | throw new Error('Cannot find "' +
|
203 | this.tsconfigPath +
|
204 | '" file. Please check webpack and ForkTsCheckerWebpackPlugin configuration. \n' +
|
205 | 'Possible errors: \n' +
|
206 | ' - wrong `context` directory in webpack configuration' +
|
207 | ' (if `tsconfig` is not set or is a relative path in fork plugin configuration)\n' +
|
208 | ' - wrong `tsconfig` path in fork plugin configuration' +
|
209 | ' (should be a relative or absolute path)');
|
210 | }
|
211 | if (!tslintOk) {
|
212 | throw new Error('Cannot find "' +
|
213 | this.tslintPath +
|
214 | '" file. Please check webpack and ForkTsCheckerWebpackPlugin configuration. \n' +
|
215 | 'Possible errors: \n' +
|
216 | ' - wrong `context` directory in webpack configuration' +
|
217 | ' (if `tslint` is not set or is a relative path in fork plugin configuration)\n' +
|
218 | ' - wrong `tslint` path in fork plugin configuration' +
|
219 | ' (should be a relative or absolute path)\n' +
|
220 | ' - `tslint` path is not set to false in fork plugin configuration' +
|
221 | ' (if you want to disable tslint support)');
|
222 | }
|
223 | }
|
224 | }
|
225 | computeContextPath(filePath) {
|
226 | return path.isAbsolute(filePath)
|
227 | ? filePath
|
228 | : path.resolve(this.compiler.options.context, filePath);
|
229 | }
|
230 | pluginStart() {
|
231 | const run = (_compiler, callback) => {
|
232 | this.isWatching = false;
|
233 | callback();
|
234 | };
|
235 | const watchRun = (_compiler, callback) => {
|
236 | this.isWatching = true;
|
237 | callback();
|
238 | };
|
239 | if ('hooks' in this.compiler) {
|
240 |
|
241 | this.compiler.hooks.run.tapAsync(checkerPluginName, run);
|
242 | this.compiler.hooks.watchRun.tapAsync(checkerPluginName, watchRun);
|
243 | }
|
244 | else {
|
245 |
|
246 | this.compiler.plugin('run', run);
|
247 | this.compiler.plugin('watch-run', watchRun);
|
248 | }
|
249 | }
|
250 | pluginStop() {
|
251 | const watchClose = () => {
|
252 | this.killService();
|
253 | };
|
254 | const done = (_stats) => {
|
255 | if (!this.isWatching) {
|
256 | this.killService();
|
257 | }
|
258 | };
|
259 | if ('hooks' in this.compiler) {
|
260 |
|
261 | this.compiler.hooks.watchClose.tap(checkerPluginName, watchClose);
|
262 | this.compiler.hooks.done.tap(checkerPluginName, done);
|
263 | }
|
264 | else {
|
265 |
|
266 | this.compiler.plugin('watch-close', watchClose);
|
267 | this.compiler.plugin('done', done);
|
268 | }
|
269 | process.on('exit', () => {
|
270 | this.killService();
|
271 | });
|
272 | }
|
273 | pluginCompile() {
|
274 | if ('hooks' in this.compiler) {
|
275 |
|
276 | const forkTsCheckerHooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(this.compiler);
|
277 | this.compiler.hooks.compile.tap(checkerPluginName, () => {
|
278 | this.compilationDone = false;
|
279 | forkTsCheckerHooks.serviceBeforeStart.callAsync(() => {
|
280 | if (this.cancellationToken) {
|
281 |
|
282 | this.cancellationToken.requestCancellation();
|
283 | forkTsCheckerHooks.cancel.call(this.cancellationToken);
|
284 | }
|
285 | this.checkDone = false;
|
286 | this.started = process.hrtime();
|
287 |
|
288 | this.cancellationToken = new CancellationToken_1.CancellationToken(this.typescript);
|
289 | if (!this.service || !this.service.connected) {
|
290 | this.spawnService();
|
291 | }
|
292 | try {
|
293 | if (this.measureTime) {
|
294 | this.startAt = this.performance.now();
|
295 | }
|
296 | this.serviceRpc.rpc(RpcTypes_1.RUN, this.cancellationToken.toJSON()).then(result => {
|
297 | if (result) {
|
298 | this.handleServiceMessage(result);
|
299 | }
|
300 | });
|
301 | }
|
302 | catch (error) {
|
303 | if (!this.silent && this.logger) {
|
304 | this.logger.error(this.colors.red('Cannot start checker service: ' +
|
305 | (error ? error.toString() : 'Unknown error')));
|
306 | }
|
307 | forkTsCheckerHooks.serviceStartError.call(error);
|
308 | }
|
309 | });
|
310 | });
|
311 | }
|
312 | else {
|
313 |
|
314 | this.compiler.plugin('compile', () => {
|
315 | this.compilationDone = false;
|
316 | this.compiler.applyPluginsAsync(hooks_1.legacyHookMap.serviceBeforeStart, () => {
|
317 | if (this.cancellationToken) {
|
318 |
|
319 | this.cancellationToken.requestCancellation();
|
320 | this.compiler.applyPlugins(hooks_1.legacyHookMap.cancel, this.cancellationToken);
|
321 | }
|
322 | this.checkDone = false;
|
323 | this.started = process.hrtime();
|
324 |
|
325 | this.cancellationToken = new CancellationToken_1.CancellationToken(this.typescript, undefined, undefined);
|
326 | if (!this.service || !this.service.connected) {
|
327 | this.spawnService();
|
328 | }
|
329 | try {
|
330 | this.serviceRpc.rpc(RpcTypes_1.RUN, this.cancellationToken.toJSON()).then(result => {
|
331 | if (result) {
|
332 | this.handleServiceMessage(result);
|
333 | }
|
334 | });
|
335 | }
|
336 | catch (error) {
|
337 | if (!this.silent && this.logger) {
|
338 | this.logger.error(this.colors.red('Cannot start checker service: ' +
|
339 | (error ? error.toString() : 'Unknown error')));
|
340 | }
|
341 | this.compiler.applyPlugins(hooks_1.legacyHookMap.serviceStartError, error);
|
342 | }
|
343 | });
|
344 | });
|
345 | }
|
346 | }
|
347 | pluginEmit() {
|
348 | const emit = (compilation, callback) => {
|
349 | if (this.isWatching && this.async) {
|
350 | callback();
|
351 | return;
|
352 | }
|
353 | this.emitCallback = this.createEmitCallback(compilation, callback);
|
354 | if (this.checkDone) {
|
355 | this.emitCallback();
|
356 | }
|
357 | this.compilationDone = true;
|
358 | };
|
359 | if ('hooks' in this.compiler) {
|
360 |
|
361 | this.compiler.hooks.emit.tapAsync(checkerPluginName, emit);
|
362 | }
|
363 | else {
|
364 |
|
365 | this.compiler.plugin('emit', emit);
|
366 | }
|
367 | }
|
368 | pluginDone() {
|
369 | if ('hooks' in this.compiler) {
|
370 |
|
371 | const forkTsCheckerHooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(this.compiler);
|
372 | this.compiler.hooks.done.tap(checkerPluginName, (_stats) => {
|
373 | if (!this.isWatching || !this.async) {
|
374 | return;
|
375 | }
|
376 | if (this.checkDone) {
|
377 | this.doneCallback();
|
378 | }
|
379 | else {
|
380 | if (this.compiler) {
|
381 | forkTsCheckerHooks.waiting.call(this.tslint !== undefined);
|
382 | }
|
383 | if (!this.silent && this.logger) {
|
384 | this.logger.info(this.tslint
|
385 | ? 'Type checking and linting in progress...'
|
386 | : 'Type checking in progress...');
|
387 | }
|
388 | }
|
389 | this.compilationDone = true;
|
390 | });
|
391 | }
|
392 | else {
|
393 |
|
394 | this.compiler.plugin('done', () => {
|
395 | if (!this.isWatching || !this.async) {
|
396 | return;
|
397 | }
|
398 | if (this.checkDone) {
|
399 | this.doneCallback();
|
400 | }
|
401 | else {
|
402 | if (this.compiler) {
|
403 | this.compiler.applyPlugins(hooks_1.legacyHookMap.waiting, this.tslint !== undefined);
|
404 | }
|
405 | if (!this.silent && this.logger) {
|
406 | this.logger.info(this.tslint
|
407 | ? 'Type checking and linting in progress...'
|
408 | : 'Type checking in progress...');
|
409 | }
|
410 | }
|
411 | this.compilationDone = true;
|
412 | });
|
413 | }
|
414 | }
|
415 | spawnService() {
|
416 | const env = Object.assign({}, process.env, { TYPESCRIPT_PATH: this.typescriptPath, TSCONFIG: this.tsconfigPath, COMPILER_OPTIONS: JSON.stringify(this.compilerOptions), TSLINT: this.tslintPath || (this.tslint ? 'true' : ''), CONTEXT: this.compiler.options.context, TSLINTAUTOFIX: String(this.tslintAutoFix), ESLINT: String(this.eslint), ESLINT_OPTIONS: JSON.stringify(this.eslintOptions), WATCH: this.isWatching ? this.watchPaths.join('|') : '', WORK_DIVISION: String(Math.max(1, this.workersNumber)), MEMORY_LIMIT: String(this.memoryLimit), CHECK_SYNTACTIC_ERRORS: String(this.checkSyntacticErrors), USE_INCREMENTAL_API: String(this.useTypescriptIncrementalApi === true), VUE: String(this.vue) });
|
417 | if (typeof this.resolveModuleNameModule !== 'undefined') {
|
418 | env.RESOLVE_MODULE_NAME = this.resolveModuleNameModule;
|
419 | }
|
420 | else {
|
421 | delete env.RESOLVE_MODULE_NAME;
|
422 | }
|
423 | if (typeof this.resolveTypeReferenceDirectiveModule !== 'undefined') {
|
424 | env.RESOLVE_TYPE_REFERENCE_DIRECTIVE = this.resolveTypeReferenceDirectiveModule;
|
425 | }
|
426 | else {
|
427 | delete env.RESOLVE_TYPE_REFERENCE_DIRECTIVE;
|
428 | }
|
429 | this.service = childProcess.fork(path.resolve(__dirname, this.workersNumber > 1 ? './cluster.js' : './service.js'), [], {
|
430 | env,
|
431 | execArgv: (this.workersNumber > 1
|
432 | ? []
|
433 | : ['--max-old-space-size=' + this.memoryLimit]).concat(this.nodeArgs),
|
434 | stdio: ['inherit', 'inherit', 'inherit', 'ipc']
|
435 | });
|
436 | this.serviceRpc = new worker_rpc_1.RpcProvider(message => this.service.send(message));
|
437 | this.service.on('message', message => this.serviceRpc.dispatch(message));
|
438 | if ('hooks' in this.compiler) {
|
439 |
|
440 | const forkTsCheckerHooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(this.compiler);
|
441 | forkTsCheckerHooks.serviceStart.call(this.tsconfigPath, this.tslintPath, this.watchPaths, this.workersNumber, this.memoryLimit);
|
442 | }
|
443 | else {
|
444 |
|
445 | this.compiler.applyPlugins(hooks_1.legacyHookMap.serviceStart, this.tsconfigPath, this.tslintPath, this.watchPaths, this.workersNumber, this.memoryLimit);
|
446 | }
|
447 | if (!this.silent && this.logger) {
|
448 | this.logger.info('Starting type checking' +
|
449 | (this.tslint ? ' and linting' : '') +
|
450 | ' service...');
|
451 | this.logger.info('Using ' +
|
452 | this.colors.bold(this.workersNumber === 1
|
453 | ? '1 worker'
|
454 | : this.workersNumber + ' workers') +
|
455 | ' with ' +
|
456 | this.colors.bold(this.memoryLimit + 'MB') +
|
457 | ' memory limit');
|
458 | if (this.watchPaths.length && this.isWatching) {
|
459 | this.logger.info('Watching:' +
|
460 | (this.watchPaths.length > 1 ? '\n' : ' ') +
|
461 | this.watchPaths.map(wpath => this.colors.grey(wpath)).join('\n'));
|
462 | }
|
463 | }
|
464 | this.service.on('exit', (code, signal) => this.handleServiceExit(code, signal));
|
465 | }
|
466 | killService() {
|
467 | if (!this.service) {
|
468 | return;
|
469 | }
|
470 | try {
|
471 | if (this.cancellationToken) {
|
472 | this.cancellationToken.cleanupCancellation();
|
473 | }
|
474 | this.service.kill();
|
475 | this.service = undefined;
|
476 | this.serviceRpc = undefined;
|
477 | }
|
478 | catch (e) {
|
479 | if (this.logger && !this.silent) {
|
480 | this.logger.error(e);
|
481 | }
|
482 | }
|
483 | }
|
484 | handleServiceMessage(message) {
|
485 | if (this.measureTime) {
|
486 | const delta = this.performance.now() - this.startAt;
|
487 | const deltaRounded = Math.round(delta * 100) / 100;
|
488 | this.logger.info(`Compilation took: ${deltaRounded} ms.`);
|
489 | }
|
490 | if (this.cancellationToken) {
|
491 | this.cancellationToken.cleanupCancellation();
|
492 |
|
493 | this.cancellationToken = undefined;
|
494 | }
|
495 | this.checkDone = true;
|
496 | this.elapsed = process.hrtime(this.started);
|
497 | this.diagnostics = message.diagnostics.map(NormalizedMessage_1.NormalizedMessage.createFromJSON);
|
498 | this.lints = message.lints.map(NormalizedMessage_1.NormalizedMessage.createFromJSON);
|
499 | if (this.ignoreDiagnostics.length) {
|
500 | this.diagnostics = this.diagnostics.filter(diagnostic => !this.ignoreDiagnostics.includes(parseInt(diagnostic.code, 10)));
|
501 | }
|
502 | if (this.ignoreLints.length) {
|
503 | this.lints = this.lints.filter(lint => !this.ignoreLints.includes(lint.code));
|
504 | }
|
505 | if (this.reportFiles.length) {
|
506 | const reportFilesPredicate = (diagnostic) => {
|
507 | if (diagnostic.file) {
|
508 | const relativeFileName = path.relative(this.compiler.options.context, diagnostic.file);
|
509 | const matchResult = micromatch([relativeFileName], this.reportFiles);
|
510 | if (matchResult.length === 0) {
|
511 | return false;
|
512 | }
|
513 | }
|
514 | return true;
|
515 | };
|
516 | this.diagnostics = this.diagnostics.filter(reportFilesPredicate);
|
517 | this.lints = this.lints.filter(reportFilesPredicate);
|
518 | }
|
519 | if ('hooks' in this.compiler) {
|
520 |
|
521 | const forkTsCheckerHooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(this.compiler);
|
522 | forkTsCheckerHooks.receive.call(this.diagnostics, this.lints);
|
523 | }
|
524 | else {
|
525 |
|
526 | this.compiler.applyPlugins(hooks_1.legacyHookMap.receive, this.diagnostics, this.lints);
|
527 | }
|
528 | if (this.compilationDone) {
|
529 | this.isWatching && this.async ? this.doneCallback() : this.emitCallback();
|
530 | }
|
531 | }
|
532 | handleServiceExit(_code, signal) {
|
533 | if (signal !== 'SIGABRT') {
|
534 | return;
|
535 | }
|
536 |
|
537 | if (this.compiler) {
|
538 | if ('hooks' in this.compiler) {
|
539 |
|
540 | const forkTsCheckerHooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(this.compiler);
|
541 | forkTsCheckerHooks.serviceOutOfMemory.call();
|
542 | }
|
543 | else {
|
544 |
|
545 | this.compiler.applyPlugins(hooks_1.legacyHookMap.serviceOutOfMemory);
|
546 | }
|
547 | }
|
548 | if (!this.silent && this.logger) {
|
549 | this.logger.error(this.colors.red('Type checking and linting aborted - probably out of memory. ' +
|
550 | 'Check `memoryLimit` option in ForkTsCheckerWebpackPlugin configuration.'));
|
551 | }
|
552 | }
|
553 | createEmitCallback(compilation, callback) {
|
554 | return function emitCallback() {
|
555 | if (!this.elapsed) {
|
556 | throw new Error('Execution order error');
|
557 | }
|
558 | const elapsed = Math.round(this.elapsed[0] * 1e9 + this.elapsed[1]);
|
559 | if ('hooks' in this.compiler) {
|
560 |
|
561 | const forkTsCheckerHooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(this.compiler);
|
562 | forkTsCheckerHooks.emit.call(this.diagnostics, this.lints, elapsed);
|
563 | }
|
564 | else {
|
565 |
|
566 | this.compiler.applyPlugins(hooks_1.legacyHookMap.emit, this.diagnostics, this.lints, elapsed);
|
567 | }
|
568 | this.diagnostics.concat(this.lints).forEach(message => {
|
569 |
|
570 | const formatted = {
|
571 | rawMessage: message.severity.toUpperCase() +
|
572 | ' ' +
|
573 | message.getFormattedCode() +
|
574 | ': ' +
|
575 | message.content,
|
576 | message: this.formatter(message, this.useColors),
|
577 | location: {
|
578 | line: message.line,
|
579 | character: message.character
|
580 | },
|
581 | file: message.file
|
582 | };
|
583 | if (message.isWarningSeverity()) {
|
584 | if (!this.ignoreLintWarnings) {
|
585 | compilation.warnings.push(formatted);
|
586 | }
|
587 | }
|
588 | else {
|
589 | compilation.errors.push(formatted);
|
590 | }
|
591 | });
|
592 | callback();
|
593 | };
|
594 | }
|
595 | createNoopEmitCallback() {
|
596 |
|
597 | return function noopEmitCallback() { };
|
598 | }
|
599 | printLoggerMessage(message, formattedMessage) {
|
600 | if (message.isWarningSeverity()) {
|
601 | if (this.ignoreLintWarnings) {
|
602 | return;
|
603 | }
|
604 | this.logger.warn(formattedMessage);
|
605 | }
|
606 | else {
|
607 | this.logger.error(formattedMessage);
|
608 | }
|
609 | }
|
610 | createDoneCallback() {
|
611 | return function doneCallback() {
|
612 | if (!this.elapsed) {
|
613 | throw new Error('Execution order error');
|
614 | }
|
615 | const elapsed = Math.round(this.elapsed[0] * 1e9 + this.elapsed[1]);
|
616 | if (this.compiler) {
|
617 | if ('hooks' in this.compiler) {
|
618 |
|
619 | const forkTsCheckerHooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(this.compiler);
|
620 | forkTsCheckerHooks.done.call(this.diagnostics, this.lints, elapsed);
|
621 | }
|
622 | else {
|
623 |
|
624 | this.compiler.applyPlugins(hooks_1.legacyHookMap.done, this.diagnostics, this.lints, elapsed);
|
625 | }
|
626 | }
|
627 | if (!this.silent && this.logger) {
|
628 | if (this.diagnostics.length || this.lints.length) {
|
629 | (this.lints || []).concat(this.diagnostics).forEach(message => {
|
630 | const formattedMessage = this.formatter(message, this.useColors);
|
631 | this.printLoggerMessage(message, formattedMessage);
|
632 | });
|
633 | }
|
634 | if (!this.diagnostics.length) {
|
635 | this.logger.info(this.colors.green('No type errors found'));
|
636 | }
|
637 | if (this.tslint && !this.lints.length) {
|
638 | this.logger.info(this.colors.green('No lint errors found'));
|
639 | }
|
640 | this.logger.info('Version: typescript ' +
|
641 | this.colors.bold(this.typescriptVersion) +
|
642 | (this.eslint
|
643 | ? ', eslint ' + this.colors.bold(this.eslintVersion)
|
644 | : this.tslint
|
645 | ? ', tslint ' + this.colors.bold(this.tslintVersion)
|
646 | : ''));
|
647 | this.logger.info('Time: ' +
|
648 | this.colors.bold(Math.round(elapsed / 1e6).toString()) +
|
649 | 'ms');
|
650 | }
|
651 | };
|
652 | }
|
653 | }
|
654 | ForkTsCheckerWebpackPlugin.DEFAULT_MEMORY_LIMIT = 2048;
|
655 | ForkTsCheckerWebpackPlugin.ONE_CPU = 1;
|
656 | ForkTsCheckerWebpackPlugin.ALL_CPUS = os.cpus && os.cpus() ? os.cpus().length : 1;
|
657 | ForkTsCheckerWebpackPlugin.ONE_CPU_FREE = Math.max(1, ForkTsCheckerWebpackPlugin.ALL_CPUS - 1);
|
658 | ForkTsCheckerWebpackPlugin.TWO_CPUS_FREE = Math.max(1, ForkTsCheckerWebpackPlugin.ALL_CPUS - 2);
|
659 | module.exports = ForkTsCheckerWebpackPlugin;
|
660 |
|
\ | No newline at end of file |