Source Code Organization (original) (raw)

Visual Studio Code consists of a layered and modular core (found as src/vs) that can be extended using extensions. Extensions are run in a separate process referred to as theextension host. Extensions are implemented by utilising the extension API. Built-in extensions can be found in the extensions folder.

Layers

The core is partitioned into the following layers:

Target Environments

The core of VS Code is fully implemented in TypeScript. Inside each layer the code is organised by the target runtime environment. This ensures that only the runtime specific APIs are used. In the code we distinguish between the following target environments:

Dependency Injection

Consuming a service

The code is organised around services of which most are defined in the platform layer. Services get to its clients via constructor injection.

A service definition is two parts: (1) the interface of a service, and (2) a service identifier - the latter is required because TypeScript doesn't use nominal but structural typing. A service identifier is a decoration (as proposed for ES7) and should have the same name as the service interface.

Declaring a service dependency happens by adding a corresponding decoration to a constructor argument. In the snippet below @IModelService is the service identifier decoration and IModelService is the (optional) type annotation for this argument.

class Client { constructor( @IModelService modelService: IModelService ) { // use services } }

Use the instantiation service to create instances for service consumers, like so instantiationService.createInstance(Client). Usually, this is done for you when being registered as a contribution, like a Viewlet or Language.

Providing a service

The best way to provide a service to others or to your own components is the registerSingleton-function. It takes a service identifier and a service constructor function.

registerSingleton( ISymbolNavigationService, // identifier SymbolNavigationService, // ctor of an implementation InstantiationType.Delayed // delay instantiation of this service until is actually needed );

Add this call into a module-scope so that it is executed during startup. The workbench will then know this service and be able to pass it onto consumers.

VS Code Editor source organisation

VS Code Workbench source organisation

The VS Code workbench (vs/workbench) is composed of many things to provide a rich development experience. Examples include full text search, integrated git and debug. At its core, the workbench does not have direct dependencies to all these contributions. Instead, we use an internal (as opposed to real extension API) mechanism to contribute these contributions to the workbench.

In a nutshell, folders are organised as:

Contributions that are contributed to the workbench all live inside the vs/workbench/contrib folder. There are some rules around the vs/workbench/contrib folder:

VS Code for Desktop / VS Code for Web

We ship both to desktop via Electron and to the Web with the goal to share as much code as possible in both environments. Writing code that only runs in the one environment should be the exception, think twice before going down that path. Ideally the same code can run in both environments.

To distinguish the environments in the product we build, there are entry files that define all the dependencies depending on the environment:

Both depend on our core entry file:

Here are some rules that apply:

Be careful when introducing a service only for the desktop and not for the web: code that runs in the web that requires the service will fail to execute if you do not provide a related service for web. It is fine to ship two different implementations of a service when you use different strategies depending on the environment.

Note: Only code that is referenced from the main entry files is loaded into the product. If you have a file that is otherwise not referenced in your code, make sure to add the import to your .contribution.ts file.