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: Add test metadata to the nodes #437

Merged
merged 3 commits into from
Jan 8, 2021
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
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,9 @@ private static List<PackageNode> getPackageFragmentRoots(PackageParams query, IP

IClasspathEntry resolvedClasspathEntry = fragmentRoot.getResolvedClasspathEntry();
if (resolvedClasspathEntry != null) {
Map<String, String> attributes = new HashMap<>();
for (IClasspathAttribute attribute : resolvedClasspathEntry.getExtraAttributes()) {
attributes.put(attribute.getName(), attribute.getValue());
node.setMetaDataValue(attribute.getName(), attribute.getValue());
}
node.setAttributes(attributes);
}

children.add(node);
Expand Down
23 changes: 23 additions & 0 deletions src/utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { Uri, window, workspace, WorkspaceFolder } from "vscode";
import { setUserError } from "vscode-extension-telemetry-wrapper";
import { INodeData } from "./java/nodeData";
import { languageServerApiManager } from "./languageServerApi/languageServerApiManager";
import { Settings } from "./settings";

Expand Down Expand Up @@ -95,3 +96,25 @@ const identifierRegExp: RegExp = /^([a-zA-Z_$][a-zA-Z\d_$]*)$/;
export function isJavaIdentifier(identifier: string): boolean {
return identifierRegExp.test(identifier);
}

export function isTest(nodeData: INodeData | undefined): boolean {
if (!nodeData) {
return false;
}

if (nodeData.metaData?.test === "true") {
return true;
}

const mavenScope: string = nodeData.metaData?.["maven.scope"] || "";
if (mavenScope.toLocaleLowerCase().includes("test")) {
return true;
}

const gradleScope: string = nodeData.metaData?.gradle_scope || "";
if (gradleScope.toLocaleLowerCase().includes("test")) {
return true;
}

return false;
}
17 changes: 12 additions & 5 deletions src/views/PrimaryTypeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Commands } from "../commands";
import { Explorer } from "../constants";
import { INodeData, TypeKind } from "../java/nodeData";
import { Settings } from "../settings";
import { isTest } from "../utility";
import { DataNode } from "./dataNode";
import { DocumentSymbolNode } from "./documentSymbolNode";
import { ExplorerNode } from "./explorerNode";
Expand All @@ -15,7 +16,7 @@ export class PrimaryTypeNode extends DataNode {

public static K_TYPE_KIND = "TypeKind";

constructor(nodeData: INodeData, parent: DataNode) {
constructor(nodeData: INodeData, parent: DataNode, protected _rootNode?: DataNode) {
super(nodeData, parent);
}

Expand Down Expand Up @@ -91,15 +92,21 @@ export class PrimaryTypeNode extends DataNode {
}

protected get contextValue(): string {
const context = Explorer.ContextValueType.Type;
let contextValue: string = Explorer.ContextValueType.Type;
const type = this.nodeData.metaData?.[PrimaryTypeNode.K_TYPE_KIND];

if (type === TypeKind.Enum) {
return `${context}+enum`;
contextValue += "+enum";
} else if (type === TypeKind.Interface) {
return `${context}+interface`;
contextValue += "+interface";
} else {
return `${context}+class`;
contextValue += "+class";
}

if (isTest(this._rootNode?.nodeData)) {
contextValue += "+test";
}

return contextValue;
}
}
2 changes: 1 addition & 1 deletion src/views/hierarchicalPackageNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class HierarchicalPackageNode extends PackageNode {
result.push(new HierarchicalPackageNode(nodeData, this, this._project, this._rootNode));
} else if (nodeData.kind === NodeKind.PrimaryType) {
if (nodeData.metaData && nodeData.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
result.push(new PrimaryTypeNode(nodeData, this));
result.push(new PrimaryTypeNode(nodeData, this, this._rootNode));
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/views/hierarchicalPackageRootNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class HierarchicalPackageRootNode extends PackageRootNode {
result.push(new FolderNode(data, this, this._project, this));
} else if (data.kind === NodeKind.PrimaryType) {
if (data.metaData && data.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
result.push(new PrimaryTypeNode(data, this));
result.push(new PrimaryTypeNode(data, this, this));
}
}
});
Expand Down
13 changes: 9 additions & 4 deletions src/views/packageNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Explorer } from "../constants";
import { Jdtls } from "../java/jdtls";
import { INodeData, NodeKind } from "../java/nodeData";
import { IPackageRootNodeData, PackageRootKind } from "../java/packageRootNodeData";
import { isTest } from "../utility";
import { DataNode } from "./dataNode";
import { ExplorerNode } from "./explorerNode";
import { FileNode } from "./fileNode";
Expand Down Expand Up @@ -34,7 +35,7 @@ export class PackageNode extends DataNode {
result.push(new FileNode(nodeData, this));
} else if (nodeData.kind === NodeKind.PrimaryType) {
if (nodeData.metaData && nodeData.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
result.push(new PrimaryTypeNode(nodeData, this));
result.push(new PrimaryTypeNode(nodeData, this, this._rootNode));
}
}
});
Expand All @@ -48,11 +49,15 @@ export class PackageNode extends DataNode {

protected get contextValue(): string | undefined {
const parentData = <IPackageRootNodeData> this._rootNode.nodeData;
let contextValue: string = Explorer.ContextValueType.Package;
if (parentData.entryKind === PackageRootKind.K_SOURCE || parentData.kind === NodeKind.Project) {
return `${Explorer.ContextValueType.Package}+source`;
contextValue += "+source";
} else if (parentData.entryKind === PackageRootKind.K_BINARY) {
return `${Explorer.ContextValueType.Package}+binary`;
contextValue += "+binary";
}
return undefined;
if (isTest(parentData)) {
contextValue += "+test";
}
return contextValue;
}
}
25 changes: 17 additions & 8 deletions src/views/packageRootNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Jdtls } from "../java/jdtls";
import { INodeData, NodeKind } from "../java/nodeData";
import { IPackageRootNodeData, PackageRootKind } from "../java/packageRootNodeData";
import { Settings } from "../settings";
import { isTest } from "../utility";
import { ContainerNode } from "./containerNode";
import { DataNode } from "./dataNode";
import { ExplorerNode } from "./explorerNode";
Expand Down Expand Up @@ -45,7 +46,7 @@ export class PackageRootNode extends DataNode {
result.push(new FolderNode(data, this, this._project, this));
} else if (data.kind === NodeKind.PrimaryType) {
if (data.metaData && data.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
result.push(new PrimaryTypeNode(data, this));
result.push(new PrimaryTypeNode(data, this, this));
}
}
});
Expand All @@ -64,20 +65,28 @@ export class PackageRootNode extends DataNode {

protected get contextValue(): string {
const data = <IPackageRootNodeData>this.nodeData;
let contextValue: string;
if (data.entryKind === PackageRootKind.K_BINARY) {
let contextValue: string = Explorer.ContextValueType.Jar;
contextValue = Explorer.ContextValueType.Jar;
const parent = <ContainerNode>this.getParent();
if (parent.path?.startsWith("REFERENCED_LIBRARIES_PATH")) {
contextValue += "+referencedLibrary";
}
return contextValue;
} else if (resourceRoots.includes(this._nodeData.name)) {
// APIs in JDT does not have a consistent result telling whether a package root
// is a source root or resource root, so we hard code some common resources root
// here as a workaround.
return `${Explorer.ContextValueType.PackageRoot}+resource`;
} else {
return `${Explorer.ContextValueType.PackageRoot}+source`;
contextValue = Explorer.ContextValueType.PackageRoot;
if (isTest(data)) {
contextValue += "+test";
}
if (resourceRoots.includes(this._nodeData.name)) {
// APIs in JDT does not have a consistent result telling whether a package root
// is a source root or resource root, so we hard code some common resources root
// here as a workaround.
contextValue += "+resource";
} else {
contextValue += "+source";
}
return contextValue;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/views/projectNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export class ProjectNode extends DataNode {
// For invisible project with empty named package root with a default package,
// types will be the project node's children
if (data.metaData && data.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
result.push(new PrimaryTypeNode(data, this));
result.push(new PrimaryTypeNode(data, this, undefined));
}
}
});
Expand Down
88 changes: 67 additions & 21 deletions test/suite/contextValue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,78 +8,99 @@ import { ContainerNode, FileNode, FolderNode, INodeData, NodeKind, PackageNode,

// tslint:disable: only-arrow-functions
// tslint:disable: no-object-literal-type-assertion

/**
* This suite is to test the context value of different nodes in the explorer,
* Users can register their commands to the nodes by writing RegExp to match the metadata.
* More details, please see: https://github.com/microsoft/vscode-java-dependency/wiki/Register-Command-onto-the-Nodes-of-Project-View
*/
suite("Context Value Tests", () => {

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

test("test Maven project node", async function() {
assert.equal((await mavenProject.getTreeItem()).contextValue, "java:project+java+maven+uri");
assert.ok(/java:project(?=.*?\b\+java\b)(?=.*?\b\+maven\b)(?=.*?\b\+uri\b)/.test((await mavenProject.getTreeItem()).contextValue || ""));
});

test("test Gradle project node", async function() {
assert.equal((await gradleProject.getTreeItem()).contextValue, "java:project+java+gradle+uri");
assert.ok(/java:project(?=.*?\b\+java\b)(?=.*?\b\+gradle\b)(?=.*?\b\+uri\b)/.test((await gradleProject.getTreeItem()).contextValue || ""));
});

test("test JRE container node", async function() {
assert.equal((await jreContainer.getTreeItem()).contextValue, "java:container+jre+uri");
assert.ok(/java:container(?=.*?\b\+jre\b)(?=.*?\b\+uri\b)/.test((await jreContainer.getTreeItem()).contextValue || ""));
});

test("test Maven container node", async function() {
assert.equal((await mavenContainer.getTreeItem()).contextValue, "java:container+maven+uri");
assert.ok(/java:container(?=.*?\b\+maven\b)(?=.*?\b\+uri\b)/.test((await mavenContainer.getTreeItem()).contextValue || ""));
});

test("test Gradle container node", async function() {
assert.equal((await gradleContainer.getTreeItem()).contextValue, "java:container+gradle+uri");
assert.ok(/java:container(?=.*?\b\+gradle\b)(?=.*?\b\+uri\b)/.test((await gradleContainer.getTreeItem()).contextValue || ""));
Copy link
Member

Choose a reason for hiding this comment

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

suggest to assign human-readable names to these regular expressions...

Copy link
Member Author

Choose a reason for hiding this comment

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

These are all the regexp that can be written in the package.json to register the commands to the node.

I add some comments at header to explain the purpose of this suite.

});

test("test Referenced Libraries container node", async function() {
assert.equal((await referencedLibrariesContainer.getTreeItem()).contextValue, "java:container+referencedLibrary+uri");
assert.ok(/java:container(?=.*?\b\+referencedLibrary\b)(?=.*?\b\+uri\b)/
.test((await referencedLibrariesContainer.getTreeItem()).contextValue || ""));
});

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

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

test("test resource root node", async function() {
assert.equal((await resourceRoot.getTreeItem()).contextValue, "java:packageRoot+resource+uri");
assert.ok(/java:packageRoot(?=.*?\b\+resource\b)(?=.*?\b\+uri\b)/.test((await resourceRoot.getTreeItem()).contextValue || ""));
});

test("test dependency jar node", async function() {
assert.equal((await dependencyJar.getTreeItem()).contextValue, "java:jar+uri");
assert.ok(/java:jar(?=.*?\b\+uri\b)/.test((await dependencyJar.getTreeItem()).contextValue || ""));
});

test("test referenced library jar node", async function() {
assert.equal((await referencedLibraryJar.getTreeItem()).contextValue, "java:jar+referencedLibrary+uri");
assert.ok(/java:jar(?=.*?\b\+referencedLibrary\b)(?=.*?\b\+uri\b)/.test((await referencedLibraryJar.getTreeItem()).contextValue || ""));
});

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

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

test("test binary package node", async function() {
assert.equal((await binaryPackage.getTreeItem()).contextValue, "java:package+binary+uri");
assert.ok(/java:package(?=.*?\b\+binary\b)(?=.*?\b\+uri\b)/.test((await binaryPackage.getTreeItem()).contextValue || ""));
});

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

test("test class type node", async function() {
assert.equal((await classType.getTreeItem()).contextValue, "java:type+class+uri");
assert.ok(/java:type(?=.*?\b\+class\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 || ""));
});

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

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

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

Expand Down Expand Up @@ -143,6 +164,16 @@ const sourceRoot: PackageRootNode = new PackageRootNode({
entryKind: PackageRootKind.K_SOURCE,
} as INodeData, mavenContainer, mavenProject);

const testSourceRoot: PackageRootNode = new PackageRootNode({
name: "src/main/java",
uri: Uri.file(__dirname).toString(),
kind: NodeKind.PackageRoot,
entryKind: PackageRootKind.K_SOURCE,
metaData: {
test: "true",
},
} as INodeData, mavenContainer, mavenProject);

const resourceRoot: PackageRootNode = new PackageRootNode({
name: "src/main/resources",
uri: Uri.file(__dirname).toString(),
Expand Down Expand Up @@ -170,6 +201,12 @@ const sourcePackage: PackageNode = new PackageNode({
kind: NodeKind.Package,
}, sourceRoot, mavenProject, sourceRoot);

const testSourcePackage: PackageNode = new PackageNode({
name: "com.microsoft.java",
uri: Uri.file(__dirname).toString(),
kind: NodeKind.Package,
}, testSourceRoot, mavenProject, testSourceRoot);

const binaryPackage: PackageNode = new PackageNode({
name: "junit",
uri: Uri.file(__dirname).toString(),
Expand All @@ -189,7 +226,16 @@ const classType: PrimaryTypeNode = new PrimaryTypeNode({
metaData: {
TypeKind: TypeKind.Class,
},
}, sourcePackage);
}, sourcePackage, sourceRoot);

const testClassType: PrimaryTypeNode = new PrimaryTypeNode({
name: "App",
uri: Uri.file(__dirname).toString(),
kind: NodeKind.PrimaryType,
metaData: {
TypeKind: TypeKind.Class,
},
}, testSourcePackage, testSourceRoot);

const enumType: PrimaryTypeNode = new PrimaryTypeNode({
name: "LanguageServerMode",
Expand All @@ -198,7 +244,7 @@ const enumType: PrimaryTypeNode = new PrimaryTypeNode({
metaData: {
TypeKind: TypeKind.Enum,
},
}, sourcePackage);
}, sourcePackage, sourceRoot);

const interfaceType: PrimaryTypeNode = new PrimaryTypeNode({
name: "Controller",
Expand All @@ -207,7 +253,7 @@ const interfaceType: PrimaryTypeNode = new PrimaryTypeNode({
metaData: {
TypeKind: TypeKind.Interface,
},
}, sourcePackage);
}, sourcePackage, sourceRoot);

const folder: FolderNode = new FolderNode({
name: "static",
Expand Down
3 changes: 2 additions & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"log",
"error"
],
"no-namespace": false
"no-namespace": false,
"prefer-conditional-expression": false
}
}