Skip to content

Check that there are no duplicate code completion results #178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions SourceKitStressTester/Sources/Common/Message.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,14 @@ public enum SourceKitError: Error {
}
}

public enum SourceKitErrorReason: String, Codable {
case errorResponse, errorTypeInResponse, errorDeserializingSyntaxTree,
sourceAndSyntaxTreeMismatch, missingExpectedResult, errorWritingModule
public enum SourceKitErrorReason: Codable {
case errorResponse
case errorTypeInResponse
case errorDeserializingSyntaxTree
case sourceAndSyntaxTreeMismatch
case missingExpectedResult
case duplicateResult(name: String)
case errorWritingModule
}

public enum RequestInfo {
Expand Down Expand Up @@ -477,6 +482,8 @@ extension SourceKitErrorReason: CustomStringConvertible {
return "SourceKit returned a syntax tree that doesn't match the expected source"
case .missingExpectedResult:
return "SourceKit returned a response that didn't contain the expected result"
case .duplicateResult(name: let name):
return "SourceKit returned a response that contained the result '\(name)' twice"
case .errorWritingModule:
return "Error while writing out module"
}
Expand Down
28 changes: 26 additions & 2 deletions SourceKitStressTester/Sources/StressTester/SourceKitDocument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -425,21 +425,45 @@ class SourceKitDocument {
}

private func checkExpectedCompletionResult(_ expected: ExpectedResult, in response: SourceKitdResponse, info: RequestInfo) throws {
/// Struct that defines a code completion result to determine if there are duplicate results.
struct CodeCompletionResultSpec: Hashable {
let description: String
let type: String
let usr: String

init(_ result: SourceKitdResponse.Dictionary) {
self.description = result.getString(.key_Description)
self.type = result.getString(.key_TypeName)
self.usr = result.getString(.key_AssociatedUSRs)
}
}
let matcher = CompletionMatcher(for: expected)
var found = false
var foundDuplicate: CodeCompletionResultSpec? = nil
var seenResults = Set<CodeCompletionResultSpec>()
response.value.getArray(.key_Results).enumerate { (_, item) -> Bool in
let result = item.getDictionary()
found = matcher.match(result.getString(.key_Name), ignoreArgLabels: shouldIgnoreArgs(of: expected, for: result))
let resultSpec = CodeCompletionResultSpec(result)
if foundDuplicate == nil, !seenResults.insert(resultSpec).inserted {
foundDuplicate = resultSpec
}
return !found
}
if !found {
lazy var truncatedResponseText = {
// FIXME: code completion responses can be huge, truncate them for now.
let maxSize = 25_000
var responseText = response.description
if responseText.count > maxSize {
responseText = responseText.prefix(maxSize) + "[truncated]"
}
throw SourceKitError.failed(.missingExpectedResult, request: info, response: responseText.trimmingCharacters(in: .newlines))
return responseText
}()
if !found {
throw SourceKitError.failed(.missingExpectedResult, request: info, response: truncatedResponseText.trimmingCharacters(in: .newlines))
}
if let foundDuplicate = foundDuplicate {
throw SourceKitError.failed(.duplicateResult(name: foundDuplicate.description), request: info, response: truncatedResponseText.trimmingCharacters(in: .newlines))
}
}

Expand Down