From ca5c59507f76b8e30658d6c815b823c9636d786a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 30 Dec 2019 19:05:41 +0100 Subject: Refactor show syntax tree action --- editors/code/src/commands/index.ts | 2 +- editors/code/src/commands/syntaxTree.ts | 76 --------------- editors/code/src/commands/syntax_tree.ts | 106 +++++++++++++++++++++ editors/code/src/ctx.ts | 4 + .../code/src/events/change_active_text_editor.ts | 9 +- editors/code/src/events/change_text_document.ts | 24 ----- editors/code/src/events/index.ts | 3 +- editors/code/src/main.ts | 26 +---- 8 files changed, 116 insertions(+), 134 deletions(-) delete mode 100644 editors/code/src/commands/syntaxTree.ts create mode 100644 editors/code/src/commands/syntax_tree.ts delete mode 100644 editors/code/src/events/change_text_document.ts (limited to 'editors') diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts index a7f3bc4c1..8f91b3b7d 100644 --- a/editors/code/src/commands/index.ts +++ b/editors/code/src/commands/index.ts @@ -5,10 +5,10 @@ import { matchingBrace } from './matching_brace'; import { joinLines } from './join_lines'; import { onEnter } from './on_enter'; import { parentModule } from './parent_module'; +import { syntaxTree } from './syntax_tree'; import * as expandMacro from './expand_macro'; import * as inlayHints from './inlay_hints'; import * as runnables from './runnables'; -import * as syntaxTree from './syntaxTree'; function collectGarbage(ctx: Ctx): Cmd { return async () => { diff --git a/editors/code/src/commands/syntaxTree.ts b/editors/code/src/commands/syntaxTree.ts deleted file mode 100644 index 89a80550c..000000000 --- a/editors/code/src/commands/syntaxTree.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as vscode from 'vscode'; -import { Range, TextDocumentIdentifier } from 'vscode-languageclient'; - -import { Server } from '../server'; - -export const syntaxTreeUri = vscode.Uri.parse('rust-analyzer://syntaxtree'); - -export class SyntaxTreeContentProvider - implements vscode.TextDocumentContentProvider { - public eventEmitter = new vscode.EventEmitter(); - public syntaxTree: string = 'Not available'; - - public provideTextDocumentContent( - uri: vscode.Uri, - ): vscode.ProviderResult { - const editor = vscode.window.activeTextEditor; - if (editor == null) { - return ''; - } - - let range: Range | undefined; - - // When the range based query is enabled we take the range of the selection - if (uri.query === 'range=true') { - range = editor.selection.isEmpty - ? undefined - : Server.client.code2ProtocolConverter.asRange( - editor.selection, - ); - } - - const request: SyntaxTreeParams = { - textDocument: { uri: editor.document.uri.toString() }, - range, - }; - return Server.client.sendRequest( - 'rust-analyzer/syntaxTree', - request, - ); - } - - get onDidChange(): vscode.Event { - return this.eventEmitter.event; - } -} - -interface SyntaxTreeParams { - textDocument: TextDocumentIdentifier; - range?: Range; -} - -type SyntaxTreeResult = string; - -// Opens the virtual file that will show the syntax tree -// -// The contents of the file come from the `TextDocumentContentProvider` -export function createHandle(provider: SyntaxTreeContentProvider) { - return async () => { - const editor = vscode.window.activeTextEditor; - const rangeEnabled = !!(editor && !editor.selection.isEmpty); - - const uri = rangeEnabled - ? vscode.Uri.parse(`${syntaxTreeUri.toString()}?range=true`) - : syntaxTreeUri; - - const document = await vscode.workspace.openTextDocument(uri); - - provider.eventEmitter.fire(uri); - - return vscode.window.showTextDocument( - document, - vscode.ViewColumn.Two, - true, - ); - }; -} diff --git a/editors/code/src/commands/syntax_tree.ts b/editors/code/src/commands/syntax_tree.ts new file mode 100644 index 000000000..e61fb36df --- /dev/null +++ b/editors/code/src/commands/syntax_tree.ts @@ -0,0 +1,106 @@ +import * as vscode from 'vscode'; +import * as lc from 'vscode-languageclient'; + +import { Ctx, Cmd } from '../ctx'; + +// Opens the virtual file that will show the syntax tree +// +// The contents of the file come from the `TextDocumentContentProvider` +export function syntaxTree(ctx: Ctx): Cmd { + const stcp = new SyntaxTreeContentProvider(ctx); + + ctx.pushCleanup( + vscode.workspace.registerTextDocumentContentProvider( + 'rust-analyzer', + stcp, + ), + ); + + vscode.workspace.onDidChangeTextDocument( + (event: vscode.TextDocumentChangeEvent) => { + const doc = event.document; + if (doc.languageId !== 'rust') return; + afterLs(() => stcp.eventEmitter.fire(stcp.uri)); + }, + ctx.subscriptions, + ); + + vscode.window.onDidChangeActiveTextEditor( + (editor: vscode.TextEditor | undefined) => { + if (!editor || editor.document.languageId !== 'rust') return; + stcp.eventEmitter.fire(stcp.uri); + }, + ctx.subscriptions, + ); + + return async () => { + const editor = vscode.window.activeTextEditor; + const rangeEnabled = !!(editor && !editor.selection.isEmpty); + + const uri = rangeEnabled + ? vscode.Uri.parse(`${stcp.uri.toString()}?range=true`) + : stcp.uri; + + const document = await vscode.workspace.openTextDocument(uri); + + stcp.eventEmitter.fire(uri); + + return vscode.window.showTextDocument( + document, + vscode.ViewColumn.Two, + true, + ); + }; +} + +// We need to order this after LS updates, but there's no API for that. +// Hence, good old setTimeout. +function afterLs(f: () => any) { + setTimeout(f, 10); +} + +interface SyntaxTreeParams { + textDocument: lc.TextDocumentIdentifier; + range?: lc.Range; +} + +export class SyntaxTreeContentProvider + implements vscode.TextDocumentContentProvider { + ctx: Ctx; + uri = vscode.Uri.parse('rust-analyzer://syntaxtree'); + eventEmitter = new vscode.EventEmitter(); + syntaxTree: string = 'Not available'; + + constructor(ctx: Ctx) { + this.ctx = ctx; + } + + provideTextDocumentContent(uri: vscode.Uri): vscode.ProviderResult { + const editor = vscode.window.activeTextEditor; + if (editor == null) return ''; + + let range: lc.Range | undefined; + + // When the range based query is enabled we take the range of the selection + if (uri.query === 'range=true') { + range = editor.selection.isEmpty + ? undefined + : this.ctx.client.code2ProtocolConverter.asRange( + editor.selection, + ); + } + + const request: SyntaxTreeParams = { + textDocument: { uri: editor.document.uri.toString() }, + range, + }; + return this.ctx.client.sendRequest( + 'rust-analyzer/syntaxTree', + request, + ); + } + + get onDidChange(): vscode.Event { + return this.eventEmitter.event; + } +} diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 22af5ef32..c3a3583b5 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -49,6 +49,10 @@ export class Ctx { } } + get subscriptions(): { dispose(): any }[] { + return this.extCtx.subscriptions; + } + pushCleanup(d: { dispose(): any }) { this.extCtx.subscriptions.push(d); } diff --git a/editors/code/src/events/change_active_text_editor.ts b/editors/code/src/events/change_active_text_editor.ts index 74b91bd48..4384ee567 100644 --- a/editors/code/src/events/change_active_text_editor.ts +++ b/editors/code/src/events/change_active_text_editor.ts @@ -1,21 +1,14 @@ import { TextEditor } from 'vscode'; import { TextDocumentIdentifier } from 'vscode-languageclient'; - -import { - SyntaxTreeContentProvider, - syntaxTreeUri, -} from '../commands/syntaxTree'; import { Decoration } from '../highlighting'; import { Server } from '../server'; -export function makeHandler(syntaxTreeProvider: SyntaxTreeContentProvider) { +export function makeHandler() { return async function handle(editor: TextEditor | undefined) { if (!editor || editor.document.languageId !== 'rust') { return; } - syntaxTreeProvider.eventEmitter.fire(syntaxTreeUri); - if (!Server.config.highlightingOn) { return; } diff --git a/editors/code/src/events/change_text_document.ts b/editors/code/src/events/change_text_document.ts deleted file mode 100644 index 2e998e889..000000000 --- a/editors/code/src/events/change_text_document.ts +++ /dev/null @@ -1,24 +0,0 @@ -import * as vscode from 'vscode'; - -import { - SyntaxTreeContentProvider, - syntaxTreeUri, -} from '../commands/syntaxTree'; - -export function createHandler(syntaxTreeProvider: SyntaxTreeContentProvider) { - return (event: vscode.TextDocumentChangeEvent) => { - const doc = event.document; - if (doc.languageId !== 'rust') { - return; - } - afterLs(() => { - syntaxTreeProvider.eventEmitter.fire(syntaxTreeUri); - }); - }; -} - -// We need to order this after LS updates, but there's no API for that. -// Hence, good old setTimeout. -function afterLs(f: () => any) { - setTimeout(f, 10); -} diff --git a/editors/code/src/events/index.ts b/editors/code/src/events/index.ts index 4c154563f..be135474d 100644 --- a/editors/code/src/events/index.ts +++ b/editors/code/src/events/index.ts @@ -1,4 +1,3 @@ import * as changeActiveTextEditor from './change_active_text_editor'; -import * as changeTextDocument from './change_text_document'; -export { changeActiveTextEditor, changeTextDocument }; +export { changeActiveTextEditor }; diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 55fedd8bb..d92cd164f 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -4,7 +4,6 @@ import * as lc from 'vscode-languageclient'; import * as commands from './commands'; import { ExpandMacroContentProvider } from './commands/expand_macro'; import { HintsUpdater } from './commands/inlay_hints'; -import { SyntaxTreeContentProvider } from './commands/syntaxTree'; import { StatusDisplay } from './commands/watch_status'; import * as events from './events'; import * as notifications from './notifications'; @@ -20,6 +19,7 @@ export async function activate(context: vscode.ExtensionContext) { ctx.registerCommand('matchingBrace', commands.matchingBrace); ctx.registerCommand('joinLines', commands.joinLines); ctx.registerCommand('parentModule', commands.parentModule); + ctx.registerCommand('syntaxTree', commands.syntaxTree); function disposeOnDeactivation(disposable: vscode.Disposable) { context.subscriptions.push(disposable); @@ -55,10 +55,7 @@ export async function activate(context: vscode.ExtensionContext) { disposeOnDeactivation(watchStatus); // Notifications are events triggered by the language server - const allNotifications: Iterable<[ - string, - lc.GenericNotificationHandler, - ]> = [ + const allNotifications: [string, lc.GenericNotificationHandler][] = [ [ 'rust-analyzer/publishDecorations', notifications.publishDecorations.handle, @@ -68,20 +65,13 @@ export async function activate(context: vscode.ExtensionContext) { params => watchStatus.handleProgressNotification(params), ], ]; - const syntaxTreeContentProvider = new SyntaxTreeContentProvider(); const expandMacroContentProvider = new ExpandMacroContentProvider(); // The events below are plain old javascript events, triggered and handled by vscode vscode.window.onDidChangeActiveTextEditor( - events.changeActiveTextEditor.makeHandler(syntaxTreeContentProvider), + events.changeActiveTextEditor.makeHandler(), ); - disposeOnDeactivation( - vscode.workspace.registerTextDocumentContentProvider( - 'rust-analyzer', - syntaxTreeContentProvider, - ), - ); disposeOnDeactivation( vscode.workspace.registerTextDocumentContentProvider( 'rust-analyzer', @@ -89,21 +79,11 @@ export async function activate(context: vscode.ExtensionContext) { ), ); - registerCommand( - 'rust-analyzer.syntaxTree', - commands.syntaxTree.createHandle(syntaxTreeContentProvider), - ); registerCommand( 'rust-analyzer.expandMacro', commands.expandMacro.createHandle(expandMacroContentProvider), ); - vscode.workspace.onDidChangeTextDocument( - events.changeTextDocument.createHandler(syntaxTreeContentProvider), - null, - context.subscriptions, - ); - const startServer = () => Server.start(allNotifications); const reloadCommand = () => reloadServer(startServer); -- cgit v1.2.3