microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
163.18k stars 28.84k forks source link

Make API commands simpler to consume #110459

Open jrieken opened 3 years ago

jrieken commented 3 years ago

Today, in vsocde.d.ts we define a generic command (which is actually a command and minimal UI) and a way to execute any command. Namely these two symbols

In the name of arbitrary commands this API is kept very generic. However, some commands are known, we call them API commands and they are currently only documented, see https://code.visualstudio.com/api/references/commands, offering no tooling.

So, in addition the generic approach we could invest in some TypeScript gymnastics that bring some specific overloads, so executeCommand something like this would work:

export interface ApiCommandMap {
  'vscode.open': (resource: Uri, options?: OpenOptions, label?: string) => Promise<boolean>;
  'vscode.diff': (left: Uri, right: Uri, options?: OpenOptions, label?: string) => Promise<boolean>;
}

export namespace commands {

  export function executeCommand<K extends keyof ApiCommandMap, T>(command: K, ...args: Parameters<ApiCommandMap[K]>): Promise<ReturnType<ApiCommandMap[K]>>;
  export function executeCommand<T>(command: string, ...rest: any[]): Promise<T | undefined>;
}

However, I still struggle to find a nice way to reuse the ApiCommandMap to create specific overloads for the Command type. I have something like this in mind:

export interface Command2<K extends keyof ApiCommandMap> {
  title: string;
  command: K;
  tooltip?: string;
  arguments: Parameters<ApiCommandMap[K]>;
}

The bottom line is that I want to make sure that a Command uses the right arguments when using a certain command identifier.

roblourens commented 3 years ago

Would be really cool to have a way to bridge the gap with the package.json and check the type signatures of commands that are registered for certain things (example https://github.com/microsoft/vscode/pull/109049). Like maybe with a TS server plugin.