Skip to content

Commit eefebb5

Browse files
authored
Support project update selection (#2513)
- If no uri is passed into the projectConfigurationUpdate() function, show a quick pick list and let user select which projects to update. - If there is only one project in the workspace, project update request for that project will directly send to server without asking. Signed-off-by: sheche <[email protected]>
1 parent def31b4 commit eefebb5

File tree

2 files changed

+90
-11
lines changed

2 files changed

+90
-11
lines changed

src/protocol.ts

+5
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ export namespace ClassFileContentsRequest {
116116

117117
export namespace ProjectConfigurationUpdateRequest {
118118
export const type = new NotificationType<TextDocumentIdentifier> ('java/projectConfigurationUpdate');
119+
export const typeV2 = new NotificationType<ProjectConfigurationsUpdateParam> ('java/projectConfigurationsUpdate');
120+
}
121+
122+
export interface ProjectConfigurationsUpdateParam {
123+
identifiers: TextDocumentIdentifier[];
119124
}
120125

121126
export namespace ActionableNotification {

src/standardLanguageClient.ts

+85-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
import { ExtensionContext, window, workspace, commands, Uri, ProgressLocation, ViewColumn, EventEmitter, extensions, Location, languages, CodeActionKind, TextEditor, CancellationToken, ConfigurationTarget, Range, Position } from "vscode";
3+
import { ExtensionContext, window, workspace, commands, Uri, ProgressLocation, ViewColumn, EventEmitter, extensions, Location, languages, CodeActionKind, TextEditor, CancellationToken, ConfigurationTarget, Range, Position, QuickPickItem } from "vscode";
44
import { Commands } from "./commands";
55
import { serverStatus, ServerStatusKind } from "./serverStatus";
66
import { prepareExecutable, awaitServerConnection } from "./javaServerStarter";
@@ -585,23 +585,97 @@ function setIncompleteClasspathSeverity(severity: string) {
585585
);
586586
}
587587

588-
function projectConfigurationUpdate(languageClient: LanguageClient, uri?: Uri) {
589-
let resource = uri;
590-
if (!(resource instanceof Uri)) {
591-
if (window.activeTextEditor) {
592-
resource = window.activeTextEditor.document.uri;
588+
async function projectConfigurationUpdate(languageClient: LanguageClient, uris?: Uri | Uri[]) {
589+
let resources = [];
590+
if (!uris) {
591+
resources = await askForProjectToUpdate();
592+
} else if (uris instanceof Uri) {
593+
resources.push(uris);
594+
} else if (Array.isArray(uris)) {
595+
for (const uri of uris) {
596+
if (uri instanceof Uri) {
597+
resources.push(uri);
598+
}
593599
}
594600
}
595-
if (!resource) {
596-
return window.showWarningMessage('No Java project to update!').then(() => false);
597-
}
598-
if (isJavaConfigFile(resource.path)) {
601+
if (resources.length === 1) {
599602
languageClient.sendNotification(ProjectConfigurationUpdateRequest.type, {
600-
uri: resource.toString()
603+
uri: resources[0].toString(),
604+
});
605+
} else if (resources.length > 1) {
606+
languageClient.sendNotification(ProjectConfigurationUpdateRequest.typeV2, {
607+
identifiers: resources.map(r => {
608+
return { uri: r.toString() };
609+
}),
601610
});
602611
}
603612
}
604613

614+
async function askForProjectToUpdate(): Promise<Uri[]> {
615+
let uriCandidate: Uri;
616+
if (window.activeTextEditor) {
617+
uriCandidate = window.activeTextEditor.document.uri;
618+
}
619+
620+
if (uriCandidate && isJavaConfigFile(uriCandidate.fsPath)) {
621+
return [uriCandidate];
622+
}
623+
624+
let projectUriStrings: string[];
625+
try {
626+
projectUriStrings = await commands.executeCommand<string[]>(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_ALL_JAVA_PROJECTS);
627+
} catch (e) {
628+
return uriCandidate ? [uriCandidate] : [];
629+
}
630+
631+
const projectPicks: QuickPickItem[] = projectUriStrings.map(uriString => {
632+
const projectPath = Uri.parse(uriString).fsPath;
633+
if (path.basename(projectPath) === "jdt.ls-java-project") {
634+
return undefined;
635+
}
636+
637+
return {
638+
label: path.basename(projectPath),
639+
detail: projectPath,
640+
};
641+
}).filter(Boolean);
642+
643+
if (projectPicks.length === 0) {
644+
return [];
645+
} else if (projectPicks.length === 1) {
646+
return [Uri.file(projectPicks[0].detail)];
647+
} else {
648+
// pre-select an active project based on the uri candidate.
649+
if (uriCandidate) {
650+
const candidatePath = uriCandidate.fsPath;
651+
let belongingIndex = -1;
652+
for (let i = 0; i < projectPicks.length; i++) {
653+
if (candidatePath.startsWith(projectPicks[i].detail)) {
654+
if (belongingIndex < 0
655+
|| projectPicks[i].detail.length > projectPicks[belongingIndex].detail.length) {
656+
belongingIndex = i;
657+
}
658+
}
659+
}
660+
if (belongingIndex >= 0) {
661+
projectPicks[belongingIndex].picked = true;
662+
}
663+
}
664+
665+
const choices: QuickPickItem[] | undefined = await window.showQuickPick(projectPicks, {
666+
matchOnDetail: true,
667+
placeHolder: "Please select the project(s) to update.",
668+
ignoreFocusOut: true,
669+
canPickMany: true,
670+
});
671+
if (choices && choices.length) {
672+
return choices.map(c => Uri.file(c.detail));
673+
}
674+
}
675+
676+
return [];
677+
}
678+
605679
function isJavaConfigFile(filePath: string) {
606680
const fileName = path.basename(filePath);
607681
const regEx = new RegExp(buildFilePatterns.map(r => `(${r})`).join('|'), 'i');

0 commit comments

Comments
 (0)