Skip to content

Commit

Permalink
feat - Suppport create package from file explorer (#845)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdneo authored Jul 8, 2024
1 parent 0904e07 commit f2dfc46
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 54 deletions.
34 changes: 24 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@
"title": "%contributes.commands.java.view.package.newPackage%",
"category": "Java"
},
{
"command": "java.view.fileExplorer.newPackage",
"title": "%contributes.commands.java.view.fileExplorer.newPackage%",
"category": "Java"
},
{
"command": "java.view.package.newFile",
"title": "%contributes.commands.java.view.package.newFile%",
Expand Down Expand Up @@ -502,6 +507,10 @@
"command": "java.view.package.deleteFilePermanently",
"when": "false"
},
{
"command": "java.view.fileExplorer.newPackage",
"when": "false"
},
{
"command": "java.project.build.workspace",
"when": "false"
Expand Down Expand Up @@ -545,24 +554,29 @@
],
"explorer/context": [
{
"command": "java.view.package.revealInProjectExplorer",
"when": "resourceFilename =~ /(.*\\.gradle)|(.*\\.gradle\\.kts)|(pom\\.xml)$/ && java:serverMode == Standard",
"group": "1_javaactions"
"submenu": "javaProject.newJavaFile",
"when": "explorerResourceIsFolder",
"group": "1_javaactions@10"
},
{
"command": "java.view.package.revealInProjectExplorer",
"when": "resourceExtname == .java && java:serverMode == Standard",
"group": "1_javaactions"
"command": "java.view.fileExplorer.newPackage",
"when": "explorerResourceIsFolder",
"group": "1_javaactions@20"
},
{
"command": "_java.project.create.from.fileexplorer.menu",
"when": "explorerResourceIsFolder",
"group": "1_javaactions"
"group": "1_javaactions@30"
},
{
"submenu": "javaProject.newJavaFile",
"when": "explorerResourceIsFolder",
"group": "1_javaactions"
"command": "java.view.package.revealInProjectExplorer",
"when": "resourceFilename =~ /(.*\\.gradle)|(.*\\.gradle\\.kts)|(pom\\.xml)$/ && java:serverMode == Standard",
"group": "1_javaactions@40"
},
{
"command": "java.view.package.revealInProjectExplorer",
"when": "resourceExtname == .java && java:serverMode == Standard",
"group": "1_javaactions@40"
}
],
"editor/title": [
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"contributes.commands.java.view.package.renameFile": "Rename",
"contributes.commands.java.view.package.moveFileToTrash": "Delete",
"contributes.commands.java.view.package.deleteFilePermanently": "Delete Permanently",
"contributes.commands.java.view.fileExplorer.newPackage": "New Java Package...",
"contributes.submenus.javaProject.new": "New",
"contributes.commands.java.view.menus.file.newJavaClass": "New Java File",
"configuration.java.dependency.showMembers": "Show the members in the explorer",
Expand Down
2 changes: 2 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export namespace Commands {

export const VIEW_PACKAGE_NEW_JAVA_PACKAGE = "java.view.package.newPackage";

export const VIEW_EXPLORER_NEW_PACKAGE = "java.view.fileExplorer.newPackage";

export const VIEW_PACKAGE_RENAME_FILE = "java.view.package.renameFile";

export const VIEW_PACKAGE_MOVE_FILE_TO_TRASH = "java.view.package.moveFileToTrash";
Expand Down
146 changes: 102 additions & 44 deletions src/explorerCommands/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,15 +321,7 @@ async function inferPackageFsPath(): Promise<string> {
return getPackageFsPathFromActiveEditor();
}

let sourcePaths: string[] | undefined;
try {
const result = await commands.executeCommand<IListCommandResult>(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.LIST_SOURCEPATHS);
if (result && result.data && result.data.length) {
sourcePaths = result.data.map((entry) => entry.path);
}
} catch (e) {
// do nothing
}
let sourcePaths: string[] | undefined = (await getSourceRoots())?.data?.map((sourcePath) => sourcePath.path);

if (!window.activeTextEditor) {
if (sourcePaths?.length === 1) {
Expand Down Expand Up @@ -420,14 +412,10 @@ async function resolvePackageName(filePath: string): Promise<string> {
return guessPackageName(filePath);
}

let sourcePaths: string[] = [];
const result: IListCommandResult =
await commands.executeCommand<IListCommandResult>(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.LIST_SOURCEPATHS);
if (result && result.data && result.data.length) {
sourcePaths = result.data.map((sourcePath) => sourcePath.path).sort((a, b) => b.length - a.length);
}
let sourcePaths: string[] = (await getSourceRoots())?.data?.map(
(sourcePath) => sourcePath.path).sort((a, b) => b.length - a.length) ?? [];

if (!sourcePaths || !sourcePaths.length) {
if (!sourcePaths?.length) {
return "";
}

Expand Down Expand Up @@ -513,40 +501,30 @@ 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 || !canCreatePackage(node)) {
export async function newPackage(node: DataNode | Uri | undefined): Promise<void> {
if (!node) {
return;
}

let defaultValue: string;
let packageRootPath: string;
const nodeKind = node.nodeData.kind;
if (nodeKind === NodeKind.Project) {
defaultValue = "";
packageRootPath = await getPackageFsPath(node) || "";
} else if (nodeKind === NodeKind.PackageRoot) {
defaultValue = "";
packageRootPath = Uri.parse(node.uri).fsPath;
} else if (nodeKind === NodeKind.Package) {
defaultValue = node.nodeData.name + ".";
packageRootPath = getPackageRootPath(Uri.parse(node.uri).fsPath, node.nodeData.name);
} else if (nodeKind === NodeKind.PrimaryType) {
const primaryTypeNode = <PrimaryTypeNode> node;
packageRootPath = primaryTypeNode.getPackageRootPath();
if (packageRootPath === "") {
window.showErrorMessage("Failed to get the package root path.");
return;
}
const packagePath = await getPackageFsPath(node);
if (!packagePath) {
window.showErrorMessage("Failed to get the package path.");
return;
}
defaultValue = path.relative(packageRootPath, packagePath).replace(/[\\\/]/g, ".") + ".";
} else {
const isUri = node instanceof Uri;
if (!isUri && (!node.uri || !canCreatePackage(node))) {
return;
}

sendInfo("", {
"triggernewpackagefrom": isUri ? "fileExplorer" : "javaProjectExplorer",
});

let {defaultValue, packageRootPath} = (isUri ? await getPackageInformationFromUri(node)
: await getPackageInformationFromNode(node)) || {};
if (defaultValue === undefined || packageRootPath === undefined) {
return;
}

if (defaultValue.length > 0 && !defaultValue.endsWith(".")) {
defaultValue += ".";
}

const packageName: string | undefined = await window.showInputBox({
value: defaultValue,
placeHolder: "Input the package name",
Expand All @@ -573,6 +551,74 @@ export async function newPackage(node?: DataNode): Promise<void> {
await fse.ensureDir(getNewPackagePath(packageRootPath, packageName));
}

async function getPackageInformationFromUri(uri: Uri): Promise<Record<string, string> | undefined> {
const defaultValue = {
defaultValue: "",
packageRootPath: uri.fsPath,
};
if (!isLanguageServerReady()) {
return defaultValue;
}

let sourcePaths: string[] = (await getSourceRoots())?.data?.map(
(sourcePath) => sourcePath.path).sort((a, b) => b.length - a.length) ?? [];

if (!sourcePaths?.length) {
return defaultValue;
}

for (const sourcePath of sourcePaths) {
if (isPrefix(sourcePath, uri.fsPath)) {
const relative = path.relative(sourcePath, uri.fsPath);
return {
defaultValue: relative.replace(/[/\\]/g, "."),
packageRootPath: sourcePath,
};
}
}

return defaultValue;
}


async function getPackageInformationFromNode(node: DataNode): Promise<Record<string, string> | undefined> {
const nodeKind = node.nodeData.kind;
if (nodeKind === NodeKind.Project) {
return {
packageRootPath: await getPackageFsPath(node) || "",
defaultValue: "",
}
} else if (nodeKind === NodeKind.PackageRoot) {
return {
packageRootPath: Uri.parse(node.uri!).fsPath,
defaultValue: "",
}
} else if (nodeKind === NodeKind.Package) {
return {
packageRootPath: getPackageRootPath(Uri.parse(node.uri!).fsPath, node.nodeData.name),
defaultValue: node.nodeData.name + ".",
}
} else if (nodeKind === NodeKind.PrimaryType) {
const primaryTypeNode = <PrimaryTypeNode> node;
const packageRootPath = primaryTypeNode.getPackageRootPath();
if (packageRootPath === "") {
window.showErrorMessage("Failed to get the package root path.");
return undefined;
}
const packagePath = await getPackageFsPath(node);
if (!packagePath) {
window.showErrorMessage("Failed to get the package path.");
return undefined;
}
return {
packageRootPath: packageRootPath,
defaultValue: path.relative(packageRootPath, packagePath).replace(/[/\\]/g, "."),
}
}

return undefined;
}

/**
* Check if the create package command is available for the given node.
* Currently the check logic is the same as the create class command.
Expand Down Expand Up @@ -708,3 +754,15 @@ function getBasePath(node: DataNode): string | undefined {
return undefined;
}
}

async function getSourceRoots(): Promise<IListCommandResult | undefined>{
try {
const result = await commands.executeCommand<IListCommandResult>(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.LIST_SOURCEPATHS);
if (result?.data?.length) {
return result;
}
} catch (e) {
// ignore;
}
return undefined;
}
3 changes: 3 additions & 0 deletions src/views/dependencyExplorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ export class DependencyExplorer implements Disposable {
}
newPackage(cmdNode);
}),
instrumentOperationAsVsCodeCommand(Commands.VIEW_EXPLORER_NEW_PACKAGE, (node: Uri) => {
newPackage(node);
}),
instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_REVEAL_FILE_OS, (node?: DataNode) => {
const cmdNode = getCmdNode(this._dependencyViewer.selection, node);
if (cmdNode?.uri) {
Expand Down

0 comments on commit f2dfc46

Please sign in to comment.