Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Language Server to Gradle Server #1525

Merged
merged 7 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 0 additions & 35 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,41 +77,6 @@
"order": 3
}
},
{
"name": "Debug Language Server: Launch Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}/extension"
],
"outFiles": [
"${workspaceFolder}/extension/dist/**/*.js"
],
"preLaunchTask": "Gradle: Build",
"env": {
"VSCODE_DEBUG_LANGUAGE_SERVER": "true",
"VSCODE_GRADLE_PORT": "6006"
},
"presentation": {
"group": "debug",
"order": 4
}
},
{
"type": "java",
"name": "Debug Language Server: Launch Language Server",
"request": "launch",
"mainClass": "com.microsoft.gradle.GradleLanguageServer",
"projectName": "gradle-language-server",
"env": {
"VSCODE_GRADLE_PORT": "6006"
},
"presentation": {
"group": "debug",
"order": 5
}
},
{
"type": "java",
"name": "Attach to Gradle Plugin",
Expand Down
50 changes: 34 additions & 16 deletions extension/src/Extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { FileWatcher } from "./util/FileWatcher";
import { DependencyTreeItem } from "./views/gradleTasks/DependencyTreeItem";
import { GRADLE_DEPENDENCY_REVEAL } from "./views/gradleTasks/DependencyUtils";
import { GradleDependencyProvider } from "./dependencies/GradleDependencyProvider";
import { isLanguageServerStarted, startLanguageServer } from "./languageServer/languageServer";
import { isLanguageServerStarted, startLanguageClientAndWaitForConnection } from "./languageServer/languageServer";
import { DefaultProjectsTreeDataProvider } from "./views/defaultProject/DefaultProjectsTreeDataProvider";
import {
CompletionKinds,
Expand All @@ -39,10 +39,11 @@ import { GradleBuildContentProvider } from "./client/GradleBuildContentProvider"
import { BuildServerController } from "./bs/BuildServerController";
import { GradleTestRunner } from "./bs/GradleTestRunner";
import { BspProxy } from "./bs/BspProxy";
import { generateRandomPipeName } from "./util/generateRandomPipeName";

export class Extension {
private readonly bspProxy: BspProxy;
private readonly client: GradleClient;
private readonly taskServerClient: GradleClient;
private readonly server: GradleServer;
private readonly pinnedTasksStore: PinnedTasksStore;
private readonly recentTasksStore: RecentTasksStore;
Expand Down Expand Up @@ -71,7 +72,7 @@ export class Extension {
private readonly onDidTerminalOpen: vscode.Event<vscode.Terminal> = this._onDidTerminalOpen.event;
private recentTerminal: vscode.Terminal | undefined;
private readonly buildServerController: BuildServerController;

private readonly languageServerPipePath: string;
public constructor(private readonly context: vscode.ExtensionContext) {
const loggingChannel = vscode.window.createOutputChannel("Gradle for Java");
logger.setLoggingChannel(loggingChannel);
Expand All @@ -85,22 +86,29 @@ export class Extension {
const bspLogger = new Logger("bspProxy");
bspLogger.setLoggingChannel(loggingChannel);

this.languageServerPipePath = generateRandomPipeName();
jdneo marked this conversation as resolved.
Show resolved Hide resolved
if (getConfigIsDebugEnabled()) {
Logger.setLogVerbosity(LogVerbosity.DEBUG);
}

const statusBarItem = vscode.window.createStatusBarItem();
this.bspProxy = new BspProxy(this.context, bspLogger);
this.server = new GradleServer({ host: "localhost" }, context, serverLogger, this.bspProxy);
this.client = new GradleClient(this.server, statusBarItem, clientLogger);
this.server = new GradleServer(
{ host: "localhost" },
context,
serverLogger,
this.bspProxy,
this.languageServerPipePath
);
this.taskServerClient = new GradleClient(this.server, statusBarItem, clientLogger);
this.pinnedTasksStore = new PinnedTasksStore(context);
this.recentTasksStore = new RecentTasksStore();
this.taskTerminalsStore = new TaskTerminalsStore();
this.rootProjectsStore = new RootProjectsStore();
this.gradleBuildContentProvider = new GradleBuildContentProvider(this.client);
this.gradleBuildContentProvider = new GradleBuildContentProvider(this.taskServerClient);
this.gradleTaskProvider = new GradleTaskProvider(
this.rootProjectsStore,
this.client,
this.taskServerClient,
this.gradleBuildContentProvider
);
this.gradleDependencyProvider = new GradleDependencyProvider(this.gradleBuildContentProvider);
Expand All @@ -114,7 +122,7 @@ export class Extension {
this.gradleTaskProvider,
this.gradleDependencyProvider,
this.icons,
this.client
this.taskServerClient
);
this.gradleTasksTreeView = vscode.window.createTreeView(GRADLE_TASKS_VIEW, {
treeDataProvider: this.gradleTasksTreeDataProvider,
Expand All @@ -130,7 +138,7 @@ export class Extension {
this.taskTerminalsStore,
this.rootProjectsStore,
this.gradleTaskProvider,
this.client,
this.taskServerClient,
this.icons
);
this.recentTasksTreeView = vscode.window.createTreeView(RECENT_TASKS_VIEW, {
Expand All @@ -140,7 +148,7 @@ export class Extension {
this.defaultProjectsTreeDataProvider = new DefaultProjectsTreeDataProvider(
this.gradleTaskProvider,
this.rootProjectsStore,
this.client,
this.taskServerClient,
this.icons
);
this.defaultProjectsTreeView = vscode.window.createTreeView(GRADLE_DEFAULT_PROJECTS_VIEW, {
Expand All @@ -151,7 +159,12 @@ export class Extension {
this.gradleTaskManager = new GradleTaskManager(context);
this.buildFileWatcher = new FileWatcher("**/*.{gradle,gradle.kts}");
this.gradleWrapperWatcher = new FileWatcher("**/gradle/wrapper/gradle-wrapper.properties");
this.api = new Api(this.client, this.gradleTasksTreeDataProvider, this.gradleTaskProvider, this.icons);
this.api = new Api(
this.taskServerClient,
this.gradleTasksTreeDataProvider,
this.gradleTaskProvider,
this.icons
);

this.commands = new Commands(
this.context,
Expand All @@ -161,7 +174,7 @@ export class Extension {
this.gradleTasksTreeDataProvider,
this.recentTasksTreeDataProvider,
this.gradleDaemonsTreeDataProvider,
this.client,
this.taskServerClient,
this.rootProjectsStore,
this.taskTerminalsStore,
this.recentTasksStore,
Expand Down Expand Up @@ -205,16 +218,21 @@ export class Extension {
)
);

this.client.onDidConnect(() => this.refresh());
this.taskServerClient.onDidConnect(() => this.refresh());
void startLanguageClientAndWaitForConnection(
this.context,
this.gradleBuildContentProvider,
this.rootProjectsStore,
this.languageServerPipePath
);
void this.activate();
void startLanguageServer(this.context, this.gradleBuildContentProvider, this.rootProjectsStore);
void vscode.commands.executeCommand("setContext", "allowParallelRun", getAllowParallelRun());
void vscode.commands.executeCommand("setContext", Context.ACTIVATION_CONTEXT_KEY, true);
}

private storeSubscriptions(): void {
this.context.subscriptions.push(
this.client,
this.taskServerClient,
this.pinnedTasksStore,
this.recentTasksStore,
this.taskTerminalsStore,
Expand Down Expand Up @@ -327,7 +345,7 @@ export class Extension {
}

private async restartServer(): Promise<void> {
await this.client.cancelBuilds();
await this.taskServerClient.cancelBuilds();
await commands.executeCommand("workbench.action.restartExtensionHost");
}

Expand Down
53 changes: 8 additions & 45 deletions extension/src/languageServer/languageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,31 @@
// Licensed under the MIT license.

import * as net from "net";
import * as path from "path";
import * as vscode from "vscode";
import { DidChangeConfigurationNotification, LanguageClientOptions } from "vscode-languageclient";
import { LanguageClient, StreamInfo } from "vscode-languageclient/node";
import { GradleBuildContentProvider } from "../client/GradleBuildContentProvider";
import { GradleBuild, GradleProject } from "../proto/gradle_pb";
import { RootProjectsStore } from "../stores";
import {
checkEnvJavaExecutable,
getConfigJavaImportGradleHome,
getConfigJavaImportGradleUserHome,
getConfigJavaImportGradleVersion,
getConfigJavaImportGradleWrapperEnabled,
findValidJavaHome,
getJavaExecutablePathFromJavaHome,
} from "../util/config";
import { prepareLanguageServerParams } from "./utils";
const CHANNEL_NAME = "Gradle for Java (Language Server)";

export let isLanguageServerStarted = false;

export async function startLanguageServer(
export async function startLanguageClientAndWaitForConnection(
context: vscode.ExtensionContext,
contentProvider: GradleBuildContentProvider,
rootProjectsStore: RootProjectsStore
rootProjectsStore: RootProjectsStore,
languageServerPipePath: string
): Promise<void> {
void vscode.window.withProgress({ location: vscode.ProgressLocation.Window }, (progress) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return new Promise<void>(async (resolve, reject) => {
return new Promise<void>(async (resolve) => {
progress.report({
message: "Initializing Gradle Language Server",
});
Expand All @@ -42,40 +38,7 @@ export async function startLanguageServer(
settings: getGradleSettings(),
},
};
let serverOptions;
if (process.env.VSCODE_DEBUG_LANGUAGE_SERVER === "true") {
// debug mode
const port = process.env.VSCODE_GRADLE_PORT;
if (!port) {
void vscode.window.showErrorMessage(
"VSCODE_GRADLE_PORT is invalid, please check it in launch.json."
);
return;
}
serverOptions = awaitServerConnection.bind(null, port);
} else {
// keep consistent with gRPC server
const javaHome = await findValidJavaHome();
let javaCommand;
if (javaHome) {
javaCommand = getJavaExecutablePathFromJavaHome(javaHome);
} else {
if (!checkEnvJavaExecutable()) {
// we have already show error message in gRPC server for no java executable found, so here we will just reject and return
return reject();
}
javaCommand = "java";
}
const args = [
...prepareLanguageServerParams(),
"-jar",
path.resolve(context.extensionPath, "lib", "gradle-language-server.jar"),
];
serverOptions = {
command: javaCommand,
args: args,
};
}
const serverOptions = () => awaitServerConnection(languageServerPipePath);
const languageClient = new LanguageClient("gradle", "Gradle Language Server", serverOptions, clientOptions);
void languageClient.onReady().then(
() => {
Expand All @@ -88,6 +51,7 @@ export async function startLanguageServer(
}
);
const disposable = languageClient.start();

context.subscriptions.push(disposable);
context.subscriptions.push(
vscode.workspace.onDidChangeConfiguration((e) => {
Expand All @@ -102,15 +66,14 @@ export async function startLanguageServer(
});
}

async function awaitServerConnection(port: string): Promise<StreamInfo> {
const addr = parseInt(port);
async function awaitServerConnection(pipeName: string): Promise<StreamInfo> {
return new Promise((resolve, reject) => {
const server = net.createServer((stream) => {
server.close();
resolve({ reader: stream, writer: stream });
});
server.on("error", reject);
server.listen(addr, () => {
server.listen(pipeName, () => {
server.removeListener("error", reject);
});
return server;
Expand Down
10 changes: 7 additions & 3 deletions extension/src/server/GradleServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export class GradleServer {
private ready = false;
private taskServerPort: number | undefined;
private restarting = false;

public readonly onDidStart: vscode.Event<null> = this._onDidStart.event;
public readonly onDidStop: vscode.Event<null> = this._onDidStop.event;
private process?: cp.ChildProcessWithoutNullStreams;
Expand All @@ -33,7 +32,8 @@ export class GradleServer {
private readonly opts: ServerOptions,
private readonly context: vscode.ExtensionContext,
private readonly logger: Logger,
private bspProxy: BspProxy
private bspProxy: BspProxy,
private languageServerPipePath: string
) {}

public async start(): Promise<void> {
Expand All @@ -47,7 +47,11 @@ export class GradleServer {
return;
}
const startBuildServer = redHatJavaInstalled() ? "true" : "false";
const args = [`--port=${this.taskServerPort}`, `--startBuildServer=${startBuildServer}`];
const args = [
`--port=${this.taskServerPort}`,
`--startBuildServer=${startBuildServer}`,
`--languageServerPipePath=${this.languageServerPipePath}`,
];
if (startBuildServer === "true") {
const buildServerPipeName = this.bspProxy.getBuildServerPipeName();
args.push(`--pipeName=${buildServerPipeName}`, `--bundleDir=${bundleDirectory}`);
Expand Down
18 changes: 12 additions & 6 deletions gradle-language-server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ plugins {
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

repositories {
Expand All @@ -32,10 +32,16 @@ dependencies {

ext.mainClass = "com.microsoft.gradle.GradleLanguageServer"

task copyJar(type: Copy) {
from "build/libs/gradle-language-server.jar"
from configurations.runtimeClasspath
into "../extension/lib"
task copyJar {
doLast {
['../extension/lib', '../gradle-server/build/libs'].each { destDir ->
copy {
from "build/libs/gradle-language-server.jar"
from configurations.runtimeClasspath
into destDir
}
}
Jiaaming marked this conversation as resolved.
Show resolved Hide resolved
}
}

tasks.build.dependsOn tasks.copyJar
Expand Down
Loading