1// SPDX-FileCopyrightText: 2025 The Project Pterodactyl Developers 2// 3// SPDX-License-Identifier: MPL-2.0 4 5import LanguageServerProtocol 6import PterodactylBuild 7import TSCBasic 8import llbuild2fx 9 10actor SourceTreeManager { 11 private let buildEngine: FXEngine 12 private let casClient: LLBCASFSClient 13 private let casContext: TSCUtility.Context 14 private(set) var sourceTree: LLBCASFileTree 15 16 init(buildEngine: FXEngine, casClient: LLBCASFSClient, casContext: TSCUtility.Context, sourceTree: LLBCASFileTree? = nil) async throws { 17 self.buildEngine = buildEngine 18 self.casClient = casClient 19 self.casContext = casContext 20 if let sourceTree { 21 self.sourceTree = sourceTree 22 } else { 23 self.sourceTree = try await casClient.storeDir(.dir([:]), casContext).get() 24 } 25 } 26 27 func setBufferText(uri: DocumentUri, text: String) async throws { 28 let path = try AbsolutePath.fromDocumentUri(uri) 29 let singletonDeclTree = LLBDeclFileTree.file(absolutePath: path, contents: text) 30 let singletonTree: LLBCASFileTree = try await casClient.storeDir(singletonDeclTree, casContext).get() 31 self.sourceTree = try await sourceTree.merge(with: singletonTree, in: casClient.db, casContext).get() 32 } 33 34 func getBufferText(uri: DocumentUri) async throws -> String? { 35 let path = try AbsolutePath.fromDocumentUri(uri) 36 guard let (id, _) = try await sourceTree.lookup(path: path, in: casClient.db, casContext).get() else { return nil } 37 return try await buildEngine.build(key: Keys.Blob.ReadContents(blobId: id), casContext).get() 38 } 39}