Skip to content

Commit 5977d61

Browse files
authored
Withhold diagnostics when fallback arguments are being used (#281)
While fallback arguments are being used (either from the fallback build system or fallback settings from the primary build system), withhold semantic diagnostics from sourcekitd and all diagnostics from clangd. This helps prevent user confusion from spurious errors. - Also remove the DocumentURI standardization in favor of proper equality + hash checks to work around the %40 --> @ encoding issue seen on CI.
1 parent e4b2b06 commit 5977d61

File tree

11 files changed

+350
-118
lines changed

11 files changed

+350
-118
lines changed

Sources/LanguageServerProtocol/SupportTypes/DocumentURI.swift

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,6 @@
1212

1313
import Foundation
1414

15-
/// Standardize the URL.
16-
///
17-
/// This normalizes escape sequences in file URLs, like `%40` --> `@`.
18-
/// But for non-file URLs, has no effect.
19-
fileprivate func standardize(url: URL) -> URL {
20-
guard url.isFileURL else { return url }
21-
22-
// This has the side-effect of removing trailing slashes from file URLs
23-
// on Linux, so we may need to add it back.
24-
let standardized = url.standardizedFileURL
25-
if url.absoluteString.hasSuffix("/") && !standardized.absoluteString.hasSuffix("/") {
26-
return URL(fileURLWithPath: standardized.path, isDirectory: true)
27-
}
28-
return standardized
29-
}
30-
3115
public struct DocumentURI: Codable, Hashable {
3216
/// The URL that store the URIs value
3317
private let storage: URL
@@ -69,7 +53,7 @@ public struct DocumentURI: Codable, Hashable {
6953
guard let url = URL(string: string) else {
7054
fatalError("Failed to construct DocumentURI from '\(string)'")
7155
}
72-
self.init(standardize(url: url))
56+
self.init(url)
7357
}
7458

7559
public init(_ url: URL) {
@@ -81,6 +65,16 @@ public struct DocumentURI: Codable, Hashable {
8165
self.init(string: try decoder.singleValueContainer().decode(String.self))
8266
}
8367

68+
/// Equality check to handle escape sequences in file URLs.
69+
public static func == (lhs: DocumentURI, rhs: DocumentURI) -> Bool {
70+
return lhs.storage.scheme == rhs.storage.scheme && lhs.pseudoPath == rhs.pseudoPath
71+
}
72+
73+
public func hash(into hasher: inout Hasher) {
74+
hasher.combine(self.storage.scheme)
75+
hasher.combine(self.pseudoPath)
76+
}
77+
8478
public func encode(to encoder: Encoder) throws {
8579
try storage.absoluteString.encode(to: encoder)
8680
}

Sources/SKCore/BuildSystemManager.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ enum MainFileStatus: Equatable {
2121
/// Waiting for the `BuildSystem` to return settings.
2222
case waiting
2323

24-
/// No response from `BuildSystem` yet, using fallback arguments.
24+
/// No response from `BuildSystem` yet, using arguments from the fallback build system.
2525
case waitingUsingFallback(FileBuildSettings)
2626

27-
/// `BuildSystem` didn't handle the file, using fallback arguments.
27+
/// Two cases here:
28+
/// - Primary build system gave us fallback arguments to use.
29+
/// - Primary build system didn't handle the file, using arguments from the fallback build system.
2830
/// No longer waiting.
2931
case fallback(FileBuildSettings)
3032

@@ -64,8 +66,8 @@ extension MainFileStatus {
6466
switch self {
6567
case .waiting: return nil
6668
case .unsupported: return .removedOrUnavailable
67-
case .waitingUsingFallback(let settings): return .modified(settings)
68-
case .fallback(let settings): return .modified(settings)
69+
case .waitingUsingFallback(let settings): return .fallback(settings)
70+
case .fallback(let settings): return .fallback(settings)
6971
case .primary(let settings): return .modified(settings)
7072
}
7173
}
@@ -194,7 +196,7 @@ extension BuildSystemManager: BuildSystem {
194196
// Only have a fallback build system. We consider it be a primary build
195197
// system that functions synchronously.
196198
if let settings = fallback.settings(for: mainFile, language) {
197-
newStatus = .fallback(settings)
199+
newStatus = .primary(settings)
198200
} else {
199201
newStatus = .unsupported
200202
}
@@ -331,7 +333,7 @@ extension BuildSystemManager: BuildSystemDelegate {
331333
let newStatus: MainFileStatus
332334

333335
if let newSettings = settingsChange.newSettings {
334-
newStatus = .primary(newSettings)
336+
newStatus = settingsChange.isFallback ? .fallback(newSettings) : .primary(newSettings)
335337
} else if let fallback = self.fallbackBuildSystem {
336338
// FIXME: we need to stop threading the language everywhere, or we need the build system
337339
// itself to pass it in here. Or alteratively cache the fallback settings/language earlier?

Sources/SKCore/FileBuildSettingsChange.swift

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ public enum FileBuildSettingsChange {
1616
/// The `BuildSystem` has no `FileBuildSettings` for the file.
1717
case removedOrUnavailable
1818

19-
/// The `FileBuildSettings` have been modified.
19+
/// The `FileBuildSettings` have been modified or are newly available.
2020
case modified(FileBuildSettings)
21+
22+
/// The `BuildSystem` is providing fallback arguments which may not be correct.
23+
case fallback(FileBuildSettings)
2124
}
2225

2326
extension FileBuildSettingsChange {
@@ -27,12 +30,26 @@ extension FileBuildSettingsChange {
2730
return nil
2831
case .modified(let settings):
2932
return settings
33+
case .fallback(let settings):
34+
return settings
35+
}
36+
}
37+
38+
/// Whether the change represents fallback arguments.
39+
public var isFallback: Bool {
40+
switch self {
41+
case .removedOrUnavailable:
42+
return false
43+
case .modified(_):
44+
return false
45+
case .fallback(_):
46+
return true
3047
}
3148
}
3249

33-
public init(_ settings: FileBuildSettings?) {
50+
public init(_ settings: FileBuildSettings?, fallback: Bool = false) {
3451
if let settings = settings {
35-
self = .modified(settings)
52+
self = fallback ? .fallback(settings) : .modified(settings)
3653
} else {
3754
self = .removedOrUnavailable
3855
}

0 commit comments

Comments
 (0)