@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.
Files changed (54) hide show
  1. package/README.md +4 -0
  2. package/out/codeBlocks/bruCodeBlocks.js +71 -0
  3. package/out/codeBlocks/bruCodeBlocks.js.map +1 -0
  4. package/out/codeChanges/codeChanges.js +144 -0
  5. package/out/codeChanges/codeChanges.js.map +1 -0
  6. package/out/collection/collectionFormat.js +69 -0
  7. package/out/collection/collectionFormat.js.map +1 -0
  8. package/out/constants.js +36 -0
  9. package/out/constants.js.map +1 -0
  10. package/out/diagnostics/filterDefaultDiagnostics.js +81 -0
  11. package/out/diagnostics/filterDefaultDiagnostics.js.map +1 -0
  12. package/out/fileContent.js +28 -0
  13. package/out/fileContent.js.map +1 -0
  14. package/out/fileTypes.js +16 -0
  15. package/out/fileTypes.js.map +1 -0
  16. package/out/index.js +18 -297
  17. package/out/index.js.map +1 -1
  18. package/out/languageService/codeChangeOverrides.js +40 -0
  19. package/out/languageService/codeChangeOverrides.js.map +1 -0
  20. package/out/languageService/diagnosticsOverrides.js +41 -0
  21. package/out/languageService/diagnosticsOverrides.js.map +1 -0
  22. package/out/languageService/formattingOverrides.js +18 -0
  23. package/out/languageService/formattingOverrides.js.map +1 -0
  24. package/out/languageService/navigationOverrides.js +98 -0
  25. package/out/languageService/navigationOverrides.js.map +1 -0
  26. package/out/pluginConfiguration.js +29 -0
  27. package/out/pluginConfiguration.js.map +1 -0
  28. package/out/yamlFiles/getIndentationOfScripts.js +24 -0
  29. package/out/yamlFiles/getIndentationOfScripts.js.map +1 -0
  30. package/out/yamlFiles/maskYamlFileContent.js +126 -0
  31. package/out/yamlFiles/maskYamlFileContent.js.map +1 -0
  32. package/out/yamlFiles/maskYamlFilesForTypescriptServer.js +94 -0
  33. package/out/yamlFiles/maskYamlFilesForTypescriptServer.js.map +1 -0
  34. package/package.json +3 -2
  35. package/src/codeBlocks/bruCodeBlocks.ts +66 -0
  36. package/src/codeChanges/codeChanges.ts +182 -0
  37. package/src/collection/collectionFormat.ts +96 -0
  38. package/src/constants.test.ts +12 -0
  39. package/src/constants.ts +31 -0
  40. package/src/diagnostics/filterDefaultDiagnostics.ts +145 -0
  41. package/src/fileContent.ts +38 -0
  42. package/src/fileTypes.ts +13 -0
  43. package/src/index.test.ts +329 -0
  44. package/src/index.ts +24 -499
  45. package/src/languageService/codeChangeOverrides.ts +90 -0
  46. package/src/languageService/diagnosticsOverrides.ts +65 -0
  47. package/src/languageService/formattingOverrides.ts +42 -0
  48. package/src/languageService/navigationOverrides.ts +201 -0
  49. package/src/pluginConfiguration.ts +34 -0
  50. package/src/yamlFiles/getIndentationOfScripts.ts +34 -0
  51. package/src/yamlFiles/maskYamlFileContent.test.ts +213 -0
  52. package/src/yamlFiles/maskYamlFileContent.ts +179 -0
  53. package/src/yamlFiles/maskYamlFilesForTypescriptServer.ts +85 -0
  54. 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.getSyntacticDiagnostics = (fileName) => {
22
- return filterDefaultDiagnostics(
23
- info,
24
- fileName,
25
- info.languageService.getSyntacticDiagnostics(fileName),
26
- ) as ts.DiagnosticWithLocation[];
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
- return {
276
- create,
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
- startIndex:
411
- blockStartIndex + startMatches[0].indexOf(openingBracketChar) + 1,
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
+ }