diff options
| author | Lukas Wirth <lukastw97@gmail.com> | 2025-01-28 16:04:21 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-28 16:04:21 +0000 |
| commit | 8ecb754eeae4828aaba9c0c321044c62d12ae1d2 (patch) | |
| tree | 4445a9c3d840cf380715876ac64cf93801b49d41 /src/tools/rust-analyzer/editors/code | |
| parent | f70ac259667acb4f03a11bc6fc9795a2e3339399 (diff) | |
| parent | 7268b3d81fd49cceb7c5f58dffb2a4d866528ec7 (diff) | |
| download | rust-8ecb754eeae4828aaba9c0c321044c62d12ae1d2.tar.gz rust-8ecb754eeae4828aaba9c0c321044c62d12ae1d2.zip | |
Merge pull request #19056 from Giga-Bowser/fix-syntax-tree-crlf
fix: Properly handle CRLF line endings in the syntax tree view
Diffstat (limited to 'src/tools/rust-analyzer/editors/code')
3 files changed, 116 insertions, 42 deletions
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<SyntaxElement const editor = vscode.window.activeTextEditor; if (editor !== undefined) { - const start = editor.document.positionAt(element.start); - const end = editor.document.positionAt(element.end); - const range = new vscode.Range(start, end); - - const text = editor.document.getText(range); + const text = editor.document.getText(element.range); item.tooltip = new vscode.MarkdownString().appendCodeblock(text, "rust"); } @@ -74,14 +70,61 @@ export class SyntaxTreeProvider implements vscode.TreeDataProvider<SyntaxElement if (editor && isRustEditor(editor)) { const params = { textDocument: { uri: editor.document.uri.toString() }, range: null }; const fileText = await this.ctx.client.sendRequest(ra.viewSyntaxTree, params); - this.root = JSON.parse(fileText, (_key, value: SyntaxElement) => { + 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<SyntaxElement this._onDidChangeTreeData.fire(); } - getElementByRange(start: number, end: number): SyntaxElement | undefined { + getElementByRange(target: vscode.Range): SyntaxElement | undefined { if (this.root === undefined) { return undefined; } let result: SyntaxElement = this.root; - if (this.root.start === start && this.root.end === end) { + if (this.root.range.isEqual(target)) { return result; } @@ -105,9 +148,9 @@ export class SyntaxTreeProvider implements vscode.TreeDataProvider<SyntaxElement outer: while (true) { for (const child of children) { - if (child.start <= start && child.end >= 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<SyntaxElement export type SyntaxNode = { type: "Node"; kind: string; - start: number; - end: number; - istart?: number; - iend?: number; + range: vscode.Range; + offsets: { + start: number; + end: number; + }; + /** This element's position within a Rust string literal, if it's inside of one. */ + inner?: { + range: vscode.Range; + offsets: { + start: number; + end: number; + }; + }; children: SyntaxElement[]; parent?: SyntaxElement; + document: vscode.TextDocument; }; type SyntaxToken = { type: "Token"; kind: string; - start: number; - end: number; - istart?: number; - iend?: number; + range: vscode.Range; + offsets: { + start: number; + end: number; + }; + /** This element's position within a Rust string literal, if it's inside of one. */ + inner?: { + range: vscode.Range; + offsets: { + start: number; + end: number; + }; + }; parent?: SyntaxElement; + document: vscode.TextDocument; }; export type SyntaxElement = SyntaxNode | SyntaxToken; +type RawNode = { + type: "Node"; + kind: string; + start: [number, number, number]; + end: [number, number, number]; + istart?: [number, number, number]; + iend?: [number, number, number]; + children: SyntaxElement[]; +}; + +type RawToken = { + type: "Token"; + kind: string; + start: [number, number, number]; + end: [number, number, number]; + istart?: [number, number, number]; + iend?: [number, number, number]; +}; + +type RawElement = RawNode | RawToken; + export class SyntaxTreeItem extends vscode.TreeItem { constructor(private readonly element: SyntaxElement) { super(element.kind); - const icon = getIcon(element.kind); - if (element.type === "Node") { + const icon = getIcon(this.element.kind); + if (this.element.type === "Node") { this.contextValue = "syntaxNode"; this.iconPath = icon ?? new vscode.ThemeIcon("list-tree"); this.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; @@ -170,11 +254,9 @@ export class SyntaxTreeItem extends vscode.TreeItem { this.collapsibleState = vscode.TreeItemCollapsibleState.None; } - if (element.istart !== undefined && element.iend !== undefined) { - this.description = `${this.element.istart}..${this.element.iend}`; - } else { - this.description = `${this.element.start}..${this.element.end}`; - } + const offsets = this.element.inner?.offsets ?? this.element.offsets; + + this.description = `${offsets.start}..${offsets.end}`; } } |
