Skip to content

Commit

Permalink
feat: Add a new and improved syntax tree viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
Giga-Bowser committed Jan 1, 2025
1 parent f0d182d commit 25bcb6b
Show file tree
Hide file tree
Showing 12 changed files with 767 additions and 1 deletion.
5 changes: 5 additions & 0 deletions crates/ide/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ mod view_hir;
mod view_item_tree;
mod view_memory_layout;
mod view_mir;
mod view_syntax_tree;

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

Expand Down Expand Up @@ -339,6 +340,10 @@ impl Analysis {
self.with_db(|db| syntax_tree::syntax_tree(db, file_id, text_range))
}

pub fn view_syntax_tree(&self, file_id: FileId) -> Cancellable<String> {
self.with_db(|db| view_syntax_tree::view_syntax_tree(db, file_id))
}

pub fn view_hir(&self, position: FilePosition) -> Cancellable<String> {
self.with_db(|db| view_hir::view_hir(db, position))
}
Expand Down
219 changes: 219 additions & 0 deletions crates/ide/src/view_syntax_tree.rs

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions crates/rust-analyzer/src/handlers/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ pub(crate) fn handle_syntax_tree(
Ok(res)
}

pub(crate) fn handle_view_syntax_tree(
snap: GlobalStateSnapshot,
params: lsp_ext::ViewSyntaxTreeParams,
) -> anyhow::Result<String> {
let _p = tracing::info_span!("handle_view_syntax_tree").entered();
let id = from_proto::file_id(&snap, &params.text_document.uri)?;
let res = snap.analysis.view_syntax_tree(id)?;
Ok(res)
}

pub(crate) fn handle_view_hir(
snap: GlobalStateSnapshot,
params: lsp_types::TextDocumentPositionParams,
Expand Down
14 changes: 14 additions & 0 deletions crates/rust-analyzer/src/lsp/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,20 @@ pub struct SyntaxTreeParams {
pub range: Option<Range>,
}

pub enum ViewSyntaxTree {}

impl Request for ViewSyntaxTree {
type Params = ViewSyntaxTreeParams;
type Result = String;
const METHOD: &'static str = "rust-analyzer/viewSyntaxTree";
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ViewSyntaxTreeParams {
pub text_document: TextDocumentIdentifier,
}

pub enum ViewHir {}

impl Request for ViewHir {
Expand Down
1 change: 1 addition & 0 deletions crates/rust-analyzer/src/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,7 @@ impl GlobalState {
.on::<NO_RETRY, lsp_ext::Ssr>(handlers::handle_ssr)
.on::<NO_RETRY, lsp_ext::ViewRecursiveMemoryLayout>(handlers::handle_view_recursive_memory_layout)
.on::<NO_RETRY, lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)
.on::<NO_RETRY, lsp_ext::ViewSyntaxTree>(handlers::handle_view_syntax_tree)
.on::<NO_RETRY, lsp_ext::ViewHir>(handlers::handle_view_hir)
.on::<NO_RETRY, lsp_ext::ViewMir>(handlers::handle_view_mir)
.on::<NO_RETRY, lsp_ext::InterpretFunction>(handlers::handle_interpret_function)
Expand Down
70 changes: 70 additions & 0 deletions editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,24 @@
"title": "Reveal File",
"category": "rust-analyzer"
},
{
"command": "rust-analyzer.syntaxTreeReveal",
"title": "Reveal Syntax Element",
"icon": "$(search)",
"category": "rust-analyzer"
},
{
"command": "rust-analyzer.syntaxTreeHideWhitespace",
"title": "Hide Whitespace",
"icon": "$(filter)",
"category": "rust-analyzer"
},
{
"command": "rust-analyzer.syntaxTreeShowWhitespace",
"title": "Show Whitespace",
"icon": "$(filter-filled)",
"category": "rust-analyzer"
},
{
"command": "rust-analyzer.viewMemoryLayout",
"title": "View Memory Layout",
Expand Down Expand Up @@ -345,6 +363,11 @@
"default": true,
"type": "boolean"
},
"rust-analyzer.showSyntaxTree": {
"markdownDescription": "Whether to show the syntax tree view.",
"default": true,
"type": "boolean"
},
"rust-analyzer.testExplorer": {
"markdownDescription": "Whether to show the test explorer.",
"default": false,
Expand Down Expand Up @@ -3362,6 +3385,18 @@
},
{
"command": "rust-analyzer.openWalkthrough"
},
{
"command": "rust-analyzer.syntaxTreeReveal",
"when": "false"
},
{
"command": "rust-analyzer.syntaxTreeHideWhitespace",
"when": "false"
},
{
"command": "rust-analyzer.syntaxTreeShowWhitespace",
"when": "false"
}
],
"editor/context": [
Expand All @@ -3375,6 +3410,25 @@
"when": "inRustProject && editorTextFocus && editorLangId == rust",
"group": "navigation@1001"
}
],
"view/title": [
{
"command": "rust-analyzer.syntaxTreeHideWhitespace",
"group": "navigation",
"when": "view == rustSyntaxTree && !rustSyntaxTree.hideWhitespace"
},
{
"command": "rust-analyzer.syntaxTreeShowWhitespace",
"group": "navigation",
"when": "view == rustSyntaxTree && rustSyntaxTree.hideWhitespace"
}
],
"view/item/context": [
{
"command": "rust-analyzer.syntaxTreeReveal",
"group": "inline",
"when": "view == rustSyntaxTree"
}
]
},
"views": {
Expand All @@ -3384,6 +3438,22 @@
"name": "Rust Dependencies",
"when": "inRustProject && config.rust-analyzer.showDependenciesExplorer"
}
],
"rustSyntaxTreeContainer": [
{
"id": "rustSyntaxTree",
"name": "Rust Syntax Tree",
"when": "inRustProject && config.rust-analyzer.showSyntaxTree"
}
]
},
"viewsContainers": {
"activitybar": [
{
"id": "rustSyntaxTreeContainer",
"title": "Rust Syntax Tree",
"icon": "$(list-tree)"
}
]
},
"jsonValidation": [
Expand Down
33 changes: 33 additions & 0 deletions editors/code/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import type { LanguageClient } from "vscode-languageclient/node";
import { HOVER_REFERENCE_COMMAND } from "./client";
import type { DependencyId } from "./dependencies_provider";
import { log } from "./util";
import type { SyntaxElement } from "./syntax_tree_provider";

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

export function syntaxTreeReveal(): Cmd {
return async (element: SyntaxElement) => {
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);

activeEditor.selection = newSelection;
activeEditor.revealRange(newSelection);
}
};
}

export function syntaxTreeHideWhitespace(ctx: CtxInit): Cmd {
return async () => {
if (ctx.syntaxTreeProvider !== undefined) {
await ctx.syntaxTreeProvider.toggleWhitespace();
}
};
}

export function syntaxTreeShowWhitespace(ctx: CtxInit): Cmd {
return async () => {
if (ctx.syntaxTreeProvider !== undefined) {
await ctx.syntaxTreeProvider.toggleWhitespace();
}
};
}

export function ssr(ctx: CtxInit): Cmd {
return async () => {
const editor = vscode.window.activeTextEditor;
Expand Down
4 changes: 4 additions & 0 deletions editors/code/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ export class Config {
return this.get<boolean>("showDependenciesExplorer");
}

get showSyntaxTree() {
return this.get<boolean>("showSyntaxTree");
}

get statusBarClickAction() {
return this.get<string>("statusBar.clickAction");
}
Expand Down
73 changes: 72 additions & 1 deletion editors/code/src/ctx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
RustDependenciesProvider,
type DependencyId,
} from "./dependencies_provider";
import { SyntaxTreeProvider, type SyntaxElement } from "./syntax_tree_provider";
import { execRevealDependency } from "./commands";
import { PersistentState } from "./persistent_state";
import { bootstrap } from "./bootstrap";
Expand Down Expand Up @@ -85,7 +86,11 @@ export class Ctx implements RustAnalyzerExtensionApi {
private commandDisposables: Disposable[];
private unlinkedFiles: vscode.Uri[];
private _dependenciesProvider: RustDependenciesProvider | undefined;
private _dependencyTreeView: vscode.TreeView<Dependency | DependencyFile | DependencyId> | undefined;
private _dependencyTreeView:
| vscode.TreeView<Dependency | DependencyFile | DependencyId>
| undefined;
private _syntaxTreeProvider: SyntaxTreeProvider | undefined;
private _syntaxTreeView: vscode.TreeView<SyntaxElement> | undefined;
private lastStatus: ServerStatusParams | { health: "stopped" } = { health: "stopped" };
private _serverVersion: string;
private statusBarActiveEditorListener: Disposable;
Expand All @@ -110,6 +115,14 @@ export class Ctx implements RustAnalyzerExtensionApi {
return this._dependenciesProvider;
}

get syntaxTreeView() {
return this._syntaxTreeView;
}

get syntaxTreeProvider() {
return this._syntaxTreeProvider;
}

constructor(
readonly extCtx: vscode.ExtensionContext,
commandFactories: Record<string, CommandFactory>,
Expand Down Expand Up @@ -278,6 +291,9 @@ export class Ctx implements RustAnalyzerExtensionApi {
if (this.config.showDependenciesExplorer) {
this.prepareTreeDependenciesView(client);
}
if (this.config.showSyntaxTree) {
this.prepareSyntaxTreeView(client);
}
}

private prepareTreeDependenciesView(client: lc.LanguageClient) {
Expand Down Expand Up @@ -326,6 +342,60 @@ export class Ctx implements RustAnalyzerExtensionApi {
);
}

private prepareSyntaxTreeView(client: lc.LanguageClient) {
const ctxInit: CtxInit = {
...this,
client: client,
};
this._syntaxTreeProvider = new SyntaxTreeProvider(ctxInit);
this._syntaxTreeView = vscode.window.createTreeView("rustSyntaxTree", {
treeDataProvider: this._syntaxTreeProvider,
showCollapseAll: true,
});

this.pushExtCleanup(this._syntaxTreeView);

vscode.window.onDidChangeActiveTextEditor(async () => {
if (this.syntaxTreeView?.visible) {
await this.syntaxTreeProvider?.refresh();
}
});

vscode.workspace.onDidChangeTextDocument(async () => {
if (this.syntaxTreeView?.visible) {
await this.syntaxTreeProvider?.refresh();
}
});

vscode.window.onDidChangeTextEditorSelection(async (e) => {
if (e.kind === vscode.TextEditorSelectionChangeKind.Command) {
return;
}

if (!this.syntaxTreeView?.visible || !isRustEditor(e.textEditor)) {
return;
}

const selection = e.selections[0];
if (selection === undefined) {
return;
}

const start = e.textEditor.document.offsetAt(selection.start);
const end = e.textEditor.document.offsetAt(selection.end);
const result = this.syntaxTreeProvider?.getElementByRange(start, end);
if (result !== undefined) {
await this.syntaxTreeView?.reveal(result);
}
});

this.syntaxTreeView?.onDidChangeVisibility(async (e) => {
if (e.visible) {
await this.syntaxTreeProvider?.refresh();
}
});
}

async restart() {
// FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed
await this.stopAndDispose();
Expand Down Expand Up @@ -424,6 +494,7 @@ export class Ctx implements RustAnalyzerExtensionApi {
statusBar.command = "rust-analyzer.openLogs";
}
this.dependenciesProvider?.refresh();
void this.syntaxTreeProvider?.refresh();
break;
case "warning":
statusBar.color = new vscode.ThemeColor("statusBarItem.warningForeground");
Expand Down
4 changes: 4 additions & 0 deletions editors/code/src/lsp_ext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ export const runFlycheck = new lc.NotificationType<{
export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>(
"rust-analyzer/syntaxTree",
);
export const viewSyntaxTree = new lc.RequestType<ViewSyntaxTreeParams, string, void>(
"rust-analyzer/viewSyntaxTree",
);
export const viewCrateGraph = new lc.RequestType<ViewCrateGraphParams, string, void>(
"rust-analyzer/viewCrateGraph",
);
Expand Down Expand Up @@ -157,6 +160,7 @@ export type SyntaxTreeParams = {
textDocument: lc.TextDocumentIdentifier;
range: lc.Range | null;
};
export type ViewSyntaxTreeParams = { textDocument: lc.TextDocumentIdentifier };
export type ViewCrateGraphParams = { full: boolean };
export type ViewItemTreeParams = { textDocument: lc.TextDocumentIdentifier };

Expand Down
3 changes: 3 additions & 0 deletions editors/code/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ function createCommands(): Record<string, CommandFactory> {
rename: { enabled: commands.rename },
openLogs: { enabled: commands.openLogs },
revealDependency: { enabled: commands.revealDependency },
syntaxTreeReveal: { enabled: commands.syntaxTreeReveal },
syntaxTreeHideWhitespace: { enabled: commands.syntaxTreeHideWhitespace },
syntaxTreeShowWhitespace: { enabled: commands.syntaxTreeShowWhitespace },
};
}

Expand Down
Loading

0 comments on commit 25bcb6b

Please sign in to comment.