Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
3 changes: 3 additions & 0 deletions images/dark/icon-add.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions images/dark/icon-remove.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions images/light/icon-add.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions images/light/icon-remove.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions jdtls.ext/com.microsoft.jdtls.ext.core/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<plugin>
<extension point="org.eclipse.jdt.ls.core.delegateCommandHandler">
<delegateCommandHandler class="com.microsoft.jdtls.ext.core.CommandHandler">
<command id="java.project.refreshLib"/>
<command id="java.project.list"/>
<command id="java.getPackageData"/>
<command id="java.resolvePath" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ public Object executeCommand(String commandId, List<Object> arguments, IProgress
if (!StringUtils.isBlank(commandId)) {
switch (commandId) {
case "java.project.list":
return ProjectCommand.execute(arguments, monitor);
return ProjectCommand.listProjects(arguments, monitor);
case "java.project.refreshLib":
return ProjectCommand.refreshLibraries(arguments, monitor);
case "java.getPackageData":
return PackageCommand.getChildren(arguments, monitor);
case "java.resolvePath":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jdt.ls.core.internal.JavaClientConnection;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.managers.UpdateClasspathJob;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
Expand All @@ -25,18 +31,30 @@ public class JdtlsExtActivator implements BundleActivator {

private static BundleContext context;

private static IJobChangeListener updateClasspathListener = new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
if (event.getJob() instanceof UpdateClasspathJob) {
JavaClientConnection connection = JavaLanguageServerPlugin.getInstance().getClientConnection();
connection.executeClientCommand("java.view.package.refresh", /* debounce = */true);
}
}
};

static BundleContext getContext() {
return context;
}

@Override
public void start(BundleContext bundleContext) throws Exception {
JdtlsExtActivator.context = bundleContext;
UpdateClasspathJob.getInstance().addJobChangeListener(JdtlsExtActivator.updateClasspathListener);
}

@Override
public void stop(BundleContext bundleContext) throws Exception {
JdtlsExtActivator.context = null;
UpdateClasspathJob.getInstance().removeJobChangeListener(JdtlsExtActivator.updateClasspathListener);
}

@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.eclipse.jdt.internal.core.JarEntryResource;
import org.eclipse.jdt.internal.core.JrtPackageFragmentRoot;
import org.eclipse.jdt.ls.core.internal.JDTUtils;
import org.eclipse.jdt.ls.core.internal.ProjectUtils;
import org.eclipse.lsp4j.jsonrpc.json.adapters.CollectionTypeAdapter;
import org.eclipse.lsp4j.jsonrpc.json.adapters.EnumTypeAdapter;

Expand Down Expand Up @@ -246,7 +247,7 @@ private static List<PackageNode> getContainers(PackageParams query, IProgressMon
.collect(Collectors.toList());
boolean isReferencedLibrariesExist = Arrays.stream(references)
.anyMatch(entry -> entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY || entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE);
if (isReferencedLibrariesExist) {
if (isReferencedLibrariesExist || !ProjectUtils.isVisibleProject(javaProject.getProject())) {
result.add(PackageNode.REFERENCED_LIBRARIES_CONTAINER);
}
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,19 @@
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.ProjectUtils;
import org.eclipse.jdt.ls.core.internal.ResourceUtils;
import org.eclipse.jdt.ls.core.internal.managers.UpdateClasspathJob;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences.ReferencedLibraries;

import com.microsoft.jdtls.ext.core.model.NodeKind;
import com.microsoft.jdtls.ext.core.model.PackageNode;

public final class ProjectCommand {

public static List<PackageNode> execute(List<Object> arguments, IProgressMonitor monitor) {
public static List<PackageNode> listProjects(List<Object> arguments, IProgressMonitor monitor) {
String workspaceUri = (String) arguments.get(0);
IPath workspacePath = ResourceUtils.canonicalFilePathFromURI(workspaceUri);
String invisibleProjectName = getWorkspaceInvisibleProjectName(workspacePath);
Expand All @@ -47,6 +52,21 @@ public static List<PackageNode> execute(List<Object> arguments, IProgressMonitor
return children;
}

public static boolean refreshLibraries(List<Object> arguments, IProgressMonitor monitor) {
String workspaceUri = (String) arguments.get(0);
IPath workspacePath = ResourceUtils.canonicalFilePathFromURI(workspaceUri);
String projectName = ProjectUtils.getWorkspaceInvisibleProjectName(workspacePath);
IProject project = getWorkspaceRoot().getProject(projectName);
try {
ReferencedLibraries libraries = JavaLanguageServerPlugin.getPreferencesManager().getPreferences().getReferencedLibraries();
UpdateClasspathJob.getInstance().updateClasspath(JavaCore.create(project), libraries);
return true;
} catch (Exception e) {
JavaLanguageServerPlugin.logException("Exception occured during waiting for classpath to be updated", e);
return false;
}
}

private static IWorkspaceRoot getWorkspaceRoot() {
return ResourcesPlugin.getWorkspace().getRoot();
}
Expand Down
50 changes: 50 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,33 @@
"title": "%contributes.commands.java.project.create%",
"category": "Java"
},
{
"command": "java.project.addLibraries",
"title": "%contributes.commands.java.project.addLibraries%",
"category": "Java",
"icon": {
"dark": "images/dark/icon-add.svg",
"light": "images/light/icon-add.svg"
}
},
{
"command": "java.project.removeLibrary",
"title": "%contributes.commands.java.project.removeLibrary%",
"category": "Java",
"icon": {
"dark": "images/dark/icon-remove.svg",
"light": "images/light/icon-remove.svg"
}
},
{
"command": "java.project.refreshLibraries",
"title": "%contributes.commands.java.view.package.refresh%",
"category": "Java",
"icon": {
"dark": "images/dark/icon-refresh.svg",
"light": "images/light/icon-refresh.svg"
}
},
{
"command": "java.view.package.refresh",
"title": "%contributes.commands.java.view.package.refresh%",
Expand Down Expand Up @@ -148,6 +175,14 @@
{
"command": "java.view.package.copyRelativeFilePath",
"when": "never"
},
{
"command": "java.project.removeLibrary",
"when": "never"
},
{
"command": "java.project.refreshLibraries",
"when": "never"
}
],
"view/title": [
Expand Down Expand Up @@ -192,6 +227,21 @@
"command": "java.view.package.copyRelativeFilePath",
"when": "view == javaDependencyExplorer && viewItem =~ /java:.*?\\+uri/",
"group": "@2"
},
{
"command": "java.project.addLibraries",
"when": "view == javaDependencyExplorer && viewItem =~ /java:container\/referenced-libraries/",
"group": "inline@0"
},
{
"command": "java.project.removeLibrary",
"when": "view == javaDependencyExplorer && viewItem =~ /java:jar\/referenced-libraries/",
"group": "inline"
},
{
"command": "java.project.refreshLibraries",
"when": "view == javaDependencyExplorer && viewItem =~ /java:container\/referenced-libraries/",
"group": "inline@1"
}
]
},
Expand Down
4 changes: 3 additions & 1 deletion package.nls.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"description": "Manage Java Dependencies in VSCode",
"contributes.commands.java.project.create": "Create Java Project",
"contributes.commands.java.project.addLibraries": "Add a jar file or a folder to project classpath",
"contributes.commands.java.project.removeLibrary": "Remove jar file from project classpath",
"contributes.commands.java.view.package.refresh": "Refresh",
"contributes.commands.java.view.package.changeRepresentation": "Change package representation",
"contributes.commands.java.view.package.changeToFlatPackageView":"Change to flat package representation",
Expand All @@ -14,6 +16,6 @@
"configuration.java.dependency.showOutline": "Enable show outline in the Java Dependency explorer",
"configuration.java.dependency.syncWithFolderExplorer": "Synchronize dependency viewer selection with folder explorer",
"configuration.java.dependency.autoRefresh": "Synchronize dependency viewer with changes",
"configuration.java.dependency.refreshDelay": "The delay time (ms) the auto refresh is invoked when changes are detected.",
"configuration.java.dependency.refreshDelay": "The delay time (ms) the auto refresh is invoked when changes are detected",
"configuration.java.dependency.packagePresentation": "Package presentation mode: flat or hierarchical"
}
4 changes: 3 additions & 1 deletion package.nls.zh.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"description": "在 VSCode 中管理 Java 依赖项",
"contributes.commands.java.project.create": "创建 Java 项目",
"contributes.commands.java.project.addLibraries": "将一个 Jar 文件或一个目录添加到 Java 项目类路径中",
"contributes.commands.java.project.removeLibrary": "将该 Jar 文件从 Java 项目类路径中移除",
"contributes.commands.java.view.package.refresh": "刷新",
"contributes.commands.java.view.package.changeRepresentation": "更改包展示形式",
"contributes.commands.java.view.package.changeToFlatPackageView":"将 Java 包显示方式切换为平行显示",
Expand All @@ -14,6 +16,6 @@
"configuration.java.dependency.showOutline": "在 Java 依赖项资源管理器中显示类成员大纲",
"configuration.java.dependency.syncWithFolderExplorer": "在 Java 依赖项资源管理器中同步关联当前打开的文件",
"configuration.java.dependency.autoRefresh": "在 Java 依赖项资源管理器中自动同步修改",
"configuration.java.dependency.refreshDelay": "控制Java 依赖项资源管理器刷新的延迟时间 (毫秒)",
"configuration.java.dependency.refreshDelay": "控制Java 依赖项资源管理器刷新的延迟时间 (毫秒)",
"configuration.java.dependency.packagePresentation": "Java 包显示方式: 平行显示或者分层显示"
}
8 changes: 8 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,16 @@ export namespace Commands {

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

export const JAVA_PROJECT_ADD_LIBRARIES = "java.project.addLibraries";

export const JAVA_PROJECT_REMOVE_LIBRARY = "java.project.removeLibrary";

export const JAVA_PROJECT_REFRESH_LIBRARIES = "java.project.refreshLibraries";

export const JAVA_PROJECT_LIST = "java.project.list";

export const JAVA_PROJECT_REFRESH_LIB_SERVER = "java.project.refreshLib";

export const JAVA_GETPACKAGEDATA = "java.getPackageData";

export const JAVA_RESOLVEPATH = "java.resolvePath";
Expand Down
69 changes: 69 additions & 0 deletions src/controllers/libraryController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import * as fse from "fs-extra";
import * as _ from "lodash";
import { commands, Disposable, ExtensionContext, Uri, window, workspace, WorkspaceFolder } from "vscode";
import { instrumentOperation } from "vscode-extension-telemetry-wrapper";
import { Commands } from "../commands";
import { Jdtls } from "../java/jdtls";
import { Settings } from "../settings";
import { Utility } from "../utility";
import { DataNode } from "../views/dataNode";

export class LibraryController implements Disposable {

private disposable: Disposable;

public constructor(public readonly context: ExtensionContext) {
this.disposable = Disposable.from(
commands.registerCommand(Commands.JAVA_PROJECT_ADD_LIBRARIES,
instrumentOperation(Commands.JAVA_PROJECT_ADD_LIBRARIES, (operationId: string, node: DataNode) => this.addLibraries())),
commands.registerCommand(Commands.JAVA_PROJECT_REMOVE_LIBRARY,
instrumentOperation(Commands.JAVA_PROJECT_REMOVE_LIBRARY, (operationId: string, node: DataNode) => this.removeLibrary(node.path))),
commands.registerCommand(Commands.JAVA_PROJECT_REFRESH_LIBRARIES,
instrumentOperation(Commands.JAVA_PROJECT_REFRESH_LIBRARIES, (operationId: string, node: DataNode) => this.refreshLibraries())),
);
}

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

public async addLibraries(libraryGlobs?: string[]) {
if (!libraryGlobs) {
libraryGlobs = [];
const workspaceFolder: WorkspaceFolder | undefined = Utility.getDefaultWorkspaceFolder();
const results: Uri[] | undefined = await window.showOpenDialog({
defaultUri: workspaceFolder && workspaceFolder.uri,
canSelectFiles: true,
canSelectFolders: true,
canSelectMany: true,
openLabel: "Select a jar file or directory to the project classpath",
});
if (!results) {
return;
}
libraryGlobs = await Promise.all(results.map(async (uri: Uri) => {
const uriPath = workspace.asRelativePath(uri, false);
return (await fse.stat(uri.fsPath)).isDirectory() ? `${uriPath}/**/*.jar` : uriPath;
}));
}
const setting = Settings.referencedLibraries();
setting.include.push(...libraryGlobs);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simply push might not work in some scenario, like:

if the original setting is:

"java.project.referencedLibraries": {
        "include": [
            "lib/**/*.jar"
        ],
        "exclude": [
            "lib/junit-platform-console-standalone-1.5.2.jar"
        ]
    }

where the junit-platform-console-standalone-1.5.2.jar is the only jar in the lib folder.

Now if I re-add the lib folder into the referenced libs, the exclude part won't be updated.

Settings.updateReferencedLibraries(setting);
}

public async removeLibrary(library: string) {
const setting = Settings.referencedLibraries();
setting.exclude.push(workspace.asRelativePath(library));
Settings.updateReferencedLibraries(setting);
}

public async refreshLibraries(): Promise<void> {
const workspaceFolder = Utility.getDefaultWorkspaceFolder();
if (workspaceFolder) {
await Jdtls.refreshLibraries(workspaceFolder.uri.toString());
}
}
}
19 changes: 16 additions & 3 deletions src/controllers/projectController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,25 @@
import * as fse from "fs-extra";
import * as _ from "lodash";
import * as path from "path";
import { commands, ExtensionContext, Uri, window, workspace } from "vscode";
import { commands, Disposable, ExtensionContext, Uri, window, workspace } from "vscode";
import { instrumentOperation } from "vscode-extension-telemetry-wrapper";
import * as xml2js from "xml2js";
import { Commands } from "../commands";
import { Utility } from "../utility";

export class ProjectController {
constructor(public readonly context: ExtensionContext) {
export class ProjectController implements Disposable {

private disposable: Disposable;

public constructor(public readonly context: ExtensionContext) {
this.disposable = Disposable.from(
commands.registerCommand(Commands.JAVA_PROJECT_CREATE,
instrumentOperation(Commands.JAVA_PROJECT_CREATE, () => this.createJavaProject())),
);
}

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

public async createJavaProject() {
Expand Down
7 changes: 3 additions & 4 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { commands, ExtensionContext } from "vscode";
import { dispose as disposeTelemetryWrapper, initializeFromJsonFile, instrumentOperation } from "vscode-extension-telemetry-wrapper";
import { Commands } from "./commands";
import { LibraryController } from "./controllers/libraryController";
import { ProjectController } from "./controllers/projectController";
import { Services } from "./services";
import { Settings } from "./settings";
Expand All @@ -20,10 +21,8 @@ function activateExtension(operationId: string, context: ExtensionContext) {
Services.initialize(context);
Settings.initialize(context);

const projectController: ProjectController = new ProjectController(context);
const instrumented = instrumentOperation(Commands.JAVA_PROJECT_CREATE, () => projectController.createJavaProject());
context.subscriptions.push(commands.registerCommand(Commands.JAVA_PROJECT_CREATE, instrumented));

context.subscriptions.push(new ProjectController(context));
context.subscriptions.push(new LibraryController(context));
context.subscriptions.push(new DependencyExplorer(context));
}

Expand Down
4 changes: 4 additions & 0 deletions src/java/jdtls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export namespace Jdtls {
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_LIST, params);
}

export function refreshLibraries(params): Thenable<boolean> {
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_REFRESH_LIB_SERVER, params);
}

export function getPackageData(params): Thenable<INodeData[]> {
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_GETPACKAGEDATA, params);
}
Expand Down
Loading