Skip to content

Commit 0ec8146

Browse files
authored
feat: Add test metadata to the nodes (#437)
1 parent 95ff1ba commit 0ec8146

File tree

10 files changed

+134
-45
lines changed

10 files changed

+134
-45
lines changed

jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,9 @@ private static List<PackageNode> getPackageFragmentRoots(PackageParams query, IP
303303

304304
IClasspathEntry resolvedClasspathEntry = fragmentRoot.getResolvedClasspathEntry();
305305
if (resolvedClasspathEntry != null) {
306-
Map<String, String> attributes = new HashMap<>();
307306
for (IClasspathAttribute attribute : resolvedClasspathEntry.getExtraAttributes()) {
308-
attributes.put(attribute.getName(), attribute.getValue());
307+
node.setMetaDataValue(attribute.getName(), attribute.getValue());
309308
}
310-
node.setAttributes(attributes);
311309
}
312310

313311
children.add(node);

src/utility.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import { Uri, window, workspace, WorkspaceFolder } from "vscode";
55
import { setUserError } from "vscode-extension-telemetry-wrapper";
6+
import { INodeData } from "./java/nodeData";
67
import { languageServerApiManager } from "./languageServerApi/languageServerApiManager";
78
import { Settings } from "./settings";
89

@@ -95,3 +96,25 @@ const identifierRegExp: RegExp = /^([a-zA-Z_$][a-zA-Z\d_$]*)$/;
9596
export function isJavaIdentifier(identifier: string): boolean {
9697
return identifierRegExp.test(identifier);
9798
}
99+
100+
export function isTest(nodeData: INodeData | undefined): boolean {
101+
if (!nodeData) {
102+
return false;
103+
}
104+
105+
if (nodeData.metaData?.test === "true") {
106+
return true;
107+
}
108+
109+
const mavenScope: string = nodeData.metaData?.["maven.scope"] || "";
110+
if (mavenScope.toLocaleLowerCase().includes("test")) {
111+
return true;
112+
}
113+
114+
const gradleScope: string = nodeData.metaData?.gradle_scope || "";
115+
if (gradleScope.toLocaleLowerCase().includes("test")) {
116+
return true;
117+
}
118+
119+
return false;
120+
}

src/views/PrimaryTypeNode.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Commands } from "../commands";
77
import { Explorer } from "../constants";
88
import { INodeData, TypeKind } from "../java/nodeData";
99
import { Settings } from "../settings";
10+
import { isTest } from "../utility";
1011
import { DataNode } from "./dataNode";
1112
import { DocumentSymbolNode } from "./documentSymbolNode";
1213
import { ExplorerNode } from "./explorerNode";
@@ -15,7 +16,7 @@ export class PrimaryTypeNode extends DataNode {
1516

1617
public static K_TYPE_KIND = "TypeKind";
1718

18-
constructor(nodeData: INodeData, parent: DataNode) {
19+
constructor(nodeData: INodeData, parent: DataNode, protected _rootNode?: DataNode) {
1920
super(nodeData, parent);
2021
}
2122

@@ -91,15 +92,21 @@ export class PrimaryTypeNode extends DataNode {
9192
}
9293

9394
protected get contextValue(): string {
94-
const context = Explorer.ContextValueType.Type;
95+
let contextValue: string = Explorer.ContextValueType.Type;
9596
const type = this.nodeData.metaData?.[PrimaryTypeNode.K_TYPE_KIND];
9697

9798
if (type === TypeKind.Enum) {
98-
return `${context}+enum`;
99+
contextValue += "+enum";
99100
} else if (type === TypeKind.Interface) {
100-
return `${context}+interface`;
101+
contextValue += "+interface";
101102
} else {
102-
return `${context}+class`;
103+
contextValue += "+class";
103104
}
105+
106+
if (isTest(this._rootNode?.nodeData)) {
107+
contextValue += "+test";
108+
}
109+
110+
return contextValue;
104111
}
105112
}

src/views/hierarchicalPackageNode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export class HierarchicalPackageNode extends PackageNode {
7272
result.push(new HierarchicalPackageNode(nodeData, this, this._project, this._rootNode));
7373
} else if (nodeData.kind === NodeKind.PrimaryType) {
7474
if (nodeData.metaData && nodeData.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
75-
result.push(new PrimaryTypeNode(nodeData, this));
75+
result.push(new PrimaryTypeNode(nodeData, this, this._rootNode));
7676
}
7777
}
7878
});

src/views/hierarchicalPackageRootNode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class HierarchicalPackageRootNode extends PackageRootNode {
4141
result.push(new FolderNode(data, this, this._project, this));
4242
} else if (data.kind === NodeKind.PrimaryType) {
4343
if (data.metaData && data.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
44-
result.push(new PrimaryTypeNode(data, this));
44+
result.push(new PrimaryTypeNode(data, this, this));
4545
}
4646
}
4747
});

src/views/packageNode.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Explorer } from "../constants";
66
import { Jdtls } from "../java/jdtls";
77
import { INodeData, NodeKind } from "../java/nodeData";
88
import { IPackageRootNodeData, PackageRootKind } from "../java/packageRootNodeData";
9+
import { isTest } from "../utility";
910
import { DataNode } from "./dataNode";
1011
import { ExplorerNode } from "./explorerNode";
1112
import { FileNode } from "./fileNode";
@@ -34,7 +35,7 @@ export class PackageNode extends DataNode {
3435
result.push(new FileNode(nodeData, this));
3536
} else if (nodeData.kind === NodeKind.PrimaryType) {
3637
if (nodeData.metaData && nodeData.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
37-
result.push(new PrimaryTypeNode(nodeData, this));
38+
result.push(new PrimaryTypeNode(nodeData, this, this._rootNode));
3839
}
3940
}
4041
});
@@ -48,11 +49,15 @@ export class PackageNode extends DataNode {
4849

4950
protected get contextValue(): string | undefined {
5051
const parentData = <IPackageRootNodeData> this._rootNode.nodeData;
52+
let contextValue: string = Explorer.ContextValueType.Package;
5153
if (parentData.entryKind === PackageRootKind.K_SOURCE || parentData.kind === NodeKind.Project) {
52-
return `${Explorer.ContextValueType.Package}+source`;
54+
contextValue += "+source";
5355
} else if (parentData.entryKind === PackageRootKind.K_BINARY) {
54-
return `${Explorer.ContextValueType.Package}+binary`;
56+
contextValue += "+binary";
5557
}
56-
return undefined;
58+
if (isTest(parentData)) {
59+
contextValue += "+test";
60+
}
61+
return contextValue;
5762
}
5863
}

src/views/packageRootNode.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Jdtls } from "../java/jdtls";
77
import { INodeData, NodeKind } from "../java/nodeData";
88
import { IPackageRootNodeData, PackageRootKind } from "../java/packageRootNodeData";
99
import { Settings } from "../settings";
10+
import { isTest } from "../utility";
1011
import { ContainerNode } from "./containerNode";
1112
import { DataNode } from "./dataNode";
1213
import { ExplorerNode } from "./explorerNode";
@@ -45,7 +46,7 @@ export class PackageRootNode extends DataNode {
4546
result.push(new FolderNode(data, this, this._project, this));
4647
} else if (data.kind === NodeKind.PrimaryType) {
4748
if (data.metaData && data.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
48-
result.push(new PrimaryTypeNode(data, this));
49+
result.push(new PrimaryTypeNode(data, this, this));
4950
}
5051
}
5152
});
@@ -64,20 +65,28 @@ export class PackageRootNode extends DataNode {
6465

6566
protected get contextValue(): string {
6667
const data = <IPackageRootNodeData>this.nodeData;
68+
let contextValue: string;
6769
if (data.entryKind === PackageRootKind.K_BINARY) {
68-
let contextValue: string = Explorer.ContextValueType.Jar;
70+
contextValue = Explorer.ContextValueType.Jar;
6971
const parent = <ContainerNode>this.getParent();
7072
if (parent.path?.startsWith("REFERENCED_LIBRARIES_PATH")) {
7173
contextValue += "+referencedLibrary";
7274
}
7375
return contextValue;
74-
} else if (resourceRoots.includes(this._nodeData.name)) {
75-
// APIs in JDT does not have a consistent result telling whether a package root
76-
// is a source root or resource root, so we hard code some common resources root
77-
// here as a workaround.
78-
return `${Explorer.ContextValueType.PackageRoot}+resource`;
7976
} else {
80-
return `${Explorer.ContextValueType.PackageRoot}+source`;
77+
contextValue = Explorer.ContextValueType.PackageRoot;
78+
if (isTest(data)) {
79+
contextValue += "+test";
80+
}
81+
if (resourceRoots.includes(this._nodeData.name)) {
82+
// APIs in JDT does not have a consistent result telling whether a package root
83+
// is a source root or resource root, so we hard code some common resources root
84+
// here as a workaround.
85+
contextValue += "+resource";
86+
} else {
87+
contextValue += "+source";
88+
}
89+
return contextValue;
8190
}
8291
}
8392

src/views/projectNode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export class ProjectNode extends DataNode {
9494
// For invisible project with empty named package root with a default package,
9595
// types will be the project node's children
9696
if (data.metaData && data.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
97-
result.push(new PrimaryTypeNode(data, this));
97+
result.push(new PrimaryTypeNode(data, this, undefined));
9898
}
9999
}
100100
});

test/suite/contextValue.test.ts

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,78 +8,99 @@ import { ContainerNode, FileNode, FolderNode, INodeData, NodeKind, PackageNode,
88

99
// tslint:disable: only-arrow-functions
1010
// tslint:disable: no-object-literal-type-assertion
11+
12+
/**
13+
* This suite is to test the context value of different nodes in the explorer,
14+
* Users can register their commands to the nodes by writing RegExp to match the metadata.
15+
* More details, please see: https://github.com/microsoft/vscode-java-dependency/wiki/Register-Command-onto-the-Nodes-of-Project-View
16+
*/
1117
suite("Context Value Tests", () => {
1218

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

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

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

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

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

3339
test("test Gradle container node", async function() {
34-
assert.equal((await gradleContainer.getTreeItem()).contextValue, "java:container+gradle+uri");
40+
assert.ok(/java:container(?=.*?\b\+gradle\b)(?=.*?\b\+uri\b)/.test((await gradleContainer.getTreeItem()).contextValue || ""));
3541
});
3642

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

4148
test("test source root node", async function() {
42-
assert.equal((await sourceRoot.getTreeItem()).contextValue, "java:packageRoot+source+uri");
49+
assert.ok(/java:packageRoot(?=.*?\b\+source\b)(?=.*?\b\+uri\b)/.test((await sourceRoot.getTreeItem()).contextValue || ""));
50+
});
51+
52+
test("test test-source root node", async function() {
53+
assert.ok(/java:packageRoot(?=.*?\b\+source\b)(?=.*?\b\+uri\b)(?=.*?\b\+test\b)/
54+
.test((await testSourceRoot.getTreeItem()).contextValue || ""));
4355
});
4456

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

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

5365
test("test referenced library jar node", async function() {
54-
assert.equal((await referencedLibraryJar.getTreeItem()).contextValue, "java:jar+referencedLibrary+uri");
66+
assert.ok(/java:jar(?=.*?\b\+referencedLibrary\b)(?=.*?\b\+uri\b)/.test((await referencedLibraryJar.getTreeItem()).contextValue || ""));
67+
});
68+
69+
test("test source package node", async function() {
70+
assert.ok(/java:package(?=.*?\b\+source\b)(?=.*?\b\+uri\b)/.test((await sourcePackage.getTreeItem()).contextValue || ""));
5571
});
5672

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

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

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

6986
test("test class type node", async function() {
70-
assert.equal((await classType.getTreeItem()).contextValue, "java:type+class+uri");
87+
assert.ok(/java:type(?=.*?\b\+class\b)(?=.*?\b\+uri\b)/.test((await classType.getTreeItem()).contextValue || ""));
88+
});
89+
90+
test("test test-class type node", async function() {
91+
assert.ok(/java:type(?=.*?\b\+class\b)(?=.*?\b\+test\b)(?=.*?\b\+uri\b)/.test((await testClassType.getTreeItem()).contextValue || ""));
7192
});
7293

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

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

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

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

167+
const testSourceRoot: PackageRootNode = new PackageRootNode({
168+
name: "src/main/java",
169+
uri: Uri.file(__dirname).toString(),
170+
kind: NodeKind.PackageRoot,
171+
entryKind: PackageRootKind.K_SOURCE,
172+
metaData: {
173+
test: "true",
174+
},
175+
} as INodeData, mavenContainer, mavenProject);
176+
146177
const resourceRoot: PackageRootNode = new PackageRootNode({
147178
name: "src/main/resources",
148179
uri: Uri.file(__dirname).toString(),
@@ -170,6 +201,12 @@ const sourcePackage: PackageNode = new PackageNode({
170201
kind: NodeKind.Package,
171202
}, sourceRoot, mavenProject, sourceRoot);
172203

204+
const testSourcePackage: PackageNode = new PackageNode({
205+
name: "com.microsoft.java",
206+
uri: Uri.file(__dirname).toString(),
207+
kind: NodeKind.Package,
208+
}, testSourceRoot, mavenProject, testSourceRoot);
209+
173210
const binaryPackage: PackageNode = new PackageNode({
174211
name: "junit",
175212
uri: Uri.file(__dirname).toString(),
@@ -189,7 +226,16 @@ const classType: PrimaryTypeNode = new PrimaryTypeNode({
189226
metaData: {
190227
TypeKind: TypeKind.Class,
191228
},
192-
}, sourcePackage);
229+
}, sourcePackage, sourceRoot);
230+
231+
const testClassType: PrimaryTypeNode = new PrimaryTypeNode({
232+
name: "App",
233+
uri: Uri.file(__dirname).toString(),
234+
kind: NodeKind.PrimaryType,
235+
metaData: {
236+
TypeKind: TypeKind.Class,
237+
},
238+
}, testSourcePackage, testSourceRoot);
193239

194240
const enumType: PrimaryTypeNode = new PrimaryTypeNode({
195241
name: "LanguageServerMode",
@@ -198,7 +244,7 @@ const enumType: PrimaryTypeNode = new PrimaryTypeNode({
198244
metaData: {
199245
TypeKind: TypeKind.Enum,
200246
},
201-
}, sourcePackage);
247+
}, sourcePackage, sourceRoot);
202248

203249
const interfaceType: PrimaryTypeNode = new PrimaryTypeNode({
204250
name: "Controller",
@@ -207,7 +253,7 @@ const interfaceType: PrimaryTypeNode = new PrimaryTypeNode({
207253
metaData: {
208254
TypeKind: TypeKind.Interface,
209255
},
210-
}, sourcePackage);
256+
}, sourcePackage, sourceRoot);
211257

212258
const folder: FolderNode = new FolderNode({
213259
name: "static",

tslint.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"log",
4040
"error"
4141
],
42-
"no-namespace": false
42+
"no-namespace": false,
43+
"prefer-conditional-expression": false
4344
}
4445
}

0 commit comments

Comments
 (0)