@tsslint/core 1.0.15 → 1.0.17

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 CHANGED
@@ -3,7 +3,7 @@ export * from './lib/watch';
3
3
  import type { Config, ProjectContext } from '@tsslint/types';
4
4
  import type * as ts from 'typescript';
5
5
  export type Linter = ReturnType<typeof createLinter>;
6
- export declare function createLinter(ctx: ProjectContext, config: Config, withStack: boolean): {
6
+ export declare function createLinter(ctx: ProjectContext, config: Config | Config[], withStack: boolean): {
7
7
  lint(fileName: string): ts.DiagnosticWithLocation[];
8
8
  hasCodeFixes(fileName: string): boolean;
9
9
  getCodeFixes(fileName: string, start: number, end: number, diagnostics?: ts.Diagnostic[]): ts.CodeFixAction[];
package/index.js CHANGED
@@ -44,16 +44,42 @@ function createLinter(ctx, config, withStack) {
44
44
  const fileFixes = new Map();
45
45
  const fileRefactors = new Map();
46
46
  const sourceFiles = new Map();
47
- const plugins = (config.plugins ?? []).map(plugin => plugin(ctx));
48
- const excludes = [];
49
- for (let exclude of config.exclude ?? []) {
50
- const basePath = path.dirname(ctx.configFile);
51
- excludes.push(path.resolve(basePath, exclude));
52
- }
47
+ const basePath = path.dirname(ctx.configFile);
48
+ const configs = (Array.isArray(config) ? config : [config])
49
+ .map(config => ({
50
+ config,
51
+ includes: (config.include ?? []).map(include => {
52
+ return path.resolve(basePath, include);
53
+ }),
54
+ excludes: (config.exclude ?? []).map(exclude => {
55
+ return path.resolve(basePath, exclude);
56
+ }),
57
+ }));
58
+ const plugins = configs.map(({ config }) => config.plugins ?? []).flat().map(plugin => plugin(ctx));
59
+ const debug = configs.some(({ config }) => config.debug);
53
60
  return {
54
61
  lint(fileName) {
55
- if (excludes.some(pattern => minimatch.minimatch(fileName, pattern))) {
56
- return [];
62
+ let diagnostics = [];
63
+ let debugInfo;
64
+ if (debug) {
65
+ debugInfo = {
66
+ category: ts.DiagnosticCategory.Suggestion,
67
+ code: 'debug',
68
+ messageText: '- Config: ' + ctx.configFile + '\n',
69
+ file: ctx.languageService.getProgram().getSourceFile(fileName),
70
+ start: 0,
71
+ length: 0,
72
+ source: 'tsslint',
73
+ relatedInformation: [],
74
+ };
75
+ diagnostics.push(debugInfo);
76
+ }
77
+ const rules = getFileRules(fileName);
78
+ if (!rules || !Object.keys(rules).length) {
79
+ if (debugInfo) {
80
+ debugInfo.messageText += '- Rules: ❌ (no rules)\n';
81
+ }
82
+ return diagnostics;
57
83
  }
58
84
  const sourceFile = ctx.languageService.getProgram()?.getSourceFile(fileName);
59
85
  if (!sourceFile) {
@@ -67,32 +93,54 @@ function createLinter(ctx, config, withStack) {
67
93
  reportSuggestion,
68
94
  };
69
95
  const token = ctx.languageServiceHost.getCancellationToken?.();
70
- const rules = getFileRules(sourceFile.fileName);
71
96
  const fixes = getFileFixes(sourceFile.fileName);
72
97
  const refactors = getFileRefactors(sourceFile.fileName);
73
- let diagnostics = [];
74
98
  let currentRuleId;
99
+ let currentIssues = 0;
100
+ let currentFixes = 0;
101
+ let currentRefactors = 0;
75
102
  fixes.clear();
76
103
  refactors.clear();
104
+ if (debugInfo) {
105
+ debugInfo.messageText += '- Rules:\n';
106
+ }
77
107
  for (const [id, rule] of Object.entries(rules)) {
78
108
  if (token?.isCancellationRequested()) {
79
109
  break;
80
110
  }
81
111
  currentRuleId = id;
112
+ currentIssues = 0;
113
+ currentFixes = 0;
114
+ currentRefactors = 0;
115
+ const start = Date.now();
82
116
  try {
83
117
  rule(rulesContext);
118
+ if (debugInfo) {
119
+ const time = Date.now() - start;
120
+ debugInfo.messageText += ` - ${id}`;
121
+ const details = [];
122
+ if (currentIssues) {
123
+ details.push(`${currentIssues} issues`);
124
+ }
125
+ if (currentFixes) {
126
+ details.push(`${currentFixes} fixes`);
127
+ }
128
+ if (currentRefactors) {
129
+ details.push(`${currentRefactors} refactors`);
130
+ }
131
+ if (time) {
132
+ details.push(`${time}ms`);
133
+ }
134
+ if (details.length) {
135
+ debugInfo.messageText += ` (${details.join(', ')})`;
136
+ }
137
+ debugInfo.messageText += '\n';
138
+ }
84
139
  }
85
140
  catch (err) {
86
- diagnostics.push({
87
- category: ts.DiagnosticCategory.Error,
88
- code: id,
89
- messageText: String(err),
90
- file: sourceFile,
91
- start: 0,
92
- length: 0,
93
- source: 'tsslint',
94
- relatedInformation: [],
95
- });
141
+ if (debugInfo) {
142
+ debugInfo.messageText += ` - ${id} (❌ ${err && typeof err === 'object' && 'stack' in err ? err.stack : String(err)}})\n`;
143
+ }
96
144
  }
97
145
  }
98
146
  for (const plugin of plugins) {
@@ -152,6 +200,7 @@ function createLinter(ctx, config, withStack) {
152
200
  }
153
201
  }
154
202
  diagnostics.push(error);
203
+ currentIssues++;
155
204
  return {
156
205
  withDeprecated() {
157
206
  error.reportsDeprecated = true;
@@ -162,6 +211,7 @@ function createLinter(ctx, config, withStack) {
162
211
  return this;
163
212
  },
164
213
  withFix(title, getEdits) {
214
+ currentFixes++;
165
215
  if (!fixes.has(currentRuleId)) {
166
216
  fixes.set(currentRuleId, []);
167
217
  }
@@ -175,6 +225,7 @@ function createLinter(ctx, config, withStack) {
175
225
  return this;
176
226
  },
177
227
  withRefactor(title, getEdits) {
228
+ currentRefactors++;
178
229
  if (!refactors.has(currentRuleId)) {
179
230
  refactors.set(currentRuleId, []);
180
231
  }
@@ -191,7 +242,9 @@ function createLinter(ctx, config, withStack) {
191
242
  }
192
243
  function pushRelatedInformation(error, stack) {
193
244
  if (stack.fileName && stack.lineNumber !== undefined && stack.columnNumber !== undefined) {
194
- let fileName = stack.fileName.replace(/\\/g, '/');
245
+ let fileName = stack.fileName
246
+ .replace(/\\/g, '/')
247
+ .split('?time=')[0];
195
248
  if (fileName.startsWith('file://')) {
196
249
  fileName = fileName.substring('file://'.length);
197
250
  }
@@ -292,7 +345,19 @@ function createLinter(ctx, config, withStack) {
292
345
  function getFileRules(fileName) {
293
346
  let rules = fileRules.get(fileName);
294
347
  if (!rules) {
295
- rules = { ...config.rules };
348
+ rules = {};
349
+ for (const { config, includes, excludes } of configs) {
350
+ if (!config.rules) {
351
+ continue;
352
+ }
353
+ if (excludes.some(pattern => minimatch.minimatch(fileName, pattern))) {
354
+ continue;
355
+ }
356
+ if (includes.length && !includes.some(pattern => minimatch.minimatch(fileName, pattern))) {
357
+ continue;
358
+ }
359
+ rules = { ...rules, ...config.rules };
360
+ }
296
361
  for (const plugin of plugins) {
297
362
  if (plugin.resolveRules) {
298
363
  rules = plugin.resolveRules(fileName, rules);
package/lib/build.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  import type { Config } from '@tsslint/config';
2
- export declare function buildConfigFile(configFilePath: string, createHash?: (path: string) => string, logger?: Pick<typeof console, 'log' | 'warn' | 'error'>): Promise<Config>;
2
+ export declare function buildConfigFile(configFilePath: string, createHash?: (path: string) => string, logger?: Pick<typeof console, 'log' | 'warn' | 'error'>): Promise<Config | Config[]>;
package/lib/watch.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import esbuild = require('esbuild');
2
2
  import type { Config } from '@tsslint/config';
3
- export declare function watchConfigFile(configFilePath: string, onBuild: (config: Config | undefined, result: esbuild.BuildResult) => void, watch?: boolean, createHash?: (path: string) => string, logger?: Pick<typeof console, 'log' | 'warn' | 'error'>): Promise<esbuild.BuildContext<{
3
+ export declare function watchConfigFile(configFilePath: string, onBuild: (config: Config | Config[] | undefined, result: esbuild.BuildResult) => void, watch?: boolean, createHash?: (path: string) => string, logger?: Pick<typeof console, 'log' | 'warn' | 'error'>): Promise<esbuild.BuildContext<{
4
4
  entryPoints: string[];
5
5
  bundle: true;
6
6
  sourcemap: true;
package/lib/watch.js CHANGED
@@ -13,8 +13,7 @@ async function watchConfigFile(configFilePath, onBuild, watch = true, createHash
13
13
  let config;
14
14
  if (!result.errors.length) {
15
15
  try {
16
- config = (await import(outFile)).default;
17
- delete require.cache[outFile];
16
+ config = (await import(outFile + '?time=' + Date.now())).default;
18
17
  }
19
18
  catch (e) {
20
19
  result.errors.push({ text: String(e) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsslint/core",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "**/*.js",
@@ -12,11 +12,11 @@
12
12
  "directory": "packages/core"
13
13
  },
14
14
  "dependencies": {
15
- "@tsslint/types": "1.0.15",
15
+ "@tsslint/types": "1.0.17",
16
16
  "error-stack-parser": "^2.1.4",
17
17
  "esbuild": "^0.23.0",
18
18
  "minimatch": "^10.0.1",
19
19
  "source-map-support": "^0.5.21"
20
20
  },
21
- "gitHead": "58de9acb2cb7a1d7e93a5fb983fec54bf083f7b9"
21
+ "gitHead": "5ffa59ffc098b272ff18579d9fc57f1658978a5e"
22
22
  }