diff --git a/src/SwiftPackage.ts b/src/SwiftPackage.ts index 8ad820312..537563354 100644 --- a/src/SwiftPackage.ts +++ b/src/SwiftPackage.ts @@ -117,9 +117,20 @@ export interface WorkspaceState { version: number; } +/** revision + (branch || version) + * ref: https://github.com/apple/swift-package-manager/blob/e25a590dc455baa430f2ec97eacc30257c172be2/Sources/Workspace/CheckoutState.swift#L19:L23 + */ +export interface CheckoutState { + revision: string; + branch: string | null; + version: string | null; +} + export interface WorkspaceStateDependency { + basedOn: WorkspaceStateDependency | null; packageRef: { identity: string; kind: string; location: string; name: string }; - state: { name: string; path?: string }; + state: { name: string; path?: string; checkoutState?: CheckoutState }; + subpath: string; } export interface PackagePlugin { diff --git a/src/ui/PackageDependencyProvider.ts b/src/ui/PackageDependencyProvider.ts index ab7877197..bafb6952f 100644 --- a/src/ui/PackageDependencyProvider.ts +++ b/src/ui/PackageDependencyProvider.ts @@ -16,12 +16,12 @@ import * as vscode from "vscode"; import * as fs from "fs/promises"; import * as path from "path"; import configuration from "../configuration"; -import { getRepositoryName, buildDirectoryFromWorkspacePath } from "../utilities/utilities"; +import { buildDirectoryFromWorkspacePath } from "../utilities/utilities"; import { WorkspaceContext } from "../WorkspaceContext"; import { FolderEvent } from "../WorkspaceContext"; import { FolderContext } from "../FolderContext"; import contextKeys from "../contextKeys"; -import { WorkspaceState } from "../SwiftPackage"; +import { WorkspaceState, WorkspaceStateDependency } from "../SwiftPackage"; /** * References: @@ -148,39 +148,24 @@ export class PackageDependenciesProvider implements vscode.TreeDataProvider item.name === child.name); - if (!editedVersion) { - uneditedChildren.push(child); - } - } - return [...uneditedChildren, ...editedChildren].sort((first, second) => - first.name.localeCompare(second.name) - ); + return this.getDependencyGraph(workspaceState, folderContext.folder.fsPath); } - const buildDirectory = buildDirectoryFromWorkspacePath(folderContext.folder.fsPath, true); + return this.getNodesInDirectory(element.path); + } - if (element instanceof PackageNode) { - // Read the contents of a package. - const packagePath = - element.type === "remote" - ? path.join(buildDirectory, "checkouts", getRepositoryName(element.path)) - : element.path; - return this.getNodesInDirectory(packagePath); - } else { - // Read the contents of a directory within a package. - return this.getNodesInDirectory(element.path); - } + private getDependencyGraph( + workspaceState: WorkspaceState | undefined, + folderContext: string + ): PackageNode[] { + return ( + workspaceState?.object.dependencies.map(dependency => { + const type = this.dependencyType(dependency); + const version = this.dependencyDisplayVersion(dependency); + const packagePath = this.dependencyPackagePath(dependency, folderContext); + return new PackageNode(dependency.packageRef.identity, packagePath, version, type); + }) ?? [] + ); } /** @@ -277,4 +262,78 @@ export class PackageDependenciesProvider implements vscode.TreeDataProvider 0) { + return "editing " + basedOnVersion; + } + } + return "editing"; + } else if (type === "local") { + return "local"; + } else { + return ( + dependency.state.checkoutState?.version ?? + dependency.state.checkoutState?.branch ?? + dependency.state.checkoutState?.revision.substring(0, 7) ?? + "unknown" + ); + } + } + + /** + * Get type of WorkspaceStateDependency for displaying in the tree: real version | edited | local + * `edited`: dependency.state.path ?? workspacePath + Packages/ + dependency.subpath + * `local`: dependency.packageRef.location + * `remote`: buildDirectory + checkouts + dependency.packageRef.location + * @param dependency + * @return the package path based on the type + */ + private dependencyPackagePath( + dependency: WorkspaceStateDependency, + workspaceFolder: string + ): string { + const type = this.dependencyType(dependency); + if (type === "editing") { + return ( + dependency.state.path ?? path.join(workspaceFolder, "Packages", dependency.subpath) + ); + } else if (type === "local") { + return dependency.state.path ?? dependency.packageRef.location; + } else { + // remote + const buildDirectory = buildDirectoryFromWorkspacePath(workspaceFolder, true); + return path.join(buildDirectory, "checkouts", dependency.subpath); + } + } }