@zentryc5t/ts-plugin-for-bruno 3.1.0 → 3.2.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/README.md +4 -0
- package/out/codeBlocks/bruCodeBlocks.js +71 -0
- package/out/codeBlocks/bruCodeBlocks.js.map +1 -0
- package/out/codeChanges/codeChanges.js +144 -0
- package/out/codeChanges/codeChanges.js.map +1 -0
- package/out/collection/collectionFormat.js +69 -0
- package/out/collection/collectionFormat.js.map +1 -0
- package/out/constants.js +36 -0
- package/out/constants.js.map +1 -0
- package/out/diagnostics/filterDefaultDiagnostics.js +81 -0
- package/out/diagnostics/filterDefaultDiagnostics.js.map +1 -0
- package/out/fileContent.js +28 -0
- package/out/fileContent.js.map +1 -0
- package/out/fileTypes.js +16 -0
- package/out/fileTypes.js.map +1 -0
- package/out/index.js +18 -297
- package/out/index.js.map +1 -1
- package/out/languageService/codeChangeOverrides.js +40 -0
- package/out/languageService/codeChangeOverrides.js.map +1 -0
- package/out/languageService/diagnosticsOverrides.js +41 -0
- package/out/languageService/diagnosticsOverrides.js.map +1 -0
- package/out/languageService/formattingOverrides.js +18 -0
- package/out/languageService/formattingOverrides.js.map +1 -0
- package/out/languageService/navigationOverrides.js +98 -0
- package/out/languageService/navigationOverrides.js.map +1 -0
- package/out/pluginConfiguration.js +29 -0
- package/out/pluginConfiguration.js.map +1 -0
- package/out/yamlFiles/getIndentationOfScripts.js +24 -0
- package/out/yamlFiles/getIndentationOfScripts.js.map +1 -0
- package/out/yamlFiles/maskYamlFileContent.js +126 -0
- package/out/yamlFiles/maskYamlFileContent.js.map +1 -0
- package/out/yamlFiles/maskYamlFilesForTypescriptServer.js +94 -0
- package/out/yamlFiles/maskYamlFilesForTypescriptServer.js.map +1 -0
- package/package.json +3 -2
- package/src/codeBlocks/bruCodeBlocks.ts +66 -0
- package/src/codeChanges/codeChanges.ts +182 -0
- package/src/collection/collectionFormat.ts +96 -0
- package/src/constants.test.ts +12 -0
- package/src/constants.ts +31 -0
- package/src/diagnostics/filterDefaultDiagnostics.ts +145 -0
- package/src/fileContent.ts +38 -0
- package/src/fileTypes.ts +13 -0
- package/src/index.test.ts +329 -0
- package/src/index.ts +24 -499
- package/src/languageService/codeChangeOverrides.ts +90 -0
- package/src/languageService/diagnosticsOverrides.ts +65 -0
- package/src/languageService/formattingOverrides.ts +42 -0
- package/src/languageService/navigationOverrides.ts +201 -0
- package/src/pluginConfiguration.ts +34 -0
- package/src/yamlFiles/getIndentationOfScripts.ts +34 -0
- package/src/yamlFiles/maskYamlFileContent.test.ts +213 -0
- package/src/yamlFiles/maskYamlFileContent.ts +179 -0
- package/src/yamlFiles/maskYamlFilesForTypescriptServer.ts +85 -0
- package/tsconfig.json +2 -1
package/src/index.ts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
import { dirname, extname } from "path";
|
|
2
1
|
import * as ts from "typescript/lib/tsserverlibrary";
|
|
2
|
+
import { maskYamlFilesForTypescriptServer } from "./yamlFiles/maskYamlFilesForTypescriptServer";
|
|
3
|
+
import { overrideCodeChanges } from "./languageService/codeChangeOverrides";
|
|
4
|
+
import { overrideDiagnostics } from "./languageService/diagnosticsOverrides";
|
|
5
|
+
import { overrideFormatting } from "./languageService/formattingOverrides";
|
|
6
|
+
import {
|
|
7
|
+
overrideHoverAndCompletions,
|
|
8
|
+
overrideReferencesAndDefinitions,
|
|
9
|
+
overrideRename,
|
|
10
|
+
} from "./languageService/navigationOverrides";
|
|
11
|
+
import { PluginConfig, PluginConfiguration } from "./pluginConfiguration";
|
|
3
12
|
|
|
4
13
|
function init(_modules: {
|
|
5
14
|
typescript: typeof import("typescript/lib/tsserverlibrary");
|
|
6
15
|
}) {
|
|
16
|
+
const configuration = new PluginConfiguration();
|
|
17
|
+
|
|
7
18
|
function create(info: ts.server.PluginCreateInfo) {
|
|
19
|
+
maskYamlFilesForTypescriptServer(info, configuration);
|
|
20
|
+
|
|
8
21
|
// Set up decorator object
|
|
9
22
|
const proxy: ts.LanguageService = Object.create(null);
|
|
10
23
|
|
|
@@ -18,512 +31,24 @@ function init(_modules: {
|
|
|
18
31
|
x.apply(info.languageService, args);
|
|
19
32
|
}
|
|
20
33
|
|
|
21
|
-
proxy
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
proxy.getSemanticDiagnostics = (fileName) => {
|
|
30
|
-
const isBruFile = isBrunoFile(fileName);
|
|
31
|
-
|
|
32
|
-
const allDiagnostics = filterDefaultDiagnostics(
|
|
33
|
-
info,
|
|
34
|
-
fileName,
|
|
35
|
-
info.languageService.getSemanticDiagnostics(fileName),
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
// The ts server always reports errors when importing a Javascript function in a .bru file.
|
|
39
|
-
return isBruFile
|
|
40
|
-
? allDiagnostics.filter(
|
|
41
|
-
// Do not show diagnostics that only make sense for Typescript files.
|
|
42
|
-
// Bru file code blocks should be treated like Javascript functions instead.
|
|
43
|
-
// A list of diagnostics can be found here: https://github.com/microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
|
|
44
|
-
({ code }) => ![7_006, 7_031, 18_046].includes(code),
|
|
45
|
-
)
|
|
46
|
-
: allDiagnostics;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
proxy.getSuggestionDiagnostics = (fileName) => {
|
|
50
|
-
const defaultDiagnostics =
|
|
51
|
-
info.languageService.getSuggestionDiagnostics(fileName);
|
|
52
|
-
|
|
53
|
-
const isBruFile = isBrunoFile(fileName);
|
|
54
|
-
|
|
55
|
-
const allDiagnostics = filterDefaultDiagnostics(
|
|
56
|
-
info,
|
|
57
|
-
fileName,
|
|
58
|
-
defaultDiagnostics,
|
|
59
|
-
) as ts.DiagnosticWithLocation[];
|
|
60
|
-
|
|
61
|
-
// The ts server always reports errors when importing a Javascript function in a .bru file.
|
|
62
|
-
return isBruFile
|
|
63
|
-
? allDiagnostics.filter(
|
|
64
|
-
// Do not show diagnostics that only make sense for Typescript files.
|
|
65
|
-
// Bru file code blocks should be treated like Javascript functions instead.
|
|
66
|
-
// A list of diagnostics can be found here: https://github.com/microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
|
|
67
|
-
({ code }) =>
|
|
68
|
-
(code < 7_043 || code > 7_050) &&
|
|
69
|
-
code != 80_001 &&
|
|
70
|
-
code != 80_004,
|
|
71
|
-
)
|
|
72
|
-
: isInABrunoCollection(info, fileName)
|
|
73
|
-
? allDiagnostics.filter(({ code }) => code != 80_001)
|
|
74
|
-
: allDiagnostics; // Bruno currently only supports CommonJS modules.)
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// All hovers are provided by the extension implementation for '.bru' files.
|
|
78
|
-
proxy.getQuickInfoAtPosition = (fileName, position) => {
|
|
79
|
-
if (isBrunoFile(fileName)) {
|
|
80
|
-
return undefined;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return info.languageService.getQuickInfoAtPosition(
|
|
84
|
-
fileName,
|
|
85
|
-
position,
|
|
86
|
-
);
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
proxy.getCompletionsAtPosition = (fileName, position, options) => {
|
|
90
|
-
// All completions are provided by the extension implementation for '.bru' files.
|
|
91
|
-
if (isBrunoFile(fileName)) {
|
|
92
|
-
return undefined;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const defaultCompletions =
|
|
96
|
-
info.languageService.getCompletionsAtPosition(
|
|
97
|
-
fileName,
|
|
98
|
-
position,
|
|
99
|
-
options,
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
return defaultCompletions && isInABrunoCollection(info, fileName)
|
|
103
|
-
? {
|
|
104
|
-
...defaultCompletions,
|
|
105
|
-
entries: defaultCompletions.entries.filter(
|
|
106
|
-
({ data }) =>
|
|
107
|
-
!data ||
|
|
108
|
-
!data.fileName ||
|
|
109
|
-
!data.fileName.includes(
|
|
110
|
-
getTempJsFileBaseNameWithoutExtension(),
|
|
111
|
-
),
|
|
112
|
-
),
|
|
113
|
-
}
|
|
114
|
-
: defaultCompletions;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
proxy.getRenameInfo = (fileName, position, preferences) => {
|
|
118
|
-
const defaultRenameInfo = info.languageService.getRenameInfo(
|
|
119
|
-
fileName,
|
|
120
|
-
position,
|
|
121
|
-
preferences as ts.UserPreferences,
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
if (
|
|
125
|
-
extname(fileName) != ".js" ||
|
|
126
|
-
!isInABrunoCollection(info, fileName)
|
|
127
|
-
) {
|
|
128
|
-
return defaultRenameInfo;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const definitionForPosition =
|
|
132
|
-
info.languageService.getDefinitionAtPosition(
|
|
133
|
-
fileName,
|
|
134
|
-
position,
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
const isForInbuiltRuntimeFunction =
|
|
138
|
-
definitionForPosition &&
|
|
139
|
-
definitionForPosition.some(({ fileName }) =>
|
|
140
|
-
fileName.includes(getTempJsFileBaseNameWithoutExtension()),
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
return isForInbuiltRuntimeFunction
|
|
144
|
-
? {
|
|
145
|
-
canRename: false,
|
|
146
|
-
localizedErrorMessage:
|
|
147
|
-
"You cannot rename elements that are provided by Bruno at runtime.",
|
|
148
|
-
}
|
|
149
|
-
: defaultRenameInfo;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
proxy.findRenameLocations = (
|
|
153
|
-
fileName,
|
|
154
|
-
position,
|
|
155
|
-
findInStrings,
|
|
156
|
-
findInComments,
|
|
157
|
-
providePrefixAndSuffixTextForRename,
|
|
158
|
-
) => {
|
|
159
|
-
const defaultRenameLocations =
|
|
160
|
-
info.languageService.findRenameLocations(
|
|
161
|
-
fileName,
|
|
162
|
-
position,
|
|
163
|
-
findInStrings,
|
|
164
|
-
findInComments,
|
|
165
|
-
providePrefixAndSuffixTextForRename &&
|
|
166
|
-
typeof providePrefixAndSuffixTextForRename != "boolean"
|
|
167
|
-
? providePrefixAndSuffixTextForRename
|
|
168
|
-
: {},
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
return defaultRenameLocations &&
|
|
172
|
-
isInABrunoCollection(info, fileName)
|
|
173
|
-
? defaultRenameLocations.filter(
|
|
174
|
-
({ fileName: fileForRenameLocation }) =>
|
|
175
|
-
!fileForRenameLocation.includes(
|
|
176
|
-
getTempJsFileBaseNameWithoutExtension(),
|
|
177
|
-
),
|
|
178
|
-
)
|
|
179
|
-
: defaultRenameLocations;
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
proxy.findReferences = (fileName, position) => {
|
|
183
|
-
const defaultReferences = info.languageService.findReferences(
|
|
184
|
-
fileName,
|
|
185
|
-
position,
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
return defaultReferences && isInABrunoCollection(info, fileName)
|
|
189
|
-
? defaultReferences.filter(
|
|
190
|
-
({ definition: { fileName: fileForDefinition } }) =>
|
|
191
|
-
!fileForDefinition.includes(
|
|
192
|
-
getTempJsFileBaseNameWithoutExtension(),
|
|
193
|
-
),
|
|
194
|
-
)
|
|
195
|
-
: defaultReferences;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
proxy.getDefinitionAtPosition = (fileName, position) => {
|
|
199
|
-
const defaultDefinitions =
|
|
200
|
-
info.languageService.getDefinitionAtPosition(
|
|
201
|
-
fileName,
|
|
202
|
-
position,
|
|
203
|
-
);
|
|
204
|
-
|
|
205
|
-
return defaultDefinitions && isInABrunoCollection(info, fileName)
|
|
206
|
-
? defaultDefinitions.filter(
|
|
207
|
-
({ fileName: fileForDefinition }) =>
|
|
208
|
-
!fileForDefinition.includes(
|
|
209
|
-
getTempJsFileBaseNameWithoutExtension(),
|
|
210
|
-
),
|
|
211
|
-
)
|
|
212
|
-
: defaultDefinitions;
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
proxy.getDefinitionAndBoundSpan = (fileName, position) => {
|
|
216
|
-
const defaultDefinition =
|
|
217
|
-
info.languageService.getDefinitionAndBoundSpan(
|
|
218
|
-
fileName,
|
|
219
|
-
position,
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
return defaultDefinition &&
|
|
223
|
-
isInABrunoCollection(info, fileName) &&
|
|
224
|
-
defaultDefinition.definitions
|
|
225
|
-
? {
|
|
226
|
-
...defaultDefinition,
|
|
227
|
-
definitions: defaultDefinition.definitions.filter(
|
|
228
|
-
({ fileName: fileForDefinition }) =>
|
|
229
|
-
!fileForDefinition.includes(
|
|
230
|
-
getTempJsFileBaseNameWithoutExtension(),
|
|
231
|
-
),
|
|
232
|
-
),
|
|
233
|
-
}
|
|
234
|
-
: defaultDefinition;
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
proxy.getTypeDefinitionAtPosition = (fileName, position) => {
|
|
238
|
-
const defaultDefinitions =
|
|
239
|
-
info.languageService.getDefinitionAtPosition(
|
|
240
|
-
fileName,
|
|
241
|
-
position,
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
return defaultDefinitions && isInABrunoCollection(info, fileName)
|
|
245
|
-
? defaultDefinitions.filter(
|
|
246
|
-
({ fileName: fileForDefinition }) =>
|
|
247
|
-
!fileForDefinition.includes(
|
|
248
|
-
getTempJsFileBaseNameWithoutExtension(),
|
|
249
|
-
),
|
|
250
|
-
)
|
|
251
|
-
: defaultDefinitions;
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
proxy.getImplementationAtPosition = (fileName, position) => {
|
|
255
|
-
const defaultImplementations =
|
|
256
|
-
info.languageService.getImplementationAtPosition(
|
|
257
|
-
fileName,
|
|
258
|
-
position,
|
|
259
|
-
);
|
|
260
|
-
|
|
261
|
-
return defaultImplementations &&
|
|
262
|
-
isInABrunoCollection(info, fileName)
|
|
263
|
-
? defaultImplementations.filter(
|
|
264
|
-
({ fileName: fileForImplementation }) =>
|
|
265
|
-
!fileForImplementation.includes(
|
|
266
|
-
getTempJsFileBaseNameWithoutExtension(),
|
|
267
|
-
),
|
|
268
|
-
)
|
|
269
|
-
: defaultImplementations;
|
|
270
|
-
};
|
|
34
|
+
overrideDiagnostics(info, proxy);
|
|
35
|
+
overrideHoverAndCompletions(info, proxy);
|
|
36
|
+
overrideRename(info, proxy);
|
|
37
|
+
overrideReferencesAndDefinitions(info, proxy);
|
|
38
|
+
overrideCodeChanges(info, proxy);
|
|
39
|
+
overrideFormatting(info, proxy);
|
|
271
40
|
|
|
272
41
|
return proxy;
|
|
273
42
|
}
|
|
274
43
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function filterDefaultDiagnostics(
|
|
281
|
-
info: ts.server.PluginCreateInfo,
|
|
282
|
-
fileName: string,
|
|
283
|
-
defaultDiagnostics: (ts.Diagnostic | ts.DiagnosticWithLocation)[],
|
|
284
|
-
) {
|
|
285
|
-
if (!isBrunoFile(fileName)) {
|
|
286
|
-
return extname(fileName) == ".js"
|
|
287
|
-
? filterDiagnosticsForJsFile(info, fileName, defaultDiagnostics)
|
|
288
|
-
: defaultDiagnostics;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
const fileContent = getFileContent(info, fileName);
|
|
292
|
-
|
|
293
|
-
if (!fileContent) {
|
|
294
|
-
return [];
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const indizes: {
|
|
298
|
-
blockName: string;
|
|
299
|
-
startIndex: number;
|
|
300
|
-
endIndex: number;
|
|
301
|
-
}[] = [];
|
|
302
|
-
|
|
303
|
-
for (const blockName of Object.values(CodeBlockName)) {
|
|
304
|
-
const indizesForBlock = getCodeBlockStartAndEndIndex(
|
|
305
|
-
fileContent,
|
|
306
|
-
blockName,
|
|
307
|
-
);
|
|
308
|
-
|
|
309
|
-
if (indizesForBlock) {
|
|
310
|
-
indizes.push({ blockName, ...indizesForBlock });
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
if (indizes.length == 0) {
|
|
315
|
-
return [];
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
return filterOutDiagnosticsForInbuiltRuntimeFunctions(
|
|
319
|
-
defaultDiagnostics.filter(
|
|
320
|
-
({ start }) =>
|
|
321
|
-
start != undefined &&
|
|
322
|
-
indizes.some(
|
|
323
|
-
({ startIndex: blockStart, endIndex: blockEnd }) =>
|
|
324
|
-
start >= blockStart && start <= blockEnd,
|
|
325
|
-
),
|
|
326
|
-
),
|
|
327
|
-
fileContent,
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
function filterDiagnosticsForJsFile(
|
|
332
|
-
info: ts.server.PluginCreateInfo,
|
|
333
|
-
fileName: string,
|
|
334
|
-
defaultDiagnostics: (ts.Diagnostic | ts.DiagnosticWithLocation)[],
|
|
335
|
-
) {
|
|
336
|
-
if (fileName.includes(getTempJsFileBaseNameWithoutExtension())) {
|
|
337
|
-
// Filter out all diagnostics for temp js files.
|
|
338
|
-
return [];
|
|
339
|
-
} else if (!isInABrunoCollection(info, fileName)) {
|
|
340
|
-
return defaultDiagnostics;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const fileContent = getFileContent(info, fileName);
|
|
344
|
-
|
|
345
|
-
if (!fileContent) {
|
|
346
|
-
return [];
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
const filteredDiagnostics = filterOutDiagnosticsForInbuiltRuntimeFunctions(
|
|
350
|
-
defaultDiagnostics,
|
|
351
|
-
fileContent,
|
|
352
|
-
);
|
|
353
|
-
|
|
354
|
-
return filteredDiagnostics.map((diagnostic) => {
|
|
355
|
-
const { relatedInformation } = diagnostic;
|
|
356
|
-
|
|
357
|
-
const referencesTempJsFile =
|
|
358
|
-
relatedInformation &&
|
|
359
|
-
relatedInformation.some(
|
|
360
|
-
({ file }) =>
|
|
361
|
-
file &&
|
|
362
|
-
file.fileName.endsWith(
|
|
363
|
-
`${getTempJsFileBaseNameWithoutExtension()}.js`,
|
|
364
|
-
),
|
|
365
|
-
);
|
|
366
|
-
|
|
367
|
-
return referencesTempJsFile
|
|
368
|
-
? { ...diagnostic, relatedInformation: undefined }
|
|
369
|
-
: diagnostic;
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
function getCodeBlockStartAndEndIndex(
|
|
374
|
-
fullTextContent: string,
|
|
375
|
-
blockName: CodeBlockName,
|
|
376
|
-
) {
|
|
377
|
-
const openingBracketChar = "{";
|
|
378
|
-
|
|
379
|
-
const startPattern = new RegExp(
|
|
380
|
-
`^\\s*${blockName}\\s*${openingBracketChar}\\s*$`,
|
|
381
|
-
"m",
|
|
382
|
-
);
|
|
383
|
-
const startMatches = startPattern.exec(fullTextContent);
|
|
384
|
-
|
|
385
|
-
if (!startMatches || startMatches.length == 0) {
|
|
386
|
-
return undefined;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
const blockStartIndex = startMatches.index;
|
|
390
|
-
const remainingDoc = fullTextContent.substring(blockStartIndex);
|
|
391
|
-
|
|
392
|
-
const sourceFile = ts.createSourceFile(
|
|
393
|
-
"test.js",
|
|
394
|
-
remainingDoc,
|
|
395
|
-
ts.ScriptTarget.ES2020,
|
|
396
|
-
);
|
|
397
|
-
|
|
398
|
-
const blockNodeInSubDocument = (sourceFile as ts.Node)
|
|
399
|
-
.getChildAt(0, sourceFile)
|
|
400
|
-
.getChildren(sourceFile)
|
|
401
|
-
.find(({ kind }) => kind == ts.SyntaxKind.Block);
|
|
402
|
-
|
|
403
|
-
if (!blockNodeInSubDocument) {
|
|
404
|
-
throw new Error(
|
|
405
|
-
`Could not find code block within given subdocument: ${remainingDoc}`,
|
|
406
|
-
);
|
|
44
|
+
function onConfigurationChanged(config: Partial<PluginConfig> | undefined) {
|
|
45
|
+
configuration.update(config);
|
|
407
46
|
}
|
|
408
47
|
|
|
409
48
|
return {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
endIndex: blockStartIndex + blockNodeInSubDocument.end,
|
|
49
|
+
create,
|
|
50
|
+
onConfigurationChanged,
|
|
413
51
|
};
|
|
414
52
|
}
|
|
415
53
|
|
|
416
|
-
function filterOutDiagnosticsForInbuiltRuntimeFunctions(
|
|
417
|
-
diagnosticsToFilter: (ts.Diagnostic | ts.DiagnosticWithLocation)[],
|
|
418
|
-
fileContent: string,
|
|
419
|
-
) {
|
|
420
|
-
return filterOutMisleadingDiagnosticsForOtherTestFrameworks(
|
|
421
|
-
diagnosticsToFilter,
|
|
422
|
-
).filter(
|
|
423
|
-
({ start, length }) =>
|
|
424
|
-
start != undefined &&
|
|
425
|
-
length != undefined &&
|
|
426
|
-
// Do not show diagnostics for functions that are provided by Bruno at runtime
|
|
427
|
-
!getNamesForInbuiltRuntimeVarsAndFunctions().includes(
|
|
428
|
-
fileContent.substring(start, start + length),
|
|
429
|
-
) &&
|
|
430
|
-
// Avoid showing incorrect error when using `require`
|
|
431
|
-
// (the error seems to only occur for short periods of time when typescript type definitions have not been reloaded for a while)
|
|
432
|
-
fileContent.substring(start, start + length) != "require",
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
function filterOutMisleadingDiagnosticsForOtherTestFrameworks(
|
|
437
|
-
diagnostics: (ts.Diagnostic | ts.DiagnosticWithLocation)[],
|
|
438
|
-
) {
|
|
439
|
-
return diagnostics.filter(({ code, messageText }) => {
|
|
440
|
-
const errorText =
|
|
441
|
-
typeof messageText == "string"
|
|
442
|
-
? messageText
|
|
443
|
-
: messageText.messageText;
|
|
444
|
-
|
|
445
|
-
// When using global type definitions for Jest, the TS server expects every `expect` statement to use the matchers for Jest.
|
|
446
|
-
return code != 2_339 || !errorText.includes("JestMatchers<any>");
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
function getFileContent(info: ts.server.PluginCreateInfo, fileName: string) {
|
|
451
|
-
const scriptSnapshot = info.languageServiceHost.getScriptSnapshot(fileName);
|
|
452
|
-
|
|
453
|
-
if (scriptSnapshot) {
|
|
454
|
-
return scriptSnapshot.getText(0, scriptSnapshot.getLength());
|
|
455
|
-
} else {
|
|
456
|
-
return info.languageServiceHost.readFile(fileName);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
function isInABrunoCollection(
|
|
461
|
-
info: ts.server.PluginCreateInfo,
|
|
462
|
-
fileName: string,
|
|
463
|
-
) {
|
|
464
|
-
let currentDirectory = dirname(fileName);
|
|
465
|
-
let isCollectionRoot = isACollectionRootFolder(info, currentDirectory);
|
|
466
|
-
|
|
467
|
-
while (
|
|
468
|
-
info.serverHost.directoryExists(currentDirectory) &&
|
|
469
|
-
!isCollectionRoot &&
|
|
470
|
-
dirname(currentDirectory) != currentDirectory // dirname of a base folder in the file system seems to return the input folder again
|
|
471
|
-
) {
|
|
472
|
-
currentDirectory = dirname(currentDirectory);
|
|
473
|
-
isCollectionRoot = isACollectionRootFolder(info, currentDirectory);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
return isCollectionRoot;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
function isACollectionRootFolder(
|
|
480
|
-
info: ts.server.PluginCreateInfo,
|
|
481
|
-
directoryPath: string,
|
|
482
|
-
) {
|
|
483
|
-
return info.serverHost
|
|
484
|
-
.readDirectory(directoryPath, undefined, undefined, undefined, 1)
|
|
485
|
-
.some((fileName) => {
|
|
486
|
-
if (!fileName.endsWith("bruno.json")) {
|
|
487
|
-
return false;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
const content = info.languageServiceHost.readFile(fileName);
|
|
491
|
-
|
|
492
|
-
if (!content) {
|
|
493
|
-
return false;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
try {
|
|
497
|
-
const parsedContent = JSON.parse(content) as
|
|
498
|
-
{ type: string } | undefined;
|
|
499
|
-
|
|
500
|
-
return parsedContent && parsedContent.type == "collection";
|
|
501
|
-
} catch {
|
|
502
|
-
return false;
|
|
503
|
-
}
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
function isBrunoFile(fileName: string) {
|
|
508
|
-
return extname(fileName) == ".bru";
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
function getTempJsFileBaseNameWithoutExtension() {
|
|
512
|
-
return "__temp_bru_reference";
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
function getNamesForInbuiltRuntimeVarsAndFunctions() {
|
|
516
|
-
return ["bru", "req", "res", "test", "expect"];
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
enum CodeBlockName {
|
|
520
|
-
Tests = "tests",
|
|
521
|
-
PreRequestScript = "script:pre-request",
|
|
522
|
-
PostResponseScript = "script:post-response",
|
|
523
|
-
GrpcBeforeCallStartScript = "script:grpc:before-call-start",
|
|
524
|
-
GrpcBeforeMessageSendScript = "script:grpc:before-message-send",
|
|
525
|
-
GrpcAfterMessageReceiveScript = "script:grpc:after-message-receive",
|
|
526
|
-
GrpcAfterCallEndScript = "script:grpc:after-call-end",
|
|
527
|
-
}
|
|
528
|
-
|
|
529
54
|
export = init;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as ts from "typescript/lib/tsserverlibrary";
|
|
2
|
+
import {
|
|
3
|
+
createCheckForChangesWithinCodeBlocks,
|
|
4
|
+
getFormatOptionsForFile,
|
|
5
|
+
} from "../codeChanges/codeChanges";
|
|
6
|
+
|
|
7
|
+
// Some code fixes and refactorings insert code outside of code blocks (e.g. an import at the top of the file),
|
|
8
|
+
// which would corrupt the content of '.bru' and '.yml' files.
|
|
9
|
+
export function overrideCodeChanges(
|
|
10
|
+
info: ts.server.PluginCreateInfo,
|
|
11
|
+
proxy: ts.LanguageService,
|
|
12
|
+
) {
|
|
13
|
+
proxy.getCodeFixesAtPosition = (
|
|
14
|
+
fileName,
|
|
15
|
+
start,
|
|
16
|
+
end,
|
|
17
|
+
errorCodes,
|
|
18
|
+
formatOptions,
|
|
19
|
+
preferences,
|
|
20
|
+
) => {
|
|
21
|
+
const areAllChangesWithinCodeBlocks =
|
|
22
|
+
createCheckForChangesWithinCodeBlocks(info);
|
|
23
|
+
|
|
24
|
+
return info.languageService
|
|
25
|
+
.getCodeFixesAtPosition(
|
|
26
|
+
fileName,
|
|
27
|
+
start,
|
|
28
|
+
end,
|
|
29
|
+
errorCodes,
|
|
30
|
+
getFormatOptionsForFile(info, fileName, formatOptions, {
|
|
31
|
+
start,
|
|
32
|
+
end,
|
|
33
|
+
}),
|
|
34
|
+
preferences,
|
|
35
|
+
)
|
|
36
|
+
.filter(({ changes }) => areAllChangesWithinCodeBlocks(changes));
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
proxy.getCombinedCodeFix = (scope, fixId, formatOptions, preferences) => {
|
|
40
|
+
const combinedFix = info.languageService.getCombinedCodeFix(
|
|
41
|
+
scope,
|
|
42
|
+
fixId,
|
|
43
|
+
getFormatOptionsForFile(info, scope.fileName, formatOptions, {
|
|
44
|
+
start: 0,
|
|
45
|
+
end: Number.MAX_SAFE_INTEGER,
|
|
46
|
+
}),
|
|
47
|
+
preferences,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// Only applying some of the changes could result in invalid code.
|
|
51
|
+
return createCheckForChangesWithinCodeBlocks(info)(combinedFix.changes)
|
|
52
|
+
? combinedFix
|
|
53
|
+
: { changes: [] };
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
proxy.getEditsForRefactor = (
|
|
57
|
+
fileName,
|
|
58
|
+
formatOptions,
|
|
59
|
+
positionOrRange,
|
|
60
|
+
refactorName,
|
|
61
|
+
actionName,
|
|
62
|
+
preferences,
|
|
63
|
+
interactiveRefactorArguments,
|
|
64
|
+
) => {
|
|
65
|
+
const refactorEdits = info.languageService.getEditsForRefactor(
|
|
66
|
+
fileName,
|
|
67
|
+
getFormatOptionsForFile(
|
|
68
|
+
info,
|
|
69
|
+
fileName,
|
|
70
|
+
formatOptions,
|
|
71
|
+
typeof positionOrRange == "number"
|
|
72
|
+
? { start: positionOrRange, end: positionOrRange }
|
|
73
|
+
: {
|
|
74
|
+
start: positionOrRange.pos,
|
|
75
|
+
end: positionOrRange.end,
|
|
76
|
+
},
|
|
77
|
+
),
|
|
78
|
+
positionOrRange,
|
|
79
|
+
refactorName,
|
|
80
|
+
actionName,
|
|
81
|
+
preferences,
|
|
82
|
+
interactiveRefactorArguments,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
return refactorEdits &&
|
|
86
|
+
createCheckForChangesWithinCodeBlocks(info)(refactorEdits.edits)
|
|
87
|
+
? refactorEdits
|
|
88
|
+
: undefined;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as ts from "typescript/lib/tsserverlibrary";
|
|
2
|
+
import { isInABrunoCollection } from "../collection/collectionFormat";
|
|
3
|
+
import { filterDefaultDiagnostics } from "../diagnostics/filterDefaultDiagnostics";
|
|
4
|
+
import { hasEmbeddedCodeBlocks } from "../fileTypes";
|
|
5
|
+
|
|
6
|
+
export function overrideDiagnostics(
|
|
7
|
+
info: ts.server.PluginCreateInfo,
|
|
8
|
+
proxy: ts.LanguageService,
|
|
9
|
+
) {
|
|
10
|
+
proxy.getSyntacticDiagnostics = (fileName) => {
|
|
11
|
+
return filterDefaultDiagnostics(
|
|
12
|
+
info,
|
|
13
|
+
fileName,
|
|
14
|
+
info.languageService.getSyntacticDiagnostics(fileName),
|
|
15
|
+
) as ts.DiagnosticWithLocation[];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
proxy.getSemanticDiagnostics = (fileName) => {
|
|
19
|
+
const hasCodeBlocks = hasEmbeddedCodeBlocks(fileName);
|
|
20
|
+
|
|
21
|
+
const allDiagnostics = filterDefaultDiagnostics(
|
|
22
|
+
info,
|
|
23
|
+
fileName,
|
|
24
|
+
info.languageService.getSemanticDiagnostics(fileName),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// The ts server always reports errors when importing a Javascript function in a .bru or .yml file.
|
|
28
|
+
return hasCodeBlocks
|
|
29
|
+
? allDiagnostics.filter(
|
|
30
|
+
// Do not show diagnostics that only make sense for Typescript files.
|
|
31
|
+
// Code blocks should be treated like Javascript functions instead.
|
|
32
|
+
// A list of diagnostics can be found here: https://github.com/microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
|
|
33
|
+
({ code }) => ![7_006, 7_031, 18_046].includes(code),
|
|
34
|
+
)
|
|
35
|
+
: allDiagnostics;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
proxy.getSuggestionDiagnostics = (fileName) => {
|
|
39
|
+
const defaultDiagnostics =
|
|
40
|
+
info.languageService.getSuggestionDiagnostics(fileName);
|
|
41
|
+
|
|
42
|
+
const hasCodeBlocks = hasEmbeddedCodeBlocks(fileName);
|
|
43
|
+
|
|
44
|
+
const allDiagnostics = filterDefaultDiagnostics(
|
|
45
|
+
info,
|
|
46
|
+
fileName,
|
|
47
|
+
defaultDiagnostics,
|
|
48
|
+
) as ts.DiagnosticWithLocation[];
|
|
49
|
+
|
|
50
|
+
// The ts server always reports errors when importing a Javascript function in a .bru or .yml file.
|
|
51
|
+
return hasCodeBlocks
|
|
52
|
+
? allDiagnostics.filter(
|
|
53
|
+
// Do not show diagnostics that only make sense for Typescript files.
|
|
54
|
+
// Code blocks should be treated like Javascript functions instead.
|
|
55
|
+
// A list of diagnostics can be found here: https://github.com/microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
|
|
56
|
+
({ code }) =>
|
|
57
|
+
(code < 7_043 || code > 7_050) &&
|
|
58
|
+
code != 80_001 &&
|
|
59
|
+
code != 80_004,
|
|
60
|
+
)
|
|
61
|
+
: isInABrunoCollection(info, fileName)
|
|
62
|
+
? allDiagnostics.filter(({ code }) => code != 80_001)
|
|
63
|
+
: allDiagnostics; // Bruno currently only supports CommonJS modules.)
|
|
64
|
+
};
|
|
65
|
+
}
|