@tsslint/core 1.5.18 → 1.6.0
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.d.ts +3 -7
- package/index.js +33 -136
- package/package.json +3 -4
package/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from './lib/build';
|
|
2
2
|
export * from './lib/watch';
|
|
3
|
-
import type { Config,
|
|
3
|
+
import type { Config, LinterContext, Rule, Rules } from '@tsslint/types';
|
|
4
4
|
import type * as ts from 'typescript';
|
|
5
5
|
export type FileLintCache = [
|
|
6
6
|
mtime: number,
|
|
@@ -8,14 +8,12 @@ export type FileLintCache = [
|
|
|
8
8
|
hasFix: boolean,
|
|
9
9
|
diagnostics: ts.DiagnosticWithLocation[]
|
|
10
10
|
]>,
|
|
11
|
-
minimatchResult: Record<string, boolean
|
|
12
|
-
formated: boolean
|
|
11
|
+
minimatchResult: Record<string, boolean>
|
|
13
12
|
];
|
|
14
13
|
export type Linter = ReturnType<typeof createLinter>;
|
|
15
|
-
export declare function createLinter(ctx:
|
|
14
|
+
export declare function createLinter(ctx: LinterContext, rootDir: string, config: Config | Config[], handleError: (diag: ts.DiagnosticWithLocation, err: Error, stackOffset: number) => void, syntaxOnlyLanguageService?: ts.LanguageService & {
|
|
16
15
|
getNonBoundSourceFile?(fileName: string): ts.SourceFile;
|
|
17
16
|
}): {
|
|
18
|
-
format(sourceFile: ts.SourceFile, minimatchCache?: FileLintCache[2]): ts.TextChange[];
|
|
19
17
|
lint(fileName: string, cache?: FileLintCache): ts.DiagnosticWithLocation[];
|
|
20
18
|
hasCodeFixes(fileName: string): boolean;
|
|
21
19
|
getCodeFixes(fileName: string, start: number, end: number, diagnostics?: ts.Diagnostic[], minimatchCache?: FileLintCache[2]): ts.CodeFixAction[];
|
|
@@ -26,10 +24,8 @@ export declare function createLinter(ctx: ProjectContext, rootDir: string, confi
|
|
|
26
24
|
include: string[] | undefined;
|
|
27
25
|
exclude: string[] | undefined;
|
|
28
26
|
rules: Rules;
|
|
29
|
-
formatting: FormattingProcess[] | undefined;
|
|
30
27
|
plugins: import("@tsslint/types").PluginInstance[];
|
|
31
28
|
}[];
|
|
32
29
|
};
|
|
33
|
-
export declare function createRelatedInformation(ts: typeof import('typescript'), err: Error, stackOffset: number): ts.DiagnosticRelatedInformation | undefined;
|
|
34
30
|
export declare function combineCodeFixes(fileName: string, fixes: ts.CodeFixAction[]): ts.TextChange[];
|
|
35
31
|
export declare function applyTextChanges(baseSnapshot: ts.IScriptSnapshot, textChanges: ts.TextChange[]): ts.IScriptSnapshot;
|
package/index.js
CHANGED
|
@@ -15,18 +15,15 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.createLinter = createLinter;
|
|
18
|
-
exports.createRelatedInformation = createRelatedInformation;
|
|
19
18
|
exports.combineCodeFixes = combineCodeFixes;
|
|
20
19
|
exports.applyTextChanges = applyTextChanges;
|
|
21
20
|
__exportStar(require("./lib/build"), exports);
|
|
22
21
|
__exportStar(require("./lib/watch"), exports);
|
|
23
|
-
const ErrorStackParser = require("error-stack-parser");
|
|
24
22
|
const path = require("path");
|
|
25
23
|
const minimatch = require("minimatch");
|
|
26
|
-
function createLinter(ctx, rootDir, config,
|
|
24
|
+
function createLinter(ctx, rootDir, config, handleError, syntaxOnlyLanguageService) {
|
|
27
25
|
const ts = ctx.typescript;
|
|
28
26
|
const fileRules = new Map();
|
|
29
|
-
const fileFmtProcesses = new Map();
|
|
30
27
|
const fileConfigs = new Map();
|
|
31
28
|
const lintResults = new Map();
|
|
32
29
|
const configs = (Array.isArray(config) ? config : [config])
|
|
@@ -34,7 +31,6 @@ function createLinter(ctx, rootDir, config, mode, syntaxOnlyLanguageService) {
|
|
|
34
31
|
include: config.include,
|
|
35
32
|
exclude: config.exclude,
|
|
36
33
|
rules: config.rules ?? {},
|
|
37
|
-
formatting: config.formatting,
|
|
38
34
|
plugins: (config.plugins ?? []).map(plugin => plugin(ctx)),
|
|
39
35
|
}));
|
|
40
36
|
const normalizedPath = new Map();
|
|
@@ -42,49 +38,10 @@ function createLinter(ctx, rootDir, config, mode, syntaxOnlyLanguageService) {
|
|
|
42
38
|
const getNonBoundSourceFile = syntaxOnlyLanguageService?.getNonBoundSourceFile;
|
|
43
39
|
let shouldEnableTypeAware = false;
|
|
44
40
|
return {
|
|
45
|
-
format(sourceFile, minimatchCache) {
|
|
46
|
-
const preprocess = getFileFmtProcesses(sourceFile.fileName, minimatchCache);
|
|
47
|
-
const changes = [];
|
|
48
|
-
const tmpChanges = [];
|
|
49
|
-
const fmtCtx = {
|
|
50
|
-
typescript: ts,
|
|
51
|
-
sourceFile,
|
|
52
|
-
insert(pos, text) {
|
|
53
|
-
tmpChanges.push({ span: { start: pos, length: 0 }, newText: text });
|
|
54
|
-
},
|
|
55
|
-
remove(start, end) {
|
|
56
|
-
tmpChanges.push({ span: { start, length: end - start }, newText: '' });
|
|
57
|
-
},
|
|
58
|
-
replace(start, end, text) {
|
|
59
|
-
tmpChanges.push({ span: { start, length: end - start }, newText: text });
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
for (const process of preprocess) {
|
|
63
|
-
process(fmtCtx);
|
|
64
|
-
if (tmpChanges.every(a => {
|
|
65
|
-
const aStart = a.span.start;
|
|
66
|
-
const aEnd = aStart + a.span.length;
|
|
67
|
-
for (const b of changes) {
|
|
68
|
-
const bStart = b.span.start;
|
|
69
|
-
const bEnd = bStart + b.span.length;
|
|
70
|
-
if ((bStart >= aEnd && bStart > aStart)
|
|
71
|
-
|| (bEnd <= aStart && bEnd < aEnd)) {
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
return true;
|
|
77
|
-
})) {
|
|
78
|
-
changes.push(...tmpChanges);
|
|
79
|
-
}
|
|
80
|
-
tmpChanges.length = 0;
|
|
81
|
-
}
|
|
82
|
-
return changes;
|
|
83
|
-
},
|
|
84
41
|
lint(fileName, cache) {
|
|
85
42
|
let currentRuleId;
|
|
86
43
|
let shouldRetry = false;
|
|
87
|
-
const rules =
|
|
44
|
+
const rules = getRulesForFile(fileName, cache?.[2]);
|
|
88
45
|
const typeAwareMode = !getNonBoundSourceFile
|
|
89
46
|
|| shouldEnableTypeAware && !Object.keys(rules).some(ruleId => !rule2Mode.has(ruleId));
|
|
90
47
|
const rulesContext = typeAwareMode
|
|
@@ -104,7 +61,7 @@ function createLinter(ctx, rootDir, config, mode, syntaxOnlyLanguageService) {
|
|
|
104
61
|
reportSuggestion,
|
|
105
62
|
};
|
|
106
63
|
const token = ctx.languageServiceHost.getCancellationToken?.();
|
|
107
|
-
const configs =
|
|
64
|
+
const configs = getConfigsForFile(fileName, cache?.[2]);
|
|
108
65
|
lintResults.set(fileName, [rulesContext.sourceFile, new Map(), []]);
|
|
109
66
|
const lintResult = lintResults.get(fileName);
|
|
110
67
|
for (const [ruleId, rule] of Object.entries(rules)) {
|
|
@@ -225,12 +182,8 @@ function createLinter(ctx, rootDir, config, mode, syntaxOnlyLanguageService) {
|
|
|
225
182
|
})),
|
|
226
183
|
});
|
|
227
184
|
}
|
|
228
|
-
if (
|
|
229
|
-
err
|
|
230
|
-
const relatedInfo = createRelatedInformation(ts, err, stackOffset);
|
|
231
|
-
if (relatedInfo) {
|
|
232
|
-
error.relatedInformation.push(relatedInfo);
|
|
233
|
-
}
|
|
185
|
+
if (typeof stackOffset === 'number') {
|
|
186
|
+
handleError(error, err ?? new Error(), stackOffset);
|
|
234
187
|
}
|
|
235
188
|
let lintResult = lintResults.get(fileName);
|
|
236
189
|
if (!lintResult) {
|
|
@@ -282,7 +235,7 @@ function createLinter(ctx, rootDir, config, mode, syntaxOnlyLanguageService) {
|
|
|
282
235
|
return [];
|
|
283
236
|
}
|
|
284
237
|
const sourceFile = lintResult[0];
|
|
285
|
-
const configs =
|
|
238
|
+
const configs = getConfigsForFile(fileName, minimatchCache);
|
|
286
239
|
const result = [];
|
|
287
240
|
for (const [diagnostic, actions] of lintResult[1]) {
|
|
288
241
|
if (diagnostics?.length && !diagnostics.includes(diagnostic)) {
|
|
@@ -352,27 +305,14 @@ function createLinter(ctx, rootDir, config, mode, syntaxOnlyLanguageService) {
|
|
|
352
305
|
}
|
|
353
306
|
}
|
|
354
307
|
},
|
|
355
|
-
getRules:
|
|
356
|
-
getConfigs:
|
|
308
|
+
getRules: getRulesForFile,
|
|
309
|
+
getConfigs: getConfigsForFile,
|
|
357
310
|
};
|
|
358
|
-
function
|
|
359
|
-
if (!fileFmtProcesses.has(fileName)) {
|
|
360
|
-
const allPreprocess = [];
|
|
361
|
-
const configs = getFileConfigs(fileName, minimatchCache);
|
|
362
|
-
for (const { formatting } of configs) {
|
|
363
|
-
if (formatting) {
|
|
364
|
-
allPreprocess.push(...formatting);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
fileFmtProcesses.set(fileName, allPreprocess);
|
|
368
|
-
}
|
|
369
|
-
return fileFmtProcesses.get(fileName);
|
|
370
|
-
}
|
|
371
|
-
function getFileRules(fileName, minimatchCache) {
|
|
311
|
+
function getRulesForFile(fileName, minimatchCache) {
|
|
372
312
|
let rules = fileRules.get(fileName);
|
|
373
313
|
if (!rules) {
|
|
374
314
|
rules = {};
|
|
375
|
-
const configs =
|
|
315
|
+
const configs = getConfigsForFile(fileName, minimatchCache);
|
|
376
316
|
for (const config of configs) {
|
|
377
317
|
collectRules(rules, config.rules, []);
|
|
378
318
|
}
|
|
@@ -387,16 +327,7 @@ function createLinter(ctx, rootDir, config, mode, syntaxOnlyLanguageService) {
|
|
|
387
327
|
}
|
|
388
328
|
return rules;
|
|
389
329
|
}
|
|
390
|
-
function
|
|
391
|
-
for (const [path, rule] of Object.entries(rules)) {
|
|
392
|
-
if (typeof rule === 'object') {
|
|
393
|
-
collectRules(record, rule, [...paths, path]);
|
|
394
|
-
continue;
|
|
395
|
-
}
|
|
396
|
-
record[[...paths, path].join('/')] = rule;
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
function getFileConfigs(fileName, minimatchCache) {
|
|
330
|
+
function getConfigsForFile(fileName, minimatchCache) {
|
|
400
331
|
let result = fileConfigs.get(fileName);
|
|
401
332
|
if (!result) {
|
|
402
333
|
result = configs.filter(({ include, exclude }) => {
|
|
@@ -409,68 +340,34 @@ function createLinter(ctx, rootDir, config, mode, syntaxOnlyLanguageService) {
|
|
|
409
340
|
return true;
|
|
410
341
|
});
|
|
411
342
|
fileConfigs.set(fileName, result);
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
let normalized = normalizedPath.get(pattern);
|
|
419
|
-
if (!normalized) {
|
|
420
|
-
normalized = ts.server.toNormalizedPath(path.resolve(rootDir, pattern));
|
|
421
|
-
normalizedPath.set(pattern, normalized);
|
|
422
|
-
}
|
|
423
|
-
const res = minimatch.minimatch(fileName, normalized, { dot: true });
|
|
424
|
-
if (minimatchCache) {
|
|
425
|
-
minimatchCache[pattern] = res;
|
|
343
|
+
}
|
|
344
|
+
return result;
|
|
345
|
+
function _minimatch(pattern) {
|
|
346
|
+
if (minimatchCache) {
|
|
347
|
+
if (pattern in minimatchCache) {
|
|
348
|
+
return minimatchCache[pattern];
|
|
426
349
|
}
|
|
427
|
-
return res;
|
|
428
350
|
}
|
|
351
|
+
let normalized = normalizedPath.get(pattern);
|
|
352
|
+
if (!normalized) {
|
|
353
|
+
normalized = ts.server.toNormalizedPath(path.resolve(rootDir, pattern));
|
|
354
|
+
normalizedPath.set(pattern, normalized);
|
|
355
|
+
}
|
|
356
|
+
const res = minimatch.minimatch(fileName, normalized, { dot: true });
|
|
357
|
+
if (minimatchCache) {
|
|
358
|
+
minimatchCache[pattern] = res;
|
|
359
|
+
}
|
|
360
|
+
return res;
|
|
429
361
|
}
|
|
430
|
-
return result;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
const fsFiles = new Map();
|
|
434
|
-
function createRelatedInformation(ts, err, stackOffset) {
|
|
435
|
-
const stacks = ErrorStackParser.parse(err);
|
|
436
|
-
if (stacks.length <= stackOffset) {
|
|
437
|
-
return;
|
|
438
362
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
445
|
-
if (fileName.includes('http-url:')) {
|
|
446
|
-
fileName = fileName.split('http-url:')[1];
|
|
447
|
-
}
|
|
448
|
-
const mtime = ts.sys.getModifiedTime?.(fileName)?.getTime() ?? 0;
|
|
449
|
-
const lastMtime = fsFiles.get(fileName)?.[1];
|
|
450
|
-
if (mtime !== lastMtime) {
|
|
451
|
-
const text = ts.sys.readFile(fileName);
|
|
452
|
-
fsFiles.set(fileName, [
|
|
453
|
-
text !== undefined,
|
|
454
|
-
mtime,
|
|
455
|
-
ts.createSourceFile(fileName, text ?? '', ts.ScriptTarget.Latest, true)
|
|
456
|
-
]);
|
|
457
|
-
}
|
|
458
|
-
const [exist, _mtime, relatedFile] = fsFiles.get(fileName);
|
|
459
|
-
let pos = 0;
|
|
460
|
-
if (exist) {
|
|
461
|
-
try {
|
|
462
|
-
pos = relatedFile.getPositionOfLineAndCharacter(stack.lineNumber - 1, stack.columnNumber - 1) ?? 0;
|
|
363
|
+
function collectRules(record, rules, paths) {
|
|
364
|
+
for (const [path, rule] of Object.entries(rules)) {
|
|
365
|
+
if (typeof rule === 'object') {
|
|
366
|
+
collectRules(record, rule, [...paths, path]);
|
|
367
|
+
continue;
|
|
463
368
|
}
|
|
464
|
-
|
|
369
|
+
record[[...paths, path].join('/')] = rule;
|
|
465
370
|
}
|
|
466
|
-
return {
|
|
467
|
-
category: ts.DiagnosticCategory.Message,
|
|
468
|
-
code: 0,
|
|
469
|
-
file: relatedFile,
|
|
470
|
-
start: pos,
|
|
471
|
-
length: 0,
|
|
472
|
-
messageText: 'at ' + (stack.functionName ?? '<anonymous>'),
|
|
473
|
-
};
|
|
474
371
|
}
|
|
475
372
|
}
|
|
476
373
|
function combineCodeFixes(fileName, fixes) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsslint/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.js",
|
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
"directory": "packages/core"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@tsslint/types": "1.
|
|
16
|
-
"error-stack-parser": "^2.1.4",
|
|
15
|
+
"@tsslint/types": "1.6.0",
|
|
17
16
|
"esbuild": ">=0.17.0",
|
|
18
17
|
"minimatch": "^10.0.1"
|
|
19
18
|
},
|
|
@@ -23,5 +22,5 @@
|
|
|
23
22
|
"scripts": {
|
|
24
23
|
"postinstall": "node scripts/cleanCache.js"
|
|
25
24
|
},
|
|
26
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "c1cec085945f166911af87454f6f1dd3e9fc2986"
|
|
27
26
|
}
|