@tsslint/typescript-plugin 1.5.18 → 1.6.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.
Files changed (2) hide show
  1. package/index.js +52 -95
  2. package/package.json +5 -4
package/index.js CHANGED
@@ -3,6 +3,7 @@ const core = require("@tsslint/core");
3
3
  const path = require("path");
4
4
  const url = require("url");
5
5
  const fs = require("fs");
6
+ const ErrorStackParser = require("error-stack-parser");
6
7
  const languageServiceDecorators = new WeakMap();
7
8
  const plugin = modules => {
8
9
  const { typescript: ts } = modules;
@@ -25,106 +26,15 @@ const plugin = modules => {
25
26
  };
26
27
  return pluginModule;
27
28
  };
29
+ const fsFiles = new Map();
28
30
  function decorateLanguageService(ts, projectRoot, info) {
29
- const { getSemanticDiagnostics, getCodeFixesAtPosition, getCombinedCodeFix, getApplicableRefactors, getEditsForRefactor, getFormattingEditsForDocument, getFormattingEditsForRange, } = info.languageService;
30
- const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
31
- const getScriptVersion = info.languageServiceHost.getScriptVersion.bind(info.languageServiceHost);
31
+ const { getSemanticDiagnostics, getCodeFixesAtPosition, getCombinedCodeFix, getApplicableRefactors, getEditsForRefactor, } = info.languageService;
32
32
  const projectFileNameKeys = new Set();
33
33
  let configFile;
34
34
  let configFileBuildContext;
35
35
  let configFileDiagnostics = [];
36
36
  let config;
37
37
  let linter;
38
- let formattingSnapshot;
39
- let formattingSnapshotVersion = 0;
40
- info.languageServiceHost.getScriptSnapshot = fileName => {
41
- if (formattingSnapshot) {
42
- return formattingSnapshot;
43
- }
44
- return getScriptSnapshot(fileName);
45
- };
46
- info.languageServiceHost.getScriptVersion = fileName => {
47
- if (formattingSnapshot) {
48
- return `tsslint-fmt-${formattingSnapshotVersion++}`;
49
- }
50
- return getScriptVersion(fileName);
51
- };
52
- info.languageService.getFormattingEditsForDocument = (fileName, options) => {
53
- if (linter) {
54
- try {
55
- const sourceFile = info.languageService.getNonBoundSourceFile(fileName);
56
- const linterEdits = linter.format(sourceFile);
57
- if (linterEdits.length) {
58
- const originalLength = sourceFile.text.length;
59
- let text = sourceFile.text;
60
- for (const edit of linterEdits.sort((a, b) => (b.span.start + b.span.length) - (a.span.start + a.span.length))) {
61
- text = text.slice(0, edit.span.start) + edit.newText + text.slice(edit.span.start + edit.span.length);
62
- }
63
- formattingSnapshot = ts.ScriptSnapshot.fromString(text);
64
- const serviceEdits = getFormattingEditsForDocument(fileName, options);
65
- formattingSnapshot = undefined;
66
- if (serviceEdits.length) {
67
- for (const edit of serviceEdits.sort((a, b) => (b.span.start + b.span.length) - (a.span.start + a.span.length))) {
68
- text = text.slice(0, edit.span.start) + edit.newText + text.slice(edit.span.start + edit.span.length);
69
- }
70
- return [{
71
- span: { start: 0, length: originalLength },
72
- newText: text,
73
- }];
74
- }
75
- else {
76
- return linterEdits;
77
- }
78
- }
79
- }
80
- catch {
81
- debugger;
82
- }
83
- }
84
- return getFormattingEditsForDocument(fileName, options);
85
- };
86
- info.languageService.getFormattingEditsForRange = (fileName, start, end, options) => {
87
- if (linter) {
88
- try {
89
- const sourceFile = info.languageService.getNonBoundSourceFile(fileName);
90
- const linterEdits = linter.format(sourceFile);
91
- if (linterEdits.length) {
92
- const originalLength = sourceFile.text.length;
93
- let text = sourceFile.text;
94
- let formattingStart = start;
95
- let formattingEnd = end;
96
- for (const edit of linterEdits.sort((a, b) => (b.span.start + b.span.length) - (a.span.start + a.span.length))) {
97
- text = text.slice(0, edit.span.start) + edit.newText + text.slice(edit.span.start + edit.span.length);
98
- if (edit.span.start < start) {
99
- formattingStart += edit.newText.length - edit.span.length;
100
- }
101
- if (edit.span.start + edit.span.length < end) {
102
- formattingEnd += edit.newText.length - edit.span.length;
103
- }
104
- }
105
- formattingSnapshot = ts.ScriptSnapshot.fromString(text);
106
- const serviceEdits = getFormattingEditsForRange(fileName, formattingStart, formattingEnd, options);
107
- formattingSnapshot = undefined;
108
- if (serviceEdits.length) {
109
- for (const edit of serviceEdits.sort((a, b) => (b.span.start + b.span.length) - (a.span.start + a.span.length))) {
110
- text = text.slice(0, edit.span.start) + edit.newText + text.slice(edit.span.start + edit.span.length);
111
- }
112
- return [{
113
- span: { start: 0, length: originalLength },
114
- newText: text,
115
- }];
116
- }
117
- else {
118
- return linterEdits;
119
- }
120
- }
121
- }
122
- catch {
123
- debugger;
124
- }
125
- }
126
- return getFormattingEditsForRange(fileName, start, end, options);
127
- };
128
38
  info.languageService.getSemanticDiagnostics = fileName => {
129
39
  let result = getSemanticDiagnostics(fileName);
130
40
  if (!isProjectFileName(fileName)) {
@@ -256,14 +166,19 @@ function decorateLanguageService(ts, projectRoot, info) {
256
166
  initSourceMapSupport();
257
167
  const mtime = ts.sys.getModifiedTime?.(builtConfig)?.getTime() ?? Date.now();
258
168
  config = (await import(url.pathToFileURL(builtConfig).toString() + '?tsslint_time=' + mtime)).default;
259
- linter = core.createLinter(projectContext, path.dirname(configFile), config, 'typescript-plugin');
169
+ linter = core.createLinter(projectContext, path.dirname(configFile), config, (diag, err, stackOffset) => {
170
+ const relatedInfo = createRelatedInformation(ts, err, stackOffset);
171
+ if (relatedInfo) {
172
+ diag.relatedInformation.push(relatedInfo);
173
+ }
174
+ });
260
175
  }
261
176
  catch (err) {
262
177
  config = undefined;
263
178
  linter = undefined;
264
179
  const prevLength = configFileDiagnostics.length;
265
180
  if (err instanceof Error) {
266
- const relatedInfo = core.createRelatedInformation(ts, err, 0);
181
+ const relatedInfo = createRelatedInformation(ts, err, 0);
267
182
  if (relatedInfo) {
268
183
  configFileDiagnostics.push({
269
184
  category: ts.DiagnosticCategory.Error,
@@ -340,5 +255,47 @@ function initSourceMapSupport() {
340
255
  },
341
256
  });
342
257
  }
258
+ function createRelatedInformation(ts, err, stackOffset) {
259
+ const stacks = ErrorStackParser.parse(err);
260
+ if (stacks.length <= stackOffset) {
261
+ return;
262
+ }
263
+ const stack = stacks[stackOffset];
264
+ if (stack.fileName && stack.lineNumber !== undefined && stack.columnNumber !== undefined) {
265
+ let fileName = stack.fileName.replace(/\\/g, '/');
266
+ if (fileName.startsWith('file://')) {
267
+ fileName = fileName.substring('file://'.length);
268
+ }
269
+ if (fileName.includes('http-url:')) {
270
+ fileName = fileName.split('http-url:')[1];
271
+ }
272
+ const mtime = ts.sys.getModifiedTime?.(fileName)?.getTime() ?? 0;
273
+ const lastMtime = fsFiles.get(fileName)?.[1];
274
+ if (mtime !== lastMtime) {
275
+ const text = ts.sys.readFile(fileName);
276
+ fsFiles.set(fileName, [
277
+ text !== undefined,
278
+ mtime,
279
+ ts.createSourceFile(fileName, text ?? '', ts.ScriptTarget.Latest, true)
280
+ ]);
281
+ }
282
+ const [exist, _mtime, relatedFile] = fsFiles.get(fileName);
283
+ let pos = 0;
284
+ if (exist) {
285
+ try {
286
+ pos = relatedFile.getPositionOfLineAndCharacter(stack.lineNumber - 1, stack.columnNumber - 1) ?? 0;
287
+ }
288
+ catch { }
289
+ }
290
+ return {
291
+ category: ts.DiagnosticCategory.Message,
292
+ code: 0,
293
+ file: relatedFile,
294
+ start: pos,
295
+ length: 0,
296
+ messageText: 'at ' + (stack.functionName ?? '<anonymous>'),
297
+ };
298
+ }
299
+ }
343
300
  module.exports = plugin;
344
301
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsslint/typescript-plugin",
3
- "version": "1.5.18",
3
+ "version": "1.6.1",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "**/*.js",
@@ -12,11 +12,12 @@
12
12
  "directory": "packages/typescript-plugin"
13
13
  },
14
14
  "dependencies": {
15
- "@tsslint/core": "1.5.18",
15
+ "@tsslint/core": "1.6.1",
16
+ "error-stack-parser": "^2.1.4",
16
17
  "source-map-support": "^0.5.21"
17
18
  },
18
19
  "devDependencies": {
19
- "@tsslint/config": "1.5.18"
20
+ "@tsslint/config": "1.6.1"
20
21
  },
21
- "gitHead": "037ab1b5d72098fcf01c750420a98db8d8f28ba6"
22
+ "gitHead": "875699df671c2d9a8331c930af8c549ebab19f17"
22
23
  }