Skip to content

Latest commit

 

History

History
58 lines (33 loc) · 5.28 KB

ARCHITECTURE.md

File metadata and controls

58 lines (33 loc) · 5.28 KB

Architecture Overview

This extension contains three major components:

Gradle Server

The gradle server is a long-running Java process that include three threads: 1. Build Server 2. Task Server 3. Language Server

Build Server

The Gradle Build Server communicates with the Build Client using the Build Server Protocol through named pipes.

Due to Java's limited support for named pipes on Windows, a TypeScript layer named BspProxy was introduced. This layer acts as a middleware and it helps by sending messages back and forth and creating a safer named pipe JSON-RPC connection between the Gradle Build Server and the Build Client.

For information about the Build Server itself, visit the Gradle Build Server.

Language Server

Language Server provides language features such as code completion and diagnostics for Gradle script files. It communicates with the Language Client using the Language Server Protocol through named pipe.

Task Server

The task server and client using gRPC as the interface between each other. It uses TypeScript (Node.js) on the client and Java on the server. A long running server provides very good performance.

On extension activate, the client starts the Java gRPC server which remains running for the period the extension is activated. The server is packaged with the extension as a fat .jar file and is started by Node.js via executables generated by Gradle CreateStartScripts.

Protocol buffers are used to define the gRPC service & messages. The Java & JavaScript message classes, as well as the client and server interfaces, are generated from the Protobuf files via the protoc compiler. TypeScript type definitions are generated from the JavaScript classes.

The Java server uses the Gradle Tooling Api to discover projects & tasks, and to run Gradle tasks.

Discovering Projects & Tasks

Tasks belong to projects and projects are hierarchical, meaning projects can have sub-projects, and any/all projects in the tree can have tasks.

The gRPC server provides a getBuild method to provide this hierarchical data structure, and accepts a projectDir argument, which the client provides.

A root project (projectDir) is defined by having a gradle wrapper script at the root (gradlew or gradlew.bat). By default the extension will search for wrapper scripts at the root of the workspaces, but you can control this behaviour by setting gradle.nestedProjects to allow the extension to discover Gradle projects at other locations.

Once the client has discovered the root projects for all workspaces, it requests project data for each root project via separate gRPC method calls using getBuild. Gradle progress and output (STDERR & STDOUT) are streamed to the client. Once the tasks have been discovered and returned to the client, it builds a single-dimensional list of vscode tasks from the Gradle project tasks. These vscode tasks have definitions that contain all the relevant task & project information.

The extension models the project hierarchical structure using the vscode tree view. The tree view data provider consumes the vscode tasks, and builds a tree of projects & tasks using the information provided in the task definitions.

Running Tasks

Gradle tasks can be run through either the Tree View or the Command Palette.

Tasks are run via the runBuild gRPC method. Similar to getting project data, Gradle progress and output (STDERR & STDOUT) is streamed to the client. Tasks are run in a custom vscode terminal. The runBuild gRPC method accepts a list of arguments which are passed to the BuildLauncher.

The Build System

Gradle is used as the build system for the extension, for both the client and the server. Gradle compiles the Java & Protobuf files and runs the relevant tasks to download & build all the dependencies of the project. The builds should work on Linux/MacOS & Windows.

Getting started on this extension is as simple as ./gradlew build.

Gradle Project Importer

The Gradle project importer works as a client of the Gradle Build Server. The importer communicates with the Gradle build server via Build Server Protocol, and convert the build targets into Java Projects of JDT Language Server.