Skip to content

Commit 78c377f

Browse files
committed
Add a new and improved syntax tree viewer
1 parent d8eb839 commit 78c377f

File tree

14 files changed

+759
-4
lines changed

14 files changed

+759
-4
lines changed

src/tools/rust-analyzer/crates/ide/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ mod view_hir;
5656
mod view_item_tree;
5757
mod view_memory_layout;
5858
mod view_mir;
59+
mod view_syntax_tree;
5960

6061
use std::{iter, panic::UnwindSafe};
6162

@@ -339,6 +340,10 @@ impl Analysis {
339340
self.with_db(|db| syntax_tree::syntax_tree(db, file_id, text_range))
340341
}
341342

343+
pub fn view_syntax_tree(&self, file_id: FileId) -> Cancellable<String> {
344+
self.with_db(|db| view_syntax_tree::view_syntax_tree(db, file_id))
345+
}
346+
342347
pub fn view_hir(&self, position: FilePosition) -> Cancellable<String> {
343348
self.with_db(|db| view_hir::view_hir(db, position))
344349
}

src/tools/rust-analyzer/crates/ide/src/syntax_tree.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ use syntax::{
44
AstNode, NodeOrToken, SourceFile, SyntaxKind::STRING, SyntaxToken, TextRange, TextSize,
55
};
66

7-
// Feature: Show Syntax Tree
7+
// Feature: Show Debug Syntax Tree
88
//
9-
// Shows the parse tree of the current file. It exists mostly for debugging
9+
// Shows the textual parse tree of the current file. It exists mostly for debugging
1010
// rust-analyzer itself.
1111
//
1212
// |===

src/tools/rust-analyzer/crates/ide/src/view_syntax_tree.rs

Lines changed: 226 additions & 0 deletions
Large diffs are not rendered by default.

src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ pub(crate) fn handle_syntax_tree(
148148
Ok(res)
149149
}
150150

151+
pub(crate) fn handle_view_syntax_tree(
152+
snap: GlobalStateSnapshot,
153+
params: lsp_ext::ViewSyntaxTreeParams,
154+
) -> anyhow::Result<String> {
155+
let _p = tracing::info_span!("handle_view_syntax_tree").entered();
156+
let id = from_proto::file_id(&snap, &params.text_document.uri)?;
157+
let res = snap.analysis.view_syntax_tree(id)?;
158+
Ok(res)
159+
}
160+
151161
pub(crate) fn handle_view_hir(
152162
snap: GlobalStateSnapshot,
153163
params: lsp_types::TextDocumentPositionParams,

src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,20 @@ pub struct SyntaxTreeParams {
123123
pub range: Option<Range>,
124124
}
125125

126+
pub enum ViewSyntaxTree {}
127+
128+
impl Request for ViewSyntaxTree {
129+
type Params = ViewSyntaxTreeParams;
130+
type Result = String;
131+
const METHOD: &'static str = "rust-analyzer/viewSyntaxTree";
132+
}
133+
134+
#[derive(Deserialize, Serialize, Debug)]
135+
#[serde(rename_all = "camelCase")]
136+
pub struct ViewSyntaxTreeParams {
137+
pub text_document: TextDocumentIdentifier,
138+
}
139+
126140
pub enum ViewHir {}
127141

128142
impl Request for ViewHir {

src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,7 @@ impl GlobalState {
11461146
.on::<NO_RETRY, lsp_ext::Ssr>(handlers::handle_ssr)
11471147
.on::<NO_RETRY, lsp_ext::ViewRecursiveMemoryLayout>(handlers::handle_view_recursive_memory_layout)
11481148
.on::<NO_RETRY, lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)
1149+
.on::<NO_RETRY, lsp_ext::ViewSyntaxTree>(handlers::handle_view_syntax_tree)
11491150
.on::<NO_RETRY, lsp_ext::ViewHir>(handlers::handle_view_hir)
11501151
.on::<NO_RETRY, lsp_ext::ViewMir>(handlers::handle_view_mir)
11511152
.on::<NO_RETRY, lsp_ext::InterpretFunction>(handlers::handle_interpret_function)

src/tools/rust-analyzer/docs/dev/lsp-extensions.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!---
2-
lsp/ext.rs hash: 6dd762ae19630ec0
2+
lsp/ext.rs hash: a85494375e528064
33
44
If you need to change the above hash to make the test pass, please check if you
55
need to adjust this doc as well and ping this issue:
@@ -710,6 +710,23 @@ interface SyntaxTreeParams {
710710
Returns textual representation of a parse tree for the file/selected region.
711711
Primarily for debugging, but very useful for all people working on rust-analyzer itself.
712712

713+
## View Syntax Tree
714+
715+
**Method:** `rust-analyzer/viewSyntaxTree`
716+
717+
**Request:**
718+
719+
```typescript
720+
interface ViewSyntaxTreeParams {
721+
textDocument: TextDocumentIdentifier,
722+
}
723+
```
724+
725+
**Response:** `string`
726+
727+
Returns json representation of the file's syntax tree.
728+
Used to create a treeView for debugging and working on rust-analyzer itself.
729+
713730
## View Hir
714731

715732
**Method:** `rust-analyzer/viewHir`

src/tools/rust-analyzer/editors/code/package.json

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,24 @@
288288
"title": "Reveal File",
289289
"category": "rust-analyzer"
290290
},
291+
{
292+
"command": "rust-analyzer.syntaxTreeReveal",
293+
"title": "Reveal Syntax Element",
294+
"icon": "$(search)",
295+
"category": "rust-analyzer (syntax tree)"
296+
},
297+
{
298+
"command": "rust-analyzer.syntaxTreeHideWhitespace",
299+
"title": "Hide Whitespace",
300+
"icon": "$(filter)",
301+
"category": "rust-analyzer (syntax tree)"
302+
},
303+
{
304+
"command": "rust-analyzer.syntaxTreeShowWhitespace",
305+
"title": "Show Whitespace",
306+
"icon": "$(filter-filled)",
307+
"category": "rust-analyzer (syntax tree)"
308+
},
291309
{
292310
"command": "rust-analyzer.viewMemoryLayout",
293311
"title": "View Memory Layout",
@@ -345,6 +363,11 @@
345363
"default": true,
346364
"type": "boolean"
347365
},
366+
"rust-analyzer.showSyntaxTree": {
367+
"markdownDescription": "Whether to show the syntax tree view.",
368+
"default": true,
369+
"type": "boolean"
370+
},
348371
"rust-analyzer.testExplorer": {
349372
"markdownDescription": "Whether to show the test explorer.",
350373
"default": false,
@@ -3362,6 +3385,18 @@
33623385
},
33633386
{
33643387
"command": "rust-analyzer.openWalkthrough"
3388+
},
3389+
{
3390+
"command": "rust-analyzer.syntaxTreeReveal",
3391+
"when": "false"
3392+
},
3393+
{
3394+
"command": "rust-analyzer.syntaxTreeHideWhitespace",
3395+
"when": "false"
3396+
},
3397+
{
3398+
"command": "rust-analyzer.syntaxTreeShowWhitespace",
3399+
"when": "false"
33653400
}
33663401
],
33673402
"editor/context": [
@@ -3375,6 +3410,25 @@
33753410
"when": "inRustProject && editorTextFocus && editorLangId == rust",
33763411
"group": "navigation@1001"
33773412
}
3413+
],
3414+
"view/title": [
3415+
{
3416+
"command": "rust-analyzer.syntaxTreeHideWhitespace",
3417+
"group": "navigation",
3418+
"when": "view == rustSyntaxTree && !rustSyntaxTree.hideWhitespace"
3419+
},
3420+
{
3421+
"command": "rust-analyzer.syntaxTreeShowWhitespace",
3422+
"group": "navigation",
3423+
"when": "view == rustSyntaxTree && rustSyntaxTree.hideWhitespace"
3424+
}
3425+
],
3426+
"view/item/context": [
3427+
{
3428+
"command": "rust-analyzer.syntaxTreeReveal",
3429+
"group": "inline",
3430+
"when": "view == rustSyntaxTree"
3431+
}
33783432
]
33793433
},
33803434
"views": {
@@ -3384,6 +3438,22 @@
33843438
"name": "Rust Dependencies",
33853439
"when": "inRustProject && config.rust-analyzer.showDependenciesExplorer"
33863440
}
3441+
],
3442+
"rustSyntaxTreeContainer": [
3443+
{
3444+
"id": "rustSyntaxTree",
3445+
"name": "Rust Syntax Tree",
3446+
"when": "inRustProject && config.rust-analyzer.showSyntaxTree"
3447+
}
3448+
]
3449+
},
3450+
"viewsContainers": {
3451+
"activitybar": [
3452+
{
3453+
"id": "rustSyntaxTreeContainer",
3454+
"title": "Rust Syntax Tree",
3455+
"icon": "$(list-tree)"
3456+
}
33873457
]
33883458
},
33893459
"jsonValidation": [

src/tools/rust-analyzer/editors/code/src/commands.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import type { LanguageClient } from "vscode-languageclient/node";
3131
import { HOVER_REFERENCE_COMMAND } from "./client";
3232
import type { DependencyId } from "./dependencies_provider";
3333
import { log } from "./util";
34+
import type { SyntaxElement } from "./syntax_tree_provider";
3435

3536
export * from "./ast_inspector";
3637
export * from "./run";
@@ -357,6 +358,38 @@ export async function execRevealDependency(e: RustEditor): Promise<void> {
357358
await vscode.commands.executeCommand("rust-analyzer.revealDependency", e);
358359
}
359360

361+
export function syntaxTreeReveal(): Cmd {
362+
return async (element: SyntaxElement) => {
363+
const activeEditor = vscode.window.activeTextEditor;
364+
365+
if (activeEditor !== undefined) {
366+
const start = activeEditor.document.positionAt(element.start);
367+
const end = activeEditor.document.positionAt(element.end);
368+
369+
const newSelection = new vscode.Selection(start, end);
370+
371+
activeEditor.selection = newSelection;
372+
activeEditor.revealRange(newSelection);
373+
}
374+
};
375+
}
376+
377+
export function syntaxTreeHideWhitespace(ctx: CtxInit): Cmd {
378+
return async () => {
379+
if (ctx.syntaxTreeProvider !== undefined) {
380+
await ctx.syntaxTreeProvider.toggleWhitespace();
381+
}
382+
};
383+
}
384+
385+
export function syntaxTreeShowWhitespace(ctx: CtxInit): Cmd {
386+
return async () => {
387+
if (ctx.syntaxTreeProvider !== undefined) {
388+
await ctx.syntaxTreeProvider.toggleWhitespace();
389+
}
390+
};
391+
}
392+
360393
export function ssr(ctx: CtxInit): Cmd {
361394
return async () => {
362395
const editor = vscode.window.activeTextEditor;

src/tools/rust-analyzer/editors/code/src/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ export class Config {
351351
return this.get<boolean>("showDependenciesExplorer");
352352
}
353353

354+
get showSyntaxTree() {
355+
return this.get<boolean>("showSyntaxTree");
356+
}
357+
354358
get statusBarClickAction() {
355359
return this.get<string>("statusBar.clickAction");
356360
}

0 commit comments

Comments
 (0)