Skip to content

Commit

Permalink
fix: Create new packages or classes does not work via hotkeys (#467)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdneo authored Mar 9, 2021
1 parent c928522 commit 292ee9f
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 30 deletions.
4 changes: 2 additions & 2 deletions src/explorerCommands/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { isMutable } from "./utility";

const confirmMessage = "Move to Recycle Bin";

export async function deleteFiles(node: DataNode): Promise<void> {
if (!isMutable(node) || !node.uri) {
export async function deleteFiles(node?: DataNode): Promise<void> {
if (!node?.uri || !isMutable(node)) {
return;
}

Expand Down
33 changes: 30 additions & 3 deletions src/explorerCommands/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import { NodeKind } from "../java/nodeData";
import { DataNode } from "../views/dataNode";
import { checkJavaQualifiedName } from "./utility";

export async function newJavaClass(node: DataNode): Promise<void> {
export async function newJavaClass(node?: DataNode): Promise<void> {
if (!node?.uri || !canCreateClass(node)) {
return;
}

const packageFsPath: string = await getPackageFsPath(node);
if (!packageFsPath) {
return;
Expand Down Expand Up @@ -43,6 +47,17 @@ export async function newJavaClass(node: DataNode): Promise<void> {
workspace.applyEdit(workspaceEdit);
}

function canCreateClass(node: DataNode): boolean {
if (node.nodeData.kind === NodeKind.Project ||
node.nodeData.kind === NodeKind.PackageRoot ||
node.nodeData.kind === NodeKind.Package ||
node.nodeData.kind === NodeKind.PrimaryType) {
return true;
}

return false;
}

async function getPackageFsPath(node: DataNode): Promise<string> {
if (node.nodeData.kind === NodeKind.Project) {
const childrenNodes: DataNode[] = await node.getChildren() as DataNode[];
Expand Down Expand Up @@ -77,6 +92,8 @@ async function getPackageFsPath(node: DataNode): Promise<string> {
);
return choice ? choice.fsPath : "";
}
} else if (node.nodeData.kind === NodeKind.PrimaryType) {
return node.uri ? path.dirname(Uri.parse(node.uri).fsPath) : "";
}

return node.uri ? Uri.parse(node.uri).fsPath : "";
Expand All @@ -89,8 +106,8 @@ function getNewFilePath(basePath: string, className: string): string {
return path.join(basePath, ...className.split(".")) + ".java";
}

export async function newPackage(node: DataNode): Promise<void> {
if (!node.uri) {
export async function newPackage(node?: DataNode): Promise<void> {
if (!node?.uri || !canCreatePackage(node)) {
return;
}

Expand Down Expand Up @@ -136,6 +153,16 @@ export async function newPackage(node: DataNode): Promise<void> {
await fse.ensureDir(getNewPackagePath(packageRootPath, packageName));
}

function canCreatePackage(node: DataNode): boolean {
if (node.nodeData.kind === NodeKind.Project ||
node.nodeData.kind === NodeKind.PackageRoot ||
node.nodeData.kind === NodeKind.Package) {
return true;
}

return false;
}

function getPackageRootPath(packageFsPath: string, packageName: string): string {
const numberOfSegment: number = packageName.split(".").length;
return path.join(packageFsPath, ...Array(numberOfSegment).fill(".."));
Expand Down
4 changes: 2 additions & 2 deletions src/explorerCommands/rename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { NodeKind } from "../java/nodeData";
import { DataNode } from "../views/dataNode";
import { checkJavaQualifiedName, isMutable } from "./utility";

export async function renameFile(node: DataNode): Promise<void> {
if (!isMutable(node) || !node.uri) {
export async function renameFile(node?: DataNode): Promise<void> {
if (!node?.uri || !isMutable(node)) {
return;
}

Expand Down
12 changes: 10 additions & 2 deletions src/explorerCommands/utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,15 @@ export function checkJavaQualifiedName(value: string): string {
return "";
}

export function getCmdNode(selectedNode: ExplorerNode, node?: DataNode): DataNode {
export function getCmdNode(selectedNodes: ExplorerNode[], node?: DataNode): DataNode | undefined {
// if command not invoked by context menu, use selected node in explorer
return node ? node : selectedNode as DataNode;
if (node) {
return node;
}

if (selectedNodes.length > 0) {
return selectedNodes[0] as DataNode;
}

return undefined;
}
21 changes: 9 additions & 12 deletions src/views/dependencyDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { instrumentOperation, instrumentOperationAsVsCodeCommand } from "vscode-
import { contextManager } from "../../extension.bundle";
import { Commands } from "../commands";
import { Context } from "../constants";
import { newJavaClass, newPackage } from "../explorerCommands/new";
import { executeExportJarTask } from "../exportJarSteps/ExportJarTaskProvider";
import { Jdtls } from "../java/jdtls";
import { INodeData, NodeKind } from "../java/nodeData";
Expand Down Expand Up @@ -41,8 +40,6 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_EXPORT_JAR, async (node: INodeData) => {
executeExportJarTask(node);
}));
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_NEW_JAVA_CLASS, (node: DataNode) => newJavaClass(node)));
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_NEW_JAVA_PACKAGE, (node: DataNode) => newPackage(node)));
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_OUTLINE, (uri, range) =>
window.showTextDocument(Uri.parse(uri), { selection: range })));
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_BUILD_WORKSPACE, () =>
Expand Down Expand Up @@ -128,15 +125,7 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
return project?.revealPaths(paths);
}

private doRefresh(element?: ExplorerNode): void {
if (!element) {
this._rootItems = undefined;
}
explorerNodeCache.removeNodeChildren(element);
this._onDidChangeTreeData.fire(element);
}

private async getRootProjects(): Promise<ExplorerNode[]> {
public async getRootProjects(): Promise<ExplorerNode[]> {
const rootElements = await this.getRootNodes();
if (rootElements[0] instanceof ProjectNode) {
return rootElements;
Expand All @@ -152,6 +141,14 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
}
}

private doRefresh(element?: ExplorerNode): void {
if (!element) {
this._rootItems = undefined;
}
explorerNodeCache.removeNodeChildren(element);
this._onDidChangeTreeData.fire(element);
}

private async getRootNodes(): Promise<ExplorerNode[]> {
try {
await this._lock.acquire();
Expand Down
60 changes: 51 additions & 9 deletions src/views/dependencyExplorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
import * as fse from "fs-extra";
import * as _ from "lodash";
import * as path from "path";
import { commands, Disposable, ExtensionContext, TextEditor, TreeView,
import { commands, Disposable, ExtensionContext, QuickPickItem, TextEditor, TreeView,
TreeViewExpansionEvent, TreeViewSelectionChangeEvent, TreeViewVisibilityChangeEvent, Uri, window } from "vscode";
import { instrumentOperationAsVsCodeCommand, sendInfo } from "vscode-extension-telemetry-wrapper";
import { Commands } from "../commands";
import { Build } from "../constants";
import { deleteFiles } from "../explorerCommands/delete";
import { newJavaClass, newPackage } from "../explorerCommands/new";
import { renameFile } from "../explorerCommands/rename";
import { getCmdNode } from "../explorerCommands/utility";
import { Jdtls } from "../java/jdtls";
Expand Down Expand Up @@ -96,29 +97,43 @@ export class DependencyExplorer implements Disposable {

// register keybinding commands
context.subscriptions.push(
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_NEW_JAVA_CLASS, async (node?: DataNode) => {
let cmdNode = getCmdNode(this._dependencyViewer.selection, node);
if (!cmdNode) {
cmdNode = await this.promptForProjectNode();
}
newJavaClass(cmdNode);
}),
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_NEW_JAVA_PACKAGE, async (node?: DataNode) => {
let cmdNode = getCmdNode(this._dependencyViewer.selection, node);
if (!cmdNode) {
cmdNode = await this.promptForProjectNode();
}
newPackage(cmdNode);
}),
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_REVEAL_FILE_OS, (node?: DataNode) => {
const cmdNode = getCmdNode(this._dependencyViewer.selection[0], node);
if (cmdNode.uri) {
const cmdNode = getCmdNode(this._dependencyViewer.selection, node);
if (cmdNode?.uri) {
commands.executeCommand("revealFileInOS", Uri.parse(cmdNode.uri));
}
}),
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_COPY_FILE_PATH, (node?: DataNode) => {
const cmdNode = getCmdNode(this._dependencyViewer.selection[0], node);
if (cmdNode.uri) {
const cmdNode = getCmdNode(this._dependencyViewer.selection, node);
if (cmdNode?.uri) {
commands.executeCommand("copyFilePath", Uri.parse(cmdNode.uri));
}
}),
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_COPY_RELATIVE_FILE_PATH, (node?: DataNode) => {
const cmdNode = getCmdNode(this._dependencyViewer.selection[0], node);
if (cmdNode.uri) {
const cmdNode = getCmdNode(this._dependencyViewer.selection, node);
if (cmdNode?.uri) {
commands.executeCommand("copyRelativeFilePath", Uri.parse(cmdNode.uri));
}
}),
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_RENAME_FILE, (node?: DataNode) => {
renameFile(getCmdNode(this._dependencyViewer.selection[0], node));
renameFile(getCmdNode(this._dependencyViewer.selection, node));
}),
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_MOVE_FILE_TO_TRASH, (node?: DataNode) => {
deleteFiles(getCmdNode(this._dependencyViewer.selection[0], node));
deleteFiles(getCmdNode(this._dependencyViewer.selection, node));
}),
);
}
Expand Down Expand Up @@ -162,4 +177,31 @@ export class DependencyExplorer implements Disposable {
public get dataProvider(): DependencyDataProvider {
return this._dataProvider;
}

private async promptForProjectNode(): Promise<DataNode | undefined> {
const projects = await this._dataProvider.getRootProjects();
if (projects.length === 0) {
window.showInformationMessage("There is no Java projects in current workspace.");
return undefined;
} else if (projects.length === 1) {
return projects[0] as DataNode;
} else {
const options: IProjectPickItem[] = projects.map((p: DataNode) => {
return {
label: p.name,
node: p,
};
});
const choice: IProjectPickItem | undefined = await window.showQuickPick(options, {
placeHolder: "Choose a project",
ignoreFocusOut: true,
});

return choice?.node as DataNode;
}
}
}

interface IProjectPickItem extends QuickPickItem {
node: ExplorerNode;
}

0 comments on commit 292ee9f

Please sign in to comment.