Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
29 changes: 19 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@
}
},
"activationEvents": [
"onLanguage:java",
"workspaceContains:pom.xml",
"workspaceContains:build.gradle",
"workspaceContains:settings.gradle",
"workspaceContains:build.gradle.kts",
"workspaceContains:settings.gradle.kts",
"workspaceContains:.classpath",
"onCommand:_java.project.open",
"onCommand:java.project.create",
"onCommand:java.view.package.exportJar",
"onCommand:java.view.package.revealInProjectExplorer",
"onCommand:java.view.package.newJavaClass",
"onView:javaProjectExplorer"
"onCommand:java.view.package.newJavaClass"
],
"license": "MIT",
"main": "./main.js",
Expand Down Expand Up @@ -266,7 +270,7 @@
"commandPalette": [
{
"command": "java.view.package.exportJar",
"when": "java:serverMode == Standard"
"when": "java:serverMode == Standard && !java:noJavaProjects"
},
{
"command": "java.view.package.refresh",
Expand Down Expand Up @@ -348,7 +352,7 @@
"explorer/context": [
{
"command": "java.view.package.revealInProjectExplorer",
"when": "resourceFilename in java:supportedBuildFiles && java:serverMode == Standard",
"when": "resourceFilename =~ /(.*\\.gradle)|(.*\\.gradle\\.kts)|(pom\\.xml)$/ && java:serverMode == Standard",
"group": "navigation@100"
},
{
Expand All @@ -360,7 +364,7 @@
"editor/title/context": [
{
"command": "java.view.package.revealInProjectExplorer",
"when": "resourceFilename in java:supportedBuildFiles && java:serverMode == Standard",
"when": "resourceFilename =~ /(.*\\.gradle)|(.*\\.gradle\\.kts)|(pom\\.xml)$/ && java:serverMode == Standard",
"group": "2_files@100"
},
{
Expand All @@ -372,7 +376,7 @@
"view/title": [
{
"command": "java.project.create",
"when": "view == javaProjectExplorer && java:serverMode == Standard",
"when": "view == javaProjectExplorer",
"group": "navigation@10"
},
{
Expand Down Expand Up @@ -515,9 +519,9 @@
{
"id": "javaProjectExplorer",
"name": "Java Projects",
"when": "java:serverMode",
"contextualTitle": "Java Projects",
"icon": "$(project)"
"icon": "$(project)",
"when": "resourceLangId == java || java:workspaceContainsBuildFiles || java:serverMode"
}
]
},
Expand All @@ -536,6 +540,11 @@
"view": "javaProjectExplorer",
"contents": "%viewsWelcome.workbench.inLightWeightMode%",
"when": "java:serverMode == LightWeight"
},
{
"view": "javaProjectExplorer",
"contents": "%viewsWelcome.workbench.installLanguageSupport%",
"when": "java:projectManagerActivated && !java:languageSupportInstalled"
}
],
"taskDefinitions": [
Expand Down
5 changes: 3 additions & 2 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"taskDefinitions.java.project.exportJar.dependencies": "The artifact dependencies in the runtime scope.",
"taskDefinitions.java.project.exportJar.testDependencies": "The artifact dependencies in the test scope.",
"viewsWelcome.workbench.createNewJavaProject": "You can also [open a Java project](command:_java.project.open), or create a new Java project by clicking the button below.\n[Create Java Project](command:java.project.create)",
"viewsWelcome.workbench.noJavaProject": "No Java projects found in the current workspace. You can [open a Java project](command:_java.project.open), or create a new Java project by clicking the button below.\n[Create Java Project](command:java.project.create)",
"viewsWelcome.workbench.inLightWeightMode": "No projects are listed because the Java Language Server is currently running in [LightWeight Mode](https://aka.ms/vscode-java-lightweight). To show projects, click on the button to switch to Standard Mode.\n[Switch to Standard Mode](command:java.server.mode.switch?%5B%22Standard%22,true%5D)"
"viewsWelcome.workbench.noJavaProject": "No Java projects found in the current workspace. You can [open a Java project folder](command:_java.project.open), or create a new Java project by clicking the button below.\n[Create Java Project](command:java.project.create)",
"viewsWelcome.workbench.inLightWeightMode": "To view the projects, you can import the projects into workspace.\n[Import Projects](command:java.server.mode.switch?%5B%22Standard%22,true%5D)",
"viewsWelcome.workbench.installLanguageSupport": "The Java Projects explorer requires [Language Support for Java(TM) by Red Hat](command:extension.open?%5B%22redhat.java%22%5D) to provide full features.\n[Install](command:workbench.extensions.installExtension?%5B%22redhat.java%22%5D)"
}
5 changes: 3 additions & 2 deletions package.nls.zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"taskDefinitions.java.project.exportJar.dependencies": "在 runtime scope 内的依赖。",
"taskDefinitions.java.project.exportJar.testDependencies": "在 test scope 内的依赖。",
"viewsWelcome.workbench.createNewJavaProject": "您也可以[打开一个 Java 项目](command:_java.project.open),或点击下方按钮创建一个新的 Java 项目。\n[创建 Java 项目](command:java.project.create)",
"viewsWelcome.workbench.noJavaProject": "当前工作空间未发现 Java 项目,您可以[打开一个 Java 项目](command:_java.project.open),或点击下方按钮创建一个新的 Java 项目。\n[创建 Java 项目](command:java.project.create)",
"viewsWelcome.workbench.inLightWeightMode": "由于 Java 语言服务正运行在 [LightWeight 模式](https://aka.ms/vscode-java-lightweight)下,因此项目将不会展示在该视图中。如果您需要展示项目信息,可以点击下方按钮将 Java 语言服务切换至 Standard 模式。\n[切换至 Standard 模式](command:java.server.mode.switch?%5B%22Standard%22,true%5D)"
"viewsWelcome.workbench.noJavaProject": "当前工作空间未发现 Java 项目,您可以[打开一个 Java 项目目录](command:_java.project.open),或点击下方按钮创建一个新的 Java 项目。\n[创建 Java 项目](command:java.project.create)",
"viewsWelcome.workbench.inLightWeightMode": "要浏览项目信息,你可以将项目导入到工作空间中。\n[导入项目](command:java.server.mode.switch?%5B%22Standard%22,true%5D)",
"viewsWelcome.workbench.installLanguageSupport": "Java 项目视图需要安装并激活 [Language Support for Java(TM) by Red Hat](command:extension.open?%5B%22redhat.java%22%5D) 以提供完整的功能。\n[安装](command:workbench.extensions.installExtension?%5B%22redhat.java%22%5D)"
}
9 changes: 3 additions & 6 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

export namespace Context {
export const EXTENSION_ACTIVATED: string = "java:projectManagerActivated";
export const SUPPORTED_BUILD_FILES: string = "java:supportedBuildFiles";
export const NO_JAVA_PEOJECT: string = "java:noJavaProjects";
export const LANGUAGE_SUPPORT_INSTALLED: string = "java:languageSupportInstalled";
export const NO_JAVA_PROJECT: string = "java:noJavaProjects";
export const WORKSPACE_CONTAINS_BUILD_FILES: string = "java:workspaceContainsBuildFiles";
}

export namespace Explorer {
Expand All @@ -21,10 +22,6 @@ export namespace Explorer {
}
}

export namespace Build {
export const FILE_NAMES: string[] = ["pom.xml", "build.gradle"];
}

export namespace ExtensionName {
export const JAVA_LANGUAGE_SUPPORT: string = "redhat.java";
}
2 changes: 1 addition & 1 deletion src/exportJarSteps/ExportJarTaskProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export async function executeExportJarTask(node?: INodeData): Promise<void> {
// save the workspace first
await workspace.saveAll(false /*includeUntitled*/);

if (!await languageServerApiManager.isStandardServerReady() || isExportingJar || await buildWorkspace() === false) {
if (!await languageServerApiManager.ready() || isExportingJar || await buildWorkspace() === false) {
return;
}
isExportingJar = true;
Expand Down
50 changes: 12 additions & 38 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import { Event, Extension, ExtensionContext, extensions, tasks, Uri } from "vscode";
import { ExtensionContext, tasks, Uri, workspace } from "vscode";
import { dispose as disposeTelemetryWrapper, initializeFromJsonFile, instrumentOperation, sendInfo } from "vscode-extension-telemetry-wrapper";
import { contextManager } from "../extension.bundle";
import { Build, Context, ExtensionName } from "./constants";
import { Context } from "./constants";
import { LibraryController } from "./controllers/libraryController";
import { ProjectController } from "./controllers/projectController";
import { init as initExpService } from "./ExperimentationService";
import { ExportJarTaskProvider } from "./exportJarSteps/ExportJarTaskProvider";
import { languageServerApiManager } from "./languageServerApi/languageServerApiManager";
import { Settings } from "./settings";
import { syncHandler } from "./syncHandler";
import { EventCounter } from "./utility";
Expand All @@ -19,53 +20,26 @@ export async function activate(context: ExtensionContext): Promise<void> {
await initializeFromJsonFile(context.asAbsolutePath("./package.json"), { firstParty: true });
await initExpService(context);
await instrumentOperation("activation", activateExtension)(context);
languageServerApiManager.initializeJavaLanguageServerApi(false);
// the when clause does not support 'workspaceContains' we used for activation event,
// so we manually find the target files and set it to a context value.
workspace.findFiles("{*.gradle,*.gradle.kts,pom.xml,.classpath}", undefined, 1).then((uris: Uri[]) => {
if (uris && uris.length) {
contextManager.setContextValue(Context.WORKSPACE_CONTAINS_BUILD_FILES, true);
}
});
contextManager.setContextValue(Context.EXTENSION_ACTIVATED, true);
contextManager.setContextValue(Context.SUPPORTED_BUILD_FILES, Build.FILE_NAMES);
}

async function activateExtension(_operationId: string, context: ExtensionContext): Promise<void> {
context.subscriptions.push(languageServerApiManager);
context.subscriptions.push(new ProjectController(context));
Settings.initialize(context);
context.subscriptions.push(new LibraryController(context));
context.subscriptions.push(DependencyExplorer.getInstance(context));
context.subscriptions.push(contextManager);
context.subscriptions.push(syncHandler);
context.subscriptions.push(tasks.registerTaskProvider(ExportJarTaskProvider.exportJarType, new ExportJarTaskProvider()));

const pollingJLS = () => {
const javaLanguageSupport: Extension<any> | undefined = extensions.getExtension(ExtensionName.JAVA_LANGUAGE_SUPPORT);
if (!javaLanguageSupport) {
return;
}

if (javaLanguageSupport.isActive) {
const extensionApi: any = javaLanguageSupport.exports;
if (!extensionApi) {
return;
}

if (extensionApi.onDidClasspathUpdate) {
const onDidClasspathUpdate: Event<Uri> = extensionApi.onDidClasspathUpdate;
context.subscriptions.push(onDidClasspathUpdate(async () => {
syncHandler.updateFileWatcher(Settings.autoRefresh());
}));
}

if (extensionApi.serverMode === "Standard") {
syncHandler.updateFileWatcher(Settings.autoRefresh());
} else {
if (extensionApi.onDidServerModeChange) {
const onDidServerModeChange: Event<string> = extensionApi.onDidServerModeChange;
context.subscriptions.push(onDidServerModeChange(async () => {
syncHandler.updateFileWatcher(Settings.autoRefresh());
}));
}
}
} else {
setTimeout(pollingJLS, 3 * 1000 /*ms*/);
}
};
pollingJLS();
}

// this method is called when your extension is deactivated
Expand Down
94 changes: 57 additions & 37 deletions src/languageServerApi/languageServerApiManager.ts
Original file line number Diff line number Diff line change
@@ -1,94 +1,114 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import { commands, Event, Extension, extensions, Uri } from "vscode";
import { commands, Disposable, Event, Extension, extensions, Uri } from "vscode";
import { Commands } from "../commands";
import { Context, ExtensionName } from "../constants";
import { contextManager } from "../contextManager";
import { Settings } from "../settings";
import { syncHandler } from "../syncHandler";
import { LanguageServerMode } from "./LanguageServerMode";

class LanguageServerApiManager {
class LanguageServerApiManager implements Disposable {
/**
* undefined means a legacy version language server
* null means the JDT.LS is not activated
*/
private serverMode: LanguageServerMode | null | undefined = null;

public async isStandardServerReady(): Promise<boolean> {
private extensionChangeListener: Disposable;

public async ready(): Promise<boolean> {
await this.checkServerMode();
// undefined serverMode indicates an older version language server
if (this.serverMode === undefined) {
return true;
}

if (this.serverMode !== LanguageServerMode.Standard) {
if (this.serverMode === null || this.serverMode === LanguageServerMode.LightWeight) {
Comment thread
Eskibear marked this conversation as resolved.
return false;
}

return true;
}

public async isLightWeightMode(): Promise<boolean> {
await this.checkServerMode();
return this.serverMode === LanguageServerMode.LightWeight;
}

public async awaitSwitchingServerFinished(): Promise<void> {
await this.checkServerMode();
if (this.serverMode === LanguageServerMode.Hybrid) {
await new Promise<void>((resolve: () => void): void => {
extensions.getExtension("redhat.java")!.exports.onDidServerModeChange(resolve);
Comment thread
Eskibear marked this conversation as resolved.
});
}
}

private async checkServerMode(): Promise<void> {
if (this.serverMode === null) {
await this.initializeJavaLanguageServerApi();
}
return true;
}

private async initializeJavaLanguageServerApi(): Promise<void> {
if (this.serverMode !== null) {
public async initializeJavaLanguageServerApi(forceActivate: boolean = true): Promise<void> {
if (this.isLanguageServerActivated()) {
return;
}
const extension: Extension<any> | undefined = extensions.getExtension("redhat.java");

if (!this.extensionChangeListener) {
this.extensionChangeListener = extensions.onDidChange(() => {
if (this.serverMode === null) {
commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH, /* debounce = */false);
}
});
}

const extension: Extension<any> | undefined = extensions.getExtension(ExtensionName.JAVA_LANGUAGE_SUPPORT);
if (extension) {
contextManager.setContextValue(Context.LANGUAGE_SUPPORT_INSTALLED, true);
if (!forceActivate) {
return;
}
await extension.activate();
const extensionApi: any = extension.exports;
if (!extensionApi) {
return;
}

this.serverMode = extensionApi.serverMode;
if (this.serverMode === LanguageServerMode.Standard) {
syncHandler.updateFileWatcher(Settings.autoRefresh());
}

if (extensionApi.onDidClasspathUpdate) {
const onDidClasspathUpdate: Event<Uri> = extensionApi.onDidClasspathUpdate;
contextManager.context.subscriptions.push(onDidClasspathUpdate(async () => {
await commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH, /* debounce = */true);
contextManager.context.subscriptions.push(onDidClasspathUpdate(() => {
commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH, /* debounce = */true);
syncHandler.updateFileWatcher(Settings.autoRefresh());
}));
}

if (extensionApi.onDidServerModeChange) {
const onDidServerModeChange: Event<string> = extensionApi.onDidServerModeChange;
contextManager.context.subscriptions.push(onDidServerModeChange(async (mode: LanguageServerMode) => {
contextManager.context.subscriptions.push(onDidServerModeChange((mode: LanguageServerMode) => {
if (this.serverMode !== mode) {
let needRefresh: boolean = true;
if (this.serverMode === "Hybrid") {
// Explorer will await when JLS is in Hybrid mode (activating),
needRefresh = false;
}
this.serverMode = mode;
if (needRefresh) {
if (mode === LanguageServerMode.Hybrid) {
commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH, /* debounce = */false);
} else if (mode === LanguageServerMode.Standard) {
syncHandler.updateFileWatcher(Settings.autoRefresh());
}
this.serverMode = mode;
}
}));
}

if (extensionApi.onDidProjectsImport) {
const onDidProjectsImport: Event<Uri[]> = extensionApi.onDidProjectsImport;
contextManager.context.subscriptions.push(onDidProjectsImport(async () => {
contextManager.context.subscriptions.push(onDidProjectsImport(() => {
commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH, /* debounce = */true);
syncHandler.updateFileWatcher(Settings.autoRefresh());
}));
}
}
}

public dispose() {
this.extensionChangeListener.dispose();
}

private isLanguageServerActivated(): boolean {
return this.serverMode !== null;
}

private async checkServerMode(): Promise<void> {
if (!this.isLanguageServerActivated()) {
await this.initializeJavaLanguageServerApi();
}
}
}

export const languageServerApiManager: LanguageServerApiManager = new LanguageServerApiManager();
7 changes: 1 addition & 6 deletions src/utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,8 @@ export class Utility {
return false;
}

await languageServerApiManager.awaitSwitchingServerFinished();
if (!await languageServerApiManager.isStandardServerReady()) {
return false;
}
return true;
return languageServerApiManager.ready();
}

}

export class EventCounter {
Expand Down
Loading