@tsslint/cli 1.5.0 → 1.5.1
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.
- package/index.js +18 -16
- package/lib/cli-options.d.ts +9 -0
- package/lib/cli-options.js +55 -0
- package/lib/logger.d.ts +25 -0
- package/lib/logger.js +42 -0
- package/lib/project.d.ts +17 -0
- package/lib/project.js +83 -0
- package/lib/runner.d.ts +31 -0
- package/lib/runner.js +151 -0
- package/package.json +4 -4
package/index.js
CHANGED
|
@@ -169,10 +169,6 @@ class Project {
|
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
else {
|
|
172
|
-
const projectsFlag = process.argv.find(arg => arg.endsWith('-projects'));
|
|
173
|
-
if (projectsFlag) {
|
|
174
|
-
clack.log.warn(lightYellow(`Please use ${projectsFlag.slice(0, -1)} instead of ${projectsFlag} starting from version 1.5.0.`));
|
|
175
|
-
}
|
|
176
172
|
const options = [
|
|
177
173
|
{
|
|
178
174
|
projectFlags: ['--project', '--projects'],
|
|
@@ -243,14 +239,9 @@ class Project {
|
|
|
243
239
|
spinner.stop(lightYellow('No input files.'));
|
|
244
240
|
process.exit(1);
|
|
245
241
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
await Promise.all(new Array(threads).fill(0).map(() => {
|
|
251
|
-
return startWorker(worker.create());
|
|
252
|
-
}));
|
|
253
|
-
}
|
|
242
|
+
await Promise.all(new Array(threads).fill(0).map(() => {
|
|
243
|
+
return startWorker(worker.create());
|
|
244
|
+
}));
|
|
254
245
|
spinner.stop(cached
|
|
255
246
|
? darkGray(`Processed ${processed} files with cache. (Use `) + cyan(`--force`) + darkGray(` to ignore cache.)`)
|
|
256
247
|
: darkGray(`Processed ${processed} files.`));
|
|
@@ -260,6 +251,14 @@ class Project {
|
|
|
260
251
|
clack.log.message(darkGray(`Found available editor settings, you can use `) + cyan(`--vscode-settings ${path.relative(process.cwd(), vscodeSettings)}`) + darkGray(` to enable code format.`));
|
|
261
252
|
}
|
|
262
253
|
}
|
|
254
|
+
const projectsFlag = process.argv.find(arg => arg.endsWith('-projects'));
|
|
255
|
+
if (projectsFlag) {
|
|
256
|
+
clack.log.warn(darkGray(`Please use `)
|
|
257
|
+
+ cyan(`${projectsFlag.slice(0, -1)}`)
|
|
258
|
+
+ darkGray(` instead of `)
|
|
259
|
+
+ cyan(`${projectsFlag}`)
|
|
260
|
+
+ darkGray(` starting from version 1.5.0.`));
|
|
261
|
+
}
|
|
263
262
|
const data = [
|
|
264
263
|
[passed, 'passed', lightGreen],
|
|
265
264
|
[errors, 'errors', lightRed],
|
|
@@ -303,7 +302,10 @@ class Project {
|
|
|
303
302
|
while (project.currentFileIndex < project.fileNames.length) {
|
|
304
303
|
const i = project.currentFileIndex++;
|
|
305
304
|
const fileName = project.fileNames[i];
|
|
306
|
-
const
|
|
305
|
+
const fileStat = fs.statSync(fileName, { throwIfNoEntry: false });
|
|
306
|
+
if (!fileStat) {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
307
309
|
addProcessFile(fileName);
|
|
308
310
|
if (Date.now() - lastSpinnerUpdate > 100) {
|
|
309
311
|
lastSpinnerUpdate = Date.now();
|
|
@@ -311,8 +313,8 @@ class Project {
|
|
|
311
313
|
}
|
|
312
314
|
let fileCache = project.cache[fileName];
|
|
313
315
|
if (fileCache) {
|
|
314
|
-
if (fileCache[0] !==
|
|
315
|
-
fileCache[0] =
|
|
316
|
+
if (fileCache[0] !== fileStat.mtimeMs) {
|
|
317
|
+
fileCache[0] = fileStat.mtimeMs;
|
|
316
318
|
fileCache[1] = {};
|
|
317
319
|
fileCache[2] = {};
|
|
318
320
|
}
|
|
@@ -321,7 +323,7 @@ class Project {
|
|
|
321
323
|
}
|
|
322
324
|
}
|
|
323
325
|
else {
|
|
324
|
-
project.cache[fileName] = fileCache = [
|
|
326
|
+
project.cache[fileName] = fileCache = [fileStat.mtimeMs, {}, {}, false];
|
|
325
327
|
}
|
|
326
328
|
let diagnostics = await linterWorker.lint(fileName, process.argv.includes('--fix'), fileCache);
|
|
327
329
|
diagnostics = diagnostics.filter(diagnostic => diagnostic.category !== ts.DiagnosticCategory.Suggestion);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface CliOptions {
|
|
2
|
+
threads: number;
|
|
3
|
+
force: boolean;
|
|
4
|
+
fix: boolean;
|
|
5
|
+
vscodeSettings?: string;
|
|
6
|
+
projects: Map<string, string[]>;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseProjectOptions(argv: string[], options: CliOptions): void;
|
|
9
|
+
export declare function parseCliOptions(argv: string[]): CliOptions;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseProjectOptions = parseProjectOptions;
|
|
4
|
+
exports.parseCliOptions = parseCliOptions;
|
|
5
|
+
const os = require("os");
|
|
6
|
+
function parseProjectOptions(argv, options) {
|
|
7
|
+
const projectFlags = [
|
|
8
|
+
{ flags: ['--project', '--projects'], language: undefined },
|
|
9
|
+
{ flags: ['--vue-project', '--vue-projects'], language: 'vue' },
|
|
10
|
+
{ flags: ['--mdx-project', '--mdx-projects'], language: 'mdx' },
|
|
11
|
+
{ flags: ['--astro-project', '--astro-projects'], language: 'astro' }
|
|
12
|
+
];
|
|
13
|
+
for (const { flags, language } of projectFlags) {
|
|
14
|
+
const flag = flags.find(f => argv.includes(f));
|
|
15
|
+
if (!flag)
|
|
16
|
+
continue;
|
|
17
|
+
const flagIndex = argv.indexOf(flag);
|
|
18
|
+
for (let i = flagIndex + 1; i < argv.length && !argv[i].startsWith('-'); i++) {
|
|
19
|
+
const tsconfig = argv[i];
|
|
20
|
+
if (!options.projects.has(tsconfig)) {
|
|
21
|
+
options.projects.set(tsconfig, []);
|
|
22
|
+
}
|
|
23
|
+
if (language) {
|
|
24
|
+
options.projects.get(tsconfig).push(language);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function parseCliOptions(argv) {
|
|
30
|
+
const options = {
|
|
31
|
+
threads: 1,
|
|
32
|
+
force: argv.includes('--force'),
|
|
33
|
+
fix: argv.includes('--fix'),
|
|
34
|
+
projects: new Map()
|
|
35
|
+
};
|
|
36
|
+
if (argv.includes('--threads')) {
|
|
37
|
+
const threadsIndex = argv.indexOf('--threads');
|
|
38
|
+
const threadsArg = argv[threadsIndex + 1];
|
|
39
|
+
if (!threadsArg || threadsArg.startsWith('-')) {
|
|
40
|
+
throw new Error('Missing argument for --threads');
|
|
41
|
+
}
|
|
42
|
+
options.threads = Math.min(os.availableParallelism(), Number(threadsArg));
|
|
43
|
+
}
|
|
44
|
+
if (argv.includes('--vscode-settings')) {
|
|
45
|
+
const settingsIndex = argv.indexOf('--vscode-settings');
|
|
46
|
+
const settingsPath = argv[settingsIndex + 1];
|
|
47
|
+
if (!settingsPath || settingsPath.startsWith('-')) {
|
|
48
|
+
throw new Error('Missing argument for --vscode-settings');
|
|
49
|
+
}
|
|
50
|
+
options.vscodeSettings = settingsPath;
|
|
51
|
+
}
|
|
52
|
+
parseProjectOptions(argv, options);
|
|
53
|
+
return options;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=cli-options.js.map
|
package/lib/logger.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface SpinnerHandle {
|
|
2
|
+
start(text?: string): void;
|
|
3
|
+
stop(text?: string): void;
|
|
4
|
+
}
|
|
5
|
+
export declare const purple: (s: string) => string;
|
|
6
|
+
export declare const cyan: (s: string) => string;
|
|
7
|
+
export declare const darkGray: (s: string) => string;
|
|
8
|
+
export declare const lightRed: (s: string) => string;
|
|
9
|
+
export declare const lightGreen: (s: string) => string;
|
|
10
|
+
export declare const lightYellow: (s: string) => string;
|
|
11
|
+
export declare const colors: {
|
|
12
|
+
ts: (s: string) => string;
|
|
13
|
+
vue: (s: string) => string;
|
|
14
|
+
mdx: (s: string) => string;
|
|
15
|
+
astro: (s: string) => string;
|
|
16
|
+
};
|
|
17
|
+
export declare class Logger {
|
|
18
|
+
private createSpinner;
|
|
19
|
+
private spinnerHandle?;
|
|
20
|
+
constructor(createSpinner: () => SpinnerHandle);
|
|
21
|
+
startSpinner(message: string): void;
|
|
22
|
+
error(msg: string): void;
|
|
23
|
+
warn(msg: string): void;
|
|
24
|
+
info(msg: string): void;
|
|
25
|
+
}
|
package/lib/logger.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = exports.colors = exports.lightYellow = exports.lightGreen = exports.lightRed = exports.darkGray = exports.cyan = exports.purple = void 0;
|
|
4
|
+
const _reset = '\x1b[0m';
|
|
5
|
+
const purple = (s) => '\x1b[35m' + s + _reset;
|
|
6
|
+
exports.purple = purple;
|
|
7
|
+
const cyan = (s) => '\x1b[36m' + s + _reset;
|
|
8
|
+
exports.cyan = cyan;
|
|
9
|
+
const darkGray = (s) => '\x1b[90m' + s + _reset;
|
|
10
|
+
exports.darkGray = darkGray;
|
|
11
|
+
const lightRed = (s) => '\x1b[91m' + s + _reset;
|
|
12
|
+
exports.lightRed = lightRed;
|
|
13
|
+
const lightGreen = (s) => '\x1b[92m' + s + _reset;
|
|
14
|
+
exports.lightGreen = lightGreen;
|
|
15
|
+
const lightYellow = (s) => '\x1b[93m' + s + _reset;
|
|
16
|
+
exports.lightYellow = lightYellow;
|
|
17
|
+
exports.colors = {
|
|
18
|
+
ts: (s) => '\x1b[34m' + s + _reset,
|
|
19
|
+
vue: (s) => '\x1b[32m' + s + _reset,
|
|
20
|
+
mdx: (s) => '\x1b[33m' + s + _reset,
|
|
21
|
+
astro: (s) => '\x1b[38;5;209m' + s + _reset
|
|
22
|
+
};
|
|
23
|
+
class Logger {
|
|
24
|
+
constructor(createSpinner) {
|
|
25
|
+
this.createSpinner = createSpinner;
|
|
26
|
+
}
|
|
27
|
+
startSpinner(message) {
|
|
28
|
+
this.spinnerHandle = this.createSpinner();
|
|
29
|
+
this.spinnerHandle.start(message);
|
|
30
|
+
}
|
|
31
|
+
error(msg) {
|
|
32
|
+
this.spinnerHandle?.stop((0, exports.lightRed)(msg));
|
|
33
|
+
}
|
|
34
|
+
warn(msg) {
|
|
35
|
+
this.spinnerHandle?.stop((0, exports.lightYellow)(msg));
|
|
36
|
+
}
|
|
37
|
+
info(msg) {
|
|
38
|
+
this.spinnerHandle?.stop(msg);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.Logger = Logger;
|
|
42
|
+
//# sourceMappingURL=logger.js.map
|
package/lib/project.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import ts = require('typescript');
|
|
2
|
+
import cache = require('./cache.js');
|
|
3
|
+
import worker = require('./worker.js');
|
|
4
|
+
export declare class Project {
|
|
5
|
+
tsconfig: string;
|
|
6
|
+
languages: string[];
|
|
7
|
+
workers: ReturnType<typeof worker.create>[];
|
|
8
|
+
fileNames: string[];
|
|
9
|
+
options: ts.CompilerOptions;
|
|
10
|
+
configFile: string | undefined;
|
|
11
|
+
currentFileIndex: number;
|
|
12
|
+
builtConfig: string | undefined;
|
|
13
|
+
cache: cache.CacheData;
|
|
14
|
+
constructor(tsconfig: string, languages: string[]);
|
|
15
|
+
init(clack: typeof import('@clack/prompts')): Promise<this>;
|
|
16
|
+
private getProjectLabels;
|
|
17
|
+
}
|
package/lib/project.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Project = void 0;
|
|
4
|
+
const ts = require("typescript");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const core = require("@tsslint/core");
|
|
7
|
+
const cache = require("./cache.js");
|
|
8
|
+
const languagePlugins = require("./languagePlugins.js");
|
|
9
|
+
const logger_js_1 = require("./logger.js");
|
|
10
|
+
class Project {
|
|
11
|
+
constructor(tsconfig, languages) {
|
|
12
|
+
this.tsconfig = tsconfig;
|
|
13
|
+
this.languages = languages;
|
|
14
|
+
this.workers = [];
|
|
15
|
+
this.fileNames = [];
|
|
16
|
+
this.options = {};
|
|
17
|
+
this.currentFileIndex = 0;
|
|
18
|
+
this.cache = {};
|
|
19
|
+
}
|
|
20
|
+
async init(clack) {
|
|
21
|
+
this.configFile = ts.findConfigFile(path.dirname(this.tsconfig), ts.sys.fileExists, 'tsslint.config.ts');
|
|
22
|
+
const labels = this.getProjectLabels();
|
|
23
|
+
const label = labels.join((0, logger_js_1.darkGray)(' | '));
|
|
24
|
+
if (!this.configFile) {
|
|
25
|
+
clack.log.error(`${label} ${path.relative(process.cwd(), this.tsconfig)} ${(0, logger_js_1.darkGray)('(No tsslint.config.ts found)')}`);
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
const spinner = clack.spinner();
|
|
29
|
+
try {
|
|
30
|
+
this.builtConfig = await core.buildConfig(this.configFile, ts.sys.createHash, spinner, (s, code) => clack.log.error((0, logger_js_1.darkGray)(s)));
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
spinner.stop();
|
|
34
|
+
if (err instanceof Error) {
|
|
35
|
+
clack.log.error(err.stack ?? err.message);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
clack.log.error(String(err));
|
|
39
|
+
}
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
if (!this.builtConfig) {
|
|
43
|
+
spinner.stop();
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
const commonLine = await parseCommonLine(this.tsconfig, this.languages);
|
|
47
|
+
this.fileNames = commonLine.fileNames;
|
|
48
|
+
this.options = commonLine.options;
|
|
49
|
+
if (!this.fileNames.length) {
|
|
50
|
+
clack.log.warn(`${label} ${path.relative(process.cwd(), this.tsconfig)} ${(0, logger_js_1.darkGray)('(No included files)')}`);
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
clack.log.info(`${label} ${path.relative(process.cwd(), this.tsconfig)} ${(0, logger_js_1.darkGray)(`(${this.fileNames.length})`)}`);
|
|
54
|
+
if (!process.argv.includes('--force')) {
|
|
55
|
+
this.cache = cache.loadCache(this.tsconfig, this.configFile, ts.sys.createHash);
|
|
56
|
+
}
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
getProjectLabels() {
|
|
60
|
+
if (this.languages.length === 0) {
|
|
61
|
+
return [logger_js_1.colors.ts('TS')];
|
|
62
|
+
}
|
|
63
|
+
const labels = [];
|
|
64
|
+
if (this.languages.includes('vue')) {
|
|
65
|
+
labels.push(logger_js_1.colors.vue('Vue'));
|
|
66
|
+
}
|
|
67
|
+
if (this.languages.includes('mdx')) {
|
|
68
|
+
labels.push(logger_js_1.colors.mdx('MDX'));
|
|
69
|
+
}
|
|
70
|
+
if (this.languages.includes('astro')) {
|
|
71
|
+
labels.push(logger_js_1.colors.astro('Astro'));
|
|
72
|
+
}
|
|
73
|
+
return labels;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.Project = Project;
|
|
77
|
+
async function parseCommonLine(tsconfig, languages) {
|
|
78
|
+
const jsonConfigFile = ts.readJsonConfigFile(tsconfig, ts.sys.readFile);
|
|
79
|
+
const plugins = await languagePlugins.load(tsconfig, languages);
|
|
80
|
+
const extraFileExtensions = plugins.flatMap(plugin => plugin.typescript?.extraFileExtensions ?? []).flat();
|
|
81
|
+
return ts.parseJsonSourceFileConfigFileContent(jsonConfigFile, ts.sys, path.dirname(tsconfig), {}, tsconfig, undefined, extraFileExtensions);
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=project.js.map
|
package/lib/runner.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Project } from './project';
|
|
2
|
+
import type { CliOptions } from './cli-options';
|
|
3
|
+
import type { Logger } from './logger';
|
|
4
|
+
export interface RunnerStats {
|
|
5
|
+
processed: number;
|
|
6
|
+
excluded: number;
|
|
7
|
+
passed: number;
|
|
8
|
+
errors: number;
|
|
9
|
+
warnings: number;
|
|
10
|
+
cached: number;
|
|
11
|
+
hasFix: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare class Runner {
|
|
14
|
+
private projects;
|
|
15
|
+
private options;
|
|
16
|
+
private logger;
|
|
17
|
+
private stats;
|
|
18
|
+
private processFiles;
|
|
19
|
+
private lastSpinnerUpdate;
|
|
20
|
+
private readonly allFilesNum;
|
|
21
|
+
constructor(projects: Project[], options: CliOptions, logger: Logger);
|
|
22
|
+
run(): Promise<RunnerStats>;
|
|
23
|
+
private startWorker;
|
|
24
|
+
private selectProject;
|
|
25
|
+
private processProject;
|
|
26
|
+
private processFile;
|
|
27
|
+
private addProcessFile;
|
|
28
|
+
private removeProcessFile;
|
|
29
|
+
private updateSpinner;
|
|
30
|
+
private updateStats;
|
|
31
|
+
}
|
package/lib/runner.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Runner = void 0;
|
|
4
|
+
const worker = require("./worker");
|
|
5
|
+
const cache = require("./cache");
|
|
6
|
+
const ts = require("typescript");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
const formatting_1 = require("./formatting");
|
|
9
|
+
const logger_1 = require("./logger");
|
|
10
|
+
class Runner {
|
|
11
|
+
constructor(projects, options, logger) {
|
|
12
|
+
this.projects = projects;
|
|
13
|
+
this.options = options;
|
|
14
|
+
this.logger = logger;
|
|
15
|
+
this.stats = {
|
|
16
|
+
processed: 0,
|
|
17
|
+
excluded: 0,
|
|
18
|
+
passed: 0,
|
|
19
|
+
errors: 0,
|
|
20
|
+
warnings: 0,
|
|
21
|
+
cached: 0,
|
|
22
|
+
hasFix: false
|
|
23
|
+
};
|
|
24
|
+
this.processFiles = new Set();
|
|
25
|
+
this.lastSpinnerUpdate = Date.now();
|
|
26
|
+
this.allFilesNum = projects.reduce((sum, p) => sum + p.fileNames.length, 0);
|
|
27
|
+
}
|
|
28
|
+
async run() {
|
|
29
|
+
if (this.allFilesNum === 0) {
|
|
30
|
+
this.logger.warn('No input files.');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
if (this.options.threads === 1) {
|
|
34
|
+
await this.startWorker(worker.createLocal());
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
await Promise.all(new Array(this.options.threads)
|
|
38
|
+
.fill(0)
|
|
39
|
+
.map(() => this.startWorker(worker.create())));
|
|
40
|
+
}
|
|
41
|
+
return this.stats;
|
|
42
|
+
}
|
|
43
|
+
async startWorker(linterWorker) {
|
|
44
|
+
const unfinishedProjects = this.projects.filter(project => project.currentFileIndex < project.fileNames.length);
|
|
45
|
+
if (!unfinishedProjects.length)
|
|
46
|
+
return;
|
|
47
|
+
const project = this.selectProject(unfinishedProjects);
|
|
48
|
+
project.workers.push(linterWorker);
|
|
49
|
+
const formattingSettings = this.options.vscodeSettings
|
|
50
|
+
? (0, formatting_1.getVSCodeFormattingSettings)(this.options.vscodeSettings)
|
|
51
|
+
: undefined;
|
|
52
|
+
const setupSuccess = await linterWorker.setup(project.tsconfig, project.languages, project.configFile, project.builtConfig, project.fileNames, project.options, formattingSettings);
|
|
53
|
+
if (!setupSuccess) {
|
|
54
|
+
this.projects = this.projects.filter(p => p !== project);
|
|
55
|
+
await this.startWorker(linterWorker);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
await this.processProject(project, linterWorker);
|
|
59
|
+
await this.startWorker(linterWorker);
|
|
60
|
+
}
|
|
61
|
+
selectProject(unfinishedProjects) {
|
|
62
|
+
// First try to find a project without workers
|
|
63
|
+
const projectWithoutWorker = unfinishedProjects.find(p => !p.workers.length);
|
|
64
|
+
if (projectWithoutWorker) {
|
|
65
|
+
return projectWithoutWorker;
|
|
66
|
+
}
|
|
67
|
+
// Otherwise choose project with most files left per worker
|
|
68
|
+
return unfinishedProjects.sort((a, b) => {
|
|
69
|
+
const aFilesPerWorker = (a.fileNames.length - a.currentFileIndex) / (a.workers.length || 1);
|
|
70
|
+
const bFilesPerWorker = (b.fileNames.length - b.currentFileIndex) / (b.workers.length || 1);
|
|
71
|
+
return bFilesPerWorker - aFilesPerWorker;
|
|
72
|
+
})[0];
|
|
73
|
+
}
|
|
74
|
+
async processProject(project, linterWorker) {
|
|
75
|
+
while (project.currentFileIndex < project.fileNames.length) {
|
|
76
|
+
await this.processFile(project, project.currentFileIndex++, linterWorker);
|
|
77
|
+
}
|
|
78
|
+
cache.saveCache(project.tsconfig, project.configFile, project.cache, ts.sys.createHash);
|
|
79
|
+
}
|
|
80
|
+
async processFile(project, fileIndex, linterWorker) {
|
|
81
|
+
const fileName = project.fileNames[fileIndex];
|
|
82
|
+
const fileStat = ts.sys.getModifiedTime(fileName);
|
|
83
|
+
this.addProcessFile(fileName);
|
|
84
|
+
if (Date.now() - this.lastSpinnerUpdate > 100) {
|
|
85
|
+
this.lastSpinnerUpdate = Date.now();
|
|
86
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
87
|
+
this.updateSpinner();
|
|
88
|
+
}
|
|
89
|
+
let fileCache = project.cache[fileName];
|
|
90
|
+
if (fileCache) {
|
|
91
|
+
if (fileCache[0] !== fileStat.getTime()) {
|
|
92
|
+
fileCache[0] = fileStat.getTime();
|
|
93
|
+
fileCache[1] = {};
|
|
94
|
+
fileCache[2] = {};
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.stats.cached++;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
project.cache[fileName] = fileCache = [fileStat.getTime(), {}, {}, false];
|
|
102
|
+
}
|
|
103
|
+
const diagnostics = await linterWorker.lint(fileName, this.options.fix, fileCache);
|
|
104
|
+
if (diagnostics.length === 0) {
|
|
105
|
+
const [hasRules] = await linterWorker.hasRules(fileName, fileCache[2]);
|
|
106
|
+
if (!hasRules) {
|
|
107
|
+
this.stats.excluded++;
|
|
108
|
+
this.removeProcessFile(fileName);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
this.stats.hasFix ||= await linterWorker.hasCodeFixes(fileName);
|
|
113
|
+
this.updateStats(diagnostics);
|
|
114
|
+
this.removeProcessFile(fileName);
|
|
115
|
+
}
|
|
116
|
+
addProcessFile(fileName) {
|
|
117
|
+
this.processFiles.add(fileName);
|
|
118
|
+
this.updateSpinner();
|
|
119
|
+
}
|
|
120
|
+
removeProcessFile(fileName) {
|
|
121
|
+
this.processFiles.delete(fileName);
|
|
122
|
+
this.updateSpinner();
|
|
123
|
+
}
|
|
124
|
+
updateSpinner() {
|
|
125
|
+
if (this.processFiles.size === 1) {
|
|
126
|
+
const fileName = Array.from(this.processFiles)[0];
|
|
127
|
+
this.logger.startSpinner((0, logger_1.darkGray)(`[${this.stats.processed + this.processFiles.size}/${this.allFilesNum}] ${path.relative(process.cwd(), fileName)}`));
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
this.logger.startSpinner((0, logger_1.darkGray)(`[${this.stats.processed + this.processFiles.size}/${this.allFilesNum}] Processing ${this.processFiles.size} files`));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
updateStats(diagnostics) {
|
|
134
|
+
if (diagnostics.length === 0) {
|
|
135
|
+
this.stats.passed++;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
for (const diagnostic of diagnostics) {
|
|
139
|
+
if (diagnostic.category === ts.DiagnosticCategory.Error) {
|
|
140
|
+
this.stats.errors++;
|
|
141
|
+
}
|
|
142
|
+
else if (diagnostic.category === ts.DiagnosticCategory.Warning) {
|
|
143
|
+
this.stats.warnings++;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
this.stats.processed++;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
exports.Runner = Runner;
|
|
151
|
+
//# sourceMappingURL=runner.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsslint/cli",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"tsslint": "./bin/tsslint.js"
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@clack/prompts": "^0.8.2",
|
|
19
|
-
"@tsslint/config": "1.5.
|
|
20
|
-
"@tsslint/core": "1.5.
|
|
19
|
+
"@tsslint/config": "1.5.1",
|
|
20
|
+
"@tsslint/core": "1.5.1",
|
|
21
21
|
"@volar/language-core": "~2.4.0",
|
|
22
22
|
"@volar/typescript": "~2.4.0",
|
|
23
23
|
"glob": "^10.4.1",
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@vue/language-core": "latest"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "a0c7b85e3ba032d5c9a92f69efbba51a9f6ce06e"
|
|
33
33
|
}
|