mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-02 18:23:24 +01:00
Convert ManualMainFilesProvider to be an actor
Refactor the code Remove unused code Refine the code
This commit is contained in:
@@ -151,7 +151,7 @@ extension BuildSystemManager {
|
||||
for document: DocumentURI,
|
||||
language: Language
|
||||
) async -> FileBuildSettings? {
|
||||
let mainFile = mainFile(for: document)
|
||||
let mainFile = await mainFile(for: document)
|
||||
guard var settings = await buildSettings(for: mainFile, language: language) else {
|
||||
return nil
|
||||
}
|
||||
@@ -182,7 +182,7 @@ extension BuildSystemManager {
|
||||
|
||||
public func registerForChangeNotifications(for uri: DocumentURI, language: Language) async {
|
||||
logger.debug("registerForChangeNotifications(\(uri.forLogging))")
|
||||
let mainFile = mainFile(for: uri)
|
||||
let mainFile = await mainFile(for: uri)
|
||||
self.watchedFiles[uri] = (mainFile, language)
|
||||
|
||||
// Register for change notifications of the main file in the underlying build
|
||||
@@ -274,7 +274,7 @@ extension BuildSystemManager: MainFilesDelegate {
|
||||
public func mainFilesChanged() async {
|
||||
var changedMainFileAssociations: Set<DocumentURI> = []
|
||||
for (file, (oldMainFile, language)) in self.watchedFiles {
|
||||
let newMainFile = self.mainFile(for: file, useCache: false)
|
||||
let newMainFile = await self.mainFile(for: file, useCache: false)
|
||||
if newMainFile != oldMainFile {
|
||||
self.watchedFiles[file] = (newMainFile, language)
|
||||
changedMainFileAssociations.insert(file)
|
||||
@@ -303,7 +303,7 @@ extension BuildSystemManager: MainFilesDelegate {
|
||||
/// For Swift or normal C files, this will be the file itself. For header
|
||||
/// files, we pick a main file that includes the header since header files
|
||||
/// don't have build settings by themselves.
|
||||
private func mainFile(for uri: DocumentURI, useCache: Bool = true) -> DocumentURI {
|
||||
private func mainFile(for uri: DocumentURI, useCache: Bool = true) async -> DocumentURI {
|
||||
if useCache, let mainFile = self.watchedFiles[uri]?.mainFile {
|
||||
// Performance optimization: We did already compute the main file and have
|
||||
// it cached. We can just return it.
|
||||
@@ -313,7 +313,7 @@ extension BuildSystemManager: MainFilesDelegate {
|
||||
return uri
|
||||
}
|
||||
|
||||
let mainFiles = mainFilesProvider.mainFilesContainingFile(uri)
|
||||
let mainFiles = await mainFilesProvider.mainFilesContainingFile(uri)
|
||||
if mainFiles.contains(uri) {
|
||||
// If the main files contain the file itself, prefer to use that one
|
||||
return uri
|
||||
|
||||
@@ -23,7 +23,7 @@ public protocol MainFilesProvider: AnyObject {
|
||||
/// mainFilesContainingFile("foo.cpp") == Set(["foo.cpp"])
|
||||
/// mainFilesContainingFile("foo.h") == Set(["foo.cpp", "bar.cpp"])
|
||||
/// ```
|
||||
func mainFilesContainingFile(_: DocumentURI) -> Set<DocumentURI>
|
||||
func mainFilesContainingFile(_: DocumentURI) async -> Set<DocumentURI>
|
||||
}
|
||||
|
||||
/// Delegate that responds to possible main file changes.
|
||||
|
||||
@@ -25,13 +25,14 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
let c = DocumentURI(string: "bsm:c")
|
||||
let d = DocumentURI(string: "bsm:d")
|
||||
|
||||
let mainFiles = ManualMainFilesProvider()
|
||||
mainFiles.mainFiles = [
|
||||
a: Set([c]),
|
||||
b: Set([c, d]),
|
||||
c: Set([c]),
|
||||
d: Set([d]),
|
||||
]
|
||||
let mainFiles = ManualMainFilesProvider(
|
||||
[
|
||||
a: [c],
|
||||
b: [c, d],
|
||||
c: [c],
|
||||
d: [d],
|
||||
]
|
||||
)
|
||||
|
||||
let bsm = await BuildSystemManager(
|
||||
buildSystem: nil,
|
||||
@@ -55,13 +56,9 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
await assertEqual(bsm._cachedMainFile(for: c), c)
|
||||
await assertEqual(bsm._cachedMainFile(for: d), d)
|
||||
|
||||
mainFiles.mainFiles = [
|
||||
a: Set([a]),
|
||||
b: Set([c, d, a]),
|
||||
c: Set([c]),
|
||||
d: Set([d]),
|
||||
]
|
||||
|
||||
await mainFiles.updateMainFiles(for: a, to: [a])
|
||||
await mainFiles.updateMainFiles(for: b, to: [c, d, a])
|
||||
|
||||
await assertEqual(bsm._cachedMainFile(for: a), c)
|
||||
await assertEqual(bsm._cachedMainFile(for: b), bMain)
|
||||
await assertEqual(bsm._cachedMainFile(for: c), c)
|
||||
@@ -92,8 +89,7 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
|
||||
func testSettingsMainFile() async throws {
|
||||
let a = DocumentURI(string: "bsm:a.swift")
|
||||
let mainFiles = ManualMainFilesProvider()
|
||||
mainFiles.mainFiles = [a: Set([a])]
|
||||
let mainFiles = ManualMainFilesProvider([a: [a]])
|
||||
let bs = ManualBuildSystem()
|
||||
let bsm = await BuildSystemManager(
|
||||
buildSystem: bs,
|
||||
@@ -116,8 +112,7 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
|
||||
func testSettingsMainFileInitialNil() async throws {
|
||||
let a = DocumentURI(string: "bsm:a.swift")
|
||||
let mainFiles = ManualMainFilesProvider()
|
||||
mainFiles.mainFiles = [a: Set([a])]
|
||||
let mainFiles = ManualMainFilesProvider([a: [a]])
|
||||
let bs = ManualBuildSystem()
|
||||
let bsm = await BuildSystemManager(
|
||||
buildSystem: bs,
|
||||
@@ -138,8 +133,7 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
|
||||
func testSettingsMainFileWithFallback() async throws {
|
||||
let a = DocumentURI(string: "bsm:a.swift")
|
||||
let mainFiles = ManualMainFilesProvider()
|
||||
mainFiles.mainFiles = [a: Set([a])]
|
||||
let mainFiles = ManualMainFilesProvider([a: [a]])
|
||||
let bs = ManualBuildSystem()
|
||||
let fallback = FallbackBuildSystem(buildSetup: .default)
|
||||
let bsm = await BuildSystemManager(
|
||||
@@ -169,8 +163,7 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
func testSettingsMainFileInitialIntersect() async throws {
|
||||
let a = DocumentURI(string: "bsm:a.swift")
|
||||
let b = DocumentURI(string: "bsm:b.swift")
|
||||
let mainFiles = ManualMainFilesProvider()
|
||||
mainFiles.mainFiles = [a: Set([a]), b: Set([b])]
|
||||
let mainFiles = ManualMainFilesProvider([a: [a], b: [b]])
|
||||
let bs = ManualBuildSystem()
|
||||
let bsm = await BuildSystemManager(
|
||||
buildSystem: bs,
|
||||
@@ -210,8 +203,7 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
func testSettingsMainFileUnchanged() async throws {
|
||||
let a = DocumentURI(string: "bsm:a.swift")
|
||||
let b = DocumentURI(string: "bsm:b.swift")
|
||||
let mainFiles = ManualMainFilesProvider()
|
||||
mainFiles.mainFiles = [a: Set([a]), b: Set([b])]
|
||||
let mainFiles = ManualMainFilesProvider([a: [a], b: [b]])
|
||||
let bs = ManualBuildSystem()
|
||||
let bsm = await BuildSystemManager(
|
||||
buildSystem: bs,
|
||||
@@ -242,12 +234,13 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
let h = DocumentURI(string: "bsm:header.h")
|
||||
let cpp1 = DocumentURI(string: "bsm:main.cpp")
|
||||
let cpp2 = DocumentURI(string: "bsm:other.cpp")
|
||||
let mainFiles = ManualMainFilesProvider()
|
||||
mainFiles.mainFiles = [
|
||||
h: Set([cpp1]),
|
||||
cpp1: Set([cpp1]),
|
||||
cpp2: Set([cpp2]),
|
||||
]
|
||||
let mainFiles = ManualMainFilesProvider(
|
||||
[
|
||||
h: [cpp1],
|
||||
cpp1: [cpp1],
|
||||
cpp2: [cpp2],
|
||||
]
|
||||
)
|
||||
|
||||
let bs = ManualBuildSystem()
|
||||
let bsm = await BuildSystemManager(
|
||||
@@ -264,7 +257,7 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
await bsm.registerForChangeNotifications(for: h, language: .c)
|
||||
assertEqual(await bsm.buildSettingsInferredFromMainFile(for: h, language: .c), bs.map[cpp1]!)
|
||||
|
||||
mainFiles.mainFiles[h] = Set([cpp2])
|
||||
await mainFiles.updateMainFiles(for: h, to: [cpp2])
|
||||
|
||||
let changed = expectation(description: "changed settings to cpp2")
|
||||
await del.setExpected([(h, .c, bs.map[cpp2]!, changed, #file, #line)])
|
||||
@@ -277,14 +270,14 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
await bsm.mainFilesChanged()
|
||||
try await fulfillmentOfOrThrow([changed2], timeout: 1)
|
||||
|
||||
mainFiles.mainFiles[h] = Set([cpp1, cpp2])
|
||||
await mainFiles.updateMainFiles(for: h, to: [cpp1, cpp2])
|
||||
|
||||
let changed3 = expectation(description: "added lexicographically earlier main file")
|
||||
await del.setExpected([(h, .c, bs.map[cpp1]!, changed3, #file, #line)])
|
||||
await bsm.mainFilesChanged()
|
||||
try await fulfillmentOfOrThrow([changed3], timeout: 1)
|
||||
|
||||
mainFiles.mainFiles[h] = Set([])
|
||||
await mainFiles.updateMainFiles(for: h, to: [])
|
||||
|
||||
let changed4 = expectation(description: "changed settings to []")
|
||||
await del.setExpected([(h, .c, nil, changed4, #file, #line)])
|
||||
@@ -296,11 +289,12 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
let h1 = DocumentURI(string: "bsm:header1.h")
|
||||
let h2 = DocumentURI(string: "bsm:header2.h")
|
||||
let cpp = DocumentURI(string: "bsm:main.cpp")
|
||||
let mainFiles = ManualMainFilesProvider()
|
||||
mainFiles.mainFiles = [
|
||||
h1: Set([cpp]),
|
||||
h2: Set([cpp]),
|
||||
]
|
||||
let mainFiles = ManualMainFilesProvider(
|
||||
[
|
||||
h1: [cpp],
|
||||
h2: [cpp],
|
||||
]
|
||||
)
|
||||
|
||||
let bs = ManualBuildSystem()
|
||||
let bsm = await BuildSystemManager(
|
||||
@@ -342,8 +336,7 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
let a = DocumentURI(string: "bsm:a.swift")
|
||||
let b = DocumentURI(string: "bsm:b.swift")
|
||||
let c = DocumentURI(string: "bsm:c.swift")
|
||||
let mainFiles = ManualMainFilesProvider()
|
||||
mainFiles.mainFiles = [a: Set([a]), b: Set([b]), c: Set([c])]
|
||||
let mainFiles = ManualMainFilesProvider([a: [a], b: [b], c: [c]])
|
||||
let bs = ManualBuildSystem()
|
||||
let bsm = await BuildSystemManager(
|
||||
buildSystem: bs,
|
||||
@@ -384,8 +377,7 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
|
||||
func testDependenciesUpdated() async throws {
|
||||
let a = DocumentURI(string: "bsm:a.swift")
|
||||
let mainFiles = ManualMainFilesProvider()
|
||||
mainFiles.mainFiles = [a: Set([a])]
|
||||
let mainFiles = ManualMainFilesProvider([a: [a]])
|
||||
|
||||
let bs = ManualBuildSystem()
|
||||
let bsm = await BuildSystemManager(
|
||||
@@ -412,12 +404,15 @@ final class BuildSystemManagerTests: XCTestCase {
|
||||
// MARK: Helper Classes for Testing
|
||||
|
||||
/// A simple `MainFilesProvider` that wraps a dictionary, for testing.
|
||||
private final class ManualMainFilesProvider: MainFilesProvider {
|
||||
let lock: DispatchQueue = DispatchQueue(label: "\(ManualMainFilesProvider.self)-lock")
|
||||
private var _mainFiles: [DocumentURI: Set<DocumentURI>] = [:]
|
||||
var mainFiles: [DocumentURI: Set<DocumentURI>] {
|
||||
get { lock.sync { _mainFiles } }
|
||||
set { lock.sync { _mainFiles = newValue } }
|
||||
private final actor ManualMainFilesProvider: MainFilesProvider {
|
||||
private var mainFiles: [DocumentURI: Set<DocumentURI>]
|
||||
|
||||
init(_ mainFiles: [DocumentURI: Set<DocumentURI>]) {
|
||||
self.mainFiles = mainFiles
|
||||
}
|
||||
|
||||
func updateMainFiles(for file: DocumentURI, to mainFiles: Set<DocumentURI>)async {
|
||||
self.mainFiles[file] = mainFiles
|
||||
}
|
||||
|
||||
func mainFilesContainingFile(_ file: DocumentURI) -> Set<DocumentURI> {
|
||||
|
||||
Reference in New Issue
Block a user