diff --git a/package.json b/package.json index b80cb450..855629d6 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,11 @@ "command": "rubyLsp.showSyntaxTree", "title": "Show syntax tree", "category": "Ruby LSP" + }, + { + "command": "rubyLsp.openFile", + "title": "Opens a local file at a given position", + "category": "Ruby LSP" } ], "configuration": { diff --git a/src/common.ts b/src/common.ts index eb968cb8..73074fe0 100644 --- a/src/common.ts +++ b/src/common.ts @@ -21,6 +21,7 @@ export enum Command { DebugTest = "rubyLsp.debugTest", OpenLink = "rubyLsp.openLink", ShowSyntaxTree = "rubyLsp.showSyntaxTree", + OpenFile = "rubyLsp.openFile", } export interface RubyInterface { diff --git a/src/fileController.ts b/src/fileController.ts new file mode 100644 index 00000000..c05aa185 --- /dev/null +++ b/src/fileController.ts @@ -0,0 +1,37 @@ +import * as vscode from "vscode"; + +import { Telemetry } from "./telemetry"; +import { Workspace } from "./workspace"; + +export class FileController { + private readonly telemetry: Telemetry; + private readonly currentWorkspace: () => Workspace | undefined; + + constructor( + _context: vscode.ExtensionContext, + telemetry: Telemetry, + currentWorkspace: () => Workspace | undefined, + ) { + this.telemetry = telemetry; + this.currentWorkspace = currentWorkspace; + } + + async openFile(sourceLocation: [string, string]) { + const workspace = this.currentWorkspace(); + const file = sourceLocation[0]; + const line = parseInt(sourceLocation[1], 10) - 1; + + const uri = vscode.Uri.parse(`file://${file}`); + const doc = await vscode.workspace.openTextDocument(uri); + await vscode.window.showTextDocument(doc, { + selection: new vscode.Range(line, 0, line, 0), + }); + + if (workspace?.lspClient?.serverVersion) { + await this.telemetry.sendCodeLensEvent( + "open_file", + workspace.lspClient.serverVersion, + ); + } + } +} diff --git a/src/rubyLsp.ts b/src/rubyLsp.ts index 48fca8d3..57dddb9e 100644 --- a/src/rubyLsp.ts +++ b/src/rubyLsp.ts @@ -10,6 +10,7 @@ import { Command, STATUS_EMITTER, pathExists } from "./common"; import { VersionManager } from "./ruby"; import { StatusItems } from "./status"; import { TestController } from "./testController"; +import { FileController } from "./fileController"; import { Debugger } from "./debugger"; // The RubyLsp class represents an instance of the entire extension. This should only be instantiated once at the @@ -21,6 +22,7 @@ export class RubyLsp { private readonly context: vscode.ExtensionContext; private readonly statusItems: StatusItems; private readonly testController: TestController; + private readonly fileController: FileController; private readonly debug: Debugger; constructor(context: vscode.ExtensionContext) { @@ -31,6 +33,11 @@ export class RubyLsp { this.telemetry, this.currentActiveWorkspace.bind(this), ); + this.fileController = new FileController( + context, + this.telemetry, + this.currentActiveWorkspace.bind(this), + ); this.debug = new Debugger(context, this.workspaceResolver.bind(this)); this.registerCommands(context); @@ -328,6 +335,10 @@ export class RubyLsp { Command.DebugTest, this.testController.debugTest.bind(this.testController), ), + vscode.commands.registerCommand( + Command.OpenFile, + this.fileController.openFile.bind(this.fileController), + ), ); } diff --git a/src/telemetry.ts b/src/telemetry.ts index ffa9f58f..b1dd36c6 100644 --- a/src/telemetry.ts +++ b/src/telemetry.ts @@ -20,7 +20,7 @@ export interface ConfigurationEvent { } export interface CodeLensEvent { - type: "test" | "debug" | "test_in_terminal" | "link"; + type: "test" | "debug" | "test_in_terminal" | "link" | "open_file"; lspVersion: string; }