Skip to content

Commit c582159

Browse files
authored
Synchronize bundles on demand (#2729)
- Allow server to ask bundles to synchronize before ready. - When new bundle is detected, instead of asking user to reload window, we will try to let JDT.LS hot load the bundle first. Signed-off-by: sheche <[email protected]>
1 parent 240a42d commit c582159

File tree

4 files changed

+59
-18
lines changed

4 files changed

+59
-18
lines changed

src/commands.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,4 +287,15 @@ export namespace Commands {
287287
* The VS Code command to create module-info.java
288288
*/
289289
export const CREATE_MODULE_INFO_COMMAND = "java.project.createModuleInfo.command";
290+
291+
/**
292+
* The JDT.LS command to reload the bundle list (java extension contributions).
293+
*/
294+
export const REFRESH_BUNDLES = "java.reloadBundles";
295+
296+
/**
297+
* The VS Code command to reload the bundle list.
298+
* JDT.LS will call this command before set the server to ready state.
299+
*/
300+
export const REFRESH_BUNDLES_COMMAND = "_java.reloadBundles.command";
290301
}

src/extension.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as fse from 'fs-extra';
77
import { workspace, extensions, ExtensionContext, window, commands, ViewColumn, Uri, languages, IndentAction, InputBoxOptions, EventEmitter, OutputChannel, TextDocument, RelativePattern, ConfigurationTarget, WorkspaceConfiguration, env, UIKind, CodeActionContext, Diagnostic, CodeActionTriggerKind, version } from 'vscode';
88
import { ExecuteCommandParams, ExecuteCommandRequest, LanguageClientOptions, RevealOutputChannelOn, ErrorHandler, Message, ErrorAction, CloseAction, DidChangeConfigurationNotification, CancellationToken, CodeActionRequest, CodeActionParams, Command } from 'vscode-languageclient';
99
import { LanguageClient } from 'vscode-languageclient/node';
10-
import { collectJavaExtensions, isContributedPartUpdated } from './plugin';
10+
import { collectJavaExtensions, getBundlesToReload, isContributedPartUpdated } from './plugin';
1111
import { HEAP_DUMP_LOCATION, prepareExecutable } from './javaServerStarter';
1212
import * as requirements from './requirements';
1313
import { initialize as initializeRecommendation } from './recommendation';
@@ -383,6 +383,10 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
383383

384384
context.subscriptions.push(commands.registerCommand(Commands.GET_WORKSPACE_PATH, () => workspacePath));
385385

386+
context.subscriptions.push(commands.registerCommand(Commands.REFRESH_BUNDLES_COMMAND, () => {
387+
return getBundlesToReload();
388+
}));
389+
386390
context.subscriptions.push(onConfigurationChange(workspacePath, context));
387391

388392
/**

src/plugin.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
import * as vscode from 'vscode';
44
import * as path from 'path';
55
import { Commands } from './commands';
6+
import { extensions } from 'vscode';
67

7-
let existingExtensions: Array<string>;
8-
export let buildFilePatterns: Array<string>;
8+
export let existingExtensions: Array<string> = [];
9+
export let buildFilePatterns: Array<string> = [];
910

1011
export function collectJavaExtensions(extensions: readonly vscode.Extension<any>[]): string[] {
1112
const result = [];
@@ -44,17 +45,40 @@ export function collectBuildFilePattern(extensions: readonly vscode.Extension<an
4445
return result;
4546
}
4647

47-
export function onExtensionChange(extensions: readonly vscode.Extension<any>[]) {
48-
if (isContributedPartUpdated(existingExtensions, collectJavaExtensions(extensions)) || isContributedPartUpdated(buildFilePatterns, collectBuildFilePattern(extensions))) {
49-
const msg = `Java Extension Contributions changed, reloading ${vscode.env.appName} is required for the changes to take effect.`;
50-
const action = 'Reload';
51-
const restartId = Commands.RELOAD_WINDOW;
52-
vscode.window.showWarningMessage(msg, action).then((selection) => {
53-
if (action === selection) {
54-
vscode.commands.executeCommand(restartId);
55-
}
56-
});
48+
export function getBundlesToReload(): string[] {
49+
const previousContributions: string[] = [...existingExtensions];
50+
const currentContributions = collectJavaExtensions(extensions.all);
51+
if (isContributedPartUpdated(previousContributions, currentContributions)) {
52+
return currentContributions;
53+
}
54+
55+
return [];
56+
}
57+
58+
export async function onExtensionChange(extensions: readonly vscode.Extension<any>[]): Promise<void> {
59+
if (isContributedPartUpdated(buildFilePatterns, collectBuildFilePattern(extensions))) {
60+
return promptToReload();
5761
}
62+
63+
const bundlesToRefresh: string[] = getBundlesToReload();
64+
if (bundlesToRefresh.length) {
65+
const success = await vscode.commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.REFRESH_BUNDLES, bundlesToRefresh);
66+
if (!success) {
67+
// if hot refreshing bundle fails, fallback to reload window.
68+
return promptToReload();
69+
}
70+
}
71+
}
72+
73+
function promptToReload() {
74+
const msg = `Java Extension Contributions changed, reloading ${vscode.env.appName} is required for the changes to take effect.`;
75+
const action = 'Reload';
76+
const restartId = Commands.RELOAD_WINDOW;
77+
vscode.window.showWarningMessage(msg, action).then((selection) => {
78+
if (action === selection) {
79+
vscode.commands.executeCommand(restartId);
80+
}
81+
});
5882
}
5983

6084
export function isContributedPartUpdated(oldContributedPart: Array<string>, newContributedPart: Array<string>) {

src/standardLanguageClient.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ export class StandardLanguageClient {
111111
apiManager.updateServerMode(ServerMode.standard);
112112
apiManager.fireDidServerModeChange(ServerMode.standard);
113113
apiManager.resolveServerReadyPromise();
114+
115+
if (extensions.onDidChange) {// Theia doesn't support this API yet
116+
extensions.onDidChange(async () => {
117+
await onExtensionChange(extensions.all);
118+
});
119+
}
120+
114121
activationProgressNotification.hide();
115122
if (!hasImported) {
116123
showImportFinishNotification(context);
@@ -539,11 +546,6 @@ export class StandardLanguageClient {
539546
refactorAction.registerCommands(this.languageClient, context);
540547
pasteAction.registerCommands(this.languageClient, context);
541548

542-
if (extensions.onDidChange) {// Theia doesn't support this API yet
543-
extensions.onDidChange(() => {
544-
onExtensionChange(extensions.all);
545-
});
546-
}
547549
excludeProjectSettingsFiles();
548550

549551
context.subscriptions.push(languages.registerCodeActionsProvider({ scheme: 'file', language: 'java' }, new RefactorDocumentProvider(), RefactorDocumentProvider.metadata));

0 commit comments

Comments
 (0)