Skip to content

Commit c76f207

Browse files
committed
traverse local dependencies
1 parent 8d7b216 commit c76f207

File tree

1 file changed

+124
-18
lines changed

1 file changed

+124
-18
lines changed

src/ui/PackageDependencyProvider.ts

+124-18
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ import { WorkspaceContext } from "../WorkspaceContext";
2121
import { FolderEvent } from "../WorkspaceContext";
2222
import { FolderContext } from "../FolderContext";
2323
import contextKeys from "../contextKeys";
24-
import { WorkspaceState, WorkspaceStateDependency } from "../SwiftPackage";
24+
import {
25+
Dependency,
26+
PackageContents,
27+
SwiftPackage,
28+
WorkspaceState,
29+
WorkspaceStateDependency,
30+
} from "../SwiftPackage";
2531

2632
/**
2733
* References:
@@ -149,31 +155,131 @@ export class PackageDependenciesProvider implements vscode.TreeDataProvider<Tree
149155
}
150156
if (!element) {
151157
const workspaceState = await folderContext.swiftPackage.loadWorkspaceState();
152-
return this.getDependencyGraph(workspaceState, folderContext.folder.fsPath);
158+
return await this.getDependencyGraph(workspaceState, folderContext);
153159
}
154160

155161
return this.getNodesInDirectory(element.path);
156162
}
157163

158-
private getDependencyGraph(
164+
private async getDependencyGraph(
159165
workspaceState: WorkspaceState | undefined,
160-
folderContext: string
161-
): PackageNode[] {
166+
folderContext: FolderContext
167+
): Promise<PackageNode[]> {
168+
if (!workspaceState) {
169+
return [];
170+
}
171+
const inUseDependencies = await this.getInUseDependencies(workspaceState, folderContext);
162172
return (
163-
workspaceState?.object.dependencies.map(dependency => {
164-
const type = this.dependencyType(dependency);
165-
const version = this.dependencyDisplayVersion(dependency);
166-
const packagePath = this.dependencyPackagePath(dependency, folderContext);
167-
const location = dependency.packageRef.location;
168-
return new PackageNode(
169-
dependency.packageRef.identity,
170-
packagePath,
171-
location,
172-
version,
173-
type
174-
);
175-
}) ?? []
173+
workspaceState?.object.dependencies
174+
.filter(dependency => inUseDependencies.has(dependency.packageRef.identity))
175+
.map(dependency => {
176+
const type = this.dependencyType(dependency);
177+
const version = this.dependencyDisplayVersion(dependency);
178+
const packagePath = this.dependencyPackagePath(
179+
dependency,
180+
folderContext.folder.fsPath
181+
);
182+
const location = dependency.packageRef.location;
183+
return new PackageNode(
184+
dependency.packageRef.identity,
185+
packagePath,
186+
location,
187+
version,
188+
type
189+
);
190+
}) ?? []
191+
);
192+
}
193+
194+
/**
195+
* * Returns a set of all dependencies that are in use in the workspace.
196+
* 1. local/remote/edited dependency has remote/edited dependencies, Package.resolved covers them
197+
* 2. remote/edited dependency has local dependency, the local dependency must has been declared in root Package.swift
198+
* 3. local dependency has a local dependency, tranverse it and find the local dependencies only recursively
199+
* 4. all pins includes all remote and edited packages for 1, 2
200+
*/
201+
private async getInUseDependencies(
202+
workspaceState: WorkspaceState,
203+
folderContext: FolderContext
204+
): Promise<Set<string>> {
205+
const localDependencies = await this.getAllLocalDependencySet(
206+
workspaceState,
207+
folderContext
176208
);
209+
const remoteDependencies = this.getRemoteDependencySet(folderContext);
210+
211+
// merge the two sets of dependencies
212+
const inUseDependencies = new Set<string>();
213+
localDependencies.forEach(dependency => inUseDependencies.add(dependency));
214+
remoteDependencies.forEach(dependency => inUseDependencies.add(dependency));
215+
return inUseDependencies;
216+
}
217+
218+
private getRemoteDependencySet(folderContext: FolderContext | undefined): Set<string> {
219+
return new Set<string>(folderContext?.swiftPackage.resolved?.pins.map(pin => pin.identity));
220+
}
221+
222+
private async getAllLocalDependencySet(
223+
workspaceState: WorkspaceState,
224+
folderContext: FolderContext
225+
): Promise<Set<string>> {
226+
const rootDependencies = folderContext?.swiftPackage.dependencies ?? [];
227+
const showingDependencies = new Set<string>();
228+
await this.getChildLocalDependencySet(
229+
rootDependencies,
230+
workspaceState?.object.dependencies ?? [],
231+
folderContext?.folder.fsPath,
232+
showingDependencies
233+
);
234+
235+
return showingDependencies;
236+
}
237+
238+
/**
239+
* tranverse only local dependency tree
240+
* @param dependencies depdencies of current node
241+
* @param workspaceStateDependencies all dependencies in workspace-state.json
242+
* @param showingDependencies result of dependencies that are showing in the tree
243+
* @returns
244+
*/
245+
private async getChildLocalDependencySet(
246+
dependencies: Dependency[],
247+
workspaceStateDependencies: WorkspaceStateDependency[],
248+
workspacePath: string,
249+
showingDependencies: Set<string>
250+
) {
251+
for (let i = 0; i < dependencies.length; i++) {
252+
const childDependency = dependencies[i];
253+
if (showingDependencies.has(childDependency.identity)) {
254+
continue;
255+
}
256+
257+
if (childDependency.type !== "local" && childDependency.type !== "fileSystem") {
258+
continue;
259+
}
260+
261+
showingDependencies.add(childDependency.identity);
262+
const workspaceStateDependency = workspaceStateDependencies.find(
263+
workspaceStateDependency =>
264+
workspaceStateDependency.packageRef.identity === childDependency.identity
265+
);
266+
if (!workspaceStateDependency) {
267+
continue;
268+
}
269+
270+
const packagePath = this.dependencyPackagePath(workspaceStateDependency, workspacePath);
271+
272+
const childDependencyContents = (await SwiftPackage.loadPackage(
273+
vscode.Uri.file(packagePath)
274+
)) as PackageContents;
275+
276+
await this.getChildLocalDependencySet(
277+
childDependencyContents.dependencies,
278+
workspaceStateDependencies,
279+
workspacePath,
280+
showingDependencies
281+
);
282+
}
177283
}
178284

179285
/**

0 commit comments

Comments
 (0)