@@ -21,7 +21,13 @@ import { WorkspaceContext } from "../WorkspaceContext";
21
21
import { FolderEvent } from "../WorkspaceContext" ;
22
22
import { FolderContext } from "../FolderContext" ;
23
23
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" ;
25
31
26
32
/**
27
33
* References:
@@ -149,31 +155,131 @@ export class PackageDependenciesProvider implements vscode.TreeDataProvider<Tree
149
155
}
150
156
if ( ! element ) {
151
157
const workspaceState = await folderContext . swiftPackage . loadWorkspaceState ( ) ;
152
- return this . getDependencyGraph ( workspaceState , folderContext . folder . fsPath ) ;
158
+ return await this . getDependencyGraph ( workspaceState , folderContext ) ;
153
159
}
154
160
155
161
return this . getNodesInDirectory ( element . path ) ;
156
162
}
157
163
158
- private getDependencyGraph (
164
+ private async getDependencyGraph (
159
165
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 ) ;
162
172
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
176
208
) ;
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
+ }
177
283
}
178
284
179
285
/**
0 commit comments