Skip to content

Commit 3f866b7

Browse files
authored
Merge pull request #1171 from ahoppen/ahoppen/6.0/update-from-main-04-08
[6.0] Merge changes from `main`
2 parents af51dc3 + c0b2ff2 commit 3f866b7

32 files changed

+886
-337
lines changed

Sources/Diagnose/SourceReducer.swift

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,10 @@ fileprivate class SourceReducer {
196196

197197
/// Replace the first `import` declaration in the source file by the contents of the Swift interface.
198198
private func inlineFirstImport(_ requestInfo: RequestInfo) async throws -> RequestInfo? {
199-
let reductionResult = try await runReductionStep(requestInfo: requestInfo) { tree in
199+
// Don't report progress after inlining an import because it might increase the file size before we have a chance
200+
// to increase `fileSizeAfterLastImportInline`. Progress will get updated again on the next successful reduction
201+
// step.
202+
let reductionResult = try await runReductionStep(requestInfo: requestInfo, reportProgress: false) { tree in
200203
let edits = await Diagnose.inlineFirstImport(
201204
in: tree,
202205
executor: sourcekitdExecutor,
@@ -216,15 +219,22 @@ fileprivate class SourceReducer {
216219
// MARK: Primitives to run reduction steps
217220

218221
private func logSuccessfulReduction(_ requestInfo: RequestInfo, tree: SourceFileSyntax) {
219-
let numberOfImports = tree.numberOfImports
222+
// The number of imports can grow if inlining a single module adds more than 1 new import.
223+
// To keep progress between 0 and 1, clamp the number of imports to the initial import count.
224+
let numberOfImports = min(tree.numberOfImports, initialImportCount)
220225
let fileSize = requestInfo.fileContents.utf8.count
221226

222227
let progressPerRemovedImport = Double(1) / Double(initialImportCount + 1)
223228
let removeImportProgress = Double(initialImportCount - numberOfImports) * progressPerRemovedImport
224229
let fileReductionProgress =
225230
(1 - Double(fileSize) / Double(fileSizeAfterLastImportInline)) * progressPerRemovedImport
226-
let progress = removeImportProgress + fileReductionProgress
227-
precondition(progress >= 0 && progress <= 1)
231+
var progress = removeImportProgress + fileReductionProgress
232+
if progress < 0 || progress > 1 {
233+
logger.fault(
234+
"Trying to report progress \(progress) from remove import progress \(removeImportProgress) and file reduction progress \(fileReductionProgress)"
235+
)
236+
progress = max(min(progress, 1), 0)
237+
}
228238
progressUpdate(progress, "Reduced to \(numberOfImports) imports and \(fileSize) bytes")
229239
}
230240

@@ -234,6 +244,7 @@ fileprivate class SourceReducer {
234244
/// Otherwise, return `nil`
235245
private func runReductionStep(
236246
requestInfo: RequestInfo,
247+
reportProgress: Bool = true,
237248
reduce: (_ tree: SourceFileSyntax) async throws -> ReducerResult
238249
) async throws -> ReductionStepResult {
239250
let tree = Parser.parse(source: requestInfo.fileContents)
@@ -263,7 +274,9 @@ fileprivate class SourceReducer {
263274
let result = try await sourcekitdExecutor.run(request: reducedRequestInfo)
264275
if case .reproducesIssue = result {
265276
logger.debug("Reduction successful")
266-
logSuccessfulReduction(reducedRequestInfo, tree: tree)
277+
if reportProgress {
278+
logSuccessfulReduction(reducedRequestInfo, tree: tree)
279+
}
267280
return .reduced(reducedRequestInfo)
268281
} else {
269282
logger.debug("Reduction did not reproduce the issue")

Sources/LSPTestSupport/TestJSONRPCConnection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ public final class TestServer: MessageHandler {
197197

198198
private let testMessageRegistry = MessageRegistry(
199199
requests: [EchoRequest.self, EchoError.self],
200-
notifications: [EchoNotification.self]
200+
notifications: [EchoNotification.self, ShowMessageNotification.self]
201201
)
202202

203203
#if compiler(<5.11)

Sources/LanguageServerProtocol/Requests/IndexedRenameRequest.swift

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ extension IndexedRenameRequest: Codable {
7272
)
7373
self.oldName = try container.decode(String.self, forKey: IndexedRenameRequest.CodingKeys.oldName)
7474
self.newName = try container.decode(String.self, forKey: IndexedRenameRequest.CodingKeys.newName)
75-
self.positions = try container.decode([String: [Position]].self, forKey: .positions).mapKeys(DocumentURI.init)
75+
self.positions = try container.decode([String: [Position]].self, forKey: .positions).compactMapKeys {
76+
try? DocumentURI(string: $0)
77+
}
7678
}
7779

7880
public func encode(to encoder: Encoder) throws {
@@ -81,13 +83,22 @@ extension IndexedRenameRequest: Codable {
8183
try container.encode(self.textDocument, forKey: IndexedRenameRequest.CodingKeys.textDocument)
8284
try container.encode(self.oldName, forKey: IndexedRenameRequest.CodingKeys.oldName)
8385
try container.encode(self.newName, forKey: IndexedRenameRequest.CodingKeys.newName)
84-
try container.encode(self.positions.mapKeys(\.stringValue), forKey: IndexedRenameRequest.CodingKeys.positions)
86+
try container.encode(
87+
self.positions.compactMapKeys { $0.stringValue },
88+
forKey: IndexedRenameRequest.CodingKeys.positions
89+
)
8590

8691
}
8792
}
8893

8994
fileprivate extension Dictionary {
90-
func mapKeys<NewKeyType: Hashable>(_ transform: (Key) -> NewKeyType) -> [NewKeyType: Value] {
91-
return [NewKeyType: Value](uniqueKeysWithValues: self.map { (transform($0.key), $0.value) })
95+
func compactMapKeys<NewKeyType: Hashable>(_ transform: (Key) -> NewKeyType?) -> [NewKeyType: Value] {
96+
let newKeysAndValues = self.compactMap { (key, value) -> (NewKeyType, Value)? in
97+
guard let newKey = transform(key) else {
98+
return nil
99+
}
100+
return (newKey, value)
101+
}
102+
return [NewKeyType: Value](uniqueKeysWithValues: newKeysAndValues)
92103
}
93104
}

Sources/LanguageServerProtocol/SupportTypes/DocumentURI.swift

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

1313
import Foundation
1414

15+
struct FailedToConstructDocumentURIFromStringError: Error, CustomStringConvertible {
16+
let string: String
17+
18+
var description: String {
19+
return "Failed to construct DocumentURI from '\(string)'"
20+
}
21+
}
22+
1523
public struct DocumentURI: Codable, Hashable, Sendable {
1624
/// The URL that store the URIs value
1725
private let storage: URL
@@ -55,9 +63,9 @@ public struct DocumentURI: Codable, Hashable, Sendable {
5563

5664
/// Construct a DocumentURI from the given URI string, automatically parsing
5765
/// it either as a URL or an opaque URI.
58-
public init(string: String) {
66+
public init(string: String) throws {
5967
guard let url = URL(string: string) else {
60-
fatalError("Failed to construct DocumentURI from '\(string)'")
68+
throw FailedToConstructDocumentURIFromStringError(string: string)
6169
}
6270
self.init(url)
6371
}
@@ -68,7 +76,7 @@ public struct DocumentURI: Codable, Hashable, Sendable {
6876
}
6977

7078
public init(from decoder: Decoder) throws {
71-
self.init(string: try decoder.singleValueContainer().decode(String.self))
79+
try self.init(string: decoder.singleValueContainer().decode(String.self))
7280
}
7381

7482
/// Equality check to handle escape sequences in file URLs.

Sources/LanguageServerProtocol/SupportTypes/TextDocumentIdentifier.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ extension TextDocumentIdentifier: LSPAnyCodable {
2626
guard case .string(let uriString)? = dictionary[CodingKeys.uri.stringValue] else {
2727
return nil
2828
}
29-
self.uri = DocumentURI(string: uriString)
29+
guard let uri = try? DocumentURI(string: uriString) else {
30+
return nil
31+
}
32+
self.uri = uri
3033
}
3134

3235
public func encodeToLSPAny() -> LSPAny {

Sources/LanguageServerProtocol/SupportTypes/WorkspaceEdit.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ extension WorkspaceEdit: Codable {
4949
if let changesDict = try container.decodeIfPresent([String: [TextEdit]].self, forKey: .changes) {
5050
var changes = [DocumentURI: [TextEdit]]()
5151
for change in changesDict {
52-
let uri = DocumentURI(string: change.key)
52+
let uri = try DocumentURI(string: change.key)
5353
changes[uri] = change.value
5454
}
5555
self.changes = changes
@@ -311,8 +311,10 @@ extension WorkspaceEdit: LSPAnyCodable {
311311
}
312312
var dictionary = [DocumentURI: [TextEdit]]()
313313
for (key, value) in lspDict {
314-
let uri = DocumentURI(string: key)
315-
guard let edits = [TextEdit](fromLSPArray: value) else {
314+
guard
315+
let uri = try? DocumentURI(string: key),
316+
let edits = [TextEdit](fromLSPArray: value)
317+
else {
316318
return nil
317319
}
318320
dictionary[uri] = edits

0 commit comments

Comments
 (0)