Skip to content

Commit 292ee9f

Browse files
authored
fix: Create new packages or classes does not work via hotkeys (#467)
1 parent c928522 commit 292ee9f

File tree

6 files changed

+104
-30
lines changed

6 files changed

+104
-30
lines changed

src/explorerCommands/delete.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import { isMutable } from "./utility";
77

88
const confirmMessage = "Move to Recycle Bin";
99

10-
export async function deleteFiles(node: DataNode): Promise<void> {
11-
if (!isMutable(node) || !node.uri) {
10+
export async function deleteFiles(node?: DataNode): Promise<void> {
11+
if (!node?.uri || !isMutable(node)) {
1212
return;
1313
}
1414

src/explorerCommands/new.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import { NodeKind } from "../java/nodeData";
88
import { DataNode } from "../views/dataNode";
99
import { checkJavaQualifiedName } from "./utility";
1010

11-
export async function newJavaClass(node: DataNode): Promise<void> {
11+
export async function newJavaClass(node?: DataNode): Promise<void> {
12+
if (!node?.uri || !canCreateClass(node)) {
13+
return;
14+
}
15+
1216
const packageFsPath: string = await getPackageFsPath(node);
1317
if (!packageFsPath) {
1418
return;
@@ -43,6 +47,17 @@ export async function newJavaClass(node: DataNode): Promise<void> {
4347
workspace.applyEdit(workspaceEdit);
4448
}
4549

50+
function canCreateClass(node: DataNode): boolean {
51+
if (node.nodeData.kind === NodeKind.Project ||
52+
node.nodeData.kind === NodeKind.PackageRoot ||
53+
node.nodeData.kind === NodeKind.Package ||
54+
node.nodeData.kind === NodeKind.PrimaryType) {
55+
return true;
56+
}
57+
58+
return false;
59+
}
60+
4661
async function getPackageFsPath(node: DataNode): Promise<string> {
4762
if (node.nodeData.kind === NodeKind.Project) {
4863
const childrenNodes: DataNode[] = await node.getChildren() as DataNode[];
@@ -77,6 +92,8 @@ async function getPackageFsPath(node: DataNode): Promise<string> {
7792
);
7893
return choice ? choice.fsPath : "";
7994
}
95+
} else if (node.nodeData.kind === NodeKind.PrimaryType) {
96+
return node.uri ? path.dirname(Uri.parse(node.uri).fsPath) : "";
8097
}
8198

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

92-
export async function newPackage(node: DataNode): Promise<void> {
93-
if (!node.uri) {
109+
export async function newPackage(node?: DataNode): Promise<void> {
110+
if (!node?.uri || !canCreatePackage(node)) {
94111
return;
95112
}
96113

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

156+
function canCreatePackage(node: DataNode): boolean {
157+
if (node.nodeData.kind === NodeKind.Project ||
158+
node.nodeData.kind === NodeKind.PackageRoot ||
159+
node.nodeData.kind === NodeKind.Package) {
160+
return true;
161+
}
162+
163+
return false;
164+
}
165+
139166
function getPackageRootPath(packageFsPath: string, packageName: string): string {
140167
const numberOfSegment: number = packageName.split(".").length;
141168
return path.join(packageFsPath, ...Array(numberOfSegment).fill(".."));

src/explorerCommands/rename.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import { NodeKind } from "../java/nodeData";
88
import { DataNode } from "../views/dataNode";
99
import { checkJavaQualifiedName, isMutable } from "./utility";
1010

11-
export async function renameFile(node: DataNode): Promise<void> {
12-
if (!isMutable(node) || !node.uri) {
11+
export async function renameFile(node?: DataNode): Promise<void> {
12+
if (!node?.uri || !isMutable(node)) {
1313
return;
1414
}
1515

src/explorerCommands/utility.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,15 @@ export function checkJavaQualifiedName(value: string): string {
3535
return "";
3636
}
3737

38-
export function getCmdNode(selectedNode: ExplorerNode, node?: DataNode): DataNode {
38+
export function getCmdNode(selectedNodes: ExplorerNode[], node?: DataNode): DataNode | undefined {
3939
// if command not invoked by context menu, use selected node in explorer
40-
return node ? node : selectedNode as DataNode;
40+
if (node) {
41+
return node;
42+
}
43+
44+
if (selectedNodes.length > 0) {
45+
return selectedNodes[0] as DataNode;
46+
}
47+
48+
return undefined;
4149
}

src/views/dependencyDataProvider.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { instrumentOperation, instrumentOperationAsVsCodeCommand } from "vscode-
1010
import { contextManager } from "../../extension.bundle";
1111
import { Commands } from "../commands";
1212
import { Context } from "../constants";
13-
import { newJavaClass, newPackage } from "../explorerCommands/new";
1413
import { executeExportJarTask } from "../exportJarSteps/ExportJarTaskProvider";
1514
import { Jdtls } from "../java/jdtls";
1615
import { INodeData, NodeKind } from "../java/nodeData";
@@ -41,8 +40,6 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
4140
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_EXPORT_JAR, async (node: INodeData) => {
4241
executeExportJarTask(node);
4342
}));
44-
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_NEW_JAVA_CLASS, (node: DataNode) => newJavaClass(node)));
45-
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_NEW_JAVA_PACKAGE, (node: DataNode) => newPackage(node)));
4643
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_OUTLINE, (uri, range) =>
4744
window.showTextDocument(Uri.parse(uri), { selection: range })));
4845
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_PROJECT_BUILD_WORKSPACE, () =>
@@ -128,15 +125,7 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
128125
return project?.revealPaths(paths);
129126
}
130127

131-
private doRefresh(element?: ExplorerNode): void {
132-
if (!element) {
133-
this._rootItems = undefined;
134-
}
135-
explorerNodeCache.removeNodeChildren(element);
136-
this._onDidChangeTreeData.fire(element);
137-
}
138-
139-
private async getRootProjects(): Promise<ExplorerNode[]> {
128+
public async getRootProjects(): Promise<ExplorerNode[]> {
140129
const rootElements = await this.getRootNodes();
141130
if (rootElements[0] instanceof ProjectNode) {
142131
return rootElements;
@@ -152,6 +141,14 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
152141
}
153142
}
154143

144+
private doRefresh(element?: ExplorerNode): void {
145+
if (!element) {
146+
this._rootItems = undefined;
147+
}
148+
explorerNodeCache.removeNodeChildren(element);
149+
this._onDidChangeTreeData.fire(element);
150+
}
151+
155152
private async getRootNodes(): Promise<ExplorerNode[]> {
156153
try {
157154
await this._lock.acquire();

src/views/dependencyExplorer.ts

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
import * as fse from "fs-extra";
55
import * as _ from "lodash";
66
import * as path from "path";
7-
import { commands, Disposable, ExtensionContext, TextEditor, TreeView,
7+
import { commands, Disposable, ExtensionContext, QuickPickItem, TextEditor, TreeView,
88
TreeViewExpansionEvent, TreeViewSelectionChangeEvent, TreeViewVisibilityChangeEvent, Uri, window } from "vscode";
99
import { instrumentOperationAsVsCodeCommand, sendInfo } from "vscode-extension-telemetry-wrapper";
1010
import { Commands } from "../commands";
1111
import { Build } from "../constants";
1212
import { deleteFiles } from "../explorerCommands/delete";
13+
import { newJavaClass, newPackage } from "../explorerCommands/new";
1314
import { renameFile } from "../explorerCommands/rename";
1415
import { getCmdNode } from "../explorerCommands/utility";
1516
import { Jdtls } from "../java/jdtls";
@@ -96,29 +97,43 @@ export class DependencyExplorer implements Disposable {
9697

9798
// register keybinding commands
9899
context.subscriptions.push(
100+
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_NEW_JAVA_CLASS, async (node?: DataNode) => {
101+
let cmdNode = getCmdNode(this._dependencyViewer.selection, node);
102+
if (!cmdNode) {
103+
cmdNode = await this.promptForProjectNode();
104+
}
105+
newJavaClass(cmdNode);
106+
}),
107+
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_NEW_JAVA_PACKAGE, async (node?: DataNode) => {
108+
let cmdNode = getCmdNode(this._dependencyViewer.selection, node);
109+
if (!cmdNode) {
110+
cmdNode = await this.promptForProjectNode();
111+
}
112+
newPackage(cmdNode);
113+
}),
99114
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_REVEAL_FILE_OS, (node?: DataNode) => {
100-
const cmdNode = getCmdNode(this._dependencyViewer.selection[0], node);
101-
if (cmdNode.uri) {
115+
const cmdNode = getCmdNode(this._dependencyViewer.selection, node);
116+
if (cmdNode?.uri) {
102117
commands.executeCommand("revealFileInOS", Uri.parse(cmdNode.uri));
103118
}
104119
}),
105120
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_COPY_FILE_PATH, (node?: DataNode) => {
106-
const cmdNode = getCmdNode(this._dependencyViewer.selection[0], node);
107-
if (cmdNode.uri) {
121+
const cmdNode = getCmdNode(this._dependencyViewer.selection, node);
122+
if (cmdNode?.uri) {
108123
commands.executeCommand("copyFilePath", Uri.parse(cmdNode.uri));
109124
}
110125
}),
111126
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_COPY_RELATIVE_FILE_PATH, (node?: DataNode) => {
112-
const cmdNode = getCmdNode(this._dependencyViewer.selection[0], node);
113-
if (cmdNode.uri) {
127+
const cmdNode = getCmdNode(this._dependencyViewer.selection, node);
128+
if (cmdNode?.uri) {
114129
commands.executeCommand("copyRelativeFilePath", Uri.parse(cmdNode.uri));
115130
}
116131
}),
117132
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_RENAME_FILE, (node?: DataNode) => {
118-
renameFile(getCmdNode(this._dependencyViewer.selection[0], node));
133+
renameFile(getCmdNode(this._dependencyViewer.selection, node));
119134
}),
120135
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_MOVE_FILE_TO_TRASH, (node?: DataNode) => {
121-
deleteFiles(getCmdNode(this._dependencyViewer.selection[0], node));
136+
deleteFiles(getCmdNode(this._dependencyViewer.selection, node));
122137
}),
123138
);
124139
}
@@ -162,4 +177,31 @@ export class DependencyExplorer implements Disposable {
162177
public get dataProvider(): DependencyDataProvider {
163178
return this._dataProvider;
164179
}
180+
181+
private async promptForProjectNode(): Promise<DataNode | undefined> {
182+
const projects = await this._dataProvider.getRootProjects();
183+
if (projects.length === 0) {
184+
window.showInformationMessage("There is no Java projects in current workspace.");
185+
return undefined;
186+
} else if (projects.length === 1) {
187+
return projects[0] as DataNode;
188+
} else {
189+
const options: IProjectPickItem[] = projects.map((p: DataNode) => {
190+
return {
191+
label: p.name,
192+
node: p,
193+
};
194+
});
195+
const choice: IProjectPickItem | undefined = await window.showQuickPick(options, {
196+
placeHolder: "Choose a project",
197+
ignoreFocusOut: true,
198+
});
199+
200+
return choice?.node as DataNode;
201+
}
202+
}
203+
}
204+
205+
interface IProjectPickItem extends QuickPickItem {
206+
node: ExplorerNode;
165207
}

0 commit comments

Comments
 (0)