aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/source_analyzer.rs17
-rw-r--r--crates/ide/src/references.rs23
-rw-r--r--editors/code/.eslintrc.js5
-rw-r--r--editors/code/src/client.ts4
-rw-r--r--editors/code/src/commands.ts12
-rw-r--r--editors/code/src/debug.ts12
-rw-r--r--editors/code/src/inlay_hints.ts2
-rw-r--r--editors/code/src/main.ts13
-rw-r--r--editors/code/src/run.ts7
-rw-r--r--editors/code/src/snippets.ts4
10 files changed, 67 insertions, 32 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 626c3078a..bed3fa50f 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -222,8 +222,9 @@ impl SourceAnalyzer {
222 db: &dyn HirDatabase, 222 db: &dyn HirDatabase,
223 path: &ast::Path, 223 path: &ast::Path,
224 ) -> Option<PathResolution> { 224 ) -> Option<PathResolution> {
225 let parent = || path.syntax().parent();
225 let mut prefer_value_ns = false; 226 let mut prefer_value_ns = false;
226 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { 227 if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) {
227 let expr_id = self.expr_id(db, &path_expr.into())?; 228 let expr_id = self.expr_id(db, &path_expr.into())?;
228 let infer = self.infer.as_ref()?; 229 let infer = self.infer.as_ref()?;
229 if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) { 230 if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) {
@@ -237,7 +238,7 @@ impl SourceAnalyzer {
237 prefer_value_ns = true; 238 prefer_value_ns = true;
238 } 239 }
239 240
240 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { 241 if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
241 let pat_id = self.pat_id(&path_pat.into())?; 242 let pat_id = self.pat_id(&path_pat.into())?;
242 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { 243 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
243 return Some(PathResolution::AssocItem(assoc.into())); 244 return Some(PathResolution::AssocItem(assoc.into()));
@@ -249,7 +250,7 @@ impl SourceAnalyzer {
249 } 250 }
250 } 251 }
251 252
252 if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordExpr::cast) { 253 if let Some(rec_lit) = parent().and_then(ast::RecordExpr::cast) {
253 let expr_id = self.expr_id(db, &rec_lit.into())?; 254 let expr_id = self.expr_id(db, &rec_lit.into())?;
254 if let Some(VariantId::EnumVariantId(variant)) = 255 if let Some(VariantId::EnumVariantId(variant)) =
255 self.infer.as_ref()?.variant_resolution_for_expr(expr_id) 256 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
@@ -258,8 +259,12 @@ impl SourceAnalyzer {
258 } 259 }
259 } 260 }
260 261
261 if let Some(rec_pat) = path.syntax().parent().and_then(ast::RecordPat::cast) { 262 if let Some(pat) = parent()
262 let pat_id = self.pat_id(&rec_pat.into())?; 263 .and_then(ast::RecordPat::cast)
264 .map(ast::Pat::from)
265 .or_else(|| parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from))
266 {
267 let pat_id = self.pat_id(&pat)?;
263 if let Some(VariantId::EnumVariantId(variant)) = 268 if let Some(VariantId::EnumVariantId(variant)) =
264 self.infer.as_ref()?.variant_resolution_for_pat(pat_id) 269 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
265 { 270 {
@@ -272,7 +277,7 @@ impl SourceAnalyzer {
272 277
273 // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we 278 // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we
274 // trying to resolve foo::bar. 279 // trying to resolve foo::bar.
275 if let Some(outer_path) = path.syntax().parent().and_then(ast::Path::cast) { 280 if let Some(outer_path) = parent().and_then(ast::Path::cast) {
276 if let Some(qualifier) = outer_path.qualifier() { 281 if let Some(qualifier) = outer_path.qualifier() {
277 if path == &qualifier { 282 if path == &qualifier {
278 return resolve_hir_path_qualifier(db, &self.resolver, &hir_path); 283 return resolve_hir_path_qualifier(db, &self.resolver, &hir_path);
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 40d9487eb..6999dacee 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -1114,4 +1114,27 @@ trait Foo {
1114 "#]], 1114 "#]],
1115 ); 1115 );
1116 } 1116 }
1117
1118 #[test]
1119 fn test_self_variant_with_payload() {
1120 check(
1121 r#"
1122enum Foo { Bar() }
1123
1124impl Foo {
1125 fn foo(self) {
1126 match self {
1127 Self::Bar$0() => (),
1128 }
1129 }
1130}
1131
1132"#,
1133 expect![[r#"
1134 Bar Variant FileId(0) 11..16 11..14 Other
1135
1136 FileId(0) 89..92 Other
1137 "#]],
1138 );
1139 }
1117} 1140}
diff --git a/editors/code/.eslintrc.js b/editors/code/.eslintrc.js
index c6bf410f4..b145330a0 100644
--- a/editors/code/.eslintrc.js
+++ b/editors/code/.eslintrc.js
@@ -14,7 +14,7 @@ module.exports = {
14 "rules": { 14 "rules": {
15 "camelcase": ["error"], 15 "camelcase": ["error"],
16 "eqeqeq": ["error", "always", { "null": "ignore" }], 16 "eqeqeq": ["error", "always", { "null": "ignore" }],
17 "no-console": ["error"], 17 "no-console": ["error", { allow: ["warn", "error"] }],
18 "prefer-const": "error", 18 "prefer-const": "error",
19 "@typescript-eslint/member-delimiter-style": [ 19 "@typescript-eslint/member-delimiter-style": [
20 "error", 20 "error",
@@ -33,6 +33,7 @@ module.exports = {
33 "error", 33 "error",
34 "always" 34 "always"
35 ], 35 ],
36 "@typescript-eslint/no-unnecessary-type-assertion": "error" 36 "@typescript-eslint/no-unnecessary-type-assertion": "error",
37 "@typescript-eslint/no-floating-promises": "error"
37 } 38 }
38}; 39};
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index 539e487ec..aec5c70c0 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -11,7 +11,7 @@ export interface Env {
11} 11}
12 12
13function renderCommand(cmd: ra.CommandLink) { 13function renderCommand(cmd: ra.CommandLink) {
14 return `[${cmd.title}](command:${cmd.command}?${encodeURIComponent(JSON.stringify(cmd.arguments))} '${cmd.tooltip!}')`; 14 return `[${cmd.title}](command:${cmd.command}?${encodeURIComponent(JSON.stringify(cmd.arguments))} '${cmd.tooltip}')`;
15} 15}
16 16
17function renderHoverActions(actions: ra.CommandLinkGroup[]): vscode.MarkdownString { 17function renderHoverActions(actions: ra.CommandLinkGroup[]): vscode.MarkdownString {
@@ -138,7 +138,7 @@ export function createClient(serverPath: string, cwd: string, extraEnv: Env): lc
138 command: "rust-analyzer.applyActionGroup", 138 command: "rust-analyzer.applyActionGroup",
139 title: "", 139 title: "",
140 arguments: [items.map((item) => { 140 arguments: [items.map((item) => {
141 return { label: item.title, arguments: item.command!!.arguments!![0] }; 141 return { label: item.title, arguments: item.command!.arguments![0] };
142 })], 142 })],
143 }; 143 };
144 144
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index cbda619ea..3729a71de 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -125,7 +125,7 @@ export function joinLines(ctx: Ctx): Cmd {
125 ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)), 125 ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)),
126 textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), 126 textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
127 }); 127 });
128 editor.edit((builder) => { 128 await editor.edit((builder) => {
129 client.protocol2CodeConverter.asTextEdits(items).forEach((edit: any) => { 129 client.protocol2CodeConverter.asTextEdits(items).forEach((edit: any) => {
130 builder.replace(edit.range, edit.newText); 130 builder.replace(edit.range, edit.newText);
131 }); 131 });
@@ -236,7 +236,7 @@ export function ssr(ctx: Ctx): Cmd {
236 const request = await vscode.window.showInputBox(options); 236 const request = await vscode.window.showInputBox(options);
237 if (!request) return; 237 if (!request) return;
238 238
239 vscode.window.withProgress({ 239 await vscode.window.withProgress({
240 location: vscode.ProgressLocation.Notification, 240 location: vscode.ProgressLocation.Notification,
241 title: "Structured search replace in progress...", 241 title: "Structured search replace in progress...",
242 cancellable: false, 242 cancellable: false,
@@ -457,10 +457,10 @@ export function reloadWorkspace(ctx: Ctx): Cmd {
457} 457}
458 458
459export function showReferences(ctx: Ctx): Cmd { 459export function showReferences(ctx: Ctx): Cmd {
460 return (uri: string, position: lc.Position, locations: lc.Location[]) => { 460 return async (uri: string, position: lc.Position, locations: lc.Location[]) => {
461 const client = ctx.client; 461 const client = ctx.client;
462 if (client) { 462 if (client) {
463 vscode.commands.executeCommand( 463 await vscode.commands.executeCommand(
464 'editor.action.showReferences', 464 'editor.action.showReferences',
465 vscode.Uri.parse(uri), 465 vscode.Uri.parse(uri),
466 client.protocol2CodeConverter.asPosition(position), 466 client.protocol2CodeConverter.asPosition(position),
@@ -474,7 +474,7 @@ export function applyActionGroup(_ctx: Ctx): Cmd {
474 return async (actions: { label: string; arguments: lc.CodeAction }[]) => { 474 return async (actions: { label: string; arguments: lc.CodeAction }[]) => {
475 const selectedAction = await vscode.window.showQuickPick(actions); 475 const selectedAction = await vscode.window.showQuickPick(actions);
476 if (!selectedAction) return; 476 if (!selectedAction) return;
477 vscode.commands.executeCommand( 477 await vscode.commands.executeCommand(
478 'rust-analyzer.resolveCodeAction', 478 'rust-analyzer.resolveCodeAction',
479 selectedAction.arguments, 479 selectedAction.arguments,
480 ); 480 );
@@ -510,7 +510,7 @@ export function openDocs(ctx: Ctx): Cmd {
510 const doclink = await client.sendRequest(ra.openDocs, { position, textDocument }); 510 const doclink = await client.sendRequest(ra.openDocs, { position, textDocument });
511 511
512 if (doclink != null) { 512 if (doclink != null) {
513 vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(doclink)); 513 await vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(doclink));
514 } 514 }
515 }; 515 };
516 516
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
index 925126a16..3889a2773 100644
--- a/editors/code/src/debug.ts
+++ b/editors/code/src/debug.ts
@@ -77,7 +77,7 @@ async function getDebugConfiguration(ctx: Ctx, runnable: ra.Runnable): Promise<v
77 } 77 }
78 78
79 if (!debugEngine) { 79 if (!debugEngine) {
80 vscode.window.showErrorMessage(`Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)` 80 await vscode.window.showErrorMessage(`Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)`
81 + ` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`); 81 + ` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`);
82 return; 82 return;
83 } 83 }
@@ -86,12 +86,14 @@ async function getDebugConfiguration(ctx: Ctx, runnable: ra.Runnable): Promise<v
86 if (ctx.config.debug.openDebugPane) { 86 if (ctx.config.debug.openDebugPane) {
87 debugOutput.show(true); 87 debugOutput.show(true);
88 } 88 }
89 89 // folder exists or RA is not active.
90 const isMultiFolderWorkspace = vscode.workspace.workspaceFolders!.length > 1; 90 // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
91 const firstWorkspace = vscode.workspace.workspaceFolders![0]; // folder exists or RA is not active. 91 const workspaceFolders = vscode.workspace.workspaceFolders!;
92 const isMultiFolderWorkspace = workspaceFolders.length > 1;
93 const firstWorkspace = workspaceFolders[0];
92 const workspace = !isMultiFolderWorkspace || !runnable.args.workspaceRoot ? 94 const workspace = !isMultiFolderWorkspace || !runnable.args.workspaceRoot ?
93 firstWorkspace : 95 firstWorkspace :
94 vscode.workspace.workspaceFolders!.find(w => runnable.args.workspaceRoot?.includes(w.uri.fsPath)) || firstWorkspace; 96 workspaceFolders.find(w => runnable.args.workspaceRoot?.includes(w.uri.fsPath)) || firstWorkspace;
95 97
96 const wsFolder = path.normalize(workspace.uri.fsPath); 98 const wsFolder = path.normalize(workspace.uri.fsPath);
97 const workspaceQualifier = isMultiFolderWorkspace ? `:${workspace.name}` : ''; 99 const workspaceQualifier = isMultiFolderWorkspace ? `:${workspace.name}` : '';
diff --git a/editors/code/src/inlay_hints.ts b/editors/code/src/inlay_hints.ts
index 38eb1c15b..61db6b8d0 100644
--- a/editors/code/src/inlay_hints.ts
+++ b/editors/code/src/inlay_hints.ts
@@ -36,7 +36,7 @@ export function activateInlayHints(ctx: Ctx) {
36 maybeUpdater.onConfigChange, maybeUpdater, ctx.subscriptions 36 maybeUpdater.onConfigChange, maybeUpdater, ctx.subscriptions
37 ); 37 );
38 38
39 maybeUpdater.onConfigChange(); 39 maybeUpdater.onConfigChange().catch(console.error);
40} 40}
41 41
42const typeHints = createHintStyle("type"); 42const typeHints = createHintStyle("type");
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 1900d900a..5c0b0be26 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -76,7 +76,7 @@ async function tryActivate(context: vscode.ExtensionContext) {
76 // This a horribly, horribly wrong way to deal with this problem. 76 // This a horribly, horribly wrong way to deal with this problem.
77 ctx = await Ctx.create(config, context, serverPath, workspaceFolder.uri.fsPath); 77 ctx = await Ctx.create(config, context, serverPath, workspaceFolder.uri.fsPath);
78 78
79 setContextValue(RUST_PROJECT_CONTEXT_NAME, true); 79 await setContextValue(RUST_PROJECT_CONTEXT_NAME, true);
80 80
81 // Commands which invokes manually via command palette, shortcut, etc. 81 // Commands which invokes manually via command palette, shortcut, etc.
82 82
@@ -142,7 +142,7 @@ async function tryActivate(context: vscode.ExtensionContext) {
142} 142}
143 143
144export async function deactivate() { 144export async function deactivate() {
145 setContextValue(RUST_PROJECT_CONTEXT_NAME, undefined); 145 await setContextValue(RUST_PROJECT_CONTEXT_NAME, undefined);
146 await ctx?.client.stop(); 146 await ctx?.client.stop();
147 ctx = undefined; 147 ctx = undefined;
148} 148}
@@ -183,10 +183,10 @@ async function bootstrapExtension(config: Config, state: PersistentState): Promi
183 183
184 const release = await downloadWithRetryDialog(state, async () => { 184 const release = await downloadWithRetryDialog(state, async () => {
185 return await fetchRelease("nightly", state.githubToken); 185 return await fetchRelease("nightly", state.githubToken);
186 }).catch((e) => { 186 }).catch(async (e) => {
187 log.error(e); 187 log.error(e);
188 if (state.releaseId === undefined) { // Show error only for the initial download 188 if (state.releaseId === undefined) { // Show error only for the initial download
189 vscode.window.showErrorMessage(`Failed to download rust-analyzer nightly ${e}`); 189 await vscode.window.showErrorMessage(`Failed to download rust-analyzer nightly ${e}`);
190 } 190 }
191 return undefined; 191 return undefined;
192 }); 192 });
@@ -298,7 +298,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string
298 }; 298 };
299 const platform = platforms[`${process.arch} ${process.platform}`]; 299 const platform = platforms[`${process.arch} ${process.platform}`];
300 if (platform === undefined) { 300 if (platform === undefined) {
301 vscode.window.showErrorMessage( 301 await vscode.window.showErrorMessage(
302 "Unfortunately we don't ship binaries for your platform yet. " + 302 "Unfortunately we don't ship binaries for your platform yet. " +
303 "You need to manually clone rust-analyzer repository and " + 303 "You need to manually clone rust-analyzer repository and " +
304 "run `cargo xtask install --server` to build the language server from sources. " + 304 "run `cargo xtask install --server` to build the language server from sources. " +
@@ -433,6 +433,7 @@ function warnAboutExtensionConflicts() {
433 vscode.window.showWarningMessage( 433 vscode.window.showWarningMessage(
434 `You have both the ${fst[0]} (${fst[1]}) and ${sec[0]} (${sec[1]}) ` + 434 `You have both the ${fst[0]} (${fst[1]}) and ${sec[0]} (${sec[1]}) ` +
435 "plugins enabled. These are known to conflict and cause various functions of " + 435 "plugins enabled. These are known to conflict and cause various functions of " +
436 "both plugins to not work correctly. You should disable one of them.", "Got it"); 436 "both plugins to not work correctly. You should disable one of them.", "Got it")
437 .then(() => { }, console.error);
437 }; 438 };
438} 439}
diff --git a/editors/code/src/run.ts b/editors/code/src/run.ts
index 17573cd82..7ac7ca3cb 100644
--- a/editors/code/src/run.ts
+++ b/editors/code/src/run.ts
@@ -45,7 +45,7 @@ export async function selectRunnable(ctx: Ctx, prevRunnable?: RunnableQuickPick,
45 if (items.length === 0) { 45 if (items.length === 0) {
46 // it is the debug case, run always has at least 'cargo check ...' 46 // it is the debug case, run always has at least 'cargo check ...'
47 // see crates\rust-analyzer\src\main_loop\handlers.rs, handle_runnables 47 // see crates\rust-analyzer\src\main_loop\handlers.rs, handle_runnables
48 vscode.window.showErrorMessage("There's no debug target!"); 48 await vscode.window.showErrorMessage("There's no debug target!");
49 return; 49 return;
50 } 50 }
51 51
@@ -65,8 +65,8 @@ export async function selectRunnable(ctx: Ctx, prevRunnable?: RunnableQuickPick,
65 disposables.push( 65 disposables.push(
66 quickPick.onDidHide(() => close()), 66 quickPick.onDidHide(() => close()),
67 quickPick.onDidAccept(() => close(quickPick.selectedItems[0])), 67 quickPick.onDidAccept(() => close(quickPick.selectedItems[0])),
68 quickPick.onDidTriggerButton((_button) => { 68 quickPick.onDidTriggerButton(async (_button) => {
69 (async () => await makeDebugConfig(ctx, quickPick.activeItems[0].runnable))(); 69 await makeDebugConfig(ctx, quickPick.activeItems[0].runnable);
70 close(); 70 close();
71 }), 71 }),
72 quickPick.onDidChangeActive((active) => { 72 quickPick.onDidChangeActive((active) => {
@@ -145,6 +145,7 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise
145 overrideCargo: runnable.args.overrideCargo, 145 overrideCargo: runnable.args.overrideCargo,
146 }; 146 };
147 147
148 // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
148 const target = vscode.workspace.workspaceFolders![0]; // safe, see main activate() 149 const target = vscode.workspace.workspaceFolders![0]; // safe, see main activate()
149 const cargoTask = await tasks.buildCargoTask(target, definition, runnable.label, args, config.cargoRunner, true); 150 const cargoTask = await tasks.buildCargoTask(target, definition, runnable.label, args, config.cargoRunner, true);
150 cargoTask.presentationOptions.clear = true; 151 cargoTask.presentationOptions.clear = true;
diff --git a/editors/code/src/snippets.ts b/editors/code/src/snippets.ts
index fee736e7d..dc53ebe2e 100644
--- a/editors/code/src/snippets.ts
+++ b/editors/code/src/snippets.ts
@@ -62,7 +62,9 @@ function parseSnippet(snip: string): [string, [number, number]] | undefined {
62 const m = snip.match(/\$(0|\{0:([^}]*)\})/); 62 const m = snip.match(/\$(0|\{0:([^}]*)\})/);
63 if (!m) return undefined; 63 if (!m) return undefined;
64 const placeholder = m[2] ?? ""; 64 const placeholder = m[2] ?? "";
65 const range: [number, number] = [m.index!!, placeholder.length]; 65 if (m.index == null)
66 return undefined;
67 const range: [number, number] = [m.index, placeholder.length];
66 const insert = snip.replace(m[0], placeholder); 68 const insert = snip.replace(m[0], placeholder);
67 return [insert, range]; 69 return [insert, range];
68} 70}