UNPKG

5.32 kBPlain TextView Raw
1// *****************************************************************************
2// Copyright (C) 2018 TypeFox and others.
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License v. 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0.
7//
8// This Source Code may also be made available under the following Secondary
9// Licenses when the conditions for such availability set forth in the Eclipse
10// Public License v. 2.0 are satisfied: GNU General Public License, version 2
11// with the GNU Classpath Exception which is available at
12// https://www.gnu.org/software/classpath/license.html.
13//
14// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15// *****************************************************************************
16
17/* eslint-disable @typescript-eslint/no-explicit-any */
18
19import { injectable } from 'inversify';
20import { MaybePromise } from '../../common/types';
21import { TreeImpl, CompositeTreeNode, TreeNode, SelectableTreeNode, ExpandableTreeNode } from '../tree';
22import { TreeElement, CompositeTreeElement, TreeSource } from './tree-source';
23
24@injectable()
25export class SourceTree extends TreeImpl {
26
27 override async resolveChildren(parent: TreeElementNodeParent): Promise<TreeNode[]> {
28 const elements = await this.resolveElements(parent);
29 const nodes: TreeNode[] = [];
30 let index = 0;
31 for (const element of elements) {
32 if (element.visible !== false) {
33 nodes.push(this.toNode(element, index++, parent));
34 }
35 }
36 return nodes;
37 }
38
39 protected resolveElements(parent: TreeElementNodeParent): MaybePromise<IterableIterator<TreeElement>> {
40 if (TreeSourceNode.is(parent)) {
41 return parent.source.getElements();
42 }
43 return parent.element.getElements();
44 }
45
46 protected toNode(element: TreeElement, index: number, parent: TreeElementNodeParent): TreeElementNode {
47 const id = element.id ? String(element.id) : (parent.id + ':' + index);
48 const name = id;
49 const existing = this.getNode(id);
50 const updated = existing && <TreeElementNode>Object.assign(existing, { element, parent });
51 if (CompositeTreeElement.hasElements(element)) {
52 if (updated) {
53 if (!ExpandableTreeNode.is(updated)) {
54 Object.assign(updated, { expanded: false });
55 }
56 if (!CompositeTreeNode.is(updated)) {
57 Object.assign(updated, { children: [] });
58 }
59 return updated;
60 }
61 return {
62 element,
63 parent,
64 id,
65 name,
66 selected: false,
67 expanded: false,
68 children: []
69 } as TreeElementNode;
70 }
71 if (CompositeTreeElementNode.is(updated)) {
72 delete (updated as any).expanded;
73 delete (updated as any).children;
74 }
75 if (updated) {
76 if (ExpandableTreeNode.is(updated)) {
77 delete (updated as any).expanded;
78 }
79 if (CompositeTreeNode.is(updated)) {
80 delete (updated as any).children;
81 }
82 return updated;
83 }
84 return {
85 element,
86 parent,
87 id,
88 name,
89 selected: false
90 };
91 }
92
93}
94
95export type TreeElementNodeParent = CompositeTreeElementNode | TreeSourceNode;
96
97export interface TreeElementNode extends TreeNode, SelectableTreeNode {
98 element: TreeElement
99 parent: TreeElementNodeParent
100}
101export namespace TreeElementNode {
102 export function is(node: TreeNode | undefined): node is TreeElementNode {
103 return SelectableTreeNode.is(node) && 'element' in node;
104 }
105}
106
107export interface CompositeTreeElementNode extends TreeElementNode, CompositeTreeNode, ExpandableTreeNode {
108 element: CompositeTreeElement
109 children: TreeElementNode[]
110 parent: TreeElementNodeParent
111}
112export namespace CompositeTreeElementNode {
113 export function is(node: TreeNode | undefined): node is CompositeTreeElementNode {
114 return TreeElementNode.is(node) && CompositeTreeNode.is(node) && ExpandableTreeNode.is(node) && !!node.visible;
115 }
116}
117
118export interface TreeSourceNode extends CompositeTreeNode, SelectableTreeNode {
119 visible: false
120 children: TreeElementNode[]
121 parent: undefined
122 source: TreeSource
123}
124export namespace TreeSourceNode {
125 export function is(node: TreeNode | undefined): node is TreeSourceNode {
126 return CompositeTreeNode.is(node) && !node.visible && 'source' in node;
127 }
128 export function to(source: undefined): undefined;
129 export function to(source: TreeSource): TreeSourceNode;
130 export function to(source: TreeSource | undefined): TreeSourceNode | undefined;
131 export function to(source: TreeSource | undefined): TreeSourceNode | undefined {
132 if (!source) {
133 return source;
134 }
135 const id = source.id || '__source__';
136 return {
137 id,
138 name: id,
139 visible: false,
140 children: [],
141 source,
142 parent: undefined,
143 selected: false
144 };
145 }
146}