Skip to content

Commit

Permalink
Add support for Swift Testing
Browse files Browse the repository at this point in the history
  • Loading branch information
ileitch committed Dec 18, 2024
1 parent e00a816 commit ebfa84f
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

##### Enhancements

- None.
- Added support for Swift Testing.

##### Bug Fixes

Expand Down
1 change: 1 addition & 0 deletions Sources/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ swift_library(
"SourceGraph/Mutators/ResultBuilderRetainer.swift",
"SourceGraph/Mutators/StringInterpolationAppendInterpolationRetainer.swift",
"SourceGraph/Mutators/StructImplicitInitializerReferenceBuilder.swift",
"SourceGraph/Mutators/SwiftTestingRetainer.swift",
"SourceGraph/Mutators/SwiftUIRetainer.swift",
"SourceGraph/Mutators/UnusedImportMarker.swift",
"SourceGraph/Mutators/UnusedParameterRetainer.swift",
Expand Down
1 change: 1 addition & 0 deletions Sources/Indexer/SwiftIndexer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ final class SwiftIndexer: Indexer {
multiplexingSyntaxVisitor.visit()

sourceFile.importStatements = importSyntaxVisitor.importStatements
sourceFile.importsSwiftTesting = importSyntaxVisitor.importStatements.contains(where: { $0.module == "Testing" })

if !configuration.disableUnusedImportAnalysis {
for stmt in sourceFile.importStatements where stmt.isExported {
Expand Down
1 change: 1 addition & 0 deletions Sources/SourceGraph/Elements/SourceFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public class SourceFile {
public let path: FilePath
public let modules: Set<String>
public var importStatements: [ImportStatement] = []
public var importsSwiftTesting = false

public init(path: FilePath, modules: Set<String>) {
self.path = path
Expand Down
35 changes: 35 additions & 0 deletions Sources/SourceGraph/Mutators/SwiftTestingRetainer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Configuration
import Foundation
import Shared

/// Retains Swift Testing declarations.
/// https://developer.apple.com/xcode/swift-testing/
final class SwiftTestingRetainer: SourceGraphMutator {
private let graph: SourceGraph

required init(graph: SourceGraph, configuration _: Configuration, swiftVersion _: SwiftVersion) {
self.graph = graph
}

func mutate() {
for decl in graph.declarations(ofKinds: [.class, .struct]) {
guard decl.location.file.importsSwiftTesting else { continue }

if decl.attributes.contains("Suite") {
graph.markRetained(decl)
}
}

for decl in graph.declarations(ofKinds: [.functionFree, .functionMethodInstance, .functionMethodClass, .functionMethodStatic]) {
guard decl.location.file.importsSwiftTesting else { continue }

if decl.attributes.contains("Test") {
graph.markRetained(decl)

if let parent = decl.parent {
graph.markRetained(parent)
}
}
}
}
}
1 change: 1 addition & 0 deletions Sources/SourceGraph/SourceGraphMutatorRunner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public final class SourceGraphMutatorRunner {
EntryPointAttributeRetainer.self,
PubliclyAccessibleRetainer.self,
XCTestRetainer.self,
SwiftTestingRetainer.self,
SwiftUIRetainer.self,
StringInterpolationAppendInterpolationRetainer.self,
PropertyWrapperRetainer.self,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#if canImport(Testing)
import Testing

@Test func swiftTestingFreeFunction() {}

class SwiftTestingClass {
@Test("displayName") func instanceMethod() {}
@Test class func classMethod() {}
@Test static func staticMethod() {}
}

@Suite struct SwiftTestingStructWithSuite {
@Test func instanceMethod() {}
@Test("displayName") static func staticMethod() {}
}

@Suite("displayName") class SwiftTestingClassWithSuite {
@Test func instanceMethod() {}
@Test("displayName") class func classMethod() {}
@Test static func staticMethod() {}
}
#endif
27 changes: 27 additions & 0 deletions Tests/PeripheryTests/RetentionTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,33 @@ final class RetentionTest: FixtureSourceGraphTestCase {
}
}

// MARK: - Swift Testing

#if canImport(Testing)
func testRetainsSwiftTestingDeclarations() {
analyze {
assertReferenced(.functionFree("swiftTestingFreeFunction()"))

assertReferenced(.class("SwiftTestingClass")) {
self.assertReferenced(.functionMethodInstance("instanceMethod()"))
self.assertReferenced(.functionMethodClass("classMethod()"))
self.assertReferenced(.functionMethodStatic("staticMethod()"))
}

assertReferenced(.struct("SwiftTestingStructWithSuite")) {
self.assertReferenced(.functionMethodInstance("instanceMethod()"))
self.assertReferenced(.functionMethodStatic("staticMethod()"))
}

assertReferenced(.class("SwiftTestingClassWithSuite")) {
self.assertReferenced(.functionMethodInstance("instanceMethod()"))
self.assertReferenced(.functionMethodClass("classMethod()"))
self.assertReferenced(.functionMethodStatic("staticMethod()"))
}
}
}
#endif

// MARK: - Assign-only properties

func testStructImplicitInitializer() {
Expand Down

0 comments on commit ebfa84f

Please sign in to comment.