Skip to content

Commit 61333f2

Browse files
authored
refactor: Use factory pattern to create explorer nodes (#731)
--------- Signed-off-by: Sheng Chen <[email protected]>
1 parent 7cab083 commit 61333f2

File tree

14 files changed

+200
-183
lines changed

14 files changed

+200
-183
lines changed

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

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -367,17 +367,20 @@ private static IPackageFragmentRoot getPackageFragmentRootFromQuery(PackageParam
367367
return packageRoot;
368368
}
369369

370-
// jar in Referenced Libraries must be constructed from path
371-
IJavaProject javaProject = getJavaProject(query.getProjectUri());
372-
if (javaProject != null) {
373-
try {
374-
packageRoot = javaProject.findPackageFragmentRoot(Path.fromPortableString(query.getRootPath()));
375-
} catch (JavaModelException e) {
376-
return null;
370+
if (query.getProjectUri() != null && query.getRootPath() != null) {
371+
// jar in Referenced Libraries must be constructed from path
372+
IJavaProject javaProject = getJavaProject(query.getProjectUri());
373+
if (javaProject != null) {
374+
try {
375+
return javaProject.findPackageFragmentRoot(Path.fromPortableString(query.getRootPath()));
376+
} catch (JavaModelException e) {
377+
JdtlsExtActivator.log(e);
378+
return null;
379+
}
377380
}
378381
}
379382

380-
return packageRoot;
383+
return null;
381384
}
382385

383386
private static List<PackageNode> getRootTypes(PackageParams query, IProgressMonitor pm) {
@@ -421,41 +424,47 @@ public static List<Object> getChildrenForPackage(IPackageFragment packageFragmen
421424
}
422425

423426
private static List<PackageNode> getFolderChildren(PackageParams query, IProgressMonitor pm) {
427+
List<Object> children = new LinkedList<>();
428+
IJavaProject javaProject = null;
424429
try {
425430
IPackageFragmentRoot packageRoot = getPackageFragmentRootFromQuery(query);
426-
if (packageRoot == null) {
427-
throw new CoreException(
428-
new Status(IStatus.ERROR, JdtlsExtActivator.PLUGIN_ID, String.format("No package root found for %s", query.getPath())));
429-
}
430-
List<Object> children = new LinkedList<>();
431-
if (packageRoot.getKind() == IPackageFragmentRoot.K_BINARY) {
432-
Object[] resources = packageRoot.getNonJavaResources();
433-
for (Object resource : resources) {
434-
if (pm.isCanceled()) {
435-
throw new OperationCanceledException();
436-
}
437-
if (resource instanceof JarEntryDirectory) {
438-
JarEntryDirectory directory = (JarEntryDirectory) resource;
439-
Object[] directoryChildren = findJarDirectoryChildren(directory, query.getPath());
440-
if (children != null) {
441-
children.addAll(Arrays.asList(directoryChildren));
431+
if (packageRoot != null) {
432+
if (packageRoot.getKind() == IPackageFragmentRoot.K_BINARY) {
433+
Object[] resources = packageRoot.getNonJavaResources();
434+
for (Object resource : resources) {
435+
if (pm.isCanceled()) {
436+
throw new OperationCanceledException();
437+
}
438+
if (resource instanceof JarEntryDirectory) {
439+
JarEntryDirectory directory = (JarEntryDirectory) resource;
440+
Object[] directoryChildren = findJarDirectoryChildren(directory, query.getPath());
441+
if (children != null) {
442+
children.addAll(Arrays.asList(directoryChildren));
443+
}
442444
}
443445
}
446+
} else {
447+
javaProject = packageRoot.getJavaProject();
448+
IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(Path.fromPortableString(query.getPath()));
449+
if (folder.exists()) {
450+
boolean isJavaElement = JavaCore.create(folder) != null;
451+
children.addAll(Arrays.stream(folder.members())
452+
.filter(f -> isJavaElement ? f instanceof IFile : true)
453+
.collect(Collectors.toList())
454+
);
455+
}
444456
}
445457
} else {
446-
IJavaProject javaProject = packageRoot.getJavaProject();
447-
IFolder folder = javaProject.getProject().getFolder(new Path(query.getPath()).makeRelativeTo(javaProject.getProject().getFullPath()));
448-
if (folder != null && folder.exists()) {
449-
boolean isJavaElement = JavaCore.create(folder) != null;
450-
children.addAll(Arrays.stream(folder.members())
451-
.filter(f -> isJavaElement ? f instanceof IFile : true)
452-
.collect(Collectors.toList())
453-
);
458+
// general resource folder.
459+
IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(Path.fromPortableString(query.getPath()));
460+
if (folder.exists()) {
461+
children.addAll(Arrays.asList(folder.members()));
462+
javaProject = JavaCore.create(folder.getProject());
454463
}
455464
}
456465

457466
ResourceSet resourceSet = new ResourceSet(children);
458-
ResourceVisitor visitor = new JavaResourceVisitor(packageRoot.getJavaProject());
467+
ResourceVisitor visitor = new JavaResourceVisitor(javaProject);
459468
resourceSet.accept(visitor);
460469
return visitor.getNodes();
461470

jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/NodeKind.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ public enum NodeKind {
1616

1717
PROJECT(2),
1818

19-
CONTAINER(3),
19+
PACKAGEROOT(3),
2020

21-
PACKAGEROOT(4),
21+
PACKAGE(4),
2222

23-
PACKAGE(5),
23+
PRIMARYTYPE(5),
2424

25-
PRIMARYTYPE(6),
25+
CONTAINER(6),
2626

2727
FOLDER(7),
2828

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@
792792
]
793793
},
794794
"scripts": {
795-
"compile": "tsc -p . && webpack --config webpack.config.js",
795+
"compile": "tsc -p . && webpack --config webpack.config.js --mode development",
796796
"watch": "webpack --mode development --watch",
797797
"test": "tsc -p . && node ./dist/test/index.js",
798798
"test-ui": "tsc -p . && node ./dist/test/ui/index.js",

src/java/nodeData.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
export enum NodeKind {
55
Workspace = 1,
66
Project = 2,
7-
Container = 3,
8-
PackageRoot = 4,
9-
Package = 5,
10-
PrimaryType = 6,
7+
PackageRoot = 3,
8+
Package = 4,
9+
PrimaryType = 5,
10+
Container = 6,
1111
Folder = 7,
1212
File = 8,
1313
}

src/views/containerNode.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { INodeData, NodeKind } from "../java/nodeData";
88
import { DataNode } from "./dataNode";
99
import { ExplorerNode } from "./explorerNode";
1010
import { NodeFactory } from "./nodeFactory";
11-
import { PackageRootNode } from "./packageRootNode";
1211
import { ProjectNode } from "./projectNode";
1312

1413
export class ContainerNode extends DataNode {
@@ -37,15 +36,15 @@ export class ContainerNode extends DataNode {
3736
protected async loadData(): Promise<INodeData[]> {
3837
return Jdtls.getPackageData({ kind: NodeKind.Container, projectUri: this._project.uri, path: this.path });
3938
}
39+
4040
protected createChildNodeList(): ExplorerNode[] {
41-
const result: PackageRootNode[] = [];
41+
const result: (ExplorerNode | undefined)[] = [];
4242
if (this.nodeData.children && this.nodeData.children.length) {
43-
this.sort();
44-
this.nodeData.children.forEach((classpathNode) => {
45-
result.push(NodeFactory.createPackageRootNode(classpathNode, this, this._project));
43+
this.nodeData.children.forEach((nodeData) => {
44+
result.push(NodeFactory.createNode(nodeData, this, this._project));
4645
});
4746
}
48-
return result;
47+
return result.filter(<T>(n?: T): n is T => Boolean(n));
4948
}
5049

5150
protected get contextValue(): string {

src/views/dataNode.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export abstract class DataNode extends ExplorerNode {
7777
const data = await this.loadData();
7878
this._nodeData.children = data;
7979
this._childrenNodes = this.createChildNodeList() || [];
80+
this.sort();
8081
return this._childrenNodes;
8182
}
8283
return this._childrenNodes;
@@ -97,12 +98,15 @@ export abstract class DataNode extends ExplorerNode {
9798
}
9899

99100
protected sort() {
100-
this.nodeData.children?.sort((a: INodeData, b: INodeData) => {
101-
if (a.kind === b.kind) {
102-
return a.name < b.name ? -1 : 1;
103-
} else {
104-
return a.kind - b.kind;
101+
this._childrenNodes.sort((a: ExplorerNode, b: ExplorerNode) => {
102+
if (a instanceof DataNode && b instanceof DataNode) {
103+
if (a.nodeData.kind === b.nodeData.kind) {
104+
return a.nodeData.name < b.nodeData.name ? -1 : 1;
105+
} else {
106+
return a.nodeData.kind - b.nodeData.kind;
107+
}
105108
}
109+
return 0;
106110
});
107111
}
108112

src/views/folderNode.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ import { Jdtls } from "../java/jdtls";
77
import { INodeData, NodeKind } from "../java/nodeData";
88
import { DataNode } from "./dataNode";
99
import { ExplorerNode } from "./explorerNode";
10-
import { FileNode } from "./fileNode";
1110
import { ProjectNode } from "./projectNode";
11+
import { NodeFactory } from "./nodeFactory";
1212

1313
export class FolderNode extends DataNode {
14-
constructor(nodeData: INodeData, parent: DataNode, private _project: ProjectNode, private _rootNode: DataNode) {
14+
constructor(nodeData: INodeData, parent: DataNode, private _project: ProjectNode, private _rootNode?: DataNode) {
1515
super(nodeData, parent);
1616
}
1717

@@ -20,24 +20,19 @@ export class FolderNode extends DataNode {
2020
kind: NodeKind.Folder,
2121
projectUri: this._project.uri,
2222
path: this.path,
23-
rootPath: this._rootNode.path,
24-
handlerIdentifier: this._rootNode.handlerIdentifier,
23+
rootPath: this._rootNode?.path,
24+
handlerIdentifier: this._rootNode?.handlerIdentifier,
2525
});
2626
}
2727

2828
protected createChildNodeList(): ExplorerNode[] {
29-
const result: ExplorerNode[] = [];
29+
const result: (ExplorerNode | undefined)[] = [];
3030
if (this.nodeData.children && this.nodeData.children.length) {
31-
this.sort();
3231
this.nodeData.children.forEach((nodeData) => {
33-
if (nodeData.kind === NodeKind.File) {
34-
result.push(new FileNode(nodeData, this));
35-
} else if (nodeData.kind === NodeKind.Folder) {
36-
result.push(new FolderNode(nodeData, this, this._project, this._rootNode));
37-
}
32+
result.push(NodeFactory.createNode(nodeData, this, this._project, this._rootNode));
3833
});
3934
}
40-
return result;
35+
return result.filter(<T>(n?: T): n is T => Boolean(n));
4136
}
4237

4338
protected get iconPath(): ThemeIcon {

src/views/hierarchicalPackageNode.ts

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@
44
import * as _ from "lodash";
55
import { TreeItem, TreeItemCollapsibleState } from "vscode";
66
import { HierarchicalPackageNodeData } from "../java/hierarchicalPackageNodeData";
7-
import { INodeData, NodeKind } from "../java/nodeData";
7+
import { INodeData } from "../java/nodeData";
88
import { explorerLock } from "../utils/Lock";
99
import { DataNode } from "./dataNode";
1010
import { ExplorerNode } from "./explorerNode";
11-
import { FileNode } from "./fileNode";
12-
import { FolderNode } from "./folderNode";
1311
import { PackageNode } from "./packageNode";
14-
import { PrimaryTypeNode } from "./PrimaryTypeNode";
1512
import { ProjectNode } from "./projectNode";
13+
import { NodeFactory } from "./nodeFactory";
1614

1715
export class HierarchicalPackageNode extends PackageNode {
1816

@@ -38,7 +36,9 @@ export class HierarchicalPackageNode extends PackageNode {
3836
this.nodeData.children = data;
3937
}
4038
}
41-
return this.createChildNodeList();
39+
this._childrenNodes = this.createChildNodeList() || [];
40+
this.sort();
41+
return this._childrenNodes;
4242
} finally {
4343
explorerLock.release();
4444
}
@@ -64,24 +64,13 @@ export class HierarchicalPackageNode extends PackageNode {
6464
}
6565

6666
protected createChildNodeList(): ExplorerNode[] {
67-
const result: ExplorerNode[] = [];
67+
const result: (ExplorerNode | undefined)[] = [];
6868
if (this.nodeData.children && this.nodeData.children.length) {
69-
this.sort();
7069
this.nodeData.children.forEach((nodeData) => {
71-
if (nodeData.kind === NodeKind.File) {
72-
result.push(new FileNode(nodeData, this));
73-
} else if (nodeData instanceof HierarchicalPackageNodeData) {
74-
result.push(new HierarchicalPackageNode(nodeData, this, this._project, this._rootNode));
75-
} else if (nodeData.kind === NodeKind.PrimaryType) {
76-
if (nodeData.metaData && nodeData.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
77-
result.push(new PrimaryTypeNode(nodeData, this, this._rootNode));
78-
}
79-
} else if (nodeData.kind === NodeKind.Folder) {
80-
result.push(new FolderNode(nodeData, this, this._project, this._rootNode));
81-
}
70+
result.push(NodeFactory.createNode(nodeData, this, this._project, this._rootNode));
8271
});
8372
}
84-
return result;
73+
return result.filter(<T>(n?: T): n is T => Boolean(n));
8574
}
8675

8776
private getHierarchicalNodeData(): HierarchicalPackageNodeData {

src/views/hierarchicalPackageRootNode.ts

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ import { HierarchicalPackageNodeData } from "../java/hierarchicalPackageNodeData
55
import { INodeData, NodeKind } from "../java/nodeData";
66
import { DataNode } from "./dataNode";
77
import { ExplorerNode } from "./explorerNode";
8-
import { FileNode } from "./fileNode";
9-
import { FolderNode } from "./folderNode";
108
import { HierarchicalPackageNode } from "./hierarchicalPackageNode";
9+
import { NodeFactory } from "./nodeFactory";
1110
import { PackageRootNode } from "./packageRootNode";
12-
import { PrimaryTypeNode } from "./PrimaryTypeNode";
1311
import { ProjectNode } from "./projectNode";
1412

1513
export class HierarchicalPackageRootNode extends PackageRootNode {
@@ -31,36 +29,27 @@ export class HierarchicalPackageRootNode extends PackageRootNode {
3129
}
3230

3331
protected createChildNodeList(): ExplorerNode[] {
34-
const result: ExplorerNode[] = [];
32+
const result: (ExplorerNode | undefined)[] = [];
33+
const packageData: any[] = [];
3534
if (this.nodeData.children && this.nodeData.children.length) {
36-
this.sort();
37-
this.nodeData.children.forEach((data) => {
38-
if (data.kind === NodeKind.File) {
39-
result.push(new FileNode(data, this));
40-
} else if (data.kind === NodeKind.Folder) {
41-
result.push(new FolderNode(data, this, this._project, this));
42-
} else if (data.kind === NodeKind.PrimaryType) {
43-
if (data.metaData && data.metaData[PrimaryTypeNode.K_TYPE_KIND]) {
44-
result.push(new PrimaryTypeNode(data, this, this));
45-
}
35+
this.nodeData.children.forEach((nodeData) => {
36+
if (nodeData.kind === NodeKind.Package) {
37+
// Invisible project may have an empty named package root (the linked folder),
38+
// in that case, we will skip it.
39+
packageData.push(nodeData);
40+
} else {
41+
result.push(NodeFactory.createNode(nodeData, this, this._project, this));
4642
}
4743
});
4844
}
49-
return result.concat(this.getHierarchicalPackageNodes());
50-
}
51-
52-
protected getHierarchicalPackageNodes(): ExplorerNode[] {
53-
const hierarchicalPackageNodeData = this.getHierarchicalPackageNodeData();
54-
return hierarchicalPackageNodeData?.children.map((hierarchicalChildrenNode) =>
55-
new HierarchicalPackageNode(hierarchicalChildrenNode, this, this._project, this)) || [];
56-
}
5745

58-
private getHierarchicalPackageNodeData(): HierarchicalPackageNodeData | undefined {
59-
if (this.nodeData.children && this.nodeData.children.length) {
60-
const nodeDataList = this.nodeData.children
61-
.filter((child) => child.kind === NodeKind.Package);
62-
return HierarchicalPackageNodeData.createHierarchicalNodeDataByPackageList(nodeDataList);
46+
if (packageData.length > 0) {
47+
const data: HierarchicalPackageNodeData = HierarchicalPackageNodeData.createHierarchicalNodeDataByPackageList(packageData);
48+
if (data) {
49+
result.push(...data.children.map(d => NodeFactory.createNode(d, this, this._project, this)));
50+
}
6351
}
64-
return undefined;
52+
53+
return result.filter(<T>(n?: T): n is T => Boolean(n));
6554
}
6655
}

0 commit comments

Comments
 (0)