diff --git a/src/index.ts b/src/index.ts index b11d055..8ea4a7f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,5 +10,13 @@ export * from "./getJavaConfig"; export * from "./installJava"; export * from "./commands/restartServer"; + export * from "./interfaces/TreeViewProtocol"; export * from "./interfaces/MetalsInitializationOptions"; +export * from "./interfaces/ClientCommands"; +export * from "./interfaces/ServerCommands"; +export * from "./interfaces/MetalsSlowTask"; +export * from "./interfaces/Extensions"; +export * from "./interfaces/MetalsInputBox"; +export * from "./interfaces/MetalsQuickPick"; +export * from "./interfaces/MetalsStatus"; diff --git a/src/interfaces/ClientCommands.ts b/src/interfaces/ClientCommands.ts new file mode 100644 index 0000000..9ef854c --- /dev/null +++ b/src/interfaces/ClientCommands.ts @@ -0,0 +1,50 @@ +/** + * These are all of the client commands that Metals supports. Note that not support + * may vary based on the `InitializationSettings` the client sets. + * + * - https://scalameta.org/metals/docs/editors/new-editor.html#metals-client-commands + */ +export const ClientCommands = { + /** + * A client command that should be forwarded back to the Metals server. + * + * Metals may register commands in the client UIs like tree view node_modules + * that should be forwarded back to the Metals server if the client clicks + * on the UI elements. + */ + EchoCommand: "metals-echo-command", + /** Focus on the window that lists all published diagnostics. */ + FocusDiagnostics: "metals-diagnostics-focus", + /** + * Move the cursor focus to the provided location. + */ + GotoLocation: "metals-goto-location", + /** Open a specific folder either in the same or new window */ + OpenFolder: "metals-open-folder", + /** + * Notifies the client that the model has been updated and it + * should be refreshed (e.g. by resending code lens request) + */ + RefreshModel: "metals-model-refresh", + /** + * Reload the contents of an open Doctor window, if any. Should be ignored if + * there is no open doctor window. + */ + ReloadDoctor: "metals-doctor-reload", + /** Focus on a window displaying troubleshooting help from the Metals doctor. */ + RunDoctor: "metals-doctor-run", + /** + * Command to trigger a debug session with Metals. Triggered by a code lens + * in the editor. + */ + StartDebugSession: "metals-debug-session-start", + /** Command to run the codev via a code lens in the editor. */ + StartRunSession: "metals-run-session-start", + /** + * Focus or remove focus on the output logs reported by the server via + * `window/logMessage`. + */ + ToggleLogs: "metals-logs-toggle", +} as const; + +export type ClientCommands = typeof ClientCommands; diff --git a/src/interfaces/Extensions.ts b/src/interfaces/Extensions.ts new file mode 100644 index 0000000..2130d1b --- /dev/null +++ b/src/interfaces/Extensions.ts @@ -0,0 +1,68 @@ +import { + NotificationType, + ExecuteCommandParams, +} from "vscode-languageserver-protocol"; + +/** + * The Metals execute client command is sent from the server to the client to + * trigger an action inside the editor. This notification is a copy of the + * workspace/executeCommand except: + * + * - execute client command is a notification, not a request + * - execute client command is initiated from the server, not the client + * + * - https://scalameta.org/metals/docs/editors/new-editor.html#metalsexecuteclientcommand + * + * All client commands can be found in the ClientCommands enum. + */ +export namespace ExecuteClientCommand { + export const type = new NotificationType( + "metals/executeClientCommand" + ); +} + +/** + * The Metals did focus notification is sent from the client to the server when the editor changes focus to a new text document. Unlike textDocument/didOpen, the did focus notification is sent even when the text document is already open. + * + * - https://scalameta.org/metals/docs/editors/new-editor.html#metalsdidfocustextdocument + */ +export namespace MetalsDidFocus { + export const type = new NotificationType( + "metals/didFocusTextDocument" + ); +} + +/** + * The `metals/windowStateDidChange` notification is sent from the client to + * the server to indicate whether the editor application window is focused or + * not. When the editor window is not focused, Metals tries to avoid triggering + * expensive computation in the background such as compilation. + * + * - https://scalameta.org/metals/docs/editors/new-editor.html#metalswindowstatedidchange + */ +export namespace MetalsWindowStateDidChange { + export const type = new NotificationType< + MetalsWindowStateDidChangeParams, + void + >("metals/windowStateDidChange"); +} + +export interface MetalsWindowStateDidChangeParams { + /** If true, the editor application window is focused. False, otherwise. */ + focused: boolean; +} + +/** + * The `metals/openWindow` params are used with the New Scala Project + * functionality. After the new project has been created, if the editor has the + * ability to open the project in a new window then these params are used with the + * the `metals-open-folder` command. + * + * - https://scalameta.org/metals/docs/editors/new-editor.html#metalsopenwindow + */ +export interface MetalsOpenWindowParams { + /** Location of the newly created project. */ + uri: string; + /** Whether or not to open the project in a new window. */ + openNewWindow: boolean; +} diff --git a/src/interfaces/MetalsInputBox.ts b/src/interfaces/MetalsInputBox.ts new file mode 100644 index 0000000..49b36ed --- /dev/null +++ b/src/interfaces/MetalsInputBox.ts @@ -0,0 +1,83 @@ +import { RequestType } from "vscode-languageserver-protocol"; + +/** + * The Metals input box request is sent from the server to the client to + * let the user provide a string value for a given prompt. Unlike + * `window/showMessageRequest`, the `metals/inputBox` request allows the user + * to provide a custom response instead of picking a pre-selected value. + * + * - https://scalameta.org/metals/docs/editors/new-editor.html#metalsinputbox + */ +export namespace MetalsInputBox { + export const type = new RequestType< + InputBoxOptions, + MetalsInputBoxResult, + void, + void + >("metals/inputBox"); + + export const handleInput = function ( + result: string | undefined + ): MetalsInputBoxResult { + if (result === undefined || result.trim() === "") { + return { cancelled: true }; + } else { + return { value: result }; + } + }; +} + +export interface MetalsInputBoxResult { + value?: string; + cancelled?: boolean; +} + +/** + * The below is ported directly from VS Code: + * + * - https://code.visualstudio.com/api/references/vscode-api#InputBoxOptions + * + * This is managed in here since the Metals API for Input Boxes matches this + * exactly meaning that we rely on it both in the VS Code extension and also + * coc-metals. If the API changes, we'll have to chage it in Metals and in here. + */ +export interface InputBoxOptions { + /** * The value to prefill in the input box. */ + value?: string; + /** * Selection of the prefilled [`value`](#InputBoxOptions.value). Defined as tuple of two number where the * first is the inclusive start index and the second the exclusive end index. When `undefined` the whole * word will be selected, when empty (start equals end) only the cursor will be set, * otherwise the defined range will be selected. */ valueSelection?: [ + number, + number + ]; + + /** + * The text to display underneath the input box. + */ + prompt?: string; + + /** + * An optional string to show as place holder in the input box to guide the user what to type. + */ + placeHolder?: string; + + /** + * Set to `true` to show a password prompt that will not show the typed value. + */ + password?: boolean; + + /** + * Set to `true` to keep the input box open when focus moves to another part of the editor or to another window. + */ + ignoreFocusOut?: boolean; + + /** + * An optional function that will be called to validate input and to give a hint + * to the user. + * + * @param value The current value of the input box. + * @return A human readable string which is presented as diagnostic message. + * Return `undefined`, `null`, or the empty string when 'value' is valid. + */ + validateInput?( + value: string + ): string | undefined | null | Thenable; +} diff --git a/src/interfaces/MetalsQuickPick.ts b/src/interfaces/MetalsQuickPick.ts new file mode 100644 index 0000000..d1cf48c --- /dev/null +++ b/src/interfaces/MetalsQuickPick.ts @@ -0,0 +1,55 @@ +import { RequestType } from "vscode-languageserver-protocol"; +/** + * The Metals quick pick request is sent from the server to the client to let + * the user provide a string value by picking one out of a number of given + * options. It is similar to `window/showMessageRequest`, but the + * `metals/quickPick` request has richer parameters, that can be used to + * filter items to pick, like description and detail. + * + * - https://scalameta.org/metals/docs/editors/new-editor.html#metalsquickpick + */ +export namespace MetalsQuickPick { + export const type = new RequestType< + MetalsQuickPickParams, + MetalsQuickPickResult, + void, + void + >("metals/quickPick"); +} + +export interface MetalsQuickPickParams { + /** An array of items that can be selected from. */ + items: MetalsQuickPickItem[]; + /** An optional flag to include the description when filtering the picks. */ + matchOnDescription?: boolean; + /** An optional flag to include the detail when filtering the picks. */ + matchOnDetail?: boolean; + /** + * An optional string to show as place holder in the input box to guide the + * user what to pick on. + */ + placeHolder?: string; + /** + * Set to `true` to keep the picker open when focus moves to another part of + * the editor or to another window. + */ + ignoreFocusOut?: boolean; +} + +export interface MetalsQuickPickResult { + itemId?: string; + cancelled?: boolean; +} + +export interface MetalsQuickPickItem { + /** An id for this items that should be return as a result of the picking. */ + id: string; + /** A human readable string which is rendered prominent. */ + label: string; + /** A human readable string which is rendered less prominent. */ + description?: string; + /** A human readable string which is rendered less prominent. */ + detail?: string; + /** Always show this item. */ + alwaysShow?: boolean; +} diff --git a/src/interfaces/MetalsSlowTask.ts b/src/interfaces/MetalsSlowTask.ts new file mode 100644 index 0000000..cbbc864 --- /dev/null +++ b/src/interfaces/MetalsSlowTask.ts @@ -0,0 +1,40 @@ +import { RequestType } from "vscode-languageserver-protocol"; + +/** + * The Metals slow task request is sent from the server to the client to notify + * the start of a long running process with unknown estimated total time. + * A cancel: true response from the client cancels the task. A $/cancelRequest + * request from the server indicates that the task has completed. + * + * - https://scalameta.org/metals/docs/editors/new-editor.html#metalsslowtask + */ +export namespace MetalsSlowTask { + export const type = new RequestType< + MetalsSlowTaskParams, + MetalsSlowTaskResult, + void, + void + >("metals/slowTask"); +} + +export interface MetalsSlowTaskParams { + /** The name of this slow task */ + message: string; + /** + * If true, the log output from this task does not need to be displayed to the user. + * + * In VS Code, the Metals "Output channel" is not toggled when this flag is true. + */ + quietLogs?: boolean; + /** Time that has elapsed since the begging of the task. */ + secondsElapsed?: number; +} + +export interface MetalsSlowTaskResult { + /** + * If true, cancel the running task. + * If false, the user dismissed the dialogue but want to + * continue running the task. + */ + cancel: boolean; +} diff --git a/src/interfaces/MetalsStatus.ts b/src/interfaces/MetalsStatus.ts new file mode 100644 index 0000000..5f43f89 --- /dev/null +++ b/src/interfaces/MetalsStatus.ts @@ -0,0 +1,29 @@ +import { NotificationType } from "vscode-languageserver-protocol"; + +/** + * The Metals status notification is sent from the server to the client to + * notify about non-critical and non-actionable events that are happening in + * the server. Metals status notifications are a complement to + * `window/showMessage` and `window/logMessage`. Unlike `window/logMessage`, + * status notifications should always be visible in the user interface. + * Unlike `window/showMessage`, status notifications are not critical meaning + * that they should not demand too much attention from the user. + */ +export namespace MetalsStatus { + export const type = new NotificationType( + "metals/status" + ); +} + +export interface MetalsStatusParams { + /** The text to display in the status bar. */ + text: string; + /** If true, show the status bar. */ + show?: boolean; + /** If true, hide the status bar. */ + hide?: boolean; + /** If set, display this message when user hovers over the status bar. */ + tooltip?: string; + /** If set, execute this command when the user clicks on the status bar item. */ + command?: string; +} diff --git a/src/interfaces/ServerCommands.ts b/src/interfaces/ServerCommands.ts new file mode 100644 index 0000000..72b9b71 --- /dev/null +++ b/src/interfaces/ServerCommands.ts @@ -0,0 +1,73 @@ +/** + * These are all of the server commands that Metals supports. Note that not support + * may vary based on the `InitializationSettings` the client sets. + * + * - https://scalameta.org/metals/docs/editors/new-editor.html#metals-server-commands + */ +export const ServerCommands = { + /** Start the Ammonite build server. */ + AmmoniteStart: "ammonite-start", + /** Stop the Ammonite build server. */ + AmmoniteStop: "ammonite-stop", + /** + * Prompt the user to select a new build server to connect to. + * + * This command does nothing in the case there are less than two installed + * build servers on the computer. + */ + BspSwitch: "bsp-switch", + /** Establish a new connection to the build server and reindex the workspace. */ + BuildConnect: "build-connect", + /** Import the latest changes from the build. */ + BuildImport: "build-import", + /** + * Unconditionally stop the current running Bloop server and start a new + * one using Bloop launcher. + */ + BuildRestart: "build-restart", + /** Cancel the current ongoing compilation, if any. */ + CancelCompilation: "compile-cancel", + /** + * Compile the current open files along with all build targets in this + * workspace that depend on those files. + * + * By default, Metals compiles only the current build target and its + * dependencies when saving a file. Run the cascade compile task to + * additionally compile the inverse dependencies of the current build target. + * For example, if you change the API in main sources and run cascade compile + * then it will also compile the test sources that depend on main. + */ + CascadeCompile: "compile-cascade", + /** Recompile all build targets in this workspace. */ + CleanCompile: "compile-clean", + /** Start debug adapter. */ + DebugAdapterStart: "debug-adapter-start", + /** Open the Metals doctor to troubleshoot potential problems with the build. */ + DoctorRun: "doctor-run", + /** Move the cursor to the definition of the argument symbol. */ + Goto: "goto", + /** Jumps to the super method/field definition of a symbol. */ + GotoSuperMethod: "goto-super-method", + /** + * Create and open a new Scala class, object, trait, package object, or + * worksheet. + */ + NewScalaFile: "new-scala-file", + /** Creaet a new Scala project using one of the available g8 templates. */ + NewScalaProject: "new-scala-project", + /** Reset a decision you made about a specific setting. */ + ResetChoice: "reset-choice", + /** Walk all the files in the workspace and index where symbols are defined. */ + SourcesScan: "sources-scan", + /** + * When user executes this command it will calculate inheritance hierarchy of + * a class that contains given method. Then it will filter out classes not + * overriding given method and a list using 'metalsQuickPick' will be + * displayed to which super method user would like to go to. Command has no + * effect on other symbols than method definition. QuickPick will show up + * only if more than one result is found. + */ + SuperMethodHierarchy: "super-method-hierarchy", +} as const; + +type ServerCommands = typeof ServerCommands;