Skip to content

Merge tests defined in extensions #1227

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

Merged
merged 6 commits into from
May 10, 2024
Merged
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
2 changes: 1 addition & 1 deletion Sources/SourceKitLSP/LanguageService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public protocol LanguageService: AnyObject {
/// This is used as a fallback to show the test cases in a file if the index for a given file is not up-to-date.
///
/// A return value of `nil` indicates that this language service does not support syntactic test discovery.
func syntacticDocumentTests(for uri: DocumentURI, in workspace: Workspace) async throws -> [TestItem]?
func syntacticDocumentTests(for uri: DocumentURI, in workspace: Workspace) async throws -> [AnnotatedTestItem]?

/// Crash the language server. Should be used for crash recovery testing only.
func _crash() async
Expand Down
55 changes: 35 additions & 20 deletions Sources/SourceKitLSP/Swift/SwiftTestingScanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,13 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
private let parentTypeNames: [String]

/// The discovered test items.
private var result: [TestItem] = []
private var result: [AnnotatedTestItem] = []

private init(snapshot: DocumentSnapshot, allTestsDisabled: Bool, parentTypeNames: [String]) {
private init(
snapshot: DocumentSnapshot,
allTestsDisabled: Bool,
parentTypeNames: [String]
) {
self.snapshot = snapshot
self.allTestsDisabled = allTestsDisabled
self.parentTypeNames = parentTypeNames
Expand All @@ -190,7 +194,7 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
public static func findTestSymbols(
in snapshot: DocumentSnapshot,
syntaxTreeManager: SyntaxTreeManager
) async -> [TestItem] {
) async -> [AnnotatedTestItem] {
guard snapshot.text.contains("Suite") || snapshot.text.contains("Test") else {
// If the file contains swift-testing tests, it must contain a `@Suite` or `@Test` attribute.
// Only check for the attribute name because the attribute may be module qualified and contain an arbitrary amount
Expand All @@ -199,7 +203,11 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
return []
}
let syntaxTree = await syntaxTreeManager.syntaxTree(for: snapshot)
let visitor = SyntacticSwiftTestingTestScanner(snapshot: snapshot, allTestsDisabled: false, parentTypeNames: [])
let visitor = SyntacticSwiftTestingTestScanner(
snapshot: snapshot,
allTestsDisabled: false,
parentTypeNames: []
)
visitor.walk(syntaxTree)
return visitor.result
}
Expand Down Expand Up @@ -241,14 +249,18 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
}

let range = snapshot.range(of: node.positionAfterSkippingLeadingTrivia..<node.endPositionBeforeTrailingTrivia)
let testItem = TestItem(
id: (parentTypeNames + typeNames).joined(separator: "/"),
label: attributeData?.displayName ?? typeNames.last!,
disabled: (attributeData?.isDisabled ?? false) || allTestsDisabled,
style: TestStyle.swiftTesting,
location: Location(uri: snapshot.uri, range: range),
children: memberScanner.result,
tags: attributeData?.tags.map(TestTag.init(id:)) ?? []
// Members won't be extensions since extensions will only be at the top level.
let testItem = AnnotatedTestItem(
testItem: TestItem(
id: (parentTypeNames + typeNames).joined(separator: "/"),
label: attributeData?.displayName ?? typeNames.last!,
disabled: (attributeData?.isDisabled ?? false) || allTestsDisabled,
style: TestStyle.swiftTesting,
location: Location(uri: snapshot.uri, range: range),
children: memberScanner.result.map(\.testItem),
tags: attributeData?.tags.map(TestTag.init(id:)) ?? []
),
isExtension: node.is(ExtensionDeclSyntax.self)
)
result.append(testItem)
return .skipChildren
Expand Down Expand Up @@ -295,14 +307,17 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
node.name.text + "(" + node.signature.parameterClause.parameters.map { "\($0.firstName.text):" }.joined() + ")"

let range = snapshot.range(of: node.positionAfterSkippingLeadingTrivia..<node.endPositionBeforeTrailingTrivia)
let testItem = TestItem(
id: (parentTypeNames + [name]).joined(separator: "/"),
label: attributeData.displayName ?? name,
disabled: attributeData.isDisabled || allTestsDisabled,
style: TestStyle.swiftTesting,
location: Location(uri: snapshot.uri, range: range),
children: [],
tags: attributeData.tags.map(TestTag.init(id:))
let testItem = AnnotatedTestItem(
testItem: TestItem(
id: (parentTypeNames + [name]).joined(separator: "/"),
label: attributeData.displayName ?? name,
disabled: attributeData.isDisabled || allTestsDisabled,
style: TestStyle.swiftTesting,
location: Location(uri: snapshot.uri, range: range),
children: [],
tags: attributeData.tags.map(TestTag.init(id:))
),
isExtension: false
)
result.append(testItem)
return .visitChildren
Expand Down
7 changes: 4 additions & 3 deletions Sources/SourceKitLSP/Swift/SyntacticTestIndex.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fileprivate enum TaskMetadata: DependencyTracker, Equatable {
/// Data from a syntactic scan of a source file for tests.
fileprivate struct IndexedTests {
/// The tests within the source file.
let tests: [TestItem]
let tests: [AnnotatedTestItem]

/// The modification date of the source file when it was scanned. A file won't get re-scanned if its modification date
/// is older or the same as this date.
Expand All @@ -63,7 +63,7 @@ fileprivate struct IndexedTests {
/// Does not write the results to the index.
///
/// The order of the returned tests is not defined. The results should be sorted before being returned to the editor.
fileprivate func testItems(in url: URL) async -> [TestItem] {
fileprivate func testItems(in url: URL) async -> [AnnotatedTestItem] {
guard url.pathExtension == "swift" else {
return []
}
Expand All @@ -79,6 +79,7 @@ fileprivate func testItems(in url: URL) async -> [TestItem] {
syntaxTreeManager: syntaxTreeManager
)
async let xcTests = SyntacticSwiftXCTestScanner.findTestSymbols(in: snapshot, syntaxTreeManager: syntaxTreeManager)

return await swiftTestingTests + xcTests
}

Expand Down Expand Up @@ -206,7 +207,7 @@ actor SyntacticTestIndex {
/// Gets all the tests in the syntactic index.
///
/// This waits for any pending document updates to be indexed before returning a result.
nonisolated func tests() async -> [TestItem] {
nonisolated func tests() async -> [AnnotatedTestItem] {
let readTask = indexingQueue.async(metadata: .read) {
return await self.indexedTests.values.flatMap { $0.tests }
}
Expand Down
Loading