Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Re-organize the new class & package commands #741

Merged
merged 4 commits into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
54 changes: 30 additions & 24 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"explorer"
],
"engines": {
"vscode": "^1.69.0"
"vscode": "^1.75.0"
},
"repository": {
"type": "git",
Expand All @@ -39,10 +39,7 @@
"workspaceContains:settings.gradle.kts",
"workspaceContains:*/settings.gradle.kts",
"workspaceContains:.classpath",
"workspaceContains:*/.classpath",
"onCommand:_java.project.open",
"onCommand:java.project.create",
"onCommand:java.view.package.newJavaClass"
"workspaceContains:*/.classpath"
],
"license": "MIT",
"main": "./main.js",
Expand Down Expand Up @@ -166,6 +163,12 @@
"title": "%contributes.commands.java.view.package.copyRelativeFilePath%",
"category": "Java"
},
{
"command": "java.view.menus.file.newJavaClass",
"title": "%contributes.commands.java.view.menus.file.newJavaClass%",
"category": "Java",
"icon": "$(add)"
},
{
"command": "java.view.package.newJavaClass",
"title": "%contributes.commands.java.view.package.newJavaClass%",
Expand Down Expand Up @@ -290,7 +293,7 @@
"menus": {
"file/newFile": [
{
"command": "java.view.package.newJavaClass"
"command": "java.view.menus.file.newJavaClass"
}
],
"commandPalette": [
Expand Down Expand Up @@ -350,6 +353,10 @@
"command": "java.project.refreshLibraries",
"when": "false"
},
{
"command": "java.view.package.newJavaClass",
"when": "false"
},
{
"command": "java.view.package.newPackage",
"when": "false"
Expand Down Expand Up @@ -522,35 +529,20 @@
"group": "8_execution@6"
},
{
"command": "java.view.package.newJavaClass",
"when": "view == javaProjectExplorer && viewItem =~ /java:(package|packageRoot)(?=.*?\\b\\+source\\b)(?=.*?\\b\\+uri\\b)/",
"submenu": "javaProject.new",
"when": "view == javaProjectExplorer && (viewItem =~ /java:(package|packageRoot)(?=.*?\\b\\+source\\b)(?=.*?\\b\\+uri\\b)/ || viewItem =~ /java:project(?=.*?\\b\\+java\\b)(?=.*?\\b\\+uri\\b)/ || viewItem =~ /java:type(?=.*?\\b\\+source\\b)(?=.*?\\b\\+uri\\b)/)",
"group": "1_new@10"
},
{
"command": "java.view.package.newJavaClass",
"when": "view == javaProjectExplorer && viewItem =~ /java:project(?=.*?\\b\\+java\\b)(?=.*?\\b\\+uri\\b)/",
"group": "inline@add_0"
},
{
"command": "java.view.package.newJavaClass",
"when": "view == javaProjectExplorer && viewItem =~ /java:project(?=.*?\\b\\+java\\b)(?=.*?\\b\\+uri\\b)/",
"group": "1_new@10"
},
{
"command": "java.view.package.newJavaClass",
"when": "view == javaProjectExplorer && viewItem =~ /java:(package|packageRoot)(?=.*?\\b\\+source\\b)(?=.*?\\b\\+uri\\b)/",
"group": "inline@add_0"
},
{
"command": "java.view.package.newPackage",
"when": "view == javaProjectExplorer && viewItem =~ /java:(package|packageRoot)(?=.*?\\b\\+source\\b)(?=.*?\\b\\+uri\\b)/",
"group": "1_new@20"
},
{
"command": "java.view.package.newPackage",
"when": "view == javaProjectExplorer && viewItem =~ /java:project(?=.*?\\b\\+java\\b)(?=.*?\\b\\+uri\\b)/",
"group": "1_new@20"
},
{
"command": "java.project.addLibraries",
"alt": "java.project.addLibraryFolders",
Expand Down Expand Up @@ -594,6 +586,16 @@
"command": "java.project.update",
"group": "gradle@10"
}
],
"javaProject.new": [
{
"command": "java.view.package.newJavaClass",
"group": "new@10"
},
{
"command": "java.view.package.newPackage",
"group": "new@40"
}
]
},
"submenus": [
Expand All @@ -604,6 +606,10 @@
{
"id": "javaProject.gradle",
"label": "Gradle"
},
{
"id": "javaProject.new",
"label": "%contributes.submenus.javaProject.new%"
}
],
"views": {
Expand Down Expand Up @@ -813,7 +819,7 @@
"@types/mocha": "^9.1.1",
"@types/node": "^16.18.11",
"@types/semver": "^7.3.13",
"@types/vscode": "1.69.0",
"@types/vscode": "1.75.0",
"@vscode/test-electron": "^2.2.2",
"copy-webpack-plugin": "^11.0.0",
"glob": "^7.2.3",
Expand Down
6 changes: 4 additions & 2 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
"contributes.commands.java.view.package.exportJar": "Export Jar...",
"contributes.commands.java.view.package.copyFilePath": "Copy Path",
"contributes.commands.java.view.package.copyRelativeFilePath": "Copy Relative Path",
"contributes.commands.java.view.package.newJavaClass": "New Java Class",
"contributes.commands.java.view.package.newPackage": "New Package",
"contributes.commands.java.view.package.newJavaClass": "Java Class",
"contributes.commands.java.view.package.newPackage": "Package",
"contributes.commands.java.view.package.renameFile": "Rename",
"contributes.commands.java.view.package.moveFileToTrash": "Delete",
"contributes.commands.java.view.package.deleteFilePermanently": "Delete Permanently",
"contributes.submenus.javaProject.new": "New",
"contributes.commands.java.view.menus.file.newJavaClass": "New Java Class",
"configuration.java.dependency.showMembers": "Show the members in the explorer",
"configuration.java.dependency.syncWithFolderExplorer": "Synchronize Java Projects explorer selection with folder explorer",
"configuration.java.dependency.autoRefresh": "Synchronize Java Projects explorer with changes",
Expand Down
6 changes: 4 additions & 2 deletions package.nls.zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
"contributes.commands.java.view.package.exportJar": "导出到 Jar 文件...",
"contributes.commands.java.view.package.copyFilePath": "复制路径",
"contributes.commands.java.view.package.copyRelativeFilePath": "复制相对路径",
"contributes.commands.java.view.package.newJavaClass": "创建 Java 类",
"contributes.commands.java.view.package.newPackage": "创建包",
"contributes.commands.java.view.package.newJavaClass": "Java 类",
"contributes.commands.java.view.package.newPackage": "",
"contributes.commands.java.view.package.renameFile": "重命名",
"contributes.commands.java.view.package.moveFileToTrash": "删除",
"contributes.commands.java.view.package.deleteFilePermanently": "永久删除",
"contributes.submenus.javaProject.new": "创建",
"contributes.commands.java.view.menus.file.newJavaClass": "创建 Java 类",
"configuration.java.dependency.showMembers": "在 Java 项目管理器中显示成员",
"configuration.java.dependency.syncWithFolderExplorer": "在 Java 项目管理器中同步关联当前打开的文件",
"configuration.java.dependency.autoRefresh": "在 Java 项目管理器中自动同步修改",
Expand Down
6 changes: 4 additions & 2 deletions package.nls.zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
"contributes.commands.java.view.package.exportJar": "匯出成 Jar 檔案...",
"contributes.commands.java.view.package.copyFilePath": "複製路徑",
"contributes.commands.java.view.package.copyRelativeFilePath": "複製相對路徑",
"contributes.commands.java.view.package.newJavaClass": "建立 Java 類別",
"contributes.commands.java.view.package.newPackage": "建立套件",
"contributes.commands.java.view.package.newJavaClass": "Java 類別",
"contributes.commands.java.view.package.newPackage": "套件",
"contributes.commands.java.view.package.renameFile": "重新命名",
"contributes.commands.java.view.package.moveFileToTrash": "刪除",
"contributes.commands.java.view.package.deleteFilePermanently": "永久刪除",
"contributes.submenus.javaProject.new": "建立",
"contributes.commands.java.view.menus.file.newJavaClass": "建立 Java 類別",
"configuration.java.dependency.showMembers": "在 Java 專案管理員中顯示成員",
"configuration.java.dependency.syncWithFolderExplorer": "在 Java 專案管理員中同步關聯當前開啟的檔案",
"configuration.java.dependency.autoRefresh": "在 Java 專案管理員中自動同步修改",
Expand Down
2 changes: 2 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export namespace Commands {

export const VIEW_PACKAGE_REVEAL_IN_PROJECT_EXPLORER = "java.view.package.revealInProjectExplorer";

export const VIEW_MENUS_FILE_NEW_JAVA_CLASS = "java.view.menus.file.newJavaClass";

export const JAVA_PROJECT_OPEN = "_java.project.open";

export const JAVA_PROJECT_CREATE = "java.project.create";
Expand Down
36 changes: 20 additions & 16 deletions src/explorerCommands/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,19 @@ import * as fse from "fs-extra";
import * as path from "path";
import { commands, Extension, extensions, languages, QuickPickItem, SnippetString, TextEditor, Uri,
window, workspace, WorkspaceEdit, WorkspaceFolder } from "vscode";
import { sendInfo } from "vscode-extension-telemetry-wrapper";
import { Commands } from "../../extension.bundle";
import { Commands, PrimaryTypeNode } from "../../extension.bundle";
import { ExtensionName } from "../constants";
import { NodeKind } from "../java/nodeData";
import { DataNode } from "../views/dataNode";
import { resourceRoots } from "../views/packageRootNode";
import { checkJavaQualifiedName } from "./utility";

// TODO: separate to two function to handle creation from menu bar and explorer.
export async function newJavaClass(node?: DataNode): Promise<void> {
let packageFsPath: string | undefined;
if (!node) {
// from the new file menu entry
sendInfo("", {
triggerNewFileFrom: "menuBar",
});
packageFsPath = await inferPackageFsPath();
} else {
sendInfo("", {
triggerNewFileFrom: "projectExplorer",
});
if (!node?.uri || !canCreateClass(node)) {
return;
}
Expand Down Expand Up @@ -209,6 +202,19 @@ export async function newPackage(node?: DataNode): Promise<void> {
} 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 {
return;
}
Expand Down Expand Up @@ -239,14 +245,12 @@ export async function newPackage(node?: DataNode): Promise<void> {
await fse.ensureDir(getNewPackagePath(packageRootPath, packageName));
}

/**
* Check if the create package command is available for the given node.
* Currently the check logic is the same as the create class command.
*/
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;
return canCreateClass(node);
}

function getPackageRootPath(packageFsPath: string, packageName: string): string {
Expand Down
3 changes: 2 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { DependencyExplorer } from "./views/dependencyExplorer";
import { DiagnosticProvider } from "./tasks/buildArtifact/migration/DiagnosticProvider";
import { setContextForDeprecatedTasks, updateExportTaskType } from "./tasks/buildArtifact/migration/utils";
import { CodeActionProvider } from "./tasks/buildArtifact/migration/CodeActionProvider";
import { newJavaClass } from "./explorerCommands/new";

export async function activate(context: ExtensionContext): Promise<void> {
contextManager.initialize(context);
Expand Down Expand Up @@ -46,7 +47,7 @@ async function activateExtension(_operationId: string, context: ExtensionContext
context.subscriptions.push(tasks.registerTaskProvider(DeprecatedExportJarTaskProvider.type, new DeprecatedExportJarTaskProvider()));
context.subscriptions.push(tasks.registerTaskProvider(BuildArtifactTaskProvider.exportJarType, new BuildArtifactTaskProvider()));
context.subscriptions.push(tasks.registerTaskProvider(BuildTaskProvider.type, new BuildTaskProvider()));

context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_MENUS_FILE_NEW_JAVA_CLASS, newJavaClass));
context.subscriptions.push(window.onDidChangeActiveTextEditor((e: TextEditor | undefined) => {
setContextForReloadProject(e?.document);
}));
Expand Down
55 changes: 55 additions & 0 deletions src/views/PrimaryTypeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { isTest } from "../utility";
import { DataNode } from "./dataNode";
import { DocumentSymbolNode } from "./documentSymbolNode";
import { ExplorerNode } from "./explorerNode";
import { ProjectNode } from "./projectNode";
import { IPackageRootNodeData, PackageRootKind } from "../java/packageRootNodeData";

export class PrimaryTypeNode extends DataNode {

Expand All @@ -20,6 +22,19 @@ export class PrimaryTypeNode extends DataNode {
super(nodeData, parent);
}

public getPackageRootPath(): string {
if (this._rootNode?.uri) {
return Uri.parse(this._rootNode.uri).fsPath;
}

const unmanagedFolder = this.getUnmanagedFolderAncestor();
if (unmanagedFolder?.uri) {
return Uri.parse(unmanagedFolder.uri).fsPath;
}

return "";
}

protected async loadData(): Promise<SymbolInformation[] | DocumentSymbol[] | undefined> {
if (!this.hasChildren() || !this.nodeData.uri) {
return undefined;
Expand Down Expand Up @@ -107,6 +122,46 @@ export class PrimaryTypeNode extends DataNode {
contextValue += "+test";
}

if (this.belongsToSourceRoot() || this.getUnmanagedFolderAncestor()) {
contextValue += "+source";
}

return contextValue;
}

/**
* Check if the type belongs to a source root. Following conditions can cause the
* result to be false:
* - The type belongs to a jar package
* - The type belongs to an unmanaged folder with '.' as its source root.
*/
private belongsToSourceRoot(): boolean {
const rootNodeData = this._rootNode?.nodeData;
if (!rootNodeData) {
return false;
}

const data = <IPackageRootNodeData>rootNodeData;
if (data.entryKind === PackageRootKind.K_SOURCE) {
return true;
}

return false;
}

/**
* @returns ProjectNode if the current node is under an unmanaged folder,
* otherwise undefined.
*/
private getUnmanagedFolderAncestor(): ProjectNode | undefined {
let ancestor = this.getParent();
while (ancestor && !(ancestor instanceof ProjectNode)) {
ancestor = ancestor.getParent();
}
if (ancestor?.isUnmanagedFolder()) {
return ancestor;
}

return undefined;
}
}
8 changes: 4 additions & 4 deletions test/suite/contextValue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,19 @@ suite("Context Value Tests", () => {
});

test("test class type node", async function() {
assert.ok(/java:type(?=.*?\b\+class\b)(?=.*?\b\+uri\b)/.test((await classType.getTreeItem()).contextValue || ""));
assert.ok(/java:type(?=.*?\b\+class\b)(?=.*?\b\+source\b)(?=.*?\b\+uri\b)/.test((await classType.getTreeItem()).contextValue || ""));
});

test("test test-class type node", async function() {
assert.ok(/java:type(?=.*?\b\+class\b)(?=.*?\b\+test\b)(?=.*?\b\+uri\b)/.test((await testClassType.getTreeItem()).contextValue || ""));
assert.ok(/java:type(?=.*?\b\+class\b)(?=.*?\b\+test\b)(?=.*?\b\+source\b)(?=.*?\b\+uri\b)/.test((await testClassType.getTreeItem()).contextValue || ""));
});

test("test enum type node", async function() {
assert.ok(/java:type(?=.*?\b\+enum\b)(?=.*?\b\+uri\b)/.test((await enumType.getTreeItem()).contextValue || ""));
assert.ok(/java:type(?=.*?\b\+enum\b)(?=.*?\b\+source\b)(?=.*?\b\+uri\b)/.test((await enumType.getTreeItem()).contextValue || ""));
});

test("test interface type node", async function() {
assert.ok(/java:type(?=.*?\b\+interface\b)(?=.*?\b\+uri\b)/.test((await interfaceType.getTreeItem()).contextValue || ""));
assert.ok(/java:type(?=.*?\b\+interface\b)(?=.*?\b\+source\b)(?=.*?\b\+uri\b)/.test((await interfaceType.getTreeItem()).contextValue || ""));
});

test("test folder node", async function() {
Expand Down