Skip to content

Commit c005544

Browse files
committed
Check that there are no duplicate code completion results
Code completion shouldn’t return the same result twice. rdar://92081219
1 parent 8275f72 commit c005544

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

SourceKitStressTester/Sources/Common/Message.swift

+10-3
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,14 @@ public enum SourceKitError: Error {
7676
}
7777
}
7878

79-
public enum SourceKitErrorReason: String, Codable {
80-
case errorResponse, errorTypeInResponse, errorDeserializingSyntaxTree,
81-
sourceAndSyntaxTreeMismatch, missingExpectedResult, errorWritingModule
79+
public enum SourceKitErrorReason: Codable {
80+
case errorResponse
81+
case errorTypeInResponse
82+
case errorDeserializingSyntaxTree
83+
case sourceAndSyntaxTreeMismatch
84+
case missingExpectedResult
85+
case duplicateResult(name: String)
86+
case errorWritingModule
8287
}
8388

8489
public enum RequestInfo {
@@ -477,6 +482,8 @@ extension SourceKitErrorReason: CustomStringConvertible {
477482
return "SourceKit returned a syntax tree that doesn't match the expected source"
478483
case .missingExpectedResult:
479484
return "SourceKit returned a response that didn't contain the expected result"
485+
case .duplicateResult(name: let name):
486+
return "SourceKit returned a response that contained the result '\(name)' twice"
480487
case .errorWritingModule:
481488
return "Error while writing out module"
482489
}

SourceKitStressTester/Sources/StressTester/SourceKitDocument.swift

+14-2
Original file line numberDiff line numberDiff line change
@@ -427,19 +427,31 @@ class SourceKitDocument {
427427
private func checkExpectedCompletionResult(_ expected: ExpectedResult, in response: SourceKitdResponse, info: RequestInfo) throws {
428428
let matcher = CompletionMatcher(for: expected)
429429
var found = false
430+
var foundDuplicate: String? = nil
431+
var seenResults = Set<String>()
430432
response.value.getArray(.key_Results).enumerate { (_, item) -> Bool in
431433
let result = item.getDictionary()
432434
found = matcher.match(result.getString(.key_Name), ignoreArgLabels: shouldIgnoreArgs(of: expected, for: result))
435+
let description = result.getString(.key_Description)
436+
if foundDuplicate == nil, !seenResults.insert(description).inserted {
437+
foundDuplicate = description
438+
}
433439
return !found
434440
}
435-
if !found {
441+
lazy var truncatedResponseText = {
436442
// FIXME: code completion responses can be huge, truncate them for now.
437443
let maxSize = 25_000
438444
var responseText = response.description
439445
if responseText.count > maxSize {
440446
responseText = responseText.prefix(maxSize) + "[truncated]"
441447
}
442-
throw SourceKitError.failed(.missingExpectedResult, request: info, response: responseText.trimmingCharacters(in: .newlines))
448+
return responseText
449+
}()
450+
if !found {
451+
throw SourceKitError.failed(.missingExpectedResult, request: info, response: truncatedResponseText.trimmingCharacters(in: .newlines))
452+
}
453+
if let foundDuplicate = foundDuplicate {
454+
throw SourceKitError.failed(.duplicateResult(name: foundDuplicate), request: info, response: truncatedResponseText.trimmingCharacters(in: .newlines))
443455
}
444456
}
445457

0 commit comments

Comments
 (0)