Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to look at the Technical Architecture of large-scale IDE from VSCode

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "how to look at large-scale IDE technical architecture from VSCode". In daily operation, I believe many people have doubts about how to see large-scale IDE technical architecture from VSCode. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the doubts of "how to see large-scale IDE technical architecture from VSCode". Next, please follow the editor to study!

What is the official definition of VSCode

Https://code.visualstudio.com/

Key words:

Code editing (tool properties)

Cross-platform operation, open source

Core functions:

IntelliSense (Code hint), debugging (Code debugging), and git (Code Management) are all core links around code editing.

Extensions (plug-in) shoulders the responsibility of creating an open ecology.

Comments:

For tools, you need to be able to figure out the boundaries. What you should focus on and which can be spilled over to third-party extensions to satisfy.

The course of development

Released in 2015-04 (4 years ago)

2015-11 (half a year after release) open source

Release VSCode Remote Development in 2019-05

Team leader: Erich Gamma. One of the authors of JUnit, one of the authors of Design patterns, the architect of Eclipse. 2011 joined Microsoft and formed a team in Zurich, Switzerland to develop an editor based on web technology, later known as monaco-editor. The VSCode development team starts with about 10 individuals, and most of the early members have a background of the Eclipse development team.

What are the engineering highlights of Visual Studio Code what is the experience of maintaining a large open source project? "Shape Up" is a way of working for small and medium-sized teams.

Erich Gamma gave a speech on the theme "The journey of visual studio code: Building an App Using JS/TypeScript, Node, Electron & 2016 OSS Components" at GOTO 2016, detailing the development of the project:

Those who don't have time to watch the video can download the full PDF.

On the first page of PPT, Erich Gamma intercepts emails describing the job content he received after joining Microsoft:

"explore a new online development tool model that is as successful as desktop IDE."

The whole team starts with about 10 people, mixing the old, middle and new generations of programmers of different levels. It is not easy to have such a grand vision in Microsoft, a giant commercial company. At the beginning, the team set the idea of working like start up, asking for ship every month.

At the same time, he also proposed that in the early days, he would frantically look for landing scenarios within the company, such as Visual Studio Online's online Code DIff page, TypeScript's official website Playground editor, OneDrive code files, Edge Dev Tool code browsing, and so on.

An important turning point is the great changes that have taken place at Microsoft itself:

With the whole open source cross-platform trend of Microsoft, Erich Gamma keenly decided to move the product from Browser Based IDE to cross-platform Desktop IDE, but still used Web technology, so electron appeared on the scene, VSCode open source these things happened one after another, and the VSCode team spent six months using Electron to desktop the Web editor and another six months to plug in the entire IDE.

Product positioning

Erich Gamma has a share of VSCode on 2017 SpringOne Platform, explaining many ideas and decisions for top-level design of VSCode based on his past experience in developing Eclipse, including product positioning for VSCode:

You can see from the figure that the VSCode positioning is halfway between the editor and the IDE and is biased towards the lightweight editor side.

The core of VSCode is "editor + code understanding + debugging", which revolves around this critical path, everything else is very restrained, and the product remains lightweight and high performance.

Comments:

Productivity tools software must stick to the main line, otherwise it is likely to become an amusement park without tickets. There must be a strong team behind the powerful products. For example, Microsoft dug up Anders Hejlsberg, created C# and TypeScript one after another, dug up Erich Gamma, and successively gave birth to pearls such as monaco and vscode.

What is Electron?

As mentioned above, one feature of VSCode is cross-platform, and its cross-platform nature is implemented through electron. So we need to have a brief understanding of electron first.

Official definition

Core technology

Use Web technology to write UI and run it with chrome browser kernel

Use NodeJS to manipulate the file system and initiate network requests

Use NodeJS C++ Addon to call the native API of the operating system

Application architecture

Https://electronjs.org/docs/tutorial/application-architecture

1 main process: an Electron App starts only one main process, which runs the script specified in the main field of the package.json

N rendering processes: the main process code can call Chromium API to create any number of web pages, while Chromium itself is a multi-process architecture, and each web page runs in its own rendering process.

Interprocess communication:

Communication between Render processes is essentially the same as communication between multiple Web pages, and various browser capabilities such as localStorage can be used.

Render processes and Main processes can also communicate with each other through API (ipcRenderer/ipcMain)

Comments:

Ordinary web pages cannot call native api, so the Render process in which the web page of electron is located can forward tasks to the Main process running in NodeJS environment, thus implementing native API. This architecture greatly expands the capability richness of electron app compared with web app, but at the same time retains the fast and smooth development experience of web, coupled with the cross-platform advantages of web itself, make electron a very cost-effective solution.

Third, VSCode technology architecture, multi-process architecture

Main process: the entry process of VSCode, which is responsible for some global tasks such as window management, inter-process communication, automatic update, etc.

Rendering process: responsible for rendering a Web page

Plug-in hosting process: the code of each plug-in runs in a host process that belongs to its own NodeJS environment, and plug-ins are not allowed to access UI

Debug process: Debugger is specialized compared to normal plug-ins

Search process: search is a kind of computing-intensive task. A single process ensures the overall experience and performance of the software.

# check out code git clone git@github.com:microsoft/vscode.gitcd vscode# installation depends on yarn# launch web version yarn watch & & yarn web# launch desktop version yarn watch & &. / scripts/code.sh# package yarn run gulp vscode- [platform] yarn run gulp vscode- [platform]-min# platforms: win32-ia32 | win32-x64 | darwin | linux-ia32 | linux-x64 | linux-arm source code organization

Https://github.com/microsoft/vscode/wiki/Source-Code-Organization

Here are some top-level key folders for the entire VSCode project, which will focus on src and extensions later:

├── build # build script ├── extensions # built-in plug-in ├── scripts # tool script ├── out # Product Directory ├── src # Source Code Directory ├── test # Test Code

The code architecture of VSCode also changes with the evolution of the product:

The following article will share some highlights and features of the entire VScode source organization:

1. Isolation of kernel (src) and plug-in (extensions), kernel layering and modularization

/ src/vs: hierarchical and modular core

/ src/vs/base: common public methods and public view components

/ src/vs/code: main entry of VSCode application

/ src/vs/platform: various pure services that can be injected by dependency

/ src/vs/editor: text editor

/ src/vs/workbench: overall view framework

/ src/typings: common foundation type

/ extensions: built-in plug-in

two。 Each floor is isolated by environment.

Each layer of code in the kernel complies with the electron specification and subdivides folders by environment:

Common: a public js method that can be run anywhere

Browser: only use the code of the browser API, you can call common

Node: use only NodeJS API code, you can call common

Electron-browser: code that uses the electron rendering thread and browser API to call common,browser,node

Electron-main: using electron main thread and NodeJS API code, you can call common, node

Test: test code

Comments:

Similar problems have been encountered in the actual development. As a low code + visual R & D platform, many functional modules need to be implemented across the edited state and the running state. If the code is not restricted and differentiated, it can easily lead to incorrect dependencies and unexpected bug, so it is finally decided to adopt a similar isolation architecture (editor/runtime/common).

3. The kernel code itself uses an extension mechanism: Contrib

You can see that there are a lot of small functional units of VSCode in the / src/vs/workbench/contrib directory:

├── backup ├── callHierarchy ├── cli ├── codeActions ├── codeEditor ├── comments ├── configExporter ├── customEditor ├── debug ├── emmet ├──.... Numerous omissions in the middle.... ├── watermark ├── webview └── welcome

Contrib has some features:

All code in the Contrib directory is not allowed to rely on any files outside this folder

Contrib mainly uses some extension points exposed by Core to do things.

If each Contrib is to be exposed, export API to eg: contrib/search/common/search.ts in an export file

If a Contrib is to be called with another Contrib, it is not allowed to use files other than export API files.

To follow up, even if Contrib can call the exit API of another Contrib, you should consider carefully and try to avoid the interdependence of the two Contrib.

I guess the purpose of the VSCode development team to do this design is that there are too many function points for heavy tool software. If the functional code is aggregated and bottled directly by the original module reference, it is a top-down architecture and a greater challenge to maintainability.

By exposing the extension point, the dependency relationship can be reversed, attached to the extension point protocol, the core functions and non-core functions can be separated, and the code implementations of independent small functions can be aggregated separately to reduce information density and improve maintainability.

However, the specific business code organization of VSCode Contrib does not seem to have many paradigms, and the extension mechanism of the kernel code, Contrib, is different from the plug-in mechanism extension, which VSCode is open to the outside world, which makes it a headache to read.

Through the communication with my classmate wood farmer developed by CloudIDE, I got two main differences:

Each extension runs in its own independent host process, while the function of contrib is basically run in the main process.

Extension can only live on core's open extension points, but contrib can get all class implemented within core through dependency injection (although not officially recommended)

4. Dependency injection

The previous section mentioned that VSCode code makes extensive use of dependency injection. This article will not elaborate on the details of the implementation of this technology. If you are interested, you can read some good implementations:

Power-di written by a classmate of the team Yangyuan

Powerful http://inversify.io for open source in the community

The common implementation principle of TS dependency injection is to use reflect-metadata to set and obtain meta-information, so that you can get the meta-information of TypeScript type that originally belongs to the edited state at runtime, specifically, the following API:

Reflect.getMetadata ("design:type", target, key): get class attribute type meta information

Reflect.getMetadata ("design:paramtypes", target, key): get the meta-information of class method parameters

Reflect.getMetadata ("design:returntype", target, key): gets the meta-information returned by the class method

Reflect.defineMetadata (metadataKey, metadataValue, target, propertyKey): setting meta-information

Reflect.getMetadata (metadataKey, target, propertyKey): get meta information

However, specific to VSCode dependency injection, it does not use reflect-metadata, but uses decorator to label meta-information, and implements its own dependency injection method. For more information, please refer to the article vscode source code parsing-dependency injection, which roughly includes the following types of roles:

Service: the implementation logic of services

Interface: interface description of the service

Client: service user

Manger: service Manager

For example, a large number of service are defined in / src/core/platform, and consumer Client can be used in other places by dependency injection. The pseudo code is as follows:

Class Client {/ / Constructor parameter injection (one of the dependency injection methods) constructor (/ / required @ IModelService modelService: IModelService, / / optional @ optional (IEditorService) editorService: IEditorService) {/ / use services}} / / instantiate instantiationService.createInstance (Client); 5. Absolute path import

Comments: absolute path import is a skill worth learning, the specific way is to configure TypeScript compilerOptions.paths

The relative path import has a high burden on the reader's brain. It relies on the current file location context information to understand the refactoring code when moving the file location. The relative path needs to modify all the import of this file, but the absolute path does not need to.

6. Command system

Both VSCode and monaco-editor have their own command systems, and students of the Ant CloudIDE team have also summarized the advantages of command systems:

The traditional module call is a mesh, so it is not easy to find an aspect to understand or govern:

On the other hand, the command system is centralized, and the end of each function becomes a flat structure:

7. TypeScript

Start the process (TLDR)

The above preliminary understanding of the technical architecture and source code organization of vscode, itchy students may be a little can not wait to try to go through the startup process of vscode.

Then before the official departure, I need to give you a little friendly reminder, if you do not have the patience to read the following VSCode start-up process, you should know that life is muddling along (╥ muddle ╥) o

Overall, VSCode startup code really show shows us how complex client software code will be engineered, which is mixed with a large number of TypeScript-based OOP-style code organization, a variety of boundaries, hosting environment, context processing, the original simple start APP rendering a page process becomes extremely complex.

Let's take a look at the following files and methods for streamlining the core startup link:

Entry: package.json {"main": ". / out/main"}: the standard startup entry for electron

/ out/main.js': is the entry file of the build product, which corresponds to the source code / src/main.js'

/ / src/main.js 's reduced core link const {app, protocol} = require ('electron'); app.once (' ready', function () {/ / electron is started, call vscode's entry onReady ();}); async function onReady () {/ / get the cache file directory address and language configuration, and launch const [cachedDataDir, nlsConfig] = await Promise.all ([nodeCachedDataDir.ensureExists (), resolveNlsConfiguration ()]) Startup (cachedDataDir, nlsConfig);} function startup (cachedDataDir, nlsConfig) {/ / load vscode's own open source AMD Loader https://github.com/Microsoft/vscode-loader/ then use this loader to load VSCode's main entry file require ('. / bootstrap-amd'). Load ('vs/code/electron-main/main') } / / src/vs/code/electron-main/main.ts streamlined core link / / initialize the main class const code = new CodeMain (); / / execute the main entry function code.main (); the class public entry of class CodeMain {main () {/ / vscode is generally an empty shell, which is really in the private logic this.startUp () } private async startup () {/ / first create dependent initialization service const [instantiationService, instanceEnvironment] = this.createServices (); / / create an editor instance and call the startUp method return instantiationService.createInstance (CodeApplication). Startup ();}} / src/vs/code/electron-main/app.tsexport class CodeApplication extends Disposable {async startup (): Promise {/ / IPCServer const electronIpcServer = new ElectronIPCServer () / / SharedProcess const sharedProcess = this.instantiationService.createInstance (SharedProcess, machineId, this.userEnv); / / create a bunch of dependent service / / IUpdateService IWindowsMainService IDialogMainService IMenubarService IStorageMainService. Const appInstantiationService = await this.createServices (machineId, trueMachineId, sharedProcess, sharedProcessClient); / / Open a window const windows = appInstantiationService.invokeFunction (accessor = > this.openFirstWindow (accessor, electronIpcServer, sharedProcessClient);} private openFirstWindow () {const windowsMainService = this.windowsMainService = accessor.get (IWindowsMainService); return windowsMainService.open () }} / src/vs/platform/windows/electron-main/windowsMainService.tsexport class WindowsMainService extends Disposable implements IWindowsMainService {open () {/ / execute open this.doOpen ();} private doOpen () {/ / Open browser window this.openInBrowserWindow () } private openInBrowserWindow () {/ / create window const createdWindow = window = this.instantiationService.createInstance (CodeWindow, {state, extensionDevelopmentPath: configuration.extensionDevelopmentPath, isExtensionTestHost:!! configuration.extensionTestsPath});} private doOpenInBrowserWindow () {/ / load page window.load (configuration) }} / / src/vs/code/electron-main/window.tsexport class CodeWindow extends Disposable implements ICodeWindow {load () {/ / call api of electron to load a url html page this._win.loadURL (this.getUrl (configuration));} private getUrl () {/ / get url let configUrl = this.doGetUrl (config) to open; return configUrl } private doGetUrl (config: object): string {/ / finally sees html! Tearful face "▽" / / Open the VSCode workbench, that is, workbench return `$ {require.toUrl ('vs/code/electron-browser/workbench/workbench.html')}? config=$ {encodeURIComponent (JSON.stringify (config))} `;}} Code Editor Technology

Because the focus of this article is not on the real code editor technology but on the engineering of large-scale software, this article will only briefly introduce some core technologies related to code editing:

Monaco-editor text editor, a very deep field, without talking, you can look at some interesting details:

Text Buffer performance optimization

MVVM architecture

Language server protocol language hint is also a major initiative of vscode:

Instead of focusing on AST and Parser, focus on Document and Position, thus achieving language independence.

The language prompt is transformed into a CS architecture, and the core is abstracted into a simple model of what response the server needs when clicking on the position of the line and column of the document. Based on the JSON RPC protocol, each language can implement a general back-end based on the protocol.

Debug Adaptor Prototal: debugging protocol

Comments:

Monaco-editor can see the domain accumulation of experts, and the design of language server protocol and Debug Adaptor Prototal, which belongs to the core competitiveness of VSCode, belongs to a strategically advantageous position, we can see the level of thinking, make our own things into standards, make ecology, and open up and win-win.

Fourth, the concept difference of VSCode plug-in system.

Compare several major IDE:

Visual Studio / IntelliJ: no plug-ins required, all in one (not open enough)

Eclipse: everything is plug-in (bloated, slow, unstable, poor experience)

VSCode: the golden mean

Strong isolation of VSCode plug-ins

Stand-alone process: VSCode plugin code runs in a separate Extension Host host process of its own

Logic and view isolation: plug-ins do not have access to DOM or operate UI at all, and plug-ins can only respond to extension points exposed by VSCode Core

View scalability is very weak: VSCode has very stable interaction and visual design, and the component slot on the UI provided to the plug-in is very small and stable

Can only be extended with limited components: VSCode has a very strong limitation on the ability to extend views. The UI in the hole cannot be drawn at will, and can only use some officially provided built-in components, such as TreeView.

What are the scalability capabilities of vscode? Https://code.visualstudio.com/api/extension-capabilities/overview

Comments:

The restraint of view extension brings a unified visual and interactive style, brings a good user experience, facilitates the establishment of a stable independent process of user mental plug-ins, is isolated from the view, and ensures the quality, performance and security of the overall software.

Workbench view structure

Https://code.visualstudio.com/docs/getstarted/userinterface

Title block: Title Bar

Activity bar: Activity Bar

Sidebar: Side Bar

Panel: Panal

Editor: Editor

Status bar: Status Bar

What is extensible in this view structure? For more information, see extending workbench:

Plug-in API injection

Plug-in developers need to introduce a npm module named vscode when calling core capabilities

Import * as vscode from 'vscode'

In fact, this is just a vscode.d.ts type declaration file, which declares the API types available to all plug-ins.

The specific implementation of these API is in src/vs/workbench/api/common/extHost.api.impl.ts createApiFactoryAndRegisterActors

So when exactly did these API be injected in the plugin execution context? In fact, it tampered with the execution of the plug-in import statement.

/ / src/vs/workbench/api/common/extHostRequireInterceptor.tsclass VSCodeNodeModuleFactory implements INodeModuleFactory {public load (_ request: string, parent: URI): any {/ / get extension id from filename and api for extension const ext = this._extensionPaths.findSubstr (parent.fsPath); if (ext) {let apiImpl = this._extApiImpl.get (ExtensionIdentifier.toKey (ext.identifier)) If (! apiImpl) {apiImpl = this._apiFactory (ext, this._extensionRegistry, this._configProvider); this._extApiImpl.set (ExtensionIdentifier.toKey (ext.identifier), apiImpl);} return apiImpl;} / / fall back to a default implementation if (! this._defaultApiImpl) {let extensionPathsPretty ='' This._extensionPaths.forEach ((value, index) = > extensionPathsPretty + = `\ t$ {index}-> ${value.identifier.value}\ n`); this._logService.warn (`Could not identify extension for 'vscode' require call from ${parent.fsPath}. These are the extension path mappings:\ n$ {extensionPathsPretty} `); this._defaultApiImpl = this._apiFactory (nullExtensionDescription, this._extensionRegistry, this._configProvider);} return this._defaultApiImpl;}}

The require of vscode plugin is all hijacked by Microsoft/vscode-loader, and the plug-in API is injected into the runtime through the hack of require.

Plug-in development and configuration

Scaffolding: https://github.com/Microsoft/vscode-generator-code

Official demo: https://github.com/Microsoft/vscode-eslint

Npm install-g yo generator-codeyo code

A plug-in core is a configuration file: Extension Manifest JSON (a field in package.json)

Https://code.visualstudio.com/api/references/extension-manifest

Some key configurations are as follows:

Main: the main file entry, such as exporting an activate method, can accept ctx to do something

Main: ". / src/extension.js"

/ / extension.jsconst vscode = require ("vscode"); function activate (context) {console.log ('Congratulations, your extension "helloworld" is now activating'); let disposable = vscode.commands.registerCommand ("extension.helloWorld", function () {vscode.window.showInformationMessage ("Hello World!");}); context.subscriptions.push (disposable);} exports.activate = activate;Activation Events activation time

OnLanguage: the file containing the language type is opened

OnLanguage:json

OnCommand: a command

OnCommand:extension.sayHello

OnDebug: start debugging

OnDebugInitialConfigurations

OnDebugResolve

WorkspaceContains: files with matching rules are opened

WorkspaceContains:**/.editorconfig

OnFileSystem: open a file for a special protocol

OnFileSystem:sftp

OnView: the view of an id is displayed

OnView:nodeDependencies

OnUri: schema registered with the operating system

Vscode://vscode.git/init

OnWebviewPanel: when the webview of some kind of viewType is opened

OnWebviewPanel:catCoding

*: open immediately as soon as you start

Contribution Points extension point

Contributes.configuration: what are the options available for users to configure this plug-in

Contributes.configurationDefaults: overrides some of vscode's default editor configurations

Contributes.commands: register some commands that can be called by users with the command system of vscode

Contributes.menus: extended menu

...

At this point, the study on "how to look at the large-scale IDE technical architecture from VSCode" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report