Skip to content

Commit 2db9a8d

Browse files
committed
Client side Controller support:
* Adding file/folder to referenced libraries * Removing a jar file from referenced libraries * Manually trigger refreshing of referenced libraries in classpath
1 parent 6e83b76 commit 2db9a8d

File tree

6 files changed

+133
-9
lines changed

6 files changed

+133
-9
lines changed

src/commands.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,16 @@ export namespace Commands {
3232

3333
export const JAVA_PROJECT_CREATE = "java.project.create";
3434

35+
export const JAVA_PROJECT_ADD_LIBRARIES = "java.project.addLibraries";
36+
37+
export const JAVA_PROJECT_REMOVE_LIBRARY = "java.project.removeLibrary";
38+
39+
export const JAVA_PROJECT_REFRESH_LIBRARIES = "java.project.refreshLibraries";
40+
3541
export const JAVA_PROJECT_LIST = "java.project.list";
3642

43+
export const JAVA_PROJECT_REFRESH_LIB_SERVER = "java.project.refreshLib";
44+
3745
export const JAVA_GETPACKAGEDATA = "java.getPackageData";
3846

3947
export const JAVA_RESOLVEPATH = "java.resolvePath";

src/controllers/libraryController.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
import * as chokidar from "chokidar";
5+
import * as fse from "fs-extra";
6+
import * as _ from "lodash";
7+
import { commands, Disposable, ExtensionContext, Uri, window, workspace, WorkspaceFolder } from "vscode";
8+
import { instrumentOperation } from "vscode-extension-telemetry-wrapper";
9+
import { Commands } from "../commands";
10+
import { Jdtls } from "../java/jdtls";
11+
import { Settings } from "../settings";
12+
import { Utility } from "../utility";
13+
import { DataNode } from "../views/dataNode";
14+
15+
export class LibraryController implements Disposable {
16+
17+
private libraryWatcher: chokidar.FSWatcher | undefined = undefined;
18+
19+
public constructor(public readonly context: ExtensionContext) {
20+
context.subscriptions.push(commands.registerCommand(Commands.JAVA_PROJECT_ADD_LIBRARIES,
21+
instrumentOperation(Commands.JAVA_PROJECT_ADD_LIBRARIES, (operationId: string, node: DataNode) => this.addLibraries())));
22+
context.subscriptions.push(commands.registerCommand(Commands.JAVA_PROJECT_REMOVE_LIBRARY,
23+
instrumentOperation(Commands.JAVA_PROJECT_REMOVE_LIBRARY, (operationId: string, node: DataNode) => this.removeLibrary(node.path))));
24+
context.subscriptions.push(commands.registerCommand(Commands.JAVA_PROJECT_REFRESH_LIBRARIES,
25+
instrumentOperation(Commands.JAVA_PROJECT_REFRESH_LIBRARIES, (operationId: string, node: DataNode) => this.refreshLibraries())));
26+
}
27+
28+
public dispose() {
29+
if (this.libraryWatcher) {
30+
this.libraryWatcher.close();
31+
this.libraryWatcher = undefined;
32+
}
33+
}
34+
35+
public async addLibraries(libraryGlobs?: string[]) {
36+
if (!libraryGlobs) {
37+
libraryGlobs = [];
38+
const workspaceFolder: WorkspaceFolder | undefined = Utility.getDefaultWorkspaceFolder();
39+
const results: Uri[] | undefined = await window.showOpenDialog({
40+
defaultUri: workspaceFolder && workspaceFolder.uri,
41+
canSelectFiles: true,
42+
canSelectFolders: true,
43+
canSelectMany: true,
44+
openLabel: "Select",
45+
});
46+
if (!results) {
47+
return;
48+
}
49+
libraryGlobs = await Promise.all(results.map(async (uri: Uri) => {
50+
const uriPath = workspace.asRelativePath(uri, false);
51+
return (await fse.stat(uri.fsPath)).isDirectory() ? `${uriPath}/**/*.jar` : uriPath;
52+
}));
53+
}
54+
const setting = Settings.referencedLibraries();
55+
if (Settings.isDefaultReferencedLibraries()) {
56+
setting.include = [];
57+
}
58+
setting.include.push(...libraryGlobs);
59+
Settings.updateReferencedLibraries(setting);
60+
}
61+
62+
public async removeLibrary(library: string) {
63+
const setting = Settings.referencedLibraries();
64+
setting.exclude.push(workspace.asRelativePath(library));
65+
Settings.updateReferencedLibraries(setting);
66+
}
67+
68+
public async refreshLibraries(): Promise<void> {
69+
const workspaceFolder = Utility.getDefaultWorkspaceFolder();
70+
if (workspaceFolder) {
71+
await Jdtls.refreshLibraries(workspaceFolder.uri.toString());
72+
}
73+
}
74+
}

src/controllers/projectController.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@
44
import * as fse from "fs-extra";
55
import * as _ from "lodash";
66
import * as path from "path";
7-
import { commands, ExtensionContext, Uri, window, workspace } from "vscode";
7+
import { commands, Disposable, ExtensionContext, Uri, window, workspace } from "vscode";
8+
import { instrumentOperation } from "vscode-extension-telemetry-wrapper";
89
import * as xml2js from "xml2js";
10+
import { Commands } from "../commands";
911
import { Utility } from "../utility";
1012

11-
export class ProjectController {
12-
constructor(public readonly context: ExtensionContext) {
13+
export class ProjectController implements Disposable {
14+
public constructor(public readonly context: ExtensionContext) {
15+
context.subscriptions.push(commands.registerCommand(Commands.JAVA_PROJECT_CREATE,
16+
instrumentOperation(Commands.JAVA_PROJECT_CREATE, () => this.createJavaProject())));
1317
}
1418

19+
public dispose() {}
20+
1521
public async createJavaProject() {
1622
const javaVersion: number = await this.getJavaVersion();
1723
if (!javaVersion) {

src/extension.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { commands, ExtensionContext } from "vscode";
55
import { dispose as disposeTelemetryWrapper, initializeFromJsonFile, instrumentOperation } from "vscode-extension-telemetry-wrapper";
66
import { Commands } from "./commands";
7+
import { LibraryController } from "./controllers/libraryController";
78
import { ProjectController } from "./controllers/projectController";
89
import { Services } from "./services";
910
import { Settings } from "./settings";
@@ -20,10 +21,8 @@ function activateExtension(operationId: string, context: ExtensionContext) {
2021
Services.initialize(context);
2122
Settings.initialize(context);
2223

23-
const projectController: ProjectController = new ProjectController(context);
24-
const instrumented = instrumentOperation(Commands.JAVA_PROJECT_CREATE, () => projectController.createJavaProject());
25-
context.subscriptions.push(commands.registerCommand(Commands.JAVA_PROJECT_CREATE, instrumented));
26-
24+
context.subscriptions.push(new ProjectController(context));
25+
context.subscriptions.push(new LibraryController(context));
2726
context.subscriptions.push(new DependencyExplorer(context));
2827
}
2928

src/java/jdtls.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ export namespace Jdtls {
1010
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_LIST, params);
1111
}
1212

13+
export function refreshLibraries(params): Thenable<boolean> {
14+
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_REFRESH_LIB_SERVER, params);
15+
}
16+
1317
export function getPackageData(params): Thenable<INodeData[]> {
1418
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_GETPACKAGEDATA, params);
1519
}

src/settings.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// Licensed under the MIT license.
33

44
import {
5-
commands, ConfigurationChangeEvent, Disposable, DocumentHighlight, ExtensionContext,
6-
window, workspace, WorkspaceConfiguration,
5+
commands, ConfigurationChangeEvent, ExtensionContext,
6+
workspace, WorkspaceConfiguration,
77
} from "vscode";
88
import { instrumentOperation } from "vscode-extension-telemetry-wrapper";
99
import { Commands } from "./commands";
@@ -73,6 +73,33 @@ export class Settings {
7373
workspace.getConfiguration().update("java.dependency.packagePresentation", PackagePresentation.Hierarchical, false);
7474
}
7575

76+
public static updateReferencedLibraries(setting: IReferencedLibraries): void {
77+
let updateSetting: string[] | Partial<IReferencedLibraries> = {
78+
include: setting.include,
79+
exclude: setting.exclude.length > 0 ? setting.exclude : undefined,
80+
sources: Object.keys(setting.sources).length > 0 ? setting.sources : undefined,
81+
};
82+
if (!updateSetting.exclude && !updateSetting.sources) {
83+
updateSetting = setting.include;
84+
}
85+
workspace.getConfiguration().update("java.project.referencedLibraries", updateSetting);
86+
}
87+
88+
public static referencedLibraries(): IReferencedLibraries {
89+
const setting = workspace.getConfiguration("java.project").get<string[] | Partial<IReferencedLibraries>>("referencedLibraries");
90+
const defaultSetting: IReferencedLibraries = { include: [], exclude: [], sources: {} };
91+
if (Array.isArray(setting)) {
92+
return { ...defaultSetting, include: setting };
93+
} else {
94+
return { ...defaultSetting, ...setting };
95+
}
96+
}
97+
98+
public static isDefaultReferencedLibraries(): boolean {
99+
const setting = workspace.getConfiguration("java.project").inspect<string[] | Partial<IReferencedLibraries>>("referencedLibraries");
100+
return setting.defaultValue && !setting.globalValue && !setting.workspaceValue && !setting.workspaceFolderValue;
101+
}
102+
76103
public static showOutline(): boolean {
77104
return this._dependencyConfig.get("showOutline");
78105
}
@@ -104,3 +131,9 @@ enum PackagePresentation {
104131
}
105132

106133
type Listener = (updatedConfig: WorkspaceConfiguration, oldConfig: WorkspaceConfiguration) => void;
134+
135+
export interface IReferencedLibraries {
136+
include: string[];
137+
exclude: string[];
138+
sources: { [binary: string]: string };
139+
}

0 commit comments

Comments
 (0)