@tsslint/typescript-plugin 0.0.1 → 0.0.3

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 CHANGED
@@ -22,7 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- const watchConfig_1 = require("./lib/watchConfig");
26
25
  const builtInPlugins_1 = require("./lib/builtInPlugins");
27
26
  const path = __importStar(require("path"));
28
27
  const languageServiceDecorators = new WeakMap();
@@ -47,20 +46,20 @@ const init = (modules) => {
47
46
  function decorateLanguageService(ts, tsconfig, info) {
48
47
  const getCompilerOptionsDiagnostics = info.languageService.getCompilerOptionsDiagnostics;
49
48
  const getSyntacticDiagnostics = info.languageService.getSyntacticDiagnostics;
50
- const getApplicableRefactors = info.languageService.getApplicableRefactors;
51
- const getEditsForRefactor = info.languageService.getEditsForRefactor;
52
- let compilerOptionsDiagnostics = [];
49
+ const getCodeFixesAtPosition = info.languageService.getCodeFixesAtPosition;
53
50
  let configFile;
54
51
  let configFileBuildContext;
52
+ let configFileDiagnostics = [];
55
53
  let config;
56
54
  let plugins = [];
57
55
  info.languageService.getCompilerOptionsDiagnostics = () => {
58
- return getCompilerOptionsDiagnostics().concat(compilerOptionsDiagnostics);
56
+ return getCompilerOptionsDiagnostics().concat(configFileDiagnostics);
59
57
  };
60
58
  info.languageService.getSyntacticDiagnostics = fileName => {
61
59
  let errors = getSyntacticDiagnostics(fileName);
60
+ errors = errors.concat(configFileDiagnostics);
62
61
  const sourceFile = info.languageService.getProgram()?.getSourceFile(fileName);
63
- if (!sourceFile) {
62
+ if (!sourceFile || sourceFile.text.length > 20000) {
64
63
  return errors;
65
64
  }
66
65
  const token = info.languageServiceHost.getCancellationToken?.();
@@ -78,63 +77,87 @@ function decorateLanguageService(ts, tsconfig, info) {
78
77
  errors = errors.concat(pluginResult);
79
78
  }
80
79
  }
80
+ if (config?.debug) {
81
+ errors.push({
82
+ category: ts.DiagnosticCategory.Warning,
83
+ source: 'tsslint',
84
+ code: 'debug-info',
85
+ messageText: JSON.stringify({
86
+ rules: Object.keys(config?.rules ?? {}),
87
+ plugins: plugins.length,
88
+ configFile,
89
+ tsconfig,
90
+ }, null, 2),
91
+ file: sourceFile,
92
+ start: 0,
93
+ length: 0,
94
+ });
95
+ }
81
96
  return errors;
82
97
  };
83
- info.languageService.getApplicableRefactors = (fileName, positionOrRange, ...rest) => {
84
- let refactors = getApplicableRefactors(fileName, positionOrRange, ...rest);
85
- const sourceFile = info.languageService.getProgram()?.getSourceFile(fileName);
86
- if (!sourceFile) {
87
- return refactors;
88
- }
98
+ info.languageService.getCodeFixesAtPosition = (fileName, start, end, errorCodes, formatOptions, preferences) => {
99
+ let fixes = getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences);
89
100
  const token = info.languageServiceHost.getCancellationToken?.();
90
101
  for (const plugin of plugins) {
91
102
  if (token?.isCancellationRequested()) {
92
103
  break;
93
104
  }
94
- refactors = refactors.concat(plugin.getFixes?.(sourceFile, positionOrRange) ?? []);
95
- }
96
- return refactors;
97
- };
98
- info.languageService.getEditsForRefactor = (fileName, formatOptions, positionOrRange, refactorName, actionName, ...rest) => {
99
- const sourceFile = info.languageService.getProgram()?.getSourceFile(fileName);
100
- if (!sourceFile) {
101
- return;
102
- }
103
- for (const plugin of plugins) {
104
- const edits = plugin.fix?.(sourceFile, refactorName, actionName);
105
- if (edits) {
106
- return { edits };
107
- }
105
+ fixes = fixes.concat(plugin.getFixes?.(fileName, start, end, errorCodes) ?? []);
108
106
  }
109
- return getEditsForRefactor(fileName, formatOptions, positionOrRange, refactorName, actionName, ...rest);
107
+ return fixes;
110
108
  };
111
109
  return { update };
112
110
  async function update(pluginConfig) {
113
- const jsonConfigFile = ts.readJsonConfigFile(tsconfig, ts.sys.readFile);
114
- const start = jsonConfigFile.text.indexOf(pluginConfig.configFile) - 1;
115
- const length = pluginConfig.configFile.length + 2;
111
+ let configOptionSpan = { start: 0, length: 0 };
116
112
  let newConfigFile;
113
+ let configImportPath;
117
114
  let configResolveError;
115
+ const jsonConfigFile = ts.readJsonConfigFile(tsconfig, ts.sys.readFile);
118
116
  try {
119
- newConfigFile = require.resolve(pluginConfig.configFile, { paths: [path.dirname(tsconfig)] });
117
+ configImportPath = require.resolve('@tsslint/config', { paths: [path.dirname(tsconfig)] });
120
118
  }
121
119
  catch (err) {
122
120
  configResolveError = err;
121
+ configFileDiagnostics = [{
122
+ category: ts.DiagnosticCategory.Error,
123
+ code: 0,
124
+ messageText: String(err),
125
+ file: jsonConfigFile,
126
+ start: 0,
127
+ length: 0,
128
+ }];
129
+ return;
130
+ }
131
+ const { findConfigFile, watchConfigFile } = require(configImportPath);
132
+ if (pluginConfig?.configFile) {
133
+ configOptionSpan = {
134
+ start: jsonConfigFile.text.indexOf(pluginConfig.configFile) - 1,
135
+ length: pluginConfig.configFile.length + 2,
136
+ };
137
+ try {
138
+ newConfigFile = require.resolve(pluginConfig.configFile, { paths: [path.dirname(tsconfig)] });
139
+ }
140
+ catch (err) {
141
+ configResolveError = err;
142
+ }
143
+ }
144
+ else {
145
+ newConfigFile = findConfigFile(tsconfig);
123
146
  }
124
147
  if (newConfigFile !== configFile) {
125
148
  configFile = newConfigFile;
126
149
  config = undefined;
127
150
  plugins = [];
128
151
  configFileBuildContext?.dispose();
129
- compilerOptionsDiagnostics = [];
152
+ configFileDiagnostics = [];
130
153
  if (configResolveError) {
131
- compilerOptionsDiagnostics.push({
154
+ configFileDiagnostics.push({
132
155
  category: ts.DiagnosticCategory.Error,
133
156
  code: 0,
134
157
  messageText: String(configResolveError),
135
158
  file: jsonConfigFile,
136
- start: start,
137
- length: length,
159
+ start: configOptionSpan.start,
160
+ length: configOptionSpan.length,
138
161
  });
139
162
  }
140
163
  if (!configFile) {
@@ -147,20 +170,34 @@ function decorateLanguageService(ts, tsconfig, info) {
147
170
  languageService: info.languageService,
148
171
  typescript: ts,
149
172
  };
150
- configFileBuildContext = await (0, watchConfig_1.watchConfig)(configFile, async (_config, { errors, warnings }) => {
173
+ configFileBuildContext = await watchConfigFile(configFile, async (_config, { errors, warnings }) => {
151
174
  config = _config;
152
- compilerOptionsDiagnostics = [
175
+ configFileDiagnostics = [
153
176
  ...errors.map(error => [error, ts.DiagnosticCategory.Error]),
154
177
  ...warnings.map(error => [error, ts.DiagnosticCategory.Warning]),
155
178
  ].map(([error, category]) => {
156
179
  const diag = {
157
180
  category,
181
+ source: 'tsslint',
158
182
  code: 0,
159
- messageText: error.text,
183
+ messageText: 'Failed to build config',
160
184
  file: jsonConfigFile,
161
- start: start,
162
- length: length,
185
+ start: configOptionSpan.start,
186
+ length: configOptionSpan.length,
163
187
  };
188
+ if (error.location) {
189
+ const fileName = path.resolve(error.location.file);
190
+ const fileText = ts.sys.readFile(error.location.file);
191
+ const sourceFile = ts.createSourceFile(fileName, fileText ?? '', ts.ScriptTarget.Latest, true);
192
+ diag.relatedInformation = [{
193
+ category,
194
+ code: error.id,
195
+ messageText: error.text,
196
+ file: sourceFile,
197
+ start: sourceFile.getPositionOfLineAndCharacter(error.location.line - 1, error.location.column),
198
+ length: error.location.lineText.length,
199
+ }];
200
+ }
164
201
  return diag;
165
202
  });
166
203
  if (config) {
@@ -1,3 +1,3 @@
1
- import { Plugin } from '@tsslint/config';
1
+ import type { Plugin } from '@tsslint/config';
2
2
  export declare const builtInPlugins: Plugin[];
3
3
  //# sourceMappingURL=builtInPlugins.d.ts.map
@@ -31,6 +31,7 @@ exports.builtInPlugins = [
31
31
  const ts = ctx.typescript;
32
32
  const fileFixes = new Map();
33
33
  const sourceFiles = new Map();
34
+ const configSourceFile = ts.createSourceFile(ctx.configFile, ts.sys.readFile(ctx.configFile) ?? '', ts.ScriptTarget.Latest, true);
34
35
  return {
35
36
  lint(sourceFile, rules) {
36
37
  const rulesContext = {
@@ -87,27 +88,21 @@ exports.builtInPlugins = [
87
88
  }
88
89
  const stackFile = sourceFiles.get(fileName);
89
90
  const pos = stackFile?.getPositionOfLineAndCharacter(stack.lineNumber - 1, stack.columnNumber - 1);
90
- let reportNode;
91
- stackFile.forEachChild(function visit(node) {
92
- if (node.end < pos || reportNode) {
93
- return;
94
- }
95
- if (node.pos <= pos) {
96
- if (node.getStart() === pos) {
97
- reportNode = node;
98
- }
99
- else {
100
- node.forEachChild(visit);
101
- }
102
- }
103
- });
104
91
  error.relatedInformation?.push({
105
92
  category: ts.DiagnosticCategory.Message,
106
93
  code: 0,
107
94
  file: stackFile,
108
95
  start: pos,
109
- length: reportNode?.end ? reportNode.end - pos : 0,
110
- messageText: '👈 Reporter',
96
+ length: 0,
97
+ messageText: 'Related rule file',
98
+ });
99
+ error.relatedInformation?.push({
100
+ category: ts.DiagnosticCategory.Message,
101
+ code: 0,
102
+ file: configSourceFile,
103
+ start: 0,
104
+ length: 0,
105
+ messageText: 'Related config file',
111
106
  });
112
107
  }
113
108
  }
@@ -136,40 +131,25 @@ exports.builtInPlugins = [
136
131
  };
137
132
  }
138
133
  },
139
- getFixes(sourceFile, positionOrRange) {
140
- const start = typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos;
141
- const end = typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.end;
142
- const fixes = getFileFixes(sourceFile.fileName);
143
- const refactors = [];
144
- for (const [errorCode, _fixes] of fixes) {
145
- for (let i = 0; i < _fixes.length; i++) {
146
- const fix = _fixes[i];
147
- if ((start <= fix.start && end >= fix.end) ||
134
+ getFixes(fileName, start, end) {
135
+ const fixesMap = getFileFixes(fileName);
136
+ const result = [];
137
+ for (const [_errorCode, fixes] of fixesMap) {
138
+ for (let i = 0; i < fixes.length; i++) {
139
+ const fix = fixes[i];
140
+ if ((fix.start >= start && fix.start <= end) ||
141
+ (fix.end >= start && fix.end <= end) ||
148
142
  (start >= fix.start && start <= fix.end) ||
149
143
  (end >= fix.start && end <= fix.end)) {
150
- if (refactors[refactors.length - 1]?.name !== 'tsslint/fix') {
151
- refactors.push({
152
- name: 'tsslint/fix',
153
- description: 'Fix ' + errorCode,
154
- actions: [],
155
- });
156
- }
157
- refactors[refactors.length - 1].actions.push({
158
- name: errorCode + '-' + i,
144
+ result.push({
145
+ fixName: `tsslint: ${fix.title}`,
159
146
  description: fix.title,
147
+ changes: fix.getEdits(),
160
148
  });
161
149
  }
162
150
  }
163
151
  }
164
- return refactors;
165
- },
166
- fix(sourceFile, refactorName, actionName) {
167
- if (refactorName === 'tsslint/fix') {
168
- const errorCode = actionName.substring(0, actionName.lastIndexOf('-'));
169
- const fixIndex = actionName.substring(actionName.lastIndexOf('-') + 1);
170
- const fix = getFileFixes(sourceFile.fileName).get(errorCode)[Number(fixIndex)];
171
- return fix.getEdits();
172
- }
152
+ return result;
173
153
  },
174
154
  };
175
155
  function getFileFixes(fileName) {
@@ -1,15 +1,4 @@
1
1
  import type { Config } from '@tsslint/config';
2
- import esbuild = require('esbuild');
3
- export declare function watchConfig(tsConfigPath: string, onBuild: (config: Config | undefined, result: esbuild.BuildResult) => void): Promise<esbuild.BuildContext<{
4
- entryPoints: string[];
5
- bundle: true;
6
- sourcemap: true;
7
- outfile: string;
8
- format: "cjs";
9
- platform: "node";
10
- plugins: {
11
- name: string;
12
- setup(build: esbuild.PluginBuild): void;
13
- }[];
14
- }>>;
2
+ import rollup = require('rollup');
3
+ export declare function watchConfig(tsConfigPath: string, onBuild: (config: Config | undefined, result: Error | undefined) => void): Promise<rollup.RollupBuild>;
15
4
  //# sourceMappingURL=watchConfig.d.ts.map
@@ -1,53 +1,88 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.watchConfig = void 0;
4
- const esbuild = require("esbuild");
4
+ const rollup = require("rollup");
5
5
  const path = require("path");
6
6
  async function watchConfig(tsConfigPath, onBuild) {
7
- const outDir = path.resolve(path.dirname(require.resolve('@tsslint/typescript-plugin/package.json')), '..', '..', '.tsslint');
7
+ const outDir = path.resolve(__dirname, '..', '..', '.tsslint');
8
8
  const outFileName = btoa(path.relative(outDir, tsConfigPath)) + '.cjs';
9
9
  const outFile = path.join(outDir, outFileName);
10
- const ctx = await esbuild.context({
11
- entryPoints: [tsConfigPath],
12
- bundle: true,
13
- sourcemap: true,
14
- outfile: outFile,
15
- format: 'cjs',
16
- platform: 'node',
10
+ // const ctx = await esbuild.context({
11
+ // entryPoints: [tsConfigPath],
12
+ // bundle: true,
13
+ // sourcemap: true,
14
+ // outfile: outFile,
15
+ // format: 'cjs',
16
+ // platform: 'node',
17
+ // plugins: [{
18
+ // name: 'tsslint',
19
+ // setup(build) {
20
+ // build.onResolve({ filter: /.*/ }, args => {
21
+ // if (!args.path.endsWith('.ts')) {
22
+ // try {
23
+ // const jsPath = require.resolve(args.path, { paths: [args.resolveDir] });
24
+ // return {
25
+ // path: jsPath,
26
+ // external: true,
27
+ // };
28
+ // } catch { }
29
+ // }
30
+ // return {};
31
+ // });
32
+ // build.onEnd(result => {
33
+ // let config: Config | undefined;
34
+ // if (!result.errors.length) {
35
+ // try {
36
+ // config = require(outFile).default;
37
+ // delete require.cache[outFile!];
38
+ // } catch (e) {
39
+ // result.errors.push({ text: String(e) } as any);
40
+ // }
41
+ // }
42
+ // onBuild(config, result);
43
+ // });
44
+ // },
45
+ // }],
46
+ // });
47
+ const bundle = await rollup.rollup({
48
+ input: tsConfigPath,
49
+ output: {
50
+ file: outFile,
51
+ format: 'cjs',
52
+ sourcemap: true,
53
+ },
54
+ watch: {},
55
+ external: ['typescript'],
17
56
  plugins: [{
18
57
  name: 'tsslint',
19
- setup(build) {
20
- build.onResolve({ filter: /.*/ }, args => {
21
- if (!args.path.endsWith('.ts')) {
22
- try {
23
- const jsPath = require.resolve(args.path, { paths: [args.resolveDir] });
24
- return {
25
- path: jsPath,
26
- external: true,
27
- };
28
- }
29
- catch { }
58
+ resolveId(id, importer) {
59
+ if (!id.endsWith('.ts') && importer) {
60
+ try {
61
+ const jsPath = require.resolve(id, { paths: [path.dirname(importer)] });
62
+ return {
63
+ id: jsPath,
64
+ external: true,
65
+ };
30
66
  }
31
- return {};
32
- });
33
- build.onEnd(result => {
34
- let config;
35
- if (!result.errors.length) {
36
- try {
37
- config = require(outFile).default;
38
- delete require.cache[outFile];
39
- }
40
- catch (e) {
41
- result.errors.push({ text: String(e) });
42
- }
67
+ catch { }
68
+ }
69
+ },
70
+ buildEnd(error) {
71
+ let config;
72
+ if (!error) {
73
+ try {
74
+ config = require(outFile).default;
75
+ delete require.cache[outFile];
76
+ }
77
+ catch (e) {
78
+ error = { message: String(e) };
43
79
  }
44
- onBuild(config, result);
45
- });
80
+ }
81
+ onBuild(config, error);
46
82
  },
47
83
  }],
48
84
  });
49
- await ctx.watch();
50
- return ctx;
85
+ return bundle;
51
86
  }
52
87
  exports.watchConfig = watchConfig;
53
88
  //# sourceMappingURL=watchConfig.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsslint/typescript-plugin",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "**/*.js",
@@ -12,10 +12,11 @@
12
12
  "directory": "packages/typescript-plugin"
13
13
  },
14
14
  "dependencies": {
15
- "@tsslint/config": "0.0.1",
16
15
  "error-stack-parser": "^2.1.4",
17
- "esbuild": "^0.19.9",
18
16
  "source-map-support": "^0.5.19"
19
17
  },
20
- "gitHead": "8a11cfe2ad196e8df0566d798c71bb40e3a2a6a0"
18
+ "devDependencies": {
19
+ "@tsslint/config": "0.0.3"
20
+ },
21
+ "gitHead": "13557d614907865f38ad32fd3582c9f198fb9ffa"
21
22
  }