diff options
author | Seivan Heidari <[email protected]> | 2019-12-23 14:35:31 +0000 |
---|---|---|
committer | Seivan Heidari <[email protected]> | 2019-12-23 14:35:31 +0000 |
commit | b21d9337d9200e2cfdc90b386591c72c302dc03e (patch) | |
tree | f81f5c08f821115cee26fa4d3ceaae88c7807fd5 /editors/code/src | |
parent | 18a0937585b836ec5ed054b9ae48e0156ab6d9ef (diff) | |
parent | ce07a2daa9e53aa86a769f8641b14c2878444fbc (diff) |
Merge branch 'master' into feature/themes
Diffstat (limited to 'editors/code/src')
31 files changed, 715 insertions, 274 deletions
diff --git a/editors/code/src/commands/analyzer_status.ts b/editors/code/src/commands/analyzer_status.ts index 63f82c92d..2777ced24 100644 --- a/editors/code/src/commands/analyzer_status.ts +++ b/editors/code/src/commands/analyzer_status.ts | |||
@@ -9,7 +9,7 @@ export class TextDocumentContentProvider | |||
9 | public syntaxTree: string = 'Not available'; | 9 | public syntaxTree: string = 'Not available'; |
10 | 10 | ||
11 | public provideTextDocumentContent( | 11 | public provideTextDocumentContent( |
12 | uri: vscode.Uri | 12 | _uri: vscode.Uri, |
13 | ): vscode.ProviderResult<string> { | 13 | ): vscode.ProviderResult<string> { |
14 | const editor = vscode.window.activeTextEditor; | 14 | const editor = vscode.window.activeTextEditor; |
15 | if (editor == null) { | 15 | if (editor == null) { |
@@ -17,7 +17,7 @@ export class TextDocumentContentProvider | |||
17 | } | 17 | } |
18 | return Server.client.sendRequest<string>( | 18 | return Server.client.sendRequest<string>( |
19 | 'rust-analyzer/analyzerStatus', | 19 | 'rust-analyzer/analyzerStatus', |
20 | null | 20 | null, |
21 | ); | 21 | ); |
22 | } | 22 | } |
23 | 23 | ||
@@ -35,8 +35,8 @@ export function makeCommand(context: vscode.ExtensionContext) { | |||
35 | context.subscriptions.push( | 35 | context.subscriptions.push( |
36 | vscode.workspace.registerTextDocumentContentProvider( | 36 | vscode.workspace.registerTextDocumentContentProvider( |
37 | 'rust-analyzer-status', | 37 | 'rust-analyzer-status', |
38 | textDocumentContentProvider | 38 | textDocumentContentProvider, |
39 | ) | 39 | ), |
40 | ); | 40 | ); |
41 | 41 | ||
42 | context.subscriptions.push({ | 42 | context.subscriptions.push({ |
@@ -44,21 +44,21 @@ export function makeCommand(context: vscode.ExtensionContext) { | |||
44 | if (poller != null) { | 44 | if (poller != null) { |
45 | clearInterval(poller); | 45 | clearInterval(poller); |
46 | } | 46 | } |
47 | } | 47 | }, |
48 | }); | 48 | }); |
49 | 49 | ||
50 | return async function handle() { | 50 | return async function handle() { |
51 | if (poller == null) { | 51 | if (poller == null) { |
52 | poller = setInterval( | 52 | poller = setInterval( |
53 | () => textDocumentContentProvider.eventEmitter.fire(statusUri), | 53 | () => textDocumentContentProvider.eventEmitter.fire(statusUri), |
54 | 1000 | 54 | 1000, |
55 | ); | 55 | ); |
56 | } | 56 | } |
57 | const document = await vscode.workspace.openTextDocument(statusUri); | 57 | const document = await vscode.workspace.openTextDocument(statusUri); |
58 | return vscode.window.showTextDocument( | 58 | return vscode.window.showTextDocument( |
59 | document, | 59 | document, |
60 | vscode.ViewColumn.Two, | 60 | vscode.ViewColumn.Two, |
61 | true | 61 | true, |
62 | ); | 62 | ); |
63 | }; | 63 | }; |
64 | } | 64 | } |
diff --git a/editors/code/src/commands/apply_source_change.ts b/editors/code/src/commands/apply_source_change.ts index dcd074b8b..8167398b1 100644 --- a/editors/code/src/commands/apply_source_change.ts +++ b/editors/code/src/commands/apply_source_change.ts | |||
@@ -11,7 +11,7 @@ export interface SourceChange { | |||
11 | 11 | ||
12 | export async function handle(change: SourceChange) { | 12 | export async function handle(change: SourceChange) { |
13 | const wsEdit = Server.client.protocol2CodeConverter.asWorkspaceEdit( | 13 | const wsEdit = Server.client.protocol2CodeConverter.asWorkspaceEdit( |
14 | change.workspaceEdit | 14 | change.workspaceEdit, |
15 | ); | 15 | ); |
16 | let created; | 16 | let created; |
17 | let moved; | 17 | let moved; |
@@ -33,10 +33,10 @@ export async function handle(change: SourceChange) { | |||
33 | await vscode.window.showTextDocument(doc); | 33 | await vscode.window.showTextDocument(doc); |
34 | } else if (toReveal) { | 34 | } else if (toReveal) { |
35 | const uri = Server.client.protocol2CodeConverter.asUri( | 35 | const uri = Server.client.protocol2CodeConverter.asUri( |
36 | toReveal.textDocument.uri | 36 | toReveal.textDocument.uri, |
37 | ); | 37 | ); |
38 | const position = Server.client.protocol2CodeConverter.asPosition( | 38 | const position = Server.client.protocol2CodeConverter.asPosition( |
39 | toReveal.position | 39 | toReveal.position, |
40 | ); | 40 | ); |
41 | const editor = vscode.window.activeTextEditor; | 41 | const editor = vscode.window.activeTextEditor; |
42 | if (!editor || editor.document.uri.toString() !== uri.toString()) { | 42 | if (!editor || editor.document.uri.toString() !== uri.toString()) { |
@@ -48,7 +48,7 @@ export async function handle(change: SourceChange) { | |||
48 | editor.selection = new vscode.Selection(position, position); | 48 | editor.selection = new vscode.Selection(position, position); |
49 | editor.revealRange( | 49 | editor.revealRange( |
50 | new vscode.Range(position, position), | 50 | new vscode.Range(position, position), |
51 | vscode.TextEditorRevealType.Default | 51 | vscode.TextEditorRevealType.Default, |
52 | ); | 52 | ); |
53 | } | 53 | } |
54 | } | 54 | } |
diff --git a/editors/code/src/commands/cargo_watch.ts b/editors/code/src/commands/cargo_watch.ts index 59d4ba97a..ac62bdd48 100644 --- a/editors/code/src/commands/cargo_watch.ts +++ b/editors/code/src/commands/cargo_watch.ts | |||
@@ -9,13 +9,13 @@ import { StatusDisplay } from './watch_status'; | |||
9 | 9 | ||
10 | import { | 10 | import { |
11 | mapRustDiagnosticToVsCode, | 11 | mapRustDiagnosticToVsCode, |
12 | RustDiagnostic | 12 | RustDiagnostic, |
13 | } from '../utils/diagnostics/rust'; | 13 | } from '../utils/diagnostics/rust'; |
14 | import SuggestedFixCollection from '../utils/diagnostics/SuggestedFixCollection'; | 14 | import SuggestedFixCollection from '../utils/diagnostics/SuggestedFixCollection'; |
15 | import { areDiagnosticsEqual } from '../utils/diagnostics/vscode'; | 15 | import { areDiagnosticsEqual } from '../utils/diagnostics/vscode'; |
16 | 16 | ||
17 | export async function registerCargoWatchProvider( | 17 | export async function registerCargoWatchProvider( |
18 | subscriptions: vscode.Disposable[] | 18 | subscriptions: vscode.Disposable[], |
19 | ): Promise<CargoWatchProvider | undefined> { | 19 | ): Promise<CargoWatchProvider | undefined> { |
20 | let cargoExists = false; | 20 | let cargoExists = false; |
21 | 21 | ||
@@ -30,7 +30,7 @@ export async function registerCargoWatchProvider( | |||
30 | 30 | ||
31 | if (!cargoExists) { | 31 | if (!cargoExists) { |
32 | vscode.window.showErrorMessage( | 32 | vscode.window.showErrorMessage( |
33 | `Couldn\'t find \'Cargo.toml\' at ${cargoTomlPath}` | 33 | `Couldn\'t find \'Cargo.toml\' at ${cargoTomlPath}`, |
34 | ); | 34 | ); |
35 | return; | 35 | return; |
36 | } | 36 | } |
@@ -52,13 +52,13 @@ export class CargoWatchProvider implements vscode.Disposable { | |||
52 | 52 | ||
53 | constructor() { | 53 | constructor() { |
54 | this.diagnosticCollection = vscode.languages.createDiagnosticCollection( | 54 | this.diagnosticCollection = vscode.languages.createDiagnosticCollection( |
55 | 'rustc' | 55 | 'rustc', |
56 | ); | 56 | ); |
57 | this.statusDisplay = new StatusDisplay( | 57 | this.statusDisplay = new StatusDisplay( |
58 | Server.config.cargoWatchOptions.command | 58 | Server.config.cargoWatchOptions.command, |
59 | ); | 59 | ); |
60 | this.outputChannel = vscode.window.createOutputChannel( | 60 | this.outputChannel = vscode.window.createOutputChannel( |
61 | 'Cargo Watch Trace' | 61 | 'Cargo Watch Trace', |
62 | ); | 62 | ); |
63 | 63 | ||
64 | // Track `rustc`'s suggested fixes so we can convert them to code actions | 64 | // Track `rustc`'s suggested fixes so we can convert them to code actions |
@@ -68,22 +68,24 @@ export class CargoWatchProvider implements vscode.Disposable { | |||
68 | this.suggestedFixCollection, | 68 | this.suggestedFixCollection, |
69 | { | 69 | { |
70 | providedCodeActionKinds: | 70 | providedCodeActionKinds: |
71 | SuggestedFixCollection.PROVIDED_CODE_ACTION_KINDS | 71 | SuggestedFixCollection.PROVIDED_CODE_ACTION_KINDS, |
72 | } | 72 | }, |
73 | ); | 73 | ); |
74 | } | 74 | } |
75 | 75 | ||
76 | public start() { | 76 | public start() { |
77 | if (this.cargoProcess) { | 77 | if (this.cargoProcess) { |
78 | vscode.window.showInformationMessage( | 78 | vscode.window.showInformationMessage( |
79 | 'Cargo Watch is already running' | 79 | 'Cargo Watch is already running', |
80 | ); | 80 | ); |
81 | return; | 81 | return; |
82 | } | 82 | } |
83 | 83 | ||
84 | let args = | 84 | let args = |
85 | Server.config.cargoWatchOptions.command + | 85 | Server.config.cargoWatchOptions.command + ' --message-format json'; |
86 | ' --all-targets --message-format json'; | 86 | if (Server.config.cargoWatchOptions.allTargets) { |
87 | args += ' --all-targets'; | ||
88 | } | ||
87 | if (Server.config.cargoWatchOptions.command.length > 0) { | 89 | if (Server.config.cargoWatchOptions.command.length > 0) { |
88 | // Excape the double quote string: | 90 | // Excape the double quote string: |
89 | args += ' ' + Server.config.cargoWatchOptions.arguments; | 91 | args += ' ' + Server.config.cargoWatchOptions.arguments; |
@@ -95,7 +97,7 @@ export class CargoWatchProvider implements vscode.Disposable { | |||
95 | 97 | ||
96 | const ignoreFlags = Server.config.cargoWatchOptions.ignore.reduce( | 98 | const ignoreFlags = Server.config.cargoWatchOptions.ignore.reduce( |
97 | (flags, pattern) => [...flags, '--ignore', pattern], | 99 | (flags, pattern) => [...flags, '--ignore', pattern], |
98 | [] as string[] | 100 | [] as string[], |
99 | ); | 101 | ); |
100 | 102 | ||
101 | // Start the cargo watch with json message | 103 | // Start the cargo watch with json message |
@@ -105,12 +107,17 @@ export class CargoWatchProvider implements vscode.Disposable { | |||
105 | { | 107 | { |
106 | stdio: ['ignore', 'pipe', 'pipe'], | 108 | stdio: ['ignore', 'pipe', 'pipe'], |
107 | cwd: vscode.workspace.rootPath, | 109 | cwd: vscode.workspace.rootPath, |
108 | windowsVerbatimArguments: true | 110 | windowsVerbatimArguments: true, |
109 | } | 111 | }, |
110 | ); | 112 | ); |
111 | 113 | ||
114 | if (!this.cargoProcess) { | ||
115 | vscode.window.showErrorMessage('Cargo Watch failed to start'); | ||
116 | return; | ||
117 | } | ||
118 | |||
112 | const stdoutData = new LineBuffer(); | 119 | const stdoutData = new LineBuffer(); |
113 | this.cargoProcess.stdout.on('data', (s: string) => { | 120 | this.cargoProcess.stdout?.on('data', (s: string) => { |
114 | stdoutData.processOutput(s, line => { | 121 | stdoutData.processOutput(s, line => { |
115 | this.logInfo(line); | 122 | this.logInfo(line); |
116 | try { | 123 | try { |
@@ -122,7 +129,7 @@ export class CargoWatchProvider implements vscode.Disposable { | |||
122 | }); | 129 | }); |
123 | 130 | ||
124 | const stderrData = new LineBuffer(); | 131 | const stderrData = new LineBuffer(); |
125 | this.cargoProcess.stderr.on('data', (s: string) => { | 132 | this.cargoProcess.stderr?.on('data', (s: string) => { |
126 | stderrData.processOutput(s, line => { | 133 | stderrData.processOutput(s, line => { |
127 | this.logError('Error on cargo-watch : {\n' + line + '}\n'); | 134 | this.logError('Error on cargo-watch : {\n' + line + '}\n'); |
128 | }); | 135 | }); |
@@ -130,7 +137,7 @@ export class CargoWatchProvider implements vscode.Disposable { | |||
130 | 137 | ||
131 | this.cargoProcess.on('error', (err: Error) => { | 138 | this.cargoProcess.on('error', (err: Error) => { |
132 | this.logError( | 139 | this.logError( |
133 | 'Error on cargo-watch process : {\n' + err.message + '}\n' | 140 | 'Error on cargo-watch process : {\n' + err.message + '}\n', |
134 | ); | 141 | ); |
135 | }); | 142 | }); |
136 | 143 | ||
@@ -223,12 +230,12 @@ export class CargoWatchProvider implements vscode.Disposable { | |||
223 | const fileUri = location.uri; | 230 | const fileUri = location.uri; |
224 | 231 | ||
225 | const diagnostics: vscode.Diagnostic[] = [ | 232 | const diagnostics: vscode.Diagnostic[] = [ |
226 | ...(this.diagnosticCollection!.get(fileUri) || []) | 233 | ...(this.diagnosticCollection!.get(fileUri) || []), |
227 | ]; | 234 | ]; |
228 | 235 | ||
229 | // If we're building multiple targets it's possible we've already seen this diagnostic | 236 | // If we're building multiple targets it's possible we've already seen this diagnostic |
230 | const isDuplicate = diagnostics.some(d => | 237 | const isDuplicate = diagnostics.some(d => |
231 | areDiagnosticsEqual(d, diagnostic) | 238 | areDiagnosticsEqual(d, diagnostic), |
232 | ); | 239 | ); |
233 | if (isDuplicate) { | 240 | if (isDuplicate) { |
234 | return; | 241 | return; |
@@ -241,7 +248,7 @@ export class CargoWatchProvider implements vscode.Disposable { | |||
241 | for (const suggestedFix of suggestedFixes) { | 248 | for (const suggestedFix of suggestedFixes) { |
242 | this.suggestedFixCollection.addSuggestedFixForDiagnostic( | 249 | this.suggestedFixCollection.addSuggestedFixForDiagnostic( |
243 | suggestedFix, | 250 | suggestedFix, |
244 | diagnostic | 251 | diagnostic, |
245 | ); | 252 | ); |
246 | } | 253 | } |
247 | 254 | ||
@@ -249,7 +256,7 @@ export class CargoWatchProvider implements vscode.Disposable { | |||
249 | vscode.commands.executeCommand( | 256 | vscode.commands.executeCommand( |
250 | 'vscode.executeCodeActionProvider', | 257 | 'vscode.executeCodeActionProvider', |
251 | fileUri, | 258 | fileUri, |
252 | diagnostic.range | 259 | diagnostic.range, |
253 | ); | 260 | ); |
254 | } | 261 | } |
255 | } | 262 | } |
diff --git a/editors/code/src/commands/expand_macro.ts b/editors/code/src/commands/expand_macro.ts index 34e0c8fb3..17c78280a 100644 --- a/editors/code/src/commands/expand_macro.ts +++ b/editors/code/src/commands/expand_macro.ts | |||
@@ -3,7 +3,7 @@ import { Position, TextDocumentIdentifier } from 'vscode-languageclient'; | |||
3 | import { Server } from '../server'; | 3 | import { Server } from '../server'; |
4 | 4 | ||
5 | export const expandMacroUri = vscode.Uri.parse( | 5 | export const expandMacroUri = vscode.Uri.parse( |
6 | 'rust-analyzer://expandMacro/[EXPANSION].rs' | 6 | 'rust-analyzer://expandMacro/[EXPANSION].rs', |
7 | ); | 7 | ); |
8 | 8 | ||
9 | export class ExpandMacroContentProvider | 9 | export class ExpandMacroContentProvider |
@@ -11,7 +11,7 @@ export class ExpandMacroContentProvider | |||
11 | public eventEmitter = new vscode.EventEmitter<vscode.Uri>(); | 11 | public eventEmitter = new vscode.EventEmitter<vscode.Uri>(); |
12 | 12 | ||
13 | public provideTextDocumentContent( | 13 | public provideTextDocumentContent( |
14 | uri: vscode.Uri | 14 | _uri: vscode.Uri, |
15 | ): vscode.ProviderResult<string> { | 15 | ): vscode.ProviderResult<string> { |
16 | async function handle() { | 16 | async function handle() { |
17 | const editor = vscode.window.activeTextEditor; | 17 | const editor = vscode.window.activeTextEditor; |
@@ -22,11 +22,11 @@ export class ExpandMacroContentProvider | |||
22 | const position = editor.selection.active; | 22 | const position = editor.selection.active; |
23 | const request: MacroExpandParams = { | 23 | const request: MacroExpandParams = { |
24 | textDocument: { uri: editor.document.uri.toString() }, | 24 | textDocument: { uri: editor.document.uri.toString() }, |
25 | position | 25 | position, |
26 | }; | 26 | }; |
27 | const expanded = await Server.client.sendRequest<ExpandedMacro>( | 27 | const expanded = await Server.client.sendRequest<ExpandedMacro>( |
28 | 'rust-analyzer/expandMacro', | 28 | 'rust-analyzer/expandMacro', |
29 | request | 29 | request, |
30 | ); | 30 | ); |
31 | 31 | ||
32 | if (expanded == null) { | 32 | if (expanded == null) { |
@@ -58,7 +58,7 @@ export function createHandle(provider: ExpandMacroContentProvider) { | |||
58 | return vscode.window.showTextDocument( | 58 | return vscode.window.showTextDocument( |
59 | document, | 59 | document, |
60 | vscode.ViewColumn.Two, | 60 | vscode.ViewColumn.Two, |
61 | true | 61 | true, |
62 | ); | 62 | ); |
63 | }; | 63 | }; |
64 | } | 64 | } |
diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts index 2ade6d331..13a696758 100644 --- a/editors/code/src/commands/index.ts +++ b/editors/code/src/commands/index.ts | |||
@@ -19,5 +19,5 @@ export { | |||
19 | runnables, | 19 | runnables, |
20 | syntaxTree, | 20 | syntaxTree, |
21 | onEnter, | 21 | onEnter, |
22 | inlayHints | 22 | inlayHints, |
23 | }; | 23 | }; |
diff --git a/editors/code/src/commands/inlay_hints.ts b/editors/code/src/commands/inlay_hints.ts index 0dbdd94fb..ac7dcce60 100644 --- a/editors/code/src/commands/inlay_hints.ts +++ b/editors/code/src/commands/inlay_hints.ts | |||
@@ -15,8 +15,8 @@ interface InlayHint { | |||
15 | 15 | ||
16 | const typeHintDecorationType = vscode.window.createTextEditorDecorationType({ | 16 | const typeHintDecorationType = vscode.window.createTextEditorDecorationType({ |
17 | after: { | 17 | after: { |
18 | color: new vscode.ThemeColor('ralsp.inlayHint') | 18 | color: new vscode.ThemeColor('ralsp.inlayHint'), |
19 | } | 19 | }, |
20 | }); | 20 | }); |
21 | 21 | ||
22 | export class HintsUpdater { | 22 | export class HintsUpdater { |
@@ -26,13 +26,13 @@ export class HintsUpdater { | |||
26 | if (this.displayHints !== displayHints) { | 26 | if (this.displayHints !== displayHints) { |
27 | this.displayHints = displayHints; | 27 | this.displayHints = displayHints; |
28 | return this.refreshVisibleEditorsHints( | 28 | return this.refreshVisibleEditorsHints( |
29 | displayHints ? undefined : [] | 29 | displayHints ? undefined : [], |
30 | ); | 30 | ); |
31 | } | 31 | } |
32 | } | 32 | } |
33 | 33 | ||
34 | public async refreshHintsForVisibleEditors( | 34 | public async refreshHintsForVisibleEditors( |
35 | cause?: TextDocumentChangeEvent | 35 | cause?: TextDocumentChangeEvent, |
36 | ): Promise<void> { | 36 | ): Promise<void> { |
37 | if (!this.displayHints) { | 37 | if (!this.displayHints) { |
38 | return; | 38 | return; |
@@ -48,21 +48,21 @@ export class HintsUpdater { | |||
48 | } | 48 | } |
49 | 49 | ||
50 | private async refreshVisibleEditorsHints( | 50 | private async refreshVisibleEditorsHints( |
51 | newDecorations?: vscode.DecorationOptions[] | 51 | newDecorations?: vscode.DecorationOptions[], |
52 | ) { | 52 | ) { |
53 | const promises: Array<Promise<void>> = []; | 53 | const promises: Array<Promise<void>> = []; |
54 | 54 | ||
55 | for (const rustEditor of vscode.window.visibleTextEditors.filter( | 55 | for (const rustEditor of vscode.window.visibleTextEditors.filter( |
56 | editor => this.isRustDocument(editor.document) | 56 | editor => this.isRustDocument(editor.document), |
57 | )) { | 57 | )) { |
58 | if (newDecorations !== undefined) { | 58 | if (newDecorations !== undefined) { |
59 | promises.push( | 59 | promises.push( |
60 | Promise.resolve( | 60 | Promise.resolve( |
61 | rustEditor.setDecorations( | 61 | rustEditor.setDecorations( |
62 | typeHintDecorationType, | 62 | typeHintDecorationType, |
63 | newDecorations | 63 | newDecorations, |
64 | ) | 64 | ), |
65 | ) | 65 | ), |
66 | ); | 66 | ); |
67 | } else { | 67 | } else { |
68 | promises.push(this.updateDecorationsFromServer(rustEditor)); | 68 | promises.push(this.updateDecorationsFromServer(rustEditor)); |
@@ -79,7 +79,7 @@ export class HintsUpdater { | |||
79 | } | 79 | } |
80 | 80 | ||
81 | private async updateDecorationsFromServer( | 81 | private async updateDecorationsFromServer( |
82 | editor: TextEditor | 82 | editor: TextEditor, |
83 | ): Promise<void> { | 83 | ): Promise<void> { |
84 | const newHints = await this.queryHints(editor.document.uri.toString()); | 84 | const newHints = await this.queryHints(editor.document.uri.toString()); |
85 | if (newHints !== null) { | 85 | if (newHints !== null) { |
@@ -87,20 +87,20 @@ export class HintsUpdater { | |||
87 | range: hint.range, | 87 | range: hint.range, |
88 | renderOptions: { | 88 | renderOptions: { |
89 | after: { | 89 | after: { |
90 | contentText: `: ${hint.label}` | 90 | contentText: `: ${hint.label}`, |
91 | } | 91 | }, |
92 | } | 92 | }, |
93 | })); | 93 | })); |
94 | return editor.setDecorations( | 94 | return editor.setDecorations( |
95 | typeHintDecorationType, | 95 | typeHintDecorationType, |
96 | newDecorations | 96 | newDecorations, |
97 | ); | 97 | ); |
98 | } | 98 | } |
99 | } | 99 | } |
100 | 100 | ||
101 | private async queryHints(documentUri: string): Promise<InlayHint[] | null> { | 101 | private async queryHints(documentUri: string): Promise<InlayHint[] | null> { |
102 | const request: InlayHintsParams = { | 102 | const request: InlayHintsParams = { |
103 | textDocument: { uri: documentUri } | 103 | textDocument: { uri: documentUri }, |
104 | }; | 104 | }; |
105 | const client = Server.client; | 105 | const client = Server.client; |
106 | return client | 106 | return client |
@@ -108,8 +108,8 @@ export class HintsUpdater { | |||
108 | .then(() => | 108 | .then(() => |
109 | client.sendRequest<InlayHint[] | null>( | 109 | client.sendRequest<InlayHint[] | null>( |
110 | 'rust-analyzer/inlayHints', | 110 | 'rust-analyzer/inlayHints', |
111 | request | 111 | request, |
112 | ) | 112 | ), |
113 | ); | 113 | ); |
114 | } | 114 | } |
115 | } | 115 | } |
diff --git a/editors/code/src/commands/join_lines.ts b/editors/code/src/commands/join_lines.ts index 0d4b12f4d..134ddc801 100644 --- a/editors/code/src/commands/join_lines.ts +++ b/editors/code/src/commands/join_lines.ts | |||
@@ -4,7 +4,7 @@ import { Range, TextDocumentIdentifier } from 'vscode-languageclient'; | |||
4 | import { Server } from '../server'; | 4 | import { Server } from '../server'; |
5 | import { | 5 | import { |
6 | handle as applySourceChange, | 6 | handle as applySourceChange, |
7 | SourceChange | 7 | SourceChange, |
8 | } from './apply_source_change'; | 8 | } from './apply_source_change'; |
9 | 9 | ||
10 | interface JoinLinesParams { | 10 | interface JoinLinesParams { |
@@ -19,11 +19,11 @@ export async function handle() { | |||
19 | } | 19 | } |
20 | const request: JoinLinesParams = { | 20 | const request: JoinLinesParams = { |
21 | range: Server.client.code2ProtocolConverter.asRange(editor.selection), | 21 | range: Server.client.code2ProtocolConverter.asRange(editor.selection), |
22 | textDocument: { uri: editor.document.uri.toString() } | 22 | textDocument: { uri: editor.document.uri.toString() }, |
23 | }; | 23 | }; |
24 | const change = await Server.client.sendRequest<SourceChange>( | 24 | const change = await Server.client.sendRequest<SourceChange>( |
25 | 'rust-analyzer/joinLines', | 25 | 'rust-analyzer/joinLines', |
26 | request | 26 | request, |
27 | ); | 27 | ); |
28 | await applySourceChange(change); | 28 | await applySourceChange(change); |
29 | } | 29 | } |
diff --git a/editors/code/src/commands/matching_brace.ts b/editors/code/src/commands/matching_brace.ts index d86faf405..364208cc7 100644 --- a/editors/code/src/commands/matching_brace.ts +++ b/editors/code/src/commands/matching_brace.ts | |||
@@ -17,15 +17,15 @@ export async function handle() { | |||
17 | textDocument: { uri: editor.document.uri.toString() }, | 17 | textDocument: { uri: editor.document.uri.toString() }, |
18 | offsets: editor.selections.map(s => { | 18 | offsets: editor.selections.map(s => { |
19 | return Server.client.code2ProtocolConverter.asPosition(s.active); | 19 | return Server.client.code2ProtocolConverter.asPosition(s.active); |
20 | }) | 20 | }), |
21 | }; | 21 | }; |
22 | const response = await Server.client.sendRequest<Position[]>( | 22 | const response = await Server.client.sendRequest<Position[]>( |
23 | 'rust-analyzer/findMatchingBrace', | 23 | 'rust-analyzer/findMatchingBrace', |
24 | request | 24 | request, |
25 | ); | 25 | ); |
26 | editor.selections = editor.selections.map((sel, idx) => { | 26 | editor.selections = editor.selections.map((sel, idx) => { |
27 | const active = Server.client.protocol2CodeConverter.asPosition( | 27 | const active = Server.client.protocol2CodeConverter.asPosition( |
28 | response[idx] | 28 | response[idx], |
29 | ); | 29 | ); |
30 | const anchor = sel.isEmpty ? active : sel.anchor; | 30 | const anchor = sel.isEmpty ? active : sel.anchor; |
31 | return new vscode.Selection(anchor, active); | 31 | return new vscode.Selection(anchor, active); |
diff --git a/editors/code/src/commands/on_enter.ts b/editors/code/src/commands/on_enter.ts index 16dcb70c8..772c64b3c 100644 --- a/editors/code/src/commands/on_enter.ts +++ b/editors/code/src/commands/on_enter.ts | |||
@@ -3,7 +3,7 @@ import * as lc from 'vscode-languageclient'; | |||
3 | import { Server } from '../server'; | 3 | import { Server } from '../server'; |
4 | import { | 4 | import { |
5 | handle as applySourceChange, | 5 | handle as applySourceChange, |
6 | SourceChange | 6 | SourceChange, |
7 | } from './apply_source_change'; | 7 | } from './apply_source_change'; |
8 | 8 | ||
9 | export async function handle(event: { text: string }): Promise<boolean> { | 9 | export async function handle(event: { text: string }): Promise<boolean> { |
@@ -18,12 +18,12 @@ export async function handle(event: { text: string }): Promise<boolean> { | |||
18 | const request: lc.TextDocumentPositionParams = { | 18 | const request: lc.TextDocumentPositionParams = { |
19 | textDocument: { uri: editor.document.uri.toString() }, | 19 | textDocument: { uri: editor.document.uri.toString() }, |
20 | position: Server.client.code2ProtocolConverter.asPosition( | 20 | position: Server.client.code2ProtocolConverter.asPosition( |
21 | editor.selection.active | 21 | editor.selection.active, |
22 | ) | 22 | ), |
23 | }; | 23 | }; |
24 | const change = await Server.client.sendRequest<undefined | SourceChange>( | 24 | const change = await Server.client.sendRequest<undefined | SourceChange>( |
25 | 'rust-analyzer/onEnter', | 25 | 'rust-analyzer/onEnter', |
26 | request | 26 | request, |
27 | ); | 27 | ); |
28 | if (!change) { | 28 | if (!change) { |
29 | return false; | 29 | return false; |
diff --git a/editors/code/src/commands/parent_module.ts b/editors/code/src/commands/parent_module.ts index 9d30b7b59..ad49e1bdb 100644 --- a/editors/code/src/commands/parent_module.ts +++ b/editors/code/src/commands/parent_module.ts | |||
@@ -11,12 +11,12 @@ export async function handle() { | |||
11 | const request: lc.TextDocumentPositionParams = { | 11 | const request: lc.TextDocumentPositionParams = { |
12 | textDocument: { uri: editor.document.uri.toString() }, | 12 | textDocument: { uri: editor.document.uri.toString() }, |
13 | position: Server.client.code2ProtocolConverter.asPosition( | 13 | position: Server.client.code2ProtocolConverter.asPosition( |
14 | editor.selection.active | 14 | editor.selection.active, |
15 | ) | 15 | ), |
16 | }; | 16 | }; |
17 | const response = await Server.client.sendRequest<lc.Location[]>( | 17 | const response = await Server.client.sendRequest<lc.Location[]>( |
18 | 'rust-analyzer/parentModule', | 18 | 'rust-analyzer/parentModule', |
19 | request | 19 | request, |
20 | ); | 20 | ); |
21 | const loc = response[0]; | 21 | const loc = response[0]; |
22 | if (loc == null) { | 22 | if (loc == null) { |
diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts index ac59bf60d..cf980e257 100644 --- a/editors/code/src/commands/runnables.ts +++ b/editors/code/src/commands/runnables.ts | |||
@@ -46,17 +46,17 @@ function createTask(spec: Runnable): vscode.Task { | |||
46 | label: spec.label, | 46 | label: spec.label, |
47 | command: spec.bin, | 47 | command: spec.bin, |
48 | args: spec.args, | 48 | args: spec.args, |
49 | env: spec.env | 49 | env: spec.env, |
50 | }; | 50 | }; |
51 | 51 | ||
52 | const execOption: vscode.ShellExecutionOptions = { | 52 | const execOption: vscode.ShellExecutionOptions = { |
53 | cwd: spec.cwd || '.', | 53 | cwd: spec.cwd || '.', |
54 | env: definition.env | 54 | env: definition.env, |
55 | }; | 55 | }; |
56 | const exec = new vscode.ShellExecution( | 56 | const exec = new vscode.ShellExecution( |
57 | definition.command, | 57 | definition.command, |
58 | definition.args, | 58 | definition.args, |
59 | execOption | 59 | execOption, |
60 | ); | 60 | ); |
61 | 61 | ||
62 | const f = vscode.workspace.workspaceFolders![0]; | 62 | const f = vscode.workspace.workspaceFolders![0]; |
@@ -66,30 +66,30 @@ function createTask(spec: Runnable): vscode.Task { | |||
66 | definition.label, | 66 | definition.label, |
67 | TASK_SOURCE, | 67 | TASK_SOURCE, |
68 | exec, | 68 | exec, |
69 | ['$rustc'] | 69 | ['$rustc'], |
70 | ); | 70 | ); |
71 | t.presentationOptions.clear = true; | 71 | t.presentationOptions.clear = true; |
72 | return t; | 72 | return t; |
73 | } | 73 | } |
74 | 74 | ||
75 | let prevRunnable: RunnableQuickPick | undefined; | 75 | let prevRunnable: RunnableQuickPick | undefined; |
76 | export async function handle() { | 76 | export async function handle(): Promise<vscode.TaskExecution | undefined> { |
77 | const editor = vscode.window.activeTextEditor; | 77 | const editor = vscode.window.activeTextEditor; |
78 | if (editor == null || editor.document.languageId !== 'rust') { | 78 | if (editor == null || editor.document.languageId !== 'rust') { |
79 | return; | 79 | return; |
80 | } | 80 | } |
81 | const textDocument: lc.TextDocumentIdentifier = { | 81 | const textDocument: lc.TextDocumentIdentifier = { |
82 | uri: editor.document.uri.toString() | 82 | uri: editor.document.uri.toString(), |
83 | }; | 83 | }; |
84 | const params: RunnablesParams = { | 84 | const params: RunnablesParams = { |
85 | textDocument, | 85 | textDocument, |
86 | position: Server.client.code2ProtocolConverter.asPosition( | 86 | position: Server.client.code2ProtocolConverter.asPosition( |
87 | editor.selection.active | 87 | editor.selection.active, |
88 | ) | 88 | ), |
89 | }; | 89 | }; |
90 | const runnables = await Server.client.sendRequest<Runnable[]>( | 90 | const runnables = await Server.client.sendRequest<Runnable[]>( |
91 | 'rust-analyzer/runnables', | 91 | 'rust-analyzer/runnables', |
92 | params | 92 | params, |
93 | ); | 93 | ); |
94 | const items: RunnableQuickPick[] = []; | 94 | const items: RunnableQuickPick[] = []; |
95 | if (prevRunnable) { | 95 | if (prevRunnable) { |
@@ -105,12 +105,14 @@ export async function handle() { | |||
105 | items.push(new RunnableQuickPick(r)); | 105 | items.push(new RunnableQuickPick(r)); |
106 | } | 106 | } |
107 | const item = await vscode.window.showQuickPick(items); | 107 | const item = await vscode.window.showQuickPick(items); |
108 | if (item) { | 108 | if (!item) { |
109 | item.detail = 'rerun'; | 109 | return; |
110 | prevRunnable = item; | ||
111 | const task = createTask(item.runnable); | ||
112 | return await vscode.tasks.executeTask(task); | ||
113 | } | 110 | } |
111 | |||
112 | item.detail = 'rerun'; | ||
113 | prevRunnable = item; | ||
114 | const task = createTask(item.runnable); | ||
115 | return await vscode.tasks.executeTask(task); | ||
114 | } | 116 | } |
115 | 117 | ||
116 | export async function handleSingle(runnable: Runnable) { | 118 | export async function handleSingle(runnable: Runnable) { |
@@ -124,7 +126,7 @@ export async function handleSingle(runnable: Runnable) { | |||
124 | task.presentationOptions = { | 126 | task.presentationOptions = { |
125 | reveal: vscode.TaskRevealKind.Always, | 127 | reveal: vscode.TaskRevealKind.Always, |
126 | panel: vscode.TaskPanelKind.Dedicated, | 128 | panel: vscode.TaskPanelKind.Dedicated, |
127 | clear: true | 129 | clear: true, |
128 | }; | 130 | }; |
129 | 131 | ||
130 | return vscode.tasks.executeTask(task); | 132 | return vscode.tasks.executeTask(task); |
@@ -136,7 +138,7 @@ export async function handleSingle(runnable: Runnable) { | |||
136 | * that, when accepted, allow us to `cargo install cargo-watch` and then run it. | 138 | * that, when accepted, allow us to `cargo install cargo-watch` and then run it. |
137 | */ | 139 | */ |
138 | export async function interactivelyStartCargoWatch( | 140 | export async function interactivelyStartCargoWatch( |
139 | context: vscode.ExtensionContext | 141 | context: vscode.ExtensionContext, |
140 | ): Promise<CargoWatchProvider | undefined> { | 142 | ): Promise<CargoWatchProvider | undefined> { |
141 | if (Server.config.cargoWatchOptions.enableOnStartup === 'disabled') { | 143 | if (Server.config.cargoWatchOptions.enableOnStartup === 'disabled') { |
142 | return; | 144 | return; |
@@ -146,7 +148,7 @@ export async function interactivelyStartCargoWatch( | |||
146 | const watch = await vscode.window.showInformationMessage( | 148 | const watch = await vscode.window.showInformationMessage( |
147 | 'Start watching changes with cargo? (Executes `cargo watch`, provides inline diagnostics)', | 149 | 'Start watching changes with cargo? (Executes `cargo watch`, provides inline diagnostics)', |
148 | 'yes', | 150 | 'yes', |
149 | 'no' | 151 | 'no', |
150 | ); | 152 | ); |
151 | if (watch !== 'yes') { | 153 | if (watch !== 'yes') { |
152 | return; | 154 | return; |
@@ -157,12 +159,12 @@ export async function interactivelyStartCargoWatch( | |||
157 | } | 159 | } |
158 | 160 | ||
159 | export async function startCargoWatch( | 161 | export async function startCargoWatch( |
160 | context: vscode.ExtensionContext | 162 | context: vscode.ExtensionContext, |
161 | ): Promise<CargoWatchProvider | undefined> { | 163 | ): Promise<CargoWatchProvider | undefined> { |
162 | const execPromise = util.promisify(child_process.exec); | 164 | const execPromise = util.promisify(child_process.exec); |
163 | 165 | ||
164 | const { stderr, code = 0 } = await execPromise( | 166 | const { stderr, code = 0 } = await execPromise( |
165 | 'cargo watch --version' | 167 | 'cargo watch --version', |
166 | ).catch(e => e); | 168 | ).catch(e => e); |
167 | 169 | ||
168 | if (stderr.includes('no such subcommand: `watch`')) { | 170 | if (stderr.includes('no such subcommand: `watch`')) { |
@@ -171,14 +173,14 @@ export async function startCargoWatch( | |||
171 | const install = await vscode.window.showInformationMessage( | 173 | const install = await vscode.window.showInformationMessage( |
172 | msg, | 174 | msg, |
173 | 'yes', | 175 | 'yes', |
174 | 'no' | 176 | 'no', |
175 | ); | 177 | ); |
176 | if (install !== 'yes') { | 178 | if (install !== 'yes') { |
177 | return; | 179 | return; |
178 | } | 180 | } |
179 | 181 | ||
180 | const label = 'install-cargo-watch'; | 182 | const label = 'install-cargo-watch'; |
181 | const taskFinished = new Promise((resolve, reject) => { | 183 | const taskFinished = new Promise((resolve, _reject) => { |
182 | const disposable = vscode.tasks.onDidEndTask(({ execution }) => { | 184 | const disposable = vscode.tasks.onDidEndTask(({ execution }) => { |
183 | if (execution.task.name === label) { | 185 | if (execution.task.name === label) { |
184 | disposable.dispose(); | 186 | disposable.dispose(); |
@@ -192,20 +194,20 @@ export async function startCargoWatch( | |||
192 | label, | 194 | label, |
193 | bin: 'cargo', | 195 | bin: 'cargo', |
194 | args: ['install', 'cargo-watch'], | 196 | args: ['install', 'cargo-watch'], |
195 | env: {} | 197 | env: {}, |
196 | }) | 198 | }), |
197 | ); | 199 | ); |
198 | await taskFinished; | 200 | await taskFinished; |
199 | const output = await execPromise('cargo watch --version').catch(e => e); | 201 | const output = await execPromise('cargo watch --version').catch(e => e); |
200 | if (output.stderr !== '') { | 202 | if (output.stderr !== '') { |
201 | vscode.window.showErrorMessage( | 203 | vscode.window.showErrorMessage( |
202 | `Couldn't install \`cargo-\`watch: ${output.stderr}` | 204 | `Couldn't install \`cargo-\`watch: ${output.stderr}`, |
203 | ); | 205 | ); |
204 | return; | 206 | return; |
205 | } | 207 | } |
206 | } else if (code !== 0) { | 208 | } else if (code !== 0) { |
207 | vscode.window.showErrorMessage( | 209 | vscode.window.showErrorMessage( |
208 | `\`cargo watch\` failed with ${code}: ${stderr}` | 210 | `\`cargo watch\` failed with ${code}: ${stderr}`, |
209 | ); | 211 | ); |
210 | return; | 212 | return; |
211 | } | 213 | } |
diff --git a/editors/code/src/commands/syntaxTree.ts b/editors/code/src/commands/syntaxTree.ts index 2f50fe14b..89a80550c 100644 --- a/editors/code/src/commands/syntaxTree.ts +++ b/editors/code/src/commands/syntaxTree.ts | |||
@@ -11,7 +11,7 @@ export class SyntaxTreeContentProvider | |||
11 | public syntaxTree: string = 'Not available'; | 11 | public syntaxTree: string = 'Not available'; |
12 | 12 | ||
13 | public provideTextDocumentContent( | 13 | public provideTextDocumentContent( |
14 | uri: vscode.Uri | 14 | uri: vscode.Uri, |
15 | ): vscode.ProviderResult<string> { | 15 | ): vscode.ProviderResult<string> { |
16 | const editor = vscode.window.activeTextEditor; | 16 | const editor = vscode.window.activeTextEditor; |
17 | if (editor == null) { | 17 | if (editor == null) { |
@@ -25,17 +25,17 @@ export class SyntaxTreeContentProvider | |||
25 | range = editor.selection.isEmpty | 25 | range = editor.selection.isEmpty |
26 | ? undefined | 26 | ? undefined |
27 | : Server.client.code2ProtocolConverter.asRange( | 27 | : Server.client.code2ProtocolConverter.asRange( |
28 | editor.selection | 28 | editor.selection, |
29 | ); | 29 | ); |
30 | } | 30 | } |
31 | 31 | ||
32 | const request: SyntaxTreeParams = { | 32 | const request: SyntaxTreeParams = { |
33 | textDocument: { uri: editor.document.uri.toString() }, | 33 | textDocument: { uri: editor.document.uri.toString() }, |
34 | range | 34 | range, |
35 | }; | 35 | }; |
36 | return Server.client.sendRequest<SyntaxTreeResult>( | 36 | return Server.client.sendRequest<SyntaxTreeResult>( |
37 | 'rust-analyzer/syntaxTree', | 37 | 'rust-analyzer/syntaxTree', |
38 | request | 38 | request, |
39 | ); | 39 | ); |
40 | } | 40 | } |
41 | 41 | ||
@@ -70,7 +70,7 @@ export function createHandle(provider: SyntaxTreeContentProvider) { | |||
70 | return vscode.window.showTextDocument( | 70 | return vscode.window.showTextDocument( |
71 | document, | 71 | document, |
72 | vscode.ViewColumn.Two, | 72 | vscode.ViewColumn.Two, |
73 | true | 73 | true, |
74 | ); | 74 | ); |
75 | }; | 75 | }; |
76 | } | 76 | } |
diff --git a/editors/code/src/commands/watch_status.ts b/editors/code/src/commands/watch_status.ts index 6c1f9041b..8d64394c7 100644 --- a/editors/code/src/commands/watch_status.ts +++ b/editors/code/src/commands/watch_status.ts | |||
@@ -13,7 +13,7 @@ export class StatusDisplay implements vscode.Disposable { | |||
13 | constructor(command: string) { | 13 | constructor(command: string) { |
14 | this.statusBarItem = vscode.window.createStatusBarItem( | 14 | this.statusBarItem = vscode.window.createStatusBarItem( |
15 | vscode.StatusBarAlignment.Left, | 15 | vscode.StatusBarAlignment.Left, |
16 | 10 | 16 | 10, |
17 | ); | 17 | ); |
18 | this.command = command; | 18 | this.command = command; |
19 | this.statusBarItem.hide(); | 19 | this.statusBarItem.hide(); |
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 4cedbea46..c06dddb1c 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -14,6 +14,13 @@ export interface CargoWatchOptions { | |||
14 | command: string; | 14 | command: string; |
15 | trace: CargoWatchTraceOptions; | 15 | trace: CargoWatchTraceOptions; |
16 | ignore: string[]; | 16 | ignore: string[]; |
17 | allTargets: boolean; | ||
18 | } | ||
19 | |||
20 | export interface CargoFeatures { | ||
21 | noDefaultFeatures: boolean; | ||
22 | allFeatures: boolean; | ||
23 | features: string[]; | ||
17 | } | 24 | } |
18 | 25 | ||
19 | export class Config { | 26 | export class Config { |
@@ -25,21 +32,30 @@ export class Config { | |||
25 | public displayInlayHints = true; | 32 | public displayInlayHints = true; |
26 | public maxInlayHintLength: null | number = null; | 33 | public maxInlayHintLength: null | number = null; |
27 | public excludeGlobs = []; | 34 | public excludeGlobs = []; |
28 | public useClientWatching = false; | 35 | public useClientWatching = true; |
29 | public featureFlags = {}; | 36 | public featureFlags = {}; |
37 | // for internal use | ||
38 | public withSysroot: null | boolean = null; | ||
30 | public cargoWatchOptions: CargoWatchOptions = { | 39 | public cargoWatchOptions: CargoWatchOptions = { |
31 | enableOnStartup: 'ask', | 40 | enableOnStartup: 'ask', |
32 | trace: 'off', | 41 | trace: 'off', |
33 | arguments: '', | 42 | arguments: '', |
34 | command: '', | 43 | command: '', |
35 | ignore: [] | 44 | ignore: [], |
45 | allTargets: true, | ||
46 | }; | ||
47 | public cargoFeatures: CargoFeatures = { | ||
48 | noDefaultFeatures: false, | ||
49 | allFeatures: true, | ||
50 | features: [], | ||
36 | }; | 51 | }; |
37 | 52 | ||
38 | private prevEnhancedTyping: null | boolean = null; | 53 | private prevEnhancedTyping: null | boolean = null; |
54 | private prevCargoFeatures: null | CargoFeatures = null; | ||
39 | 55 | ||
40 | constructor() { | 56 | constructor() { |
41 | vscode.workspace.onDidChangeConfiguration(_ => | 57 | vscode.workspace.onDidChangeConfiguration(_ => |
42 | this.userConfigChanged() | 58 | this.userConfigChanged(), |
43 | ); | 59 | ); |
44 | this.userConfigChanged(); | 60 | this.userConfigChanged(); |
45 | } | 61 | } |
@@ -49,6 +65,8 @@ export class Config { | |||
49 | 65 | ||
50 | Server.highlighter.removeHighlights(); | 66 | Server.highlighter.removeHighlights(); |
51 | 67 | ||
68 | let requireReloadMessage = null; | ||
69 | |||
52 | if (config.has('highlightingOn')) { | 70 | if (config.has('highlightingOn')) { |
53 | this.highlightingOn = config.get('highlightingOn') as boolean; | 71 | this.highlightingOn = config.get('highlightingOn') as boolean; |
54 | if (this.highlightingOn) { | 72 | if (this.highlightingOn) { |
@@ -59,13 +77,13 @@ export class Config { | |||
59 | 77 | ||
60 | if (config.has('rainbowHighlightingOn')) { | 78 | if (config.has('rainbowHighlightingOn')) { |
61 | this.rainbowHighlightingOn = config.get( | 79 | this.rainbowHighlightingOn = config.get( |
62 | 'rainbowHighlightingOn' | 80 | 'rainbowHighlightingOn', |
63 | ) as boolean; | 81 | ) as boolean; |
64 | } | 82 | } |
65 | 83 | ||
66 | if (config.has('enableEnhancedTyping')) { | 84 | if (config.has('enableEnhancedTyping')) { |
67 | this.enableEnhancedTyping = config.get( | 85 | this.enableEnhancedTyping = config.get( |
68 | 'enableEnhancedTyping' | 86 | 'enableEnhancedTyping', |
69 | ) as boolean; | 87 | ) as boolean; |
70 | 88 | ||
71 | if (this.prevEnhancedTyping === null) { | 89 | if (this.prevEnhancedTyping === null) { |
@@ -76,19 +94,8 @@ export class Config { | |||
76 | } | 94 | } |
77 | 95 | ||
78 | if (this.prevEnhancedTyping !== this.enableEnhancedTyping) { | 96 | if (this.prevEnhancedTyping !== this.enableEnhancedTyping) { |
79 | const reloadAction = 'Reload now'; | 97 | requireReloadMessage = |
80 | vscode.window | 98 | 'Changing enhanced typing setting requires a reload'; |
81 | .showInformationMessage( | ||
82 | 'Changing enhanced typing setting requires a reload', | ||
83 | reloadAction | ||
84 | ) | ||
85 | .then(selectedAction => { | ||
86 | if (selectedAction === reloadAction) { | ||
87 | vscode.commands.executeCommand( | ||
88 | 'workbench.action.reloadWindow' | ||
89 | ); | ||
90 | } | ||
91 | }); | ||
92 | this.prevEnhancedTyping = this.enableEnhancedTyping; | 99 | this.prevEnhancedTyping = this.enableEnhancedTyping; |
93 | } | 100 | } |
94 | 101 | ||
@@ -106,28 +113,35 @@ export class Config { | |||
106 | if (config.has('trace.cargo-watch')) { | 113 | if (config.has('trace.cargo-watch')) { |
107 | this.cargoWatchOptions.trace = config.get<CargoWatchTraceOptions>( | 114 | this.cargoWatchOptions.trace = config.get<CargoWatchTraceOptions>( |
108 | 'trace.cargo-watch', | 115 | 'trace.cargo-watch', |
109 | 'off' | 116 | 'off', |
110 | ); | 117 | ); |
111 | } | 118 | } |
112 | 119 | ||
113 | if (config.has('cargo-watch.arguments')) { | 120 | if (config.has('cargo-watch.arguments')) { |
114 | this.cargoWatchOptions.arguments = config.get<string>( | 121 | this.cargoWatchOptions.arguments = config.get<string>( |
115 | 'cargo-watch.arguments', | 122 | 'cargo-watch.arguments', |
116 | '' | 123 | '', |
117 | ); | 124 | ); |
118 | } | 125 | } |
119 | 126 | ||
120 | if (config.has('cargo-watch.command')) { | 127 | if (config.has('cargo-watch.command')) { |
121 | this.cargoWatchOptions.command = config.get<string>( | 128 | this.cargoWatchOptions.command = config.get<string>( |
122 | 'cargo-watch.command', | 129 | 'cargo-watch.command', |
123 | '' | 130 | '', |
124 | ); | 131 | ); |
125 | } | 132 | } |
126 | 133 | ||
127 | if (config.has('cargo-watch.ignore')) { | 134 | if (config.has('cargo-watch.ignore')) { |
128 | this.cargoWatchOptions.ignore = config.get<string[]>( | 135 | this.cargoWatchOptions.ignore = config.get<string[]>( |
129 | 'cargo-watch.ignore', | 136 | 'cargo-watch.ignore', |
130 | [] | 137 | [], |
138 | ); | ||
139 | } | ||
140 | |||
141 | if (config.has('cargo-watch.allTargets')) { | ||
142 | this.cargoWatchOptions.allTargets = config.get<boolean>( | ||
143 | 'cargo-watch.allTargets', | ||
144 | true, | ||
131 | ); | 145 | ); |
132 | } | 146 | } |
133 | 147 | ||
@@ -140,17 +154,68 @@ export class Config { | |||
140 | } | 154 | } |
141 | if (config.has('maxInlayHintLength')) { | 155 | if (config.has('maxInlayHintLength')) { |
142 | this.maxInlayHintLength = config.get( | 156 | this.maxInlayHintLength = config.get( |
143 | 'maxInlayHintLength' | 157 | 'maxInlayHintLength', |
144 | ) as number; | 158 | ) as number; |
145 | } | 159 | } |
146 | if (config.has('excludeGlobs')) { | 160 | if (config.has('excludeGlobs')) { |
147 | this.excludeGlobs = config.get('excludeGlobs') || []; | 161 | this.excludeGlobs = config.get('excludeGlobs') || []; |
148 | } | 162 | } |
149 | if (config.has('useClientWatching')) { | 163 | if (config.has('useClientWatching')) { |
150 | this.useClientWatching = config.get('useClientWatching') || false; | 164 | this.useClientWatching = config.get('useClientWatching') || true; |
151 | } | 165 | } |
152 | if (config.has('featureFlags')) { | 166 | if (config.has('featureFlags')) { |
153 | this.featureFlags = config.get('featureFlags') || {}; | 167 | this.featureFlags = config.get('featureFlags') || {}; |
154 | } | 168 | } |
169 | if (config.has('withSysroot')) { | ||
170 | this.withSysroot = config.get('withSysroot') || false; | ||
171 | } | ||
172 | |||
173 | if (config.has('cargoFeatures.noDefaultFeatures')) { | ||
174 | this.cargoFeatures.noDefaultFeatures = config.get( | ||
175 | 'cargoFeatures.noDefaultFeatures', | ||
176 | false, | ||
177 | ); | ||
178 | } | ||
179 | if (config.has('cargoFeatures.allFeatures')) { | ||
180 | this.cargoFeatures.allFeatures = config.get( | ||
181 | 'cargoFeatures.allFeatures', | ||
182 | true, | ||
183 | ); | ||
184 | } | ||
185 | if (config.has('cargoFeatures.features')) { | ||
186 | this.cargoFeatures.features = config.get( | ||
187 | 'cargoFeatures.features', | ||
188 | [], | ||
189 | ); | ||
190 | } | ||
191 | |||
192 | if ( | ||
193 | this.prevCargoFeatures !== null && | ||
194 | (this.cargoFeatures.allFeatures !== | ||
195 | this.prevCargoFeatures.allFeatures || | ||
196 | this.cargoFeatures.noDefaultFeatures !== | ||
197 | this.prevCargoFeatures.noDefaultFeatures || | ||
198 | this.cargoFeatures.features.length !== | ||
199 | this.prevCargoFeatures.features.length || | ||
200 | this.cargoFeatures.features.some( | ||
201 | (v, i) => v !== this.prevCargoFeatures!.features[i], | ||
202 | )) | ||
203 | ) { | ||
204 | requireReloadMessage = 'Changing cargo features requires a reload'; | ||
205 | } | ||
206 | this.prevCargoFeatures = { ...this.cargoFeatures }; | ||
207 | |||
208 | if (requireReloadMessage !== null) { | ||
209 | const reloadAction = 'Reload now'; | ||
210 | vscode.window | ||
211 | .showInformationMessage(requireReloadMessage, reloadAction) | ||
212 | .then(selectedAction => { | ||
213 | if (selectedAction === reloadAction) { | ||
214 | vscode.commands.executeCommand( | ||
215 | 'workbench.action.reloadWindow', | ||
216 | ); | ||
217 | } | ||
218 | }); | ||
219 | } | ||
155 | } | 220 | } |
156 | } | 221 | } |
diff --git a/editors/code/src/events/change_active_text_editor.ts b/editors/code/src/events/change_active_text_editor.ts index 64be56225..74b91bd48 100644 --- a/editors/code/src/events/change_active_text_editor.ts +++ b/editors/code/src/events/change_active_text_editor.ts | |||
@@ -3,7 +3,7 @@ import { TextDocumentIdentifier } from 'vscode-languageclient'; | |||
3 | 3 | ||
4 | import { | 4 | import { |
5 | SyntaxTreeContentProvider, | 5 | SyntaxTreeContentProvider, |
6 | syntaxTreeUri | 6 | syntaxTreeUri, |
7 | } from '../commands/syntaxTree'; | 7 | } from '../commands/syntaxTree'; |
8 | import { Decoration } from '../highlighting'; | 8 | import { Decoration } from '../highlighting'; |
9 | import { Server } from '../server'; | 9 | import { Server } from '../server'; |
@@ -21,11 +21,11 @@ export function makeHandler(syntaxTreeProvider: SyntaxTreeContentProvider) { | |||
21 | } | 21 | } |
22 | 22 | ||
23 | const params: TextDocumentIdentifier = { | 23 | const params: TextDocumentIdentifier = { |
24 | uri: editor.document.uri.toString() | 24 | uri: editor.document.uri.toString(), |
25 | }; | 25 | }; |
26 | const decorations = await Server.client.sendRequest<Decoration[]>( | 26 | const decorations = await Server.client.sendRequest<Decoration[]>( |
27 | 'rust-analyzer/decorationsRequest', | 27 | 'rust-analyzer/decorationsRequest', |
28 | params | 28 | params, |
29 | ); | 29 | ); |
30 | Server.highlighter.setHighlights(editor, decorations); | 30 | Server.highlighter.setHighlights(editor, decorations); |
31 | }; | 31 | }; |
diff --git a/editors/code/src/events/change_text_document.ts b/editors/code/src/events/change_text_document.ts index 89488bc61..2e998e889 100644 --- a/editors/code/src/events/change_text_document.ts +++ b/editors/code/src/events/change_text_document.ts | |||
@@ -2,7 +2,7 @@ import * as vscode from 'vscode'; | |||
2 | 2 | ||
3 | import { | 3 | import { |
4 | SyntaxTreeContentProvider, | 4 | SyntaxTreeContentProvider, |
5 | syntaxTreeUri | 5 | syntaxTreeUri, |
6 | } from '../commands/syntaxTree'; | 6 | } from '../commands/syntaxTree'; |
7 | 7 | ||
8 | export function createHandler(syntaxTreeProvider: SyntaxTreeContentProvider) { | 8 | export function createHandler(syntaxTreeProvider: SyntaxTreeContentProvider) { |
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 683497dfd..815f3692c 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts | |||
@@ -7,14 +7,14 @@ import { ExpandMacroContentProvider } from './commands/expand_macro'; | |||
7 | import { HintsUpdater } from './commands/inlay_hints'; | 7 | import { HintsUpdater } from './commands/inlay_hints'; |
8 | import { | 8 | import { |
9 | interactivelyStartCargoWatch, | 9 | interactivelyStartCargoWatch, |
10 | startCargoWatch | 10 | startCargoWatch, |
11 | } from './commands/runnables'; | 11 | } from './commands/runnables'; |
12 | import { SyntaxTreeContentProvider } from './commands/syntaxTree'; | 12 | import { SyntaxTreeContentProvider } from './commands/syntaxTree'; |
13 | import * as events from './events'; | 13 | import * as events from './events'; |
14 | import * as notifications from './notifications'; | 14 | import * as notifications from './notifications'; |
15 | import { Server } from './server'; | 15 | import { Server } from './server'; |
16 | 16 | ||
17 | export function activate(context: vscode.ExtensionContext) { | 17 | export async function activate(context: vscode.ExtensionContext) { |
18 | function disposeOnDeactivation(disposable: vscode.Disposable) { | 18 | function disposeOnDeactivation(disposable: vscode.Disposable) { |
19 | context.subscriptions.push(disposable); | 19 | context.subscriptions.push(disposable); |
20 | } | 20 | } |
@@ -24,7 +24,7 @@ export function activate(context: vscode.ExtensionContext) { | |||
24 | } | 24 | } |
25 | function overrideCommand( | 25 | function overrideCommand( |
26 | name: string, | 26 | name: string, |
27 | f: (...args: any[]) => Promise<boolean> | 27 | f: (...args: any[]) => Promise<boolean>, |
28 | ) { | 28 | ) { |
29 | const defaultCmd = `default:${name}`; | 29 | const defaultCmd = `default:${name}`; |
30 | const original = (...args: any[]) => | 30 | const original = (...args: any[]) => |
@@ -46,7 +46,7 @@ export function activate(context: vscode.ExtensionContext) { | |||
46 | }); | 46 | }); |
47 | } catch (_) { | 47 | } catch (_) { |
48 | vscode.window.showWarningMessage( | 48 | vscode.window.showWarningMessage( |
49 | 'Enhanced typing feature is disabled because of incompatibility with VIM extension, consider turning off rust-analyzer.enableEnhancedTyping: https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/README.md#settings' | 49 | 'Enhanced typing feature is disabled because of incompatibility with VIM extension, consider turning off rust-analyzer.enableEnhancedTyping: https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/README.md#settings', |
50 | ); | 50 | ); |
51 | } | 51 | } |
52 | } | 52 | } |
@@ -54,14 +54,14 @@ export function activate(context: vscode.ExtensionContext) { | |||
54 | // Commands are requests from vscode to the language server | 54 | // Commands are requests from vscode to the language server |
55 | registerCommand( | 55 | registerCommand( |
56 | 'rust-analyzer.analyzerStatus', | 56 | 'rust-analyzer.analyzerStatus', |
57 | commands.analyzerStatus.makeCommand(context) | 57 | commands.analyzerStatus.makeCommand(context), |
58 | ); | 58 | ); |
59 | registerCommand('rust-analyzer.collectGarbage', () => | 59 | registerCommand('rust-analyzer.collectGarbage', () => |
60 | Server.client.sendRequest<null>('rust-analyzer/collectGarbage', null) | 60 | Server.client.sendRequest<null>('rust-analyzer/collectGarbage', null), |
61 | ); | 61 | ); |
62 | registerCommand( | 62 | registerCommand( |
63 | 'rust-analyzer.matchingBrace', | 63 | 'rust-analyzer.matchingBrace', |
64 | commands.matchingBrace.handle | 64 | commands.matchingBrace.handle, |
65 | ); | 65 | ); |
66 | registerCommand('rust-analyzer.joinLines', commands.joinLines.handle); | 66 | registerCommand('rust-analyzer.joinLines', commands.joinLines.handle); |
67 | registerCommand('rust-analyzer.parentModule', commands.parentModule.handle); | 67 | registerCommand('rust-analyzer.parentModule', commands.parentModule.handle); |
@@ -70,7 +70,7 @@ export function activate(context: vscode.ExtensionContext) { | |||
70 | registerCommand('rust-analyzer.runSingle', commands.runnables.handleSingle); | 70 | registerCommand('rust-analyzer.runSingle', commands.runnables.handleSingle); |
71 | registerCommand( | 71 | registerCommand( |
72 | 'rust-analyzer.applySourceChange', | 72 | 'rust-analyzer.applySourceChange', |
73 | commands.applySourceChange.handle | 73 | commands.applySourceChange.handle, |
74 | ); | 74 | ); |
75 | registerCommand( | 75 | registerCommand( |
76 | 'rust-analyzer.showReferences', | 76 | 'rust-analyzer.showReferences', |
@@ -79,9 +79,9 @@ export function activate(context: vscode.ExtensionContext) { | |||
79 | 'editor.action.showReferences', | 79 | 'editor.action.showReferences', |
80 | vscode.Uri.parse(uri), | 80 | vscode.Uri.parse(uri), |
81 | Server.client.protocol2CodeConverter.asPosition(position), | 81 | Server.client.protocol2CodeConverter.asPosition(position), |
82 | locations.map(Server.client.protocol2CodeConverter.asLocation) | 82 | locations.map(Server.client.protocol2CodeConverter.asLocation), |
83 | ); | 83 | ); |
84 | } | 84 | }, |
85 | ); | 85 | ); |
86 | 86 | ||
87 | if (Server.config.enableEnhancedTyping) { | 87 | if (Server.config.enableEnhancedTyping) { |
@@ -89,48 +89,49 @@ export function activate(context: vscode.ExtensionContext) { | |||
89 | } | 89 | } |
90 | 90 | ||
91 | // Notifications are events triggered by the language server | 91 | // Notifications are events triggered by the language server |
92 | const allNotifications: Iterable< | 92 | const allNotifications: Iterable<[ |
93 | [string, lc.GenericNotificationHandler] | 93 | string, |
94 | > = [ | 94 | lc.GenericNotificationHandler, |
95 | ]> = [ | ||
95 | [ | 96 | [ |
96 | 'rust-analyzer/publishDecorations', | 97 | 'rust-analyzer/publishDecorations', |
97 | notifications.publishDecorations.handle | 98 | notifications.publishDecorations.handle, |
98 | ] | 99 | ], |
99 | ]; | 100 | ]; |
100 | const syntaxTreeContentProvider = new SyntaxTreeContentProvider(); | 101 | const syntaxTreeContentProvider = new SyntaxTreeContentProvider(); |
101 | const expandMacroContentProvider = new ExpandMacroContentProvider(); | 102 | const expandMacroContentProvider = new ExpandMacroContentProvider(); |
102 | 103 | ||
103 | // The events below are plain old javascript events, triggered and handled by vscode | 104 | // The events below are plain old javascript events, triggered and handled by vscode |
104 | vscode.window.onDidChangeActiveTextEditor( | 105 | vscode.window.onDidChangeActiveTextEditor( |
105 | events.changeActiveTextEditor.makeHandler(syntaxTreeContentProvider) | 106 | events.changeActiveTextEditor.makeHandler(syntaxTreeContentProvider), |
106 | ); | 107 | ); |
107 | 108 | ||
108 | disposeOnDeactivation( | 109 | disposeOnDeactivation( |
109 | vscode.workspace.registerTextDocumentContentProvider( | 110 | vscode.workspace.registerTextDocumentContentProvider( |
110 | 'rust-analyzer', | 111 | 'rust-analyzer', |
111 | syntaxTreeContentProvider | 112 | syntaxTreeContentProvider, |
112 | ) | 113 | ), |
113 | ); | 114 | ); |
114 | disposeOnDeactivation( | 115 | disposeOnDeactivation( |
115 | vscode.workspace.registerTextDocumentContentProvider( | 116 | vscode.workspace.registerTextDocumentContentProvider( |
116 | 'rust-analyzer', | 117 | 'rust-analyzer', |
117 | expandMacroContentProvider | 118 | expandMacroContentProvider, |
118 | ) | 119 | ), |
119 | ); | 120 | ); |
120 | 121 | ||
121 | registerCommand( | 122 | registerCommand( |
122 | 'rust-analyzer.syntaxTree', | 123 | 'rust-analyzer.syntaxTree', |
123 | commands.syntaxTree.createHandle(syntaxTreeContentProvider) | 124 | commands.syntaxTree.createHandle(syntaxTreeContentProvider), |
124 | ); | 125 | ); |
125 | registerCommand( | 126 | registerCommand( |
126 | 'rust-analyzer.expandMacro', | 127 | 'rust-analyzer.expandMacro', |
127 | commands.expandMacro.createHandle(expandMacroContentProvider) | 128 | commands.expandMacro.createHandle(expandMacroContentProvider), |
128 | ); | 129 | ); |
129 | 130 | ||
130 | vscode.workspace.onDidChangeTextDocument( | 131 | vscode.workspace.onDidChangeTextDocument( |
131 | events.changeTextDocument.createHandler(syntaxTreeContentProvider), | 132 | events.changeTextDocument.createHandler(syntaxTreeContentProvider), |
132 | null, | 133 | null, |
133 | context.subscriptions | 134 | context.subscriptions, |
134 | ); | 135 | ); |
135 | 136 | ||
136 | const startServer = () => Server.start(allNotifications); | 137 | const startServer = () => Server.start(allNotifications); |
@@ -159,7 +160,11 @@ export function activate(context: vscode.ExtensionContext) { | |||
159 | }); | 160 | }); |
160 | 161 | ||
161 | // Start the language server, finally! | 162 | // Start the language server, finally! |
162 | startServer(); | 163 | try { |
164 | await startServer(); | ||
165 | } catch (e) { | ||
166 | vscode.window.showErrorMessage(e.message); | ||
167 | } | ||
163 | 168 | ||
164 | if (Server.config.displayInlayHints) { | 169 | if (Server.config.displayInlayHints) { |
165 | const hintsUpdater = new HintsUpdater(); | 170 | const hintsUpdater = new HintsUpdater(); |
@@ -173,25 +178,25 @@ export function activate(context: vscode.ExtensionContext) { | |||
173 | editorChangeDisposable.dispose(); | 178 | editorChangeDisposable.dispose(); |
174 | } | 179 | } |
175 | return hintsUpdater.refreshHintsForVisibleEditors(); | 180 | return hintsUpdater.refreshHintsForVisibleEditors(); |
176 | } | 181 | }, |
177 | ); | 182 | ); |
178 | 183 | ||
179 | disposeOnDeactivation( | 184 | disposeOnDeactivation( |
180 | vscode.window.onDidChangeVisibleTextEditors(_ => | 185 | vscode.window.onDidChangeVisibleTextEditors(_ => |
181 | hintsUpdater.refreshHintsForVisibleEditors() | 186 | hintsUpdater.refreshHintsForVisibleEditors(), |
182 | ) | 187 | ), |
183 | ); | 188 | ); |
184 | disposeOnDeactivation( | 189 | disposeOnDeactivation( |
185 | vscode.workspace.onDidChangeTextDocument(e => | 190 | vscode.workspace.onDidChangeTextDocument(e => |
186 | hintsUpdater.refreshHintsForVisibleEditors(e) | 191 | hintsUpdater.refreshHintsForVisibleEditors(e), |
187 | ) | 192 | ), |
188 | ); | 193 | ); |
189 | disposeOnDeactivation( | 194 | disposeOnDeactivation( |
190 | vscode.workspace.onDidChangeConfiguration(_ => | 195 | vscode.workspace.onDidChangeConfiguration(_ => |
191 | hintsUpdater.toggleHintsDisplay( | 196 | hintsUpdater.toggleHintsDisplay( |
192 | Server.config.displayInlayHints | 197 | Server.config.displayInlayHints, |
193 | ) | 198 | ), |
194 | ) | 199 | ), |
195 | ); | 200 | ); |
196 | }); | 201 | }); |
197 | } | 202 | } |
@@ -204,10 +209,10 @@ export function deactivate(): Thenable<void> { | |||
204 | return Server.client.stop(); | 209 | return Server.client.stop(); |
205 | } | 210 | } |
206 | 211 | ||
207 | async function reloadServer(startServer: () => void) { | 212 | async function reloadServer(startServer: () => Promise<void>) { |
208 | if (Server.client != null) { | 213 | if (Server.client != null) { |
209 | vscode.window.showInformationMessage('Reloading rust-analyzer...'); | 214 | vscode.window.showInformationMessage('Reloading rust-analyzer...'); |
210 | await Server.client.stop(); | 215 | await Server.client.stop(); |
211 | startServer(); | 216 | await startServer(); |
212 | } | 217 | } |
213 | } | 218 | } |
diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 0a38c9ef6..68eae0941 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts | |||
@@ -67,7 +67,7 @@ export class Highlighter { | |||
67 | > { | 67 | > { |
68 | const decoration = ( | 68 | const decoration = ( |
69 | tag: string, | 69 | tag: string, |
70 | textDecoration?: string | 70 | textDecoration?: string, |
71 | ): [string, vscode.TextEditorDecorationType] => { | 71 | ): [string, vscode.TextEditorDecorationType] => { |
72 | const rule = scopesMapper.toRule(tag, scopes.find); | 72 | const rule = scopesMapper.toRule(tag, scopes.find); |
73 | 73 | ||
@@ -90,9 +90,10 @@ export class Highlighter { | |||
90 | } | 90 | } |
91 | }; | 91 | }; |
92 | 92 | ||
93 | const decorations: Iterable< | 93 | const decorations: Iterable<[ |
94 | [string, vscode.TextEditorDecorationType] | 94 | string, |
95 | > = [ | 95 | vscode.TextEditorDecorationType, |
96 | ]> = [ | ||
96 | decoration('comment'), | 97 | decoration('comment'), |
97 | decoration('string'), | 98 | decoration('string'), |
98 | decoration('keyword'), | 99 | decoration('keyword'), |
@@ -101,16 +102,23 @@ export class Highlighter { | |||
101 | decoration('function'), | 102 | decoration('function'), |
102 | decoration('parameter'), | 103 | decoration('parameter'), |
103 | decoration('constant'), | 104 | decoration('constant'), |
105 | decoration('type.builtin'), | ||
106 | decoration('type.generic'), | ||
107 | decoration('type.lifetime'), | ||
108 | decoration('type.param'), | ||
109 | decoration('type.self'), | ||
104 | decoration('type'), | 110 | decoration('type'), |
105 | decoration('builtin'), | ||
106 | decoration('text'), | 111 | decoration('text'), |
107 | decoration('attribute'), | 112 | decoration('attribute'), |
108 | decoration('literal'), | 113 | decoration('literal'), |
114 | decoration('literal.numeric'), | ||
115 | decoration('literal.char'), | ||
116 | decoration('literal.byte'), | ||
109 | decoration('macro'), | 117 | decoration('macro'), |
110 | decoration('variable'), | 118 | decoration('variable'), |
111 | decoration('variable.mut', 'underline'), | 119 | decoration('variable.mut', 'underline'), |
112 | decoration('field'), | 120 | decoration('field'), |
113 | decoration('module') | 121 | decoration('module'), |
114 | ]; | 122 | ]; |
115 | 123 | ||
116 | return new Map<string, vscode.TextEditorDecorationType>(decorations); | 124 | return new Map<string, vscode.TextEditorDecorationType>(decorations); |
@@ -139,7 +147,6 @@ export class Highlighter { | |||
139 | // | 147 | // |
140 | // Note: decoration objects need to be kept around so we can dispose them | 148 | // Note: decoration objects need to be kept around so we can dispose them |
141 | // if the user disables syntax highlighting | 149 | // if the user disables syntax highlighting |
142 | |||
143 | if (this.decorations == null) { | 150 | if (this.decorations == null) { |
144 | this.decorations = Highlighter.initDecorations(); | 151 | this.decorations = Highlighter.initDecorations(); |
145 | } | 152 | } |
@@ -168,23 +175,22 @@ export class Highlighter { | |||
168 | colorfulIdents | 175 | colorfulIdents |
169 | .get(d.bindingHash)![0] | 176 | .get(d.bindingHash)![0] |
170 | .push( | 177 | .push( |
171 | Server.client.protocol2CodeConverter.asRange(d.range) | 178 | Server.client.protocol2CodeConverter.asRange(d.range), |
172 | ); | 179 | ); |
173 | } else { | 180 | } else { |
174 | byTag | 181 | byTag |
175 | .get(d.tag)! | 182 | .get(d.tag)! |
176 | .push( | 183 | .push( |
177 | Server.client.protocol2CodeConverter.asRange(d.range) | 184 | Server.client.protocol2CodeConverter.asRange(d.range), |
178 | ); | 185 | ); |
179 | } | 186 | } |
180 | } | 187 | } |
181 | 188 | ||
182 | for (const tag of byTag.keys()) { | 189 | for (const tag of byTag.keys()) { |
183 | const dec = this.decorations.get( | 190 | const dec = this.decorations.get( |
184 | tag | 191 | tag, |
185 | ) as vscode.TextEditorDecorationType; | 192 | ) as vscode.TextEditorDecorationType; |
186 | const ranges = byTag.get(tag)!; | 193 | const ranges = byTag.get(tag)!; |
187 | |||
188 | editor.setDecorations(dec, ranges); | 194 | editor.setDecorations(dec, ranges); |
189 | } | 195 | } |
190 | 196 | ||
@@ -192,7 +198,7 @@ export class Highlighter { | |||
192 | const textDecoration = mut ? 'underline' : undefined; | 198 | const textDecoration = mut ? 'underline' : undefined; |
193 | const dec = vscode.window.createTextEditorDecorationType({ | 199 | const dec = vscode.window.createTextEditorDecorationType({ |
194 | light: { color: fancify(hash, 'light'), textDecoration }, | 200 | light: { color: fancify(hash, 'light'), textDecoration }, |
195 | dark: { color: fancify(hash, 'dark'), textDecoration } | 201 | dark: { color: fancify(hash, 'dark'), textDecoration }, |
196 | }); | 202 | }); |
197 | editor.setDecorations(dec, ranges); | 203 | editor.setDecorations(dec, ranges); |
198 | } | 204 | } |
diff --git a/editors/code/src/notifications/publish_decorations.ts b/editors/code/src/notifications/publish_decorations.ts index 3180019b7..f23e286ad 100644 --- a/editors/code/src/notifications/publish_decorations.ts +++ b/editors/code/src/notifications/publish_decorations.ts | |||
@@ -9,11 +9,16 @@ export interface PublishDecorationsParams { | |||
9 | } | 9 | } |
10 | 10 | ||
11 | export function handle(params: PublishDecorationsParams) { | 11 | export function handle(params: PublishDecorationsParams) { |
12 | const targetEditor = vscode.window.visibleTextEditors.find( | 12 | const targetEditor = vscode.window.visibleTextEditors.find(editor => { |
13 | editor => editor.document.uri.toString() === params.uri | 13 | const unescapedUri = unescape(editor.document.uri.toString()); |
14 | ); | 14 | // Unescaped URI looks like: |
15 | // file:///c:/Workspace/ra-test/src/main.rs | ||
16 | return unescapedUri === params.uri; | ||
17 | }); | ||
18 | |||
15 | if (!Server.config.highlightingOn || !targetEditor) { | 19 | if (!Server.config.highlightingOn || !targetEditor) { |
16 | return; | 20 | return; |
17 | } | 21 | } |
22 | |||
18 | Server.highlighter.setHighlights(targetEditor, params.decorations); | 23 | Server.highlighter.setHighlights(targetEditor, params.decorations); |
19 | } | 24 | } |
diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index 7907b70bc..5ace1d0fa 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { homedir } from 'os'; | 1 | import { lookpath } from 'lookpath'; |
2 | import { homedir, platform } from 'os'; | ||
2 | import * as lc from 'vscode-languageclient'; | 3 | import * as lc from 'vscode-languageclient'; |
3 | 4 | ||
4 | import { window, workspace } from 'vscode'; | 5 | import { window, workspace } from 'vscode'; |
@@ -17,8 +18,8 @@ export class Server { | |||
17 | public static config = new Config(); | 18 | public static config = new Config(); |
18 | public static client: lc.LanguageClient; | 19 | public static client: lc.LanguageClient; |
19 | 20 | ||
20 | public static start( | 21 | public static async start( |
21 | notificationHandlers: Iterable<[string, lc.GenericNotificationHandler]> | 22 | notificationHandlers: Iterable<[string, lc.GenericNotificationHandler]>, |
22 | ) { | 23 | ) { |
23 | // '.' Is the fallback if no folder is open | 24 | // '.' Is the fallback if no folder is open |
24 | // TODO?: Workspace folders support Uri's (eg: file://test.txt). It might be a good idea to test if the uri points to a file. | 25 | // TODO?: Workspace folders support Uri's (eg: file://test.txt). It might be a good idea to test if the uri points to a file. |
@@ -27,16 +28,26 @@ export class Server { | |||
27 | folder = workspace.workspaceFolders[0].uri.fsPath.toString(); | 28 | folder = workspace.workspaceFolders[0].uri.fsPath.toString(); |
28 | } | 29 | } |
29 | 30 | ||
31 | const command = expandPathResolving(this.config.raLspServerPath); | ||
32 | // FIXME: remove check when the following issue is fixed: | ||
33 | // https://github.com/otiai10/lookpath/issues/4 | ||
34 | if (platform() !== 'win32') { | ||
35 | if (!(await lookpath(command))) { | ||
36 | throw new Error( | ||
37 | `Cannot find rust-analyzer server \`${command}\` in PATH.`, | ||
38 | ); | ||
39 | } | ||
40 | } | ||
30 | const run: lc.Executable = { | 41 | const run: lc.Executable = { |
31 | command: expandPathResolving(this.config.raLspServerPath), | 42 | command, |
32 | options: { cwd: folder } | 43 | options: { cwd: folder }, |
33 | }; | 44 | }; |
34 | const serverOptions: lc.ServerOptions = { | 45 | const serverOptions: lc.ServerOptions = { |
35 | run, | 46 | run, |
36 | debug: run | 47 | debug: run, |
37 | }; | 48 | }; |
38 | const traceOutputChannel = window.createOutputChannel( | 49 | const traceOutputChannel = window.createOutputChannel( |
39 | 'Rust Analyzer Language Server Trace' | 50 | 'Rust Analyzer Language Server Trace', |
40 | ); | 51 | ); |
41 | const clientOptions: lc.LanguageClientOptions = { | 52 | const clientOptions: lc.LanguageClientOptions = { |
42 | documentSelector: [{ scheme: 'file', language: 'rust' }], | 53 | documentSelector: [{ scheme: 'file', language: 'rust' }], |
@@ -46,16 +57,18 @@ export class Server { | |||
46 | maxInlayHintLength: Server.config.maxInlayHintLength, | 57 | maxInlayHintLength: Server.config.maxInlayHintLength, |
47 | excludeGlobs: Server.config.excludeGlobs, | 58 | excludeGlobs: Server.config.excludeGlobs, |
48 | useClientWatching: Server.config.useClientWatching, | 59 | useClientWatching: Server.config.useClientWatching, |
49 | featureFlags: Server.config.featureFlags | 60 | featureFlags: Server.config.featureFlags, |
61 | withSysroot: Server.config.withSysroot, | ||
62 | cargoFeatures: Server.config.cargoFeatures, | ||
50 | }, | 63 | }, |
51 | traceOutputChannel | 64 | traceOutputChannel, |
52 | }; | 65 | }; |
53 | 66 | ||
54 | Server.client = new lc.LanguageClient( | 67 | Server.client = new lc.LanguageClient( |
55 | 'rust-analyzer', | 68 | 'rust-analyzer', |
56 | 'Rust Analyzer Language Server', | 69 | 'Rust Analyzer Language Server', |
57 | serverOptions, | 70 | serverOptions, |
58 | clientOptions | 71 | clientOptions, |
59 | ); | 72 | ); |
60 | // HACK: This is an awful way of filtering out the decorations notifications | 73 | // HACK: This is an awful way of filtering out the decorations notifications |
61 | // However, pending proper support, this is the most effecitve approach | 74 | // However, pending proper support, this is the most effecitve approach |
@@ -68,10 +81,10 @@ export class Server { | |||
68 | if (typeof messageOrDataObject === 'string') { | 81 | if (typeof messageOrDataObject === 'string') { |
69 | if ( | 82 | if ( |
70 | messageOrDataObject.includes( | 83 | messageOrDataObject.includes( |
71 | 'rust-analyzer/publishDecorations' | 84 | 'rust-analyzer/publishDecorations', |
72 | ) || | 85 | ) || |
73 | messageOrDataObject.includes( | 86 | messageOrDataObject.includes( |
74 | 'rust-analyzer/decorationsRequest' | 87 | 'rust-analyzer/decorationsRequest', |
75 | ) | 88 | ) |
76 | ) { | 89 | ) { |
77 | // Don't log publish decorations requests | 90 | // Don't log publish decorations requests |
@@ -83,7 +96,7 @@ export class Server { | |||
83 | // @ts-ignore | 96 | // @ts-ignore |
84 | Server.client.logObjectTrace(messageOrDataObject); | 97 | Server.client.logObjectTrace(messageOrDataObject); |
85 | } | 98 | } |
86 | } | 99 | }, |
87 | }; | 100 | }; |
88 | Server.client.registerProposedFeatures(); | 101 | Server.client.registerProposedFeatures(); |
89 | Server.client.onReady().then(() => { | 102 | Server.client.onReady().then(() => { |
diff --git a/editors/code/src/test/fixtures/rust-diagnostics/error/E0277.json b/editors/code/src/test/fixtures/rust-diagnostics/error/E0277.json new file mode 100644 index 000000000..bfef33c7d --- /dev/null +++ b/editors/code/src/test/fixtures/rust-diagnostics/error/E0277.json | |||
@@ -0,0 +1,261 @@ | |||
1 | { | ||
2 | "rendered": "error[E0277]: can't compare `{integer}` with `&str`\n --> src/main.rs:2:5\n |\n2 | assert_eq!(1, \"love\");\n | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &str`\n |\n = help: the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`\n = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)\n\n", | ||
3 | "children": [ | ||
4 | { | ||
5 | "children": [], | ||
6 | "code": null, | ||
7 | "level": "help", | ||
8 | "message": "the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`", | ||
9 | "rendered": null, | ||
10 | "spans": [] | ||
11 | } | ||
12 | ], | ||
13 | "code": { | ||
14 | "code": "E0277", | ||
15 | "explanation": "\nYou tried to use a type which doesn't implement some trait in a place which\nexpected that trait. Erroneous code example:\n\n```compile_fail,E0277\n// here we declare the Foo trait with a bar method\ntrait Foo {\n fn bar(&self);\n}\n\n// we now declare a function which takes an object implementing the Foo trait\nfn some_func<T: Foo>(foo: T) {\n foo.bar();\n}\n\nfn main() {\n // we now call the method with the i32 type, which doesn't implement\n // the Foo trait\n some_func(5i32); // error: the trait bound `i32 : Foo` is not satisfied\n}\n```\n\nIn order to fix this error, verify that the type you're using does implement\nthe trait. Example:\n\n```\ntrait Foo {\n fn bar(&self);\n}\n\nfn some_func<T: Foo>(foo: T) {\n foo.bar(); // we can now use this method since i32 implements the\n // Foo trait\n}\n\n// we implement the trait on the i32 type\nimpl Foo for i32 {\n fn bar(&self) {}\n}\n\nfn main() {\n some_func(5i32); // ok!\n}\n```\n\nOr in a generic context, an erroneous code example would look like:\n\n```compile_fail,E0277\nfn some_func<T>(foo: T) {\n println!(\"{:?}\", foo); // error: the trait `core::fmt::Debug` is not\n // implemented for the type `T`\n}\n\nfn main() {\n // We now call the method with the i32 type,\n // which *does* implement the Debug trait.\n some_func(5i32);\n}\n```\n\nNote that the error here is in the definition of the generic function: Although\nwe only call it with a parameter that does implement `Debug`, the compiler\nstill rejects the function: It must work with all possible input types. In\norder to make this example compile, we need to restrict the generic type we're\naccepting:\n\n```\nuse std::fmt;\n\n// Restrict the input type to types that implement Debug.\nfn some_func<T: fmt::Debug>(foo: T) {\n println!(\"{:?}\", foo);\n}\n\nfn main() {\n // Calling the method is still fine, as i32 implements Debug.\n some_func(5i32);\n\n // This would fail to compile now:\n // struct WithoutDebug;\n // some_func(WithoutDebug);\n}\n```\n\nRust only looks at the signature of the called function, as such it must\nalready specify all requirements that will be used for every type parameter.\n" | ||
16 | }, | ||
17 | "level": "error", | ||
18 | "message": "can't compare `{integer}` with `&str`", | ||
19 | "spans": [ | ||
20 | { | ||
21 | "byte_end": 155, | ||
22 | "byte_start": 153, | ||
23 | "column_end": 33, | ||
24 | "column_start": 31, | ||
25 | "expansion": { | ||
26 | "def_site_span": { | ||
27 | "byte_end": 940, | ||
28 | "byte_start": 0, | ||
29 | "column_end": 6, | ||
30 | "column_start": 1, | ||
31 | "expansion": null, | ||
32 | "file_name": "<::core::macros::assert_eq macros>", | ||
33 | "is_primary": false, | ||
34 | "label": null, | ||
35 | "line_end": 36, | ||
36 | "line_start": 1, | ||
37 | "suggested_replacement": null, | ||
38 | "suggestion_applicability": null, | ||
39 | "text": [ | ||
40 | { | ||
41 | "highlight_end": 35, | ||
42 | "highlight_start": 1, | ||
43 | "text": "($ left : expr, $ right : expr) =>" | ||
44 | }, | ||
45 | { | ||
46 | "highlight_end": 3, | ||
47 | "highlight_start": 1, | ||
48 | "text": "({" | ||
49 | }, | ||
50 | { | ||
51 | "highlight_end": 33, | ||
52 | "highlight_start": 1, | ||
53 | "text": " match (& $ left, & $ right)" | ||
54 | }, | ||
55 | { | ||
56 | "highlight_end": 7, | ||
57 | "highlight_start": 1, | ||
58 | "text": " {" | ||
59 | }, | ||
60 | { | ||
61 | "highlight_end": 34, | ||
62 | "highlight_start": 1, | ||
63 | "text": " (left_val, right_val) =>" | ||
64 | }, | ||
65 | { | ||
66 | "highlight_end": 11, | ||
67 | "highlight_start": 1, | ||
68 | "text": " {" | ||
69 | }, | ||
70 | { | ||
71 | "highlight_end": 46, | ||
72 | "highlight_start": 1, | ||
73 | "text": " if ! (* left_val == * right_val)" | ||
74 | }, | ||
75 | { | ||
76 | "highlight_end": 15, | ||
77 | "highlight_start": 1, | ||
78 | "text": " {" | ||
79 | }, | ||
80 | { | ||
81 | "highlight_end": 25, | ||
82 | "highlight_start": 1, | ||
83 | "text": " panic !" | ||
84 | }, | ||
85 | { | ||
86 | "highlight_end": 57, | ||
87 | "highlight_start": 1, | ||
88 | "text": " (r#\"assertion failed: `(left == right)`" | ||
89 | }, | ||
90 | { | ||
91 | "highlight_end": 16, | ||
92 | "highlight_start": 1, | ||
93 | "text": " left: `{:?}`," | ||
94 | }, | ||
95 | { | ||
96 | "highlight_end": 18, | ||
97 | "highlight_start": 1, | ||
98 | "text": " right: `{:?}`\"#," | ||
99 | }, | ||
100 | { | ||
101 | "highlight_end": 47, | ||
102 | "highlight_start": 1, | ||
103 | "text": " & * left_val, & * right_val)" | ||
104 | }, | ||
105 | { | ||
106 | "highlight_end": 15, | ||
107 | "highlight_start": 1, | ||
108 | "text": " }" | ||
109 | }, | ||
110 | { | ||
111 | "highlight_end": 11, | ||
112 | "highlight_start": 1, | ||
113 | "text": " }" | ||
114 | }, | ||
115 | { | ||
116 | "highlight_end": 7, | ||
117 | "highlight_start": 1, | ||
118 | "text": " }" | ||
119 | }, | ||
120 | { | ||
121 | "highlight_end": 42, | ||
122 | "highlight_start": 1, | ||
123 | "text": " }) ; ($ left : expr, $ right : expr,) =>" | ||
124 | }, | ||
125 | { | ||
126 | "highlight_end": 49, | ||
127 | "highlight_start": 1, | ||
128 | "text": "({ $ crate :: assert_eq ! ($ left, $ right) }) ;" | ||
129 | }, | ||
130 | { | ||
131 | "highlight_end": 53, | ||
132 | "highlight_start": 1, | ||
133 | "text": "($ left : expr, $ right : expr, $ ($ arg : tt) +) =>" | ||
134 | }, | ||
135 | { | ||
136 | "highlight_end": 3, | ||
137 | "highlight_start": 1, | ||
138 | "text": "({" | ||
139 | }, | ||
140 | { | ||
141 | "highlight_end": 37, | ||
142 | "highlight_start": 1, | ||
143 | "text": " match (& ($ left), & ($ right))" | ||
144 | }, | ||
145 | { | ||
146 | "highlight_end": 7, | ||
147 | "highlight_start": 1, | ||
148 | "text": " {" | ||
149 | }, | ||
150 | { | ||
151 | "highlight_end": 34, | ||
152 | "highlight_start": 1, | ||
153 | "text": " (left_val, right_val) =>" | ||
154 | }, | ||
155 | { | ||
156 | "highlight_end": 11, | ||
157 | "highlight_start": 1, | ||
158 | "text": " {" | ||
159 | }, | ||
160 | { | ||
161 | "highlight_end": 46, | ||
162 | "highlight_start": 1, | ||
163 | "text": " if ! (* left_val == * right_val)" | ||
164 | }, | ||
165 | { | ||
166 | "highlight_end": 15, | ||
167 | "highlight_start": 1, | ||
168 | "text": " {" | ||
169 | }, | ||
170 | { | ||
171 | "highlight_end": 25, | ||
172 | "highlight_start": 1, | ||
173 | "text": " panic !" | ||
174 | }, | ||
175 | { | ||
176 | "highlight_end": 57, | ||
177 | "highlight_start": 1, | ||
178 | "text": " (r#\"assertion failed: `(left == right)`" | ||
179 | }, | ||
180 | { | ||
181 | "highlight_end": 16, | ||
182 | "highlight_start": 1, | ||
183 | "text": " left: `{:?}`," | ||
184 | }, | ||
185 | { | ||
186 | "highlight_end": 22, | ||
187 | "highlight_start": 1, | ||
188 | "text": " right: `{:?}`: {}\"#," | ||
189 | }, | ||
190 | { | ||
191 | "highlight_end": 72, | ||
192 | "highlight_start": 1, | ||
193 | "text": " & * left_val, & * right_val, $ crate :: format_args !" | ||
194 | }, | ||
195 | { | ||
196 | "highlight_end": 33, | ||
197 | "highlight_start": 1, | ||
198 | "text": " ($ ($ arg) +))" | ||
199 | }, | ||
200 | { | ||
201 | "highlight_end": 15, | ||
202 | "highlight_start": 1, | ||
203 | "text": " }" | ||
204 | }, | ||
205 | { | ||
206 | "highlight_end": 11, | ||
207 | "highlight_start": 1, | ||
208 | "text": " }" | ||
209 | }, | ||
210 | { | ||
211 | "highlight_end": 7, | ||
212 | "highlight_start": 1, | ||
213 | "text": " }" | ||
214 | }, | ||
215 | { | ||
216 | "highlight_end": 6, | ||
217 | "highlight_start": 1, | ||
218 | "text": " }) ;" | ||
219 | } | ||
220 | ] | ||
221 | }, | ||
222 | "macro_decl_name": "assert_eq!", | ||
223 | "span": { | ||
224 | "byte_end": 38, | ||
225 | "byte_start": 16, | ||
226 | "column_end": 27, | ||
227 | "column_start": 5, | ||
228 | "expansion": null, | ||
229 | "file_name": "src/main.rs", | ||
230 | "is_primary": false, | ||
231 | "label": null, | ||
232 | "line_end": 2, | ||
233 | "line_start": 2, | ||
234 | "suggested_replacement": null, | ||
235 | "suggestion_applicability": null, | ||
236 | "text": [ | ||
237 | { | ||
238 | "highlight_end": 27, | ||
239 | "highlight_start": 5, | ||
240 | "text": " assert_eq!(1, \"love\");" | ||
241 | } | ||
242 | ] | ||
243 | } | ||
244 | }, | ||
245 | "file_name": "<::core::macros::assert_eq macros>", | ||
246 | "is_primary": true, | ||
247 | "label": "no implementation for `{integer} == &str`", | ||
248 | "line_end": 7, | ||
249 | "line_start": 7, | ||
250 | "suggested_replacement": null, | ||
251 | "suggestion_applicability": null, | ||
252 | "text": [ | ||
253 | { | ||
254 | "highlight_end": 33, | ||
255 | "highlight_start": 31, | ||
256 | "text": " if ! (* left_val == * right_val)" | ||
257 | } | ||
258 | ] | ||
259 | } | ||
260 | ] | ||
261 | } | ||
diff --git a/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts b/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts index 6c7f436f3..2b25eb705 100644 --- a/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts +++ b/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts | |||
@@ -6,12 +6,12 @@ import SuggestedFix from '../../../utils/diagnostics/SuggestedFix'; | |||
6 | 6 | ||
7 | const location1 = new vscode.Location( | 7 | const location1 = new vscode.Location( |
8 | vscode.Uri.file('/file/1'), | 8 | vscode.Uri.file('/file/1'), |
9 | new vscode.Range(new vscode.Position(1, 2), new vscode.Position(3, 4)) | 9 | new vscode.Range(new vscode.Position(1, 2), new vscode.Position(3, 4)), |
10 | ); | 10 | ); |
11 | 11 | ||
12 | const location2 = new vscode.Location( | 12 | const location2 = new vscode.Location( |
13 | vscode.Uri.file('/file/2'), | 13 | vscode.Uri.file('/file/2'), |
14 | new vscode.Range(new vscode.Position(5, 6), new vscode.Position(7, 8)) | 14 | new vscode.Range(new vscode.Position(5, 6), new vscode.Position(7, 8)), |
15 | ); | 15 | ); |
16 | 16 | ||
17 | describe('SuggestedFix', () => { | 17 | describe('SuggestedFix', () => { |
@@ -20,13 +20,13 @@ describe('SuggestedFix', () => { | |||
20 | const suggestion1 = new SuggestedFix( | 20 | const suggestion1 = new SuggestedFix( |
21 | 'Replace me!', | 21 | 'Replace me!', |
22 | location1, | 22 | location1, |
23 | 'With this!' | 23 | 'With this!', |
24 | ); | 24 | ); |
25 | 25 | ||
26 | const suggestion2 = new SuggestedFix( | 26 | const suggestion2 = new SuggestedFix( |
27 | 'Replace me!', | 27 | 'Replace me!', |
28 | location1, | 28 | location1, |
29 | 'With this!' | 29 | 'With this!', |
30 | ); | 30 | ); |
31 | 31 | ||
32 | assert(suggestion1.isEqual(suggestion2)); | 32 | assert(suggestion1.isEqual(suggestion2)); |
@@ -36,13 +36,13 @@ describe('SuggestedFix', () => { | |||
36 | const suggestion1 = new SuggestedFix( | 36 | const suggestion1 = new SuggestedFix( |
37 | 'Replace me!', | 37 | 'Replace me!', |
38 | location1, | 38 | location1, |
39 | 'With this!' | 39 | 'With this!', |
40 | ); | 40 | ); |
41 | 41 | ||
42 | const suggestion2 = new SuggestedFix( | 42 | const suggestion2 = new SuggestedFix( |
43 | 'Not the same title!', | 43 | 'Not the same title!', |
44 | location1, | 44 | location1, |
45 | 'With this!' | 45 | 'With this!', |
46 | ); | 46 | ); |
47 | 47 | ||
48 | assert(!suggestion1.isEqual(suggestion2)); | 48 | assert(!suggestion1.isEqual(suggestion2)); |
@@ -52,13 +52,13 @@ describe('SuggestedFix', () => { | |||
52 | const suggestion1 = new SuggestedFix( | 52 | const suggestion1 = new SuggestedFix( |
53 | 'Replace me!', | 53 | 'Replace me!', |
54 | location1, | 54 | location1, |
55 | 'With this!' | 55 | 'With this!', |
56 | ); | 56 | ); |
57 | 57 | ||
58 | const suggestion2 = new SuggestedFix( | 58 | const suggestion2 = new SuggestedFix( |
59 | 'Replace me!', | 59 | 'Replace me!', |
60 | location1, | 60 | location1, |
61 | 'With something else!' | 61 | 'With something else!', |
62 | ); | 62 | ); |
63 | 63 | ||
64 | assert(!suggestion1.isEqual(suggestion2)); | 64 | assert(!suggestion1.isEqual(suggestion2)); |
@@ -68,13 +68,13 @@ describe('SuggestedFix', () => { | |||
68 | const suggestion1 = new SuggestedFix( | 68 | const suggestion1 = new SuggestedFix( |
69 | 'Replace me!', | 69 | 'Replace me!', |
70 | location1, | 70 | location1, |
71 | 'With this!' | 71 | 'With this!', |
72 | ); | 72 | ); |
73 | 73 | ||
74 | const suggestion2 = new SuggestedFix( | 74 | const suggestion2 = new SuggestedFix( |
75 | 'Replace me!', | 75 | 'Replace me!', |
76 | location2, | 76 | location2, |
77 | 'With this!' | 77 | 'With this!', |
78 | ); | 78 | ); |
79 | 79 | ||
80 | assert(!suggestion1.isEqual(suggestion2)); | 80 | assert(!suggestion1.isEqual(suggestion2)); |
@@ -85,14 +85,14 @@ describe('SuggestedFix', () => { | |||
85 | 'Replace me!', | 85 | 'Replace me!', |
86 | location1, | 86 | location1, |
87 | 'With this!', | 87 | 'With this!', |
88 | SuggestionApplicability.MachineApplicable | 88 | SuggestionApplicability.MachineApplicable, |
89 | ); | 89 | ); |
90 | 90 | ||
91 | const suggestion2 = new SuggestedFix( | 91 | const suggestion2 = new SuggestedFix( |
92 | 'Replace me!', | 92 | 'Replace me!', |
93 | location2, | 93 | location2, |
94 | 'With this!', | 94 | 'With this!', |
95 | SuggestionApplicability.HasPlaceholders | 95 | SuggestionApplicability.HasPlaceholders, |
96 | ); | 96 | ); |
97 | 97 | ||
98 | assert(!suggestion1.isEqual(suggestion2)); | 98 | assert(!suggestion1.isEqual(suggestion2)); |
@@ -104,7 +104,7 @@ describe('SuggestedFix', () => { | |||
104 | const suggestion = new SuggestedFix( | 104 | const suggestion = new SuggestedFix( |
105 | 'Replace me!', | 105 | 'Replace me!', |
106 | location1, | 106 | location1, |
107 | 'With this!' | 107 | 'With this!', |
108 | ); | 108 | ); |
109 | 109 | ||
110 | const codeAction = suggestion.toCodeAction(); | 110 | const codeAction = suggestion.toCodeAction(); |
@@ -114,7 +114,8 @@ describe('SuggestedFix', () => { | |||
114 | 114 | ||
115 | const edit = codeAction.edit; | 115 | const edit = codeAction.edit; |
116 | if (!edit) { | 116 | if (!edit) { |
117 | return assert.fail('Code Action edit unexpectedly missing'); | 117 | assert.fail('Code Action edit unexpectedly missing'); |
118 | return; | ||
118 | } | 119 | } |
119 | 120 | ||
120 | const editEntries = edit.entries(); | 121 | const editEntries = edit.entries(); |
diff --git a/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts b/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts index f0328893e..ef09013f4 100644 --- a/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts +++ b/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts | |||
@@ -8,20 +8,20 @@ const uri1 = vscode.Uri.file('/file/1'); | |||
8 | const uri2 = vscode.Uri.file('/file/2'); | 8 | const uri2 = vscode.Uri.file('/file/2'); |
9 | 9 | ||
10 | const mockDocument1 = ({ | 10 | const mockDocument1 = ({ |
11 | uri: uri1 | 11 | uri: uri1, |
12 | } as unknown) as vscode.TextDocument; | 12 | } as unknown) as vscode.TextDocument; |
13 | 13 | ||
14 | const mockDocument2 = ({ | 14 | const mockDocument2 = ({ |
15 | uri: uri2 | 15 | uri: uri2, |
16 | } as unknown) as vscode.TextDocument; | 16 | } as unknown) as vscode.TextDocument; |
17 | 17 | ||
18 | const range1 = new vscode.Range( | 18 | const range1 = new vscode.Range( |
19 | new vscode.Position(1, 2), | 19 | new vscode.Position(1, 2), |
20 | new vscode.Position(3, 4) | 20 | new vscode.Position(3, 4), |
21 | ); | 21 | ); |
22 | const range2 = new vscode.Range( | 22 | const range2 = new vscode.Range( |
23 | new vscode.Position(5, 6), | 23 | new vscode.Position(5, 6), |
24 | new vscode.Position(7, 8) | 24 | new vscode.Position(7, 8), |
25 | ); | 25 | ); |
26 | 26 | ||
27 | const diagnostic1 = new vscode.Diagnostic(range1, 'First diagnostic'); | 27 | const diagnostic1 = new vscode.Diagnostic(range1, 'First diagnostic'); |
@@ -32,7 +32,7 @@ function suggestion1(): SuggestedFix { | |||
32 | return new SuggestedFix( | 32 | return new SuggestedFix( |
33 | 'Replace me!', | 33 | 'Replace me!', |
34 | new vscode.Location(uri1, range1), | 34 | new vscode.Location(uri1, range1), |
35 | 'With this!' | 35 | 'With this!', |
36 | ); | 36 | ); |
37 | } | 37 | } |
38 | 38 | ||
@@ -44,7 +44,7 @@ describe('SuggestedFixCollection', () => { | |||
44 | // Specify the document and range that exactly matches | 44 | // Specify the document and range that exactly matches |
45 | const codeActions = suggestedFixes.provideCodeActions( | 45 | const codeActions = suggestedFixes.provideCodeActions( |
46 | mockDocument1, | 46 | mockDocument1, |
47 | range1 | 47 | range1, |
48 | ); | 48 | ); |
49 | 49 | ||
50 | assert.strictEqual(codeActions.length, 1); | 50 | assert.strictEqual(codeActions.length, 1); |
@@ -53,7 +53,8 @@ describe('SuggestedFixCollection', () => { | |||
53 | 53 | ||
54 | const { diagnostics } = codeAction; | 54 | const { diagnostics } = codeAction; |
55 | if (!diagnostics) { | 55 | if (!diagnostics) { |
56 | return assert.fail('Diagnostics unexpectedly missing'); | 56 | assert.fail('Diagnostics unexpectedly missing'); |
57 | return; | ||
57 | } | 58 | } |
58 | 59 | ||
59 | assert.strictEqual(diagnostics.length, 1); | 60 | assert.strictEqual(diagnostics.length, 1); |
@@ -66,7 +67,7 @@ describe('SuggestedFixCollection', () => { | |||
66 | 67 | ||
67 | const codeActions = suggestedFixes.provideCodeActions( | 68 | const codeActions = suggestedFixes.provideCodeActions( |
68 | mockDocument1, | 69 | mockDocument1, |
69 | range2 | 70 | range2, |
70 | ); | 71 | ); |
71 | 72 | ||
72 | assert(!codeActions || codeActions.length === 0); | 73 | assert(!codeActions || codeActions.length === 0); |
@@ -78,7 +79,7 @@ describe('SuggestedFixCollection', () => { | |||
78 | 79 | ||
79 | const codeActions = suggestedFixes.provideCodeActions( | 80 | const codeActions = suggestedFixes.provideCodeActions( |
80 | mockDocument2, | 81 | mockDocument2, |
81 | range1 | 82 | range1, |
82 | ); | 83 | ); |
83 | 84 | ||
84 | assert(!codeActions || codeActions.length === 0); | 85 | assert(!codeActions || codeActions.length === 0); |
@@ -91,7 +92,7 @@ describe('SuggestedFixCollection', () => { | |||
91 | 92 | ||
92 | const codeActions = suggestedFixes.provideCodeActions( | 93 | const codeActions = suggestedFixes.provideCodeActions( |
93 | mockDocument1, | 94 | mockDocument1, |
94 | range1 | 95 | range1, |
95 | ); | 96 | ); |
96 | 97 | ||
97 | assert(!codeActions || codeActions.length === 0); | 98 | assert(!codeActions || codeActions.length === 0); |
@@ -106,7 +107,7 @@ describe('SuggestedFixCollection', () => { | |||
106 | 107 | ||
107 | const codeActions = suggestedFixes.provideCodeActions( | 108 | const codeActions = suggestedFixes.provideCodeActions( |
108 | mockDocument1, | 109 | mockDocument1, |
109 | range1 | 110 | range1, |
110 | ); | 111 | ); |
111 | 112 | ||
112 | assert.strictEqual(codeActions.length, 1); | 113 | assert.strictEqual(codeActions.length, 1); |
@@ -114,7 +115,8 @@ describe('SuggestedFixCollection', () => { | |||
114 | const { diagnostics } = codeAction; | 115 | const { diagnostics } = codeAction; |
115 | 116 | ||
116 | if (!diagnostics) { | 117 | if (!diagnostics) { |
117 | return assert.fail('Diagnostics unexpectedly missing'); | 118 | assert.fail('Diagnostics unexpectedly missing'); |
119 | return; | ||
118 | } | 120 | } |
119 | 121 | ||
120 | // We should be associated with both diagnostics | 122 | // We should be associated with both diagnostics |
diff --git a/editors/code/src/test/utils/diagnotics/rust.test.ts b/editors/code/src/test/utils/diagnotics/rust.test.ts index 327d15046..358325cc8 100644 --- a/editors/code/src/test/utils/diagnotics/rust.test.ts +++ b/editors/code/src/test/utils/diagnotics/rust.test.ts | |||
@@ -6,14 +6,14 @@ import { | |||
6 | MappedRustDiagnostic, | 6 | MappedRustDiagnostic, |
7 | mapRustDiagnosticToVsCode, | 7 | mapRustDiagnosticToVsCode, |
8 | RustDiagnostic, | 8 | RustDiagnostic, |
9 | SuggestionApplicability | 9 | SuggestionApplicability, |
10 | } from '../../../utils/diagnostics/rust'; | 10 | } from '../../../utils/diagnostics/rust'; |
11 | 11 | ||
12 | function loadDiagnosticFixture(name: string): RustDiagnostic { | 12 | function loadDiagnosticFixture(name: string): RustDiagnostic { |
13 | const jsonText = fs | 13 | const jsonText = fs |
14 | .readFileSync( | 14 | .readFileSync( |
15 | // We're actually in our JavaScript output directory, climb out | 15 | // We're actually in our JavaScript output directory, climb out |
16 | `${__dirname}/../../../../src/test/fixtures/rust-diagnostics/${name}.json` | 16 | `${__dirname}/../../../../src/test/fixtures/rust-diagnostics/${name}.json`, |
17 | ) | 17 | ) |
18 | .toString(); | 18 | .toString(); |
19 | 19 | ||
@@ -33,12 +33,12 @@ function mapFixtureToVsCode(name: string): MappedRustDiagnostic { | |||
33 | describe('mapRustDiagnosticToVsCode', () => { | 33 | describe('mapRustDiagnosticToVsCode', () => { |
34 | it('should map an incompatible type for trait error', () => { | 34 | it('should map an incompatible type for trait error', () => { |
35 | const { diagnostic, suggestedFixes } = mapFixtureToVsCode( | 35 | const { diagnostic, suggestedFixes } = mapFixtureToVsCode( |
36 | 'error/E0053' | 36 | 'error/E0053', |
37 | ); | 37 | ); |
38 | 38 | ||
39 | assert.strictEqual( | 39 | assert.strictEqual( |
40 | diagnostic.severity, | 40 | diagnostic.severity, |
41 | vscode.DiagnosticSeverity.Error | 41 | vscode.DiagnosticSeverity.Error, |
42 | ); | 42 | ); |
43 | assert.strictEqual(diagnostic.source, 'rustc'); | 43 | assert.strictEqual(diagnostic.source, 'rustc'); |
44 | assert.strictEqual( | 44 | assert.strictEqual( |
@@ -46,8 +46,8 @@ describe('mapRustDiagnosticToVsCode', () => { | |||
46 | [ | 46 | [ |
47 | `method \`next\` has an incompatible type for trait`, | 47 | `method \`next\` has an incompatible type for trait`, |
48 | `expected type \`fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>\``, | 48 | `expected type \`fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>\``, |
49 | ` found type \`fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>\`` | 49 | ` found type \`fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>\``, |
50 | ].join('\n') | 50 | ].join('\n'), |
51 | ); | 51 | ); |
52 | assert.strictEqual(diagnostic.code, 'E0053'); | 52 | assert.strictEqual(diagnostic.code, 'E0053'); |
53 | assert.deepStrictEqual(diagnostic.tags, []); | 53 | assert.deepStrictEqual(diagnostic.tags, []); |
@@ -61,24 +61,24 @@ describe('mapRustDiagnosticToVsCode', () => { | |||
61 | 61 | ||
62 | it('should map an unused variable warning', () => { | 62 | it('should map an unused variable warning', () => { |
63 | const { diagnostic, suggestedFixes } = mapFixtureToVsCode( | 63 | const { diagnostic, suggestedFixes } = mapFixtureToVsCode( |
64 | 'warning/unused_variables' | 64 | 'warning/unused_variables', |
65 | ); | 65 | ); |
66 | 66 | ||
67 | assert.strictEqual( | 67 | assert.strictEqual( |
68 | diagnostic.severity, | 68 | diagnostic.severity, |
69 | vscode.DiagnosticSeverity.Warning | 69 | vscode.DiagnosticSeverity.Warning, |
70 | ); | 70 | ); |
71 | assert.strictEqual( | 71 | assert.strictEqual( |
72 | diagnostic.message, | 72 | diagnostic.message, |
73 | [ | 73 | [ |
74 | 'unused variable: `foo`', | 74 | 'unused variable: `foo`', |
75 | '#[warn(unused_variables)] on by default' | 75 | '#[warn(unused_variables)] on by default', |
76 | ].join('\n') | 76 | ].join('\n'), |
77 | ); | 77 | ); |
78 | assert.strictEqual(diagnostic.code, 'unused_variables'); | 78 | assert.strictEqual(diagnostic.code, 'unused_variables'); |
79 | assert.strictEqual(diagnostic.source, 'rustc'); | 79 | assert.strictEqual(diagnostic.source, 'rustc'); |
80 | assert.deepStrictEqual(diagnostic.tags, [ | 80 | assert.deepStrictEqual(diagnostic.tags, [ |
81 | vscode.DiagnosticTag.Unnecessary | 81 | vscode.DiagnosticTag.Unnecessary, |
82 | ]); | 82 | ]); |
83 | 83 | ||
84 | // No related information | 84 | // No related information |
@@ -89,29 +89,29 @@ describe('mapRustDiagnosticToVsCode', () => { | |||
89 | const [suggestedFix] = suggestedFixes; | 89 | const [suggestedFix] = suggestedFixes; |
90 | assert.strictEqual( | 90 | assert.strictEqual( |
91 | suggestedFix.title, | 91 | suggestedFix.title, |
92 | 'consider prefixing with an underscore: `_foo`' | 92 | 'consider prefixing with an underscore: `_foo`', |
93 | ); | 93 | ); |
94 | assert.strictEqual( | 94 | assert.strictEqual( |
95 | suggestedFix.applicability, | 95 | suggestedFix.applicability, |
96 | SuggestionApplicability.MachineApplicable | 96 | SuggestionApplicability.MachineApplicable, |
97 | ); | 97 | ); |
98 | }); | 98 | }); |
99 | 99 | ||
100 | it('should map a wrong number of parameters error', () => { | 100 | it('should map a wrong number of parameters error', () => { |
101 | const { diagnostic, suggestedFixes } = mapFixtureToVsCode( | 101 | const { diagnostic, suggestedFixes } = mapFixtureToVsCode( |
102 | 'error/E0061' | 102 | 'error/E0061', |
103 | ); | 103 | ); |
104 | 104 | ||
105 | assert.strictEqual( | 105 | assert.strictEqual( |
106 | diagnostic.severity, | 106 | diagnostic.severity, |
107 | vscode.DiagnosticSeverity.Error | 107 | vscode.DiagnosticSeverity.Error, |
108 | ); | 108 | ); |
109 | assert.strictEqual( | 109 | assert.strictEqual( |
110 | diagnostic.message, | 110 | diagnostic.message, |
111 | [ | 111 | [ |
112 | 'this function takes 2 parameters but 3 parameters were supplied', | 112 | 'this function takes 2 parameters but 3 parameters were supplied', |
113 | 'expected 2 parameters' | 113 | 'expected 2 parameters', |
114 | ].join('\n') | 114 | ].join('\n'), |
115 | ); | 115 | ); |
116 | assert.strictEqual(diagnostic.code, 'E0061'); | 116 | assert.strictEqual(diagnostic.code, 'E0061'); |
117 | assert.strictEqual(diagnostic.source, 'rustc'); | 117 | assert.strictEqual(diagnostic.source, 'rustc'); |
@@ -120,7 +120,8 @@ describe('mapRustDiagnosticToVsCode', () => { | |||
120 | // One related information for the original definition | 120 | // One related information for the original definition |
121 | const relatedInformation = diagnostic.relatedInformation; | 121 | const relatedInformation = diagnostic.relatedInformation; |
122 | if (!relatedInformation) { | 122 | if (!relatedInformation) { |
123 | return assert.fail('Related information unexpectedly undefined'); | 123 | assert.fail('Related information unexpectedly undefined'); |
124 | return; | ||
124 | } | 125 | } |
125 | assert.strictEqual(relatedInformation.length, 1); | 126 | assert.strictEqual(relatedInformation.length, 1); |
126 | const [related] = relatedInformation; | 127 | const [related] = relatedInformation; |
@@ -132,12 +133,12 @@ describe('mapRustDiagnosticToVsCode', () => { | |||
132 | 133 | ||
133 | it('should map a Clippy copy pass by ref warning', () => { | 134 | it('should map a Clippy copy pass by ref warning', () => { |
134 | const { diagnostic, suggestedFixes } = mapFixtureToVsCode( | 135 | const { diagnostic, suggestedFixes } = mapFixtureToVsCode( |
135 | 'clippy/trivially_copy_pass_by_ref' | 136 | 'clippy/trivially_copy_pass_by_ref', |
136 | ); | 137 | ); |
137 | 138 | ||
138 | assert.strictEqual( | 139 | assert.strictEqual( |
139 | diagnostic.severity, | 140 | diagnostic.severity, |
140 | vscode.DiagnosticSeverity.Warning | 141 | vscode.DiagnosticSeverity.Warning, |
141 | ); | 142 | ); |
142 | assert.strictEqual(diagnostic.source, 'clippy'); | 143 | assert.strictEqual(diagnostic.source, 'clippy'); |
143 | assert.strictEqual( | 144 | assert.strictEqual( |
@@ -145,8 +146,8 @@ describe('mapRustDiagnosticToVsCode', () => { | |||
145 | [ | 146 | [ |
146 | 'this argument is passed by reference, but would be more efficient if passed by value', | 147 | 'this argument is passed by reference, but would be more efficient if passed by value', |
147 | '#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]', | 148 | '#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]', |
148 | 'for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref' | 149 | 'for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref', |
149 | ].join('\n') | 150 | ].join('\n'), |
150 | ); | 151 | ); |
151 | assert.strictEqual(diagnostic.code, 'trivially_copy_pass_by_ref'); | 152 | assert.strictEqual(diagnostic.code, 'trivially_copy_pass_by_ref'); |
152 | assert.deepStrictEqual(diagnostic.tags, []); | 153 | assert.deepStrictEqual(diagnostic.tags, []); |
@@ -154,7 +155,8 @@ describe('mapRustDiagnosticToVsCode', () => { | |||
154 | // One related information for the lint definition | 155 | // One related information for the lint definition |
155 | const relatedInformation = diagnostic.relatedInformation; | 156 | const relatedInformation = diagnostic.relatedInformation; |
156 | if (!relatedInformation) { | 157 | if (!relatedInformation) { |
157 | return assert.fail('Related information unexpectedly undefined'); | 158 | assert.fail('Related information unexpectedly undefined'); |
159 | return; | ||
158 | } | 160 | } |
159 | assert.strictEqual(relatedInformation.length, 1); | 161 | assert.strictEqual(relatedInformation.length, 1); |
160 | const [related] = relatedInformation; | 162 | const [related] = relatedInformation; |
@@ -165,27 +167,27 @@ describe('mapRustDiagnosticToVsCode', () => { | |||
165 | const [suggestedFix] = suggestedFixes; | 167 | const [suggestedFix] = suggestedFixes; |
166 | assert.strictEqual( | 168 | assert.strictEqual( |
167 | suggestedFix.title, | 169 | suggestedFix.title, |
168 | 'consider passing by value instead: `self`' | 170 | 'consider passing by value instead: `self`', |
169 | ); | 171 | ); |
170 | // Clippy does not mark this with any applicability | 172 | // Clippy does not mark this with any applicability |
171 | assert.strictEqual( | 173 | assert.strictEqual( |
172 | suggestedFix.applicability, | 174 | suggestedFix.applicability, |
173 | SuggestionApplicability.Unspecified | 175 | SuggestionApplicability.Unspecified, |
174 | ); | 176 | ); |
175 | }); | 177 | }); |
176 | 178 | ||
177 | it('should map a mismatched type error', () => { | 179 | it('should map a mismatched type error', () => { |
178 | const { diagnostic, suggestedFixes } = mapFixtureToVsCode( | 180 | const { diagnostic, suggestedFixes } = mapFixtureToVsCode( |
179 | 'error/E0308' | 181 | 'error/E0308', |
180 | ); | 182 | ); |
181 | 183 | ||
182 | assert.strictEqual( | 184 | assert.strictEqual( |
183 | diagnostic.severity, | 185 | diagnostic.severity, |
184 | vscode.DiagnosticSeverity.Error | 186 | vscode.DiagnosticSeverity.Error, |
185 | ); | 187 | ); |
186 | assert.strictEqual( | 188 | assert.strictEqual( |
187 | diagnostic.message, | 189 | diagnostic.message, |
188 | ['mismatched types', 'expected usize, found u32'].join('\n') | 190 | ['mismatched types', 'expected usize, found u32'].join('\n'), |
189 | ); | 191 | ); |
190 | assert.strictEqual(diagnostic.code, 'E0308'); | 192 | assert.strictEqual(diagnostic.code, 'E0308'); |
191 | assert.strictEqual(diagnostic.source, 'rustc'); | 193 | assert.strictEqual(diagnostic.source, 'rustc'); |
@@ -197,4 +199,38 @@ describe('mapRustDiagnosticToVsCode', () => { | |||
197 | // There are no suggested fixes | 199 | // There are no suggested fixes |
198 | assert.strictEqual(suggestedFixes.length, 0); | 200 | assert.strictEqual(suggestedFixes.length, 0); |
199 | }); | 201 | }); |
202 | |||
203 | it('should map a macro invocation location to normal file path', () => { | ||
204 | const { location, diagnostic, suggestedFixes } = mapFixtureToVsCode( | ||
205 | 'error/E0277', | ||
206 | ); | ||
207 | |||
208 | assert.strictEqual( | ||
209 | diagnostic.severity, | ||
210 | vscode.DiagnosticSeverity.Error, | ||
211 | ); | ||
212 | assert.strictEqual( | ||
213 | diagnostic.message, | ||
214 | [ | ||
215 | "can't compare `{integer}` with `&str`", | ||
216 | 'the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`', | ||
217 | ].join('\n'), | ||
218 | ); | ||
219 | assert.strictEqual(diagnostic.code, 'E0277'); | ||
220 | assert.strictEqual(diagnostic.source, 'rustc'); | ||
221 | assert.deepStrictEqual(diagnostic.tags, []); | ||
222 | |||
223 | // No related information | ||
224 | assert.deepStrictEqual(diagnostic.relatedInformation, []); | ||
225 | |||
226 | // There are no suggested fixes | ||
227 | assert.strictEqual(suggestedFixes.length, 0); | ||
228 | |||
229 | // The file url should be normal file | ||
230 | // Ignore the first part because it depends on vs workspace location | ||
231 | assert.strictEqual( | ||
232 | location.uri.path.substr(-'src/main.rs'.length), | ||
233 | 'src/main.rs', | ||
234 | ); | ||
235 | }); | ||
200 | }); | 236 | }); |
diff --git a/editors/code/src/test/utils/diagnotics/vscode.test.ts b/editors/code/src/test/utils/diagnotics/vscode.test.ts index 542dec1f5..4944dd032 100644 --- a/editors/code/src/test/utils/diagnotics/vscode.test.ts +++ b/editors/code/src/test/utils/diagnotics/vscode.test.ts | |||
@@ -5,12 +5,12 @@ import { areDiagnosticsEqual } from '../../../utils/diagnostics/vscode'; | |||
5 | 5 | ||
6 | const range1 = new vscode.Range( | 6 | const range1 = new vscode.Range( |
7 | new vscode.Position(1, 2), | 7 | new vscode.Position(1, 2), |
8 | new vscode.Position(3, 4) | 8 | new vscode.Position(3, 4), |
9 | ); | 9 | ); |
10 | 10 | ||
11 | const range2 = new vscode.Range( | 11 | const range2 = new vscode.Range( |
12 | new vscode.Position(5, 6), | 12 | new vscode.Position(5, 6), |
13 | new vscode.Position(7, 8) | 13 | new vscode.Position(7, 8), |
14 | ); | 14 | ); |
15 | 15 | ||
16 | describe('areDiagnosticsEqual', () => { | 16 | describe('areDiagnosticsEqual', () => { |
@@ -18,13 +18,13 @@ describe('areDiagnosticsEqual', () => { | |||
18 | const diagnostic1 = new vscode.Diagnostic( | 18 | const diagnostic1 = new vscode.Diagnostic( |
19 | range1, | 19 | range1, |
20 | 'Hello, world!', | 20 | 'Hello, world!', |
21 | vscode.DiagnosticSeverity.Error | 21 | vscode.DiagnosticSeverity.Error, |
22 | ); | 22 | ); |
23 | 23 | ||
24 | const diagnostic2 = new vscode.Diagnostic( | 24 | const diagnostic2 = new vscode.Diagnostic( |
25 | range1, | 25 | range1, |
26 | 'Hello, world!', | 26 | 'Hello, world!', |
27 | vscode.DiagnosticSeverity.Error | 27 | vscode.DiagnosticSeverity.Error, |
28 | ); | 28 | ); |
29 | 29 | ||
30 | assert(areDiagnosticsEqual(diagnostic1, diagnostic2)); | 30 | assert(areDiagnosticsEqual(diagnostic1, diagnostic2)); |
@@ -34,14 +34,14 @@ describe('areDiagnosticsEqual', () => { | |||
34 | const diagnostic1 = new vscode.Diagnostic( | 34 | const diagnostic1 = new vscode.Diagnostic( |
35 | range1, | 35 | range1, |
36 | 'Hello, world!', | 36 | 'Hello, world!', |
37 | vscode.DiagnosticSeverity.Error | 37 | vscode.DiagnosticSeverity.Error, |
38 | ); | 38 | ); |
39 | diagnostic1.source = 'rustc'; | 39 | diagnostic1.source = 'rustc'; |
40 | 40 | ||
41 | const diagnostic2 = new vscode.Diagnostic( | 41 | const diagnostic2 = new vscode.Diagnostic( |
42 | range1, | 42 | range1, |
43 | 'Hello, world!', | 43 | 'Hello, world!', |
44 | vscode.DiagnosticSeverity.Error | 44 | vscode.DiagnosticSeverity.Error, |
45 | ); | 45 | ); |
46 | diagnostic2.source = 'clippy'; | 46 | diagnostic2.source = 'clippy'; |
47 | 47 | ||
@@ -52,13 +52,13 @@ describe('areDiagnosticsEqual', () => { | |||
52 | const diagnostic1 = new vscode.Diagnostic( | 52 | const diagnostic1 = new vscode.Diagnostic( |
53 | range1, | 53 | range1, |
54 | 'Hello, world!', | 54 | 'Hello, world!', |
55 | vscode.DiagnosticSeverity.Error | 55 | vscode.DiagnosticSeverity.Error, |
56 | ); | 56 | ); |
57 | 57 | ||
58 | const diagnostic2 = new vscode.Diagnostic( | 58 | const diagnostic2 = new vscode.Diagnostic( |
59 | range2, | 59 | range2, |
60 | 'Hello, world!', | 60 | 'Hello, world!', |
61 | vscode.DiagnosticSeverity.Error | 61 | vscode.DiagnosticSeverity.Error, |
62 | ); | 62 | ); |
63 | 63 | ||
64 | assert(!areDiagnosticsEqual(diagnostic1, diagnostic2)); | 64 | assert(!areDiagnosticsEqual(diagnostic1, diagnostic2)); |
@@ -68,13 +68,13 @@ describe('areDiagnosticsEqual', () => { | |||
68 | const diagnostic1 = new vscode.Diagnostic( | 68 | const diagnostic1 = new vscode.Diagnostic( |
69 | range1, | 69 | range1, |
70 | 'Hello, world!', | 70 | 'Hello, world!', |
71 | vscode.DiagnosticSeverity.Error | 71 | vscode.DiagnosticSeverity.Error, |
72 | ); | 72 | ); |
73 | 73 | ||
74 | const diagnostic2 = new vscode.Diagnostic( | 74 | const diagnostic2 = new vscode.Diagnostic( |
75 | range1, | 75 | range1, |
76 | 'Goodbye!, world!', | 76 | 'Goodbye!, world!', |
77 | vscode.DiagnosticSeverity.Error | 77 | vscode.DiagnosticSeverity.Error, |
78 | ); | 78 | ); |
79 | 79 | ||
80 | assert(!areDiagnosticsEqual(diagnostic1, diagnostic2)); | 80 | assert(!areDiagnosticsEqual(diagnostic1, diagnostic2)); |
@@ -84,13 +84,13 @@ describe('areDiagnosticsEqual', () => { | |||
84 | const diagnostic1 = new vscode.Diagnostic( | 84 | const diagnostic1 = new vscode.Diagnostic( |
85 | range1, | 85 | range1, |
86 | 'Hello, world!', | 86 | 'Hello, world!', |
87 | vscode.DiagnosticSeverity.Warning | 87 | vscode.DiagnosticSeverity.Warning, |
88 | ); | 88 | ); |
89 | 89 | ||
90 | const diagnostic2 = new vscode.Diagnostic( | 90 | const diagnostic2 = new vscode.Diagnostic( |
91 | range1, | 91 | range1, |
92 | 'Hello, world!', | 92 | 'Hello, world!', |
93 | vscode.DiagnosticSeverity.Error | 93 | vscode.DiagnosticSeverity.Error, |
94 | ); | 94 | ); |
95 | 95 | ||
96 | assert(!areDiagnosticsEqual(diagnostic1, diagnostic2)); | 96 | assert(!areDiagnosticsEqual(diagnostic1, diagnostic2)); |
diff --git a/editors/code/src/test/utils/index.ts b/editors/code/src/test/utils/index.ts index 16715a286..9927daaf6 100644 --- a/editors/code/src/test/utils/index.ts +++ b/editors/code/src/test/utils/index.ts | |||
@@ -17,7 +17,7 @@ import * as path from 'path'; | |||
17 | export function run(): Promise<void> { | 17 | export function run(): Promise<void> { |
18 | // Create the mocha test | 18 | // Create the mocha test |
19 | const mocha = new Mocha({ | 19 | const mocha = new Mocha({ |
20 | ui: 'bdd' | 20 | ui: 'bdd', |
21 | }); | 21 | }); |
22 | mocha.useColors(true); | 22 | mocha.useColors(true); |
23 | 23 | ||
diff --git a/editors/code/src/utils/diagnostics/SuggestedFix.ts b/editors/code/src/utils/diagnostics/SuggestedFix.ts index b1be2a225..6e660bb61 100644 --- a/editors/code/src/utils/diagnostics/SuggestedFix.ts +++ b/editors/code/src/utils/diagnostics/SuggestedFix.ts | |||
@@ -24,7 +24,7 @@ export default class SuggestedFix { | |||
24 | title: string, | 24 | title: string, |
25 | location: vscode.Location, | 25 | location: vscode.Location, |
26 | replacement: string, | 26 | replacement: string, |
27 | applicability: SuggestionApplicability = SuggestionApplicability.Unspecified | 27 | applicability: SuggestionApplicability = SuggestionApplicability.Unspecified, |
28 | ) { | 28 | ) { |
29 | this.title = title; | 29 | this.title = title; |
30 | this.location = location; | 30 | this.location = location; |
@@ -51,7 +51,7 @@ export default class SuggestedFix { | |||
51 | public toCodeAction(): vscode.CodeAction { | 51 | public toCodeAction(): vscode.CodeAction { |
52 | const codeAction = new vscode.CodeAction( | 52 | const codeAction = new vscode.CodeAction( |
53 | this.title, | 53 | this.title, |
54 | vscode.CodeActionKind.QuickFix | 54 | vscode.CodeActionKind.QuickFix, |
55 | ); | 55 | ); |
56 | 56 | ||
57 | const edit = new vscode.WorkspaceEdit(); | 57 | const edit = new vscode.WorkspaceEdit(); |
diff --git a/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts b/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts index 132ce12f8..57c9856cf 100644 --- a/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts +++ b/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts | |||
@@ -38,13 +38,13 @@ export default class SuggestedFixCollection | |||
38 | */ | 38 | */ |
39 | public addSuggestedFixForDiagnostic( | 39 | public addSuggestedFixForDiagnostic( |
40 | suggestedFix: SuggestedFix, | 40 | suggestedFix: SuggestedFix, |
41 | diagnostic: vscode.Diagnostic | 41 | diagnostic: vscode.Diagnostic, |
42 | ): void { | 42 | ): void { |
43 | const fileUriString = suggestedFix.location.uri.toString(); | 43 | const fileUriString = suggestedFix.location.uri.toString(); |
44 | const fileSuggestions = this.suggestedFixes.get(fileUriString) || []; | 44 | const fileSuggestions = this.suggestedFixes.get(fileUriString) || []; |
45 | 45 | ||
46 | const existingSuggestion = fileSuggestions.find(s => | 46 | const existingSuggestion = fileSuggestions.find(s => |
47 | s.isEqual(suggestedFix) | 47 | s.isEqual(suggestedFix), |
48 | ); | 48 | ); |
49 | 49 | ||
50 | if (existingSuggestion) { | 50 | if (existingSuggestion) { |
@@ -65,7 +65,7 @@ export default class SuggestedFixCollection | |||
65 | */ | 65 | */ |
66 | public provideCodeActions( | 66 | public provideCodeActions( |
67 | document: vscode.TextDocument, | 67 | document: vscode.TextDocument, |
68 | range: vscode.Range | 68 | range: vscode.Range, |
69 | ): vscode.CodeAction[] { | 69 | ): vscode.CodeAction[] { |
70 | const documentUriString = document.uri.toString(); | 70 | const documentUriString = document.uri.toString(); |
71 | 71 | ||
diff --git a/editors/code/src/utils/diagnostics/rust.ts b/editors/code/src/utils/diagnostics/rust.ts index 0550d0372..1f0c0d3e4 100644 --- a/editors/code/src/utils/diagnostics/rust.ts +++ b/editors/code/src/utils/diagnostics/rust.ts | |||
@@ -7,7 +7,13 @@ export enum SuggestionApplicability { | |||
7 | MachineApplicable = 'MachineApplicable', | 7 | MachineApplicable = 'MachineApplicable', |
8 | HasPlaceholders = 'HasPlaceholders', | 8 | HasPlaceholders = 'HasPlaceholders', |
9 | MaybeIncorrect = 'MaybeIncorrect', | 9 | MaybeIncorrect = 'MaybeIncorrect', |
10 | Unspecified = 'Unspecified' | 10 | Unspecified = 'Unspecified', |
11 | } | ||
12 | |||
13 | export interface RustDiagnosticSpanMacroExpansion { | ||
14 | span: RustDiagnosticSpan; | ||
15 | macro_decl_name: string; | ||
16 | def_site_span?: RustDiagnosticSpan; | ||
11 | } | 17 | } |
12 | 18 | ||
13 | // Reference: | 19 | // Reference: |
@@ -20,6 +26,7 @@ export interface RustDiagnosticSpan { | |||
20 | is_primary: boolean; | 26 | is_primary: boolean; |
21 | file_name: string; | 27 | file_name: string; |
22 | label?: string; | 28 | label?: string; |
29 | expansion?: RustDiagnosticSpanMacroExpansion; | ||
23 | suggested_replacement?: string; | 30 | suggested_replacement?: string; |
24 | suggestion_applicability?: SuggestionApplicability; | 31 | suggestion_applicability?: SuggestionApplicability; |
25 | } | 32 | } |
@@ -61,15 +68,46 @@ function mapLevelToSeverity(s: string): vscode.DiagnosticSeverity { | |||
61 | } | 68 | } |
62 | 69 | ||
63 | /** | 70 | /** |
71 | * Check whether a file name is from macro invocation | ||
72 | */ | ||
73 | function isFromMacro(fileName: string): boolean { | ||
74 | return fileName.startsWith('<') && fileName.endsWith('>'); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * Converts a Rust macro span to a VsCode location recursively | ||
79 | */ | ||
80 | function mapMacroSpanToLocation( | ||
81 | spanMacro: RustDiagnosticSpanMacroExpansion, | ||
82 | ): vscode.Location | undefined { | ||
83 | if (!isFromMacro(spanMacro.span.file_name)) { | ||
84 | return mapSpanToLocation(spanMacro.span); | ||
85 | } | ||
86 | |||
87 | if (spanMacro.span.expansion) { | ||
88 | return mapMacroSpanToLocation(spanMacro.span.expansion); | ||
89 | } | ||
90 | |||
91 | return; | ||
92 | } | ||
93 | |||
94 | /** | ||
64 | * Converts a Rust span to a VsCode location | 95 | * Converts a Rust span to a VsCode location |
65 | */ | 96 | */ |
66 | function mapSpanToLocation(span: RustDiagnosticSpan): vscode.Location { | 97 | function mapSpanToLocation(span: RustDiagnosticSpan): vscode.Location { |
98 | if (isFromMacro(span.file_name) && span.expansion) { | ||
99 | const macroLoc = mapMacroSpanToLocation(span.expansion); | ||
100 | if (macroLoc) { | ||
101 | return macroLoc; | ||
102 | } | ||
103 | } | ||
104 | |||
67 | const fileName = path.join(vscode.workspace.rootPath || '', span.file_name); | 105 | const fileName = path.join(vscode.workspace.rootPath || '', span.file_name); |
68 | const fileUri = vscode.Uri.file(fileName); | 106 | const fileUri = vscode.Uri.file(fileName); |
69 | 107 | ||
70 | const range = new vscode.Range( | 108 | const range = new vscode.Range( |
71 | new vscode.Position(span.line_start - 1, span.column_start - 1), | 109 | new vscode.Position(span.line_start - 1, span.column_start - 1), |
72 | new vscode.Position(span.line_end - 1, span.column_end - 1) | 110 | new vscode.Position(span.line_end - 1, span.column_end - 1), |
73 | ); | 111 | ); |
74 | 112 | ||
75 | return new vscode.Location(fileUri, range); | 113 | return new vscode.Location(fileUri, range); |
@@ -81,7 +119,7 @@ function mapSpanToLocation(span: RustDiagnosticSpan): vscode.Location { | |||
81 | * If the span is unlabelled this will return `undefined`. | 119 | * If the span is unlabelled this will return `undefined`. |
82 | */ | 120 | */ |
83 | function mapSecondarySpanToRelated( | 121 | function mapSecondarySpanToRelated( |
84 | span: RustDiagnosticSpan | 122 | span: RustDiagnosticSpan, |
85 | ): vscode.DiagnosticRelatedInformation | undefined { | 123 | ): vscode.DiagnosticRelatedInformation | undefined { |
86 | if (!span.label) { | 124 | if (!span.label) { |
87 | // Nothing to label this with | 125 | // Nothing to label this with |
@@ -107,7 +145,7 @@ function isUnusedOrUnnecessary(rd: RustDiagnostic): boolean { | |||
107 | 'unused_attributes', | 145 | 'unused_attributes', |
108 | 'unused_imports', | 146 | 'unused_imports', |
109 | 'unused_macros', | 147 | 'unused_macros', |
110 | 'unused_variables' | 148 | 'unused_variables', |
111 | ].includes(rd.code.code); | 149 | ].includes(rd.code.code); |
112 | } | 150 | } |
113 | 151 | ||
@@ -157,13 +195,13 @@ function mapRustChildDiagnostic(rd: RustDiagnostic): MappedRustChildDiagnostic { | |||
157 | title, | 195 | title, |
158 | location, | 196 | location, |
159 | span.suggested_replacement, | 197 | span.suggested_replacement, |
160 | span.suggestion_applicability | 198 | span.suggestion_applicability, |
161 | ) | 199 | ), |
162 | }; | 200 | }; |
163 | } else { | 201 | } else { |
164 | const related = new vscode.DiagnosticRelatedInformation( | 202 | const related = new vscode.DiagnosticRelatedInformation( |
165 | location, | 203 | location, |
166 | rd.message | 204 | rd.message, |
167 | ); | 205 | ); |
168 | 206 | ||
169 | return { related }; | 207 | return { related }; |
@@ -183,7 +221,7 @@ function mapRustChildDiagnostic(rd: RustDiagnostic): MappedRustChildDiagnostic { | |||
183 | * If the diagnostic has no primary span this will return `undefined` | 221 | * If the diagnostic has no primary span this will return `undefined` |
184 | */ | 222 | */ |
185 | export function mapRustDiagnosticToVsCode( | 223 | export function mapRustDiagnosticToVsCode( |
186 | rd: RustDiagnostic | 224 | rd: RustDiagnostic, |
187 | ): MappedRustDiagnostic | undefined { | 225 | ): MappedRustDiagnostic | undefined { |
188 | const primarySpan = rd.spans.find(s => s.is_primary); | 226 | const primarySpan = rd.spans.find(s => s.is_primary); |
189 | if (!primarySpan) { | 227 | if (!primarySpan) { |
@@ -223,7 +261,7 @@ export function mapRustDiagnosticToVsCode( | |||
223 | const suggestedFixes = []; | 261 | const suggestedFixes = []; |
224 | for (const child of rd.children) { | 262 | for (const child of rd.children) { |
225 | const { related, suggestedFix, messageLine } = mapRustChildDiagnostic( | 263 | const { related, suggestedFix, messageLine } = mapRustChildDiagnostic( |
226 | child | 264 | child, |
227 | ); | 265 | ); |
228 | 266 | ||
229 | if (related) { | 267 | if (related) { |
@@ -256,6 +294,6 @@ export function mapRustDiagnosticToVsCode( | |||
256 | return { | 294 | return { |
257 | location, | 295 | location, |
258 | diagnostic: vd, | 296 | diagnostic: vd, |
259 | suggestedFixes | 297 | suggestedFixes, |
260 | }; | 298 | }; |
261 | } | 299 | } |
diff --git a/editors/code/src/utils/diagnostics/vscode.ts b/editors/code/src/utils/diagnostics/vscode.ts index d8b85b720..f4a5450e2 100644 --- a/editors/code/src/utils/diagnostics/vscode.ts +++ b/editors/code/src/utils/diagnostics/vscode.ts | |||
@@ -3,7 +3,7 @@ import * as vscode from 'vscode'; | |||
3 | /** Compares two `vscode.Diagnostic`s for equality */ | 3 | /** Compares two `vscode.Diagnostic`s for equality */ |
4 | export function areDiagnosticsEqual( | 4 | export function areDiagnosticsEqual( |
5 | left: vscode.Diagnostic, | 5 | left: vscode.Diagnostic, |
6 | right: vscode.Diagnostic | 6 | right: vscode.Diagnostic, |
7 | ): boolean { | 7 | ): boolean { |
8 | return ( | 8 | return ( |
9 | left.source === right.source && | 9 | left.source === right.source && |
diff --git a/editors/code/src/utils/processes.ts b/editors/code/src/utils/processes.ts index da8be9eb1..a1d6b7eaf 100644 --- a/editors/code/src/utils/processes.ts +++ b/editors/code/src/utils/processes.ts | |||
@@ -22,7 +22,7 @@ export function terminate(process: ChildProcess, cwd?: string): boolean { | |||
22 | // Ignore stderr since this is otherwise piped to parent.stderr | 22 | // Ignore stderr since this is otherwise piped to parent.stderr |
23 | // which might be already closed. | 23 | // which might be already closed. |
24 | const options: any = { | 24 | const options: any = { |
25 | stdio: ['pipe', 'pipe', 'ignore'] | 25 | stdio: ['pipe', 'pipe', 'ignore'], |
26 | }; | 26 | }; |
27 | if (cwd) { | 27 | if (cwd) { |
28 | options.cwd = cwd; | 28 | options.cwd = cwd; |
@@ -30,7 +30,7 @@ export function terminate(process: ChildProcess, cwd?: string): boolean { | |||
30 | cp.execFileSync( | 30 | cp.execFileSync( |
31 | 'taskkill', | 31 | 'taskkill', |
32 | ['/T', '/F', '/PID', process.pid.toString()], | 32 | ['/T', '/F', '/PID', process.pid.toString()], |
33 | options | 33 | options, |
34 | ); | 34 | ); |
35 | return true; | 35 | return true; |
36 | } catch (err) { | 36 | } catch (err) { |