Link Search Menu Expand Document

=== commands

use

programmatically execute a command

links:

import * as vscode from "vscode";

function commentLine() {
  vscode.commands.executeCommand("editor.action.addCommentLine");
}
  • eg: pass argument and work with result
import * as vscode from "vscode";

async function printDefinitionsForActiveEditor() {
  const activeEditor = vscode.window.activeTextEditor;
  if (!activeEditor) {
    return;
  }

  const definitions = await vscode.commands.executeCommand<vscode.Location[]>(
    "vscode.executeDefinitionProvider",
    activeEditor.document.uri,
    activeEditor.selection.active
  );

  for (const definition of definitions) {
    console.log(definition);
  }
}

=== extensions

related

  • ExtensionContext
  • EnvironmentVariableCollection

=== languages

registerDefinitionProvider

link: https://code.visualstudio.com/api/references/vscode-api#languages.registerDefinitionProvider

  • params
    • selector: DocumentSelector
      • A selector that defines the documents this provider is applicable to.
    • provider: DefinitionProvider
      • A definition provider.

=== patterns

Dispose pattern

links:

  • https://en.wikipedia.org/wiki/Dispose_pattern
  • https://code.visualstudio.com/api/references/vscode-api#disposables

  • a resource is held by an object, and released by calling a method – usually called close, dispose, free, release

  • Many languages offer language constructs to avoid having to call the dispose method explicitly in common situations

  • motivation
    • Resources are typically represented by handles (abstract references)
      • used to communicate with an external system that provides the resource
      • eg: files are provided by the operating system (specifically the file system), which in many systems represents files with a file descriptor (an integer representing the file).
    • These handles can be used directly, by storing the value in a variable and passing it as an argument to functions that use the resource
    • frequently useful to abstract from the handle itself (for example, if different operating systems represent files differently), and to store additional auxiliary data with the handle, so handles can be stored as a field in a record, along with other data
      • eg: in C file input/output, files are represented by objects of the FILE type
        • which stores an (operating system) handle to the file (such as a file descriptor), together with auxiliary information like I/O mode (reading, writing) and position in the stream
        • These objects are created by calling fopen (in object-oriented terms, a factory), which acquires the resource and returns a pointer to it
        • the resource is released by calling fclose on a pointer to the FILE object[1]. In code
FILE *f = fopen(filename, mode);
// Do something with f.
fclose(f);

  • fundamental problem that the dispose pattern aims to solve is that resources are expensive (for example, there may be a limit on the number of open files), and thus should be released promptly
  • some finalization work is often needed, particularly for I/O, such as flushing buffers to ensure that all data is actually written.
  • If a resource is unlimited or effectively unlimited, and no explicit finalization is necessary, it is not important to release it, and in fact short-lived programs often do not explicitly release resources
  • Explicit disposal means that resource finalization and release is deterministic and prompt: the dispose method does not complete until these are done.
  • alternative to requiring explicit disposal is to tie resource management to object lifetime
  • This approach is known as the Resource Acquisition Is Initialization (RAII) idiom

issues

early exit

  • key problem with the dispose pattern is that if the dispose method is not called, the resource is leaked

  • A common cause of this is early exit from a function, due to an early return or exception.

  • to solve early exit, languages have constructs that auto-release

  • eg: python with statement

with resource_context_manager() as resource:
    # Perform actions with the resource.
    ...
# Perform other actions where the resource is guaranteed to be deallocated.
...

class invariance

  • A fundamental problem is that having a resource is no longer a class invariant (the resource is held from object creation until it is disposed, but the object is still live at this point), so the resource may not be available when the object tries to use it, for example trying to read from a closed file

  • all methods on the object that use the resource potentially fail, concretely usually by returning an error or raising an exception

  • A standard way to implement this is to add a boolean field to the object, called disposed, which is set to true by dispose, and checked by a guard clause to all methods (that use the resource), raising an exception (such as ObjectDisposedException in .NET) if the object has been disposed.[5]

  • Further, it is possible to call dispose on an object more than once

    • preferable for dispose to be idempotent
    • easily implemented by using the same boolean disposed field and checking it in a guard clause at the start of dispose

Events

  • Calls to subscribe return a Disposable which removes the event listener upon dispose
var listener = function (event) {
  console.log("It happened", event);
};

// start listening
var subscription = fsWatcher.onDidDelete(listener);

// do more stuff

subscription.dispose(); // stop listening
  • Names of events follow the on[Will|Did]VerbNoun? pattern
    • The name signals if the event is going to happen (onWill) or already happened (onDid), what happened (verb), and the context (noun) unless obvious from the context.
    • An example from the VS Code API is window.onDidChangeActiveTextEditor which is an event fired when the active text editor (noun) has been (onDid) changed (verb).

=== bucket

Welcome View Content API

— Others

events

onDidChange

release: 1.27

A new event extensions.onDidChange was added which fires when the extensions.all array changes. This can happen when extensions are installed, uninstalled, enabled, or disabled. See the No reload on extension install section.

/**
 * An event which fires when `extensions.all` changes. This can happen when extensions are
 * installed, uninstalled, enabled or disabled.
 */
export const onDidChange: Event<void>;

onStartupFinished

  • similar to the already existing * activation event. The new onStartupFinished activation event should be used when an extension wishes to be activated sometime soon after VS Code startup, but not as part of the startup.

=== Bucket

=== Utils

Terminal

updates

The Terminal object has a new creationOptions property that can be used by extensions to identify how the terminal was created.

vscode.Uri

file

File path casing

We have fixed a couple of bugs with how VS Code handles paths and URIs on case-insensitive file systems. Before this release, paths with different casing would not open the same document but separate, disconnected documents. That behavior often caused confusion and sometimes data loss.

However, in fixing these bugs, the behavior of the openTextDocument function has changed. The function can now return a document with a URI with different casing than the URI that was passed in. This means extensions should use TextDocument#uri as the source of truth, not the URI that they request it with.

The sample below illustrates the new behavior:

// case-insensitive file system

const uriA = vscode.Uri.file("/foo/bar.code");
const docA = await vscode.workspace.openTextDocument(uriA);

const uriB = vscode.Uri.file("/foo/BAR.code");
const docB = await vscode.workspace.openTextDocument(uriB);

assert.ok(docA === docB); // same document
assert.ok(docB.uri.toString() === uriA.toString()); // uriA is used, NOT uriB
assert.ok(docB.uri.toString() !== uriB.toString());

joinPath

We have added a vscode.Uri.joinPath utility. It is a factory function that creates new URIs by joining path segments with an existing URI. Think of this as Node.js’ path.join utility but for URIs.

  • NOTE: s/extensionUri/extensionPath
const fileUri = vscode.Uri.joinPath(context.extensionUri, "./file.png");
const bytes = await vscode.workspace.fs.readFile(fileUri);

vscode.env

vscode.env.openExternal

we have added a new API vscode.env.openExternal. It expects a URL and can be used to open website-links, mail-links, or application-url-handler. Also, file URLs are accepted to open them in their default app, like a PDF file.

// open default browser
await vscode.env.openExternal(
  vscode.Uri.parse("https://github.com/Microsoft/vscode/issues/66741")
);

filesystem

We have added FileSystemError#code, which is a string identifying the error. When a file system error is created through any of its factory functions, then code is the name of that function, for example FileSystemError.FileNotFound(msg).code === 'FileNotFound'.

icons

For most VS Code icons, the codicon icon-font is used. Extensions can now reuse those icons in simple and declarative ways:

  • The vscode.ThemeIcon type can now be instantiated with the name of a codicon. For example, new vscode.ThemeIcon("zap").
  • The vscode.MarkdownString type now supports the $(<name>) inline syntax. For example, myMdString.appendMarkdown('Hello $(globe)');. Note that to use codicons within MarkdownString, you must enable the supportThemeIcons constructor argument.
  • commands defined in an extension’s package.json file can now use a codicon for their icon. Use the inline syntax, for example "icon": "$(zap)".

All available codicons displayed in a hover


Table of contents


Copyright © 2020 Thence LLC