diff options
Diffstat (limited to 'editors/code/src/utils/diagnostics/SuggestedFixCollection.ts')
-rw-r--r-- | editors/code/src/utils/diagnostics/SuggestedFixCollection.ts | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts b/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts new file mode 100644 index 000000000..3b0bf7468 --- /dev/null +++ b/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts | |||
@@ -0,0 +1,74 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | import SuggestedFix from './SuggestedFix'; | ||
3 | |||
4 | /** | ||
5 | * Collection of suggested fixes across multiple documents | ||
6 | * | ||
7 | * This stores `SuggestedFix` model objects and returns them via the | ||
8 | * `vscode.CodeActionProvider` interface. | ||
9 | */ | ||
10 | export default class SuggestedFixCollection | ||
11 | implements vscode.CodeActionProvider { | ||
12 | public static PROVIDED_CODE_ACTION_KINDS = [vscode.CodeActionKind.QuickFix]; | ||
13 | |||
14 | private suggestedFixes: Map<string, SuggestedFix[]>; | ||
15 | |||
16 | constructor() { | ||
17 | this.suggestedFixes = new Map(); | ||
18 | } | ||
19 | |||
20 | /** | ||
21 | * Clears all suggested fixes across all documents | ||
22 | */ | ||
23 | public clear(): void { | ||
24 | this.suggestedFixes = new Map(); | ||
25 | } | ||
26 | |||
27 | /** | ||
28 | * Adds a suggested fix for the given diagnostic | ||
29 | * | ||
30 | * Some suggested fixes will appear in multiple diagnostics. For example, | ||
31 | * forgetting a `mut` on a variable will suggest changing the delaration on | ||
32 | * every mutable usage site. If the suggested fix has already been added | ||
33 | * this method will instead associate the existing fix with the new | ||
34 | * diagnostic. | ||
35 | */ | ||
36 | public addSuggestedFixForDiagnostic( | ||
37 | suggestedFix: SuggestedFix, | ||
38 | diagnostic: vscode.Diagnostic | ||
39 | ): void { | ||
40 | const fileUriString = suggestedFix.location.uri.toString(); | ||
41 | const fileSuggestions = this.suggestedFixes.get(fileUriString) || []; | ||
42 | |||
43 | const existingSuggestion = fileSuggestions.find(s => | ||
44 | s.isEqual(suggestedFix) | ||
45 | ); | ||
46 | |||
47 | if (existingSuggestion) { | ||
48 | // The existing suggestion also applies to this new diagnostic | ||
49 | existingSuggestion.diagnostics.push(diagnostic); | ||
50 | } else { | ||
51 | // We haven't seen this suggestion before | ||
52 | suggestedFix.diagnostics.push(diagnostic); | ||
53 | fileSuggestions.push(suggestedFix); | ||
54 | } | ||
55 | |||
56 | this.suggestedFixes.set(fileUriString, fileSuggestions); | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * Filters suggested fixes by their document and range and converts them to | ||
61 | * code actions | ||
62 | */ | ||
63 | public provideCodeActions( | ||
64 | document: vscode.TextDocument, | ||
65 | range: vscode.Range | ||
66 | ): vscode.CodeAction[] { | ||
67 | const documentUriString = document.uri.toString(); | ||
68 | |||
69 | const suggestedFixes = this.suggestedFixes.get(documentUriString); | ||
70 | return (suggestedFixes || []) | ||
71 | .filter(({ location }) => location.range.intersection(range)) | ||
72 | .map(suggestedEdit => suggestedEdit.toCodeAction()); | ||
73 | } | ||
74 | } | ||