From 7268b3d81fd49cceb7c5f58dffb2a4d866528ec7 Mon Sep 17 00:00:00 2001 From: Giga Bowser <45986823+Giga-Bowser@users.noreply.github.com> Date: Mon, 27 Jan 2025 15:05:20 -0500 Subject: fix: Properly handle CRLF line endings in the syntax tree view --- .../rust-analyzer/editors/code/src/commands.ts | 14 +-- src/tools/rust-analyzer/editors/code/src/ctx.ts | 4 +- .../editors/code/src/syntax_tree_provider.ts | 140 ++++++++++++++++----- 3 files changed, 116 insertions(+), 42 deletions(-) (limited to 'src/tools/rust-analyzer/editors/code') diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts index b3aa04af7ed..eee623ecae9 100644 --- a/src/tools/rust-analyzer/editors/code/src/commands.ts +++ b/src/tools/rust-analyzer/editors/code/src/commands.ts @@ -361,10 +361,7 @@ export function syntaxTreeReveal(): Cmd { const activeEditor = vscode.window.activeTextEditor; if (activeEditor !== undefined) { - const start = activeEditor.document.positionAt(element.start); - const end = activeEditor.document.positionAt(element.end); - - const newSelection = new vscode.Selection(start, end); + const newSelection = new vscode.Selection(element.range.start, element.range.end); activeEditor.selection = newSelection; activeEditor.revealRange(newSelection); @@ -378,15 +375,12 @@ function elementToString( depth: number = 0, ): string { let result = " ".repeat(depth); - const start = element.istart ?? element.start; - const end = element.iend ?? element.end; + const offsets = element.inner?.offsets ?? element.offsets; - result += `${element.kind}@${start}..${end}`; + result += `${element.kind}@${offsets.start}..${offsets.end}`; if (element.type === "Token") { - const startPosition = activeDocument.positionAt(element.start); - const endPosition = activeDocument.positionAt(element.end); - const text = activeDocument.getText(new vscode.Range(startPosition, endPosition)); + const text = activeDocument.getText(element.range).replaceAll("\r\n", "\n"); // JSON.stringify quotes and escapes the string for us. result += ` ${JSON.stringify(text)}\n`; } else { diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts index 96dc4f19b82..4248305d5cc 100644 --- a/src/tools/rust-analyzer/editors/code/src/ctx.ts +++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts @@ -384,9 +384,7 @@ export class Ctx implements RustAnalyzerExtensionApi { return; } - const start = e.textEditor.document.offsetAt(selection.start); - const end = e.textEditor.document.offsetAt(selection.end); - const result = this.syntaxTreeProvider?.getElementByRange(start, end); + const result = this.syntaxTreeProvider?.getElementByRange(selection); if (result !== undefined) { await this.syntaxTreeView?.reveal(result); } diff --git a/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts b/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts index c7e8007e838..3f7e30f13a3 100644 --- a/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts +++ b/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts @@ -37,11 +37,7 @@ export class SyntaxTreeProvider implements vscode.TreeDataProvider { + this.root = JSON.parse(fileText, (_key, value: RawElement): SyntaxElement => { + if (value.type !== "Node" && value.type !== "Token") { + // This is something other than a RawElement. + return value; + } + const [startOffset, startLine, startCol] = value.start; + const [endOffset, endLine, endCol] = value.end; + const range = new vscode.Range(startLine, startCol, endLine, endCol); + const offsets = { + start: startOffset, + end: endOffset, + }; + + let inner; + if (value.istart && value.iend) { + const [istartOffset, istartLine, istartCol] = value.istart; + const [iendOffset, iendLine, iendCol] = value.iend; + + inner = { + offsets: { + start: istartOffset, + end: iendOffset, + }, + range: new vscode.Range(istartLine, istartCol, iendLine, iendCol), + }; + } + if (value.type === "Node") { - for (const child of value.children) { - child.parent = value; + const result = { + type: value.type, + kind: value.kind, + offsets, + range, + inner, + children: value.children, + parent: undefined, + document: editor.document, + }; + + for (const child of result.children) { + child.parent = result; } - } - return value; + return result; + } else { + return { + type: value.type, + kind: value.kind, + offsets, + range, + inner, + parent: undefined, + document: editor.document, + }; + } }); } else { this.root = undefined; @@ -90,14 +133,14 @@ export class SyntaxTreeProvider implements vscode.TreeDataProvider= end) { + if (child.range.contains(target)) { result = child; - if (start === end && start === child.end) { + if (target.isEmpty && target.start === child.range.end) { // When the cursor is on the very end of a token, // we assume the user wants the next token instead. continue; @@ -136,31 +179,72 @@ export class SyntaxTreeProvider implements vscode.TreeDataProvider