Skip to content

Commit 4bb7761

Browse files
authored
Merge pull request #562 from ahoppen/pr/syntax-comparison-improvements
Multiple improvements to SwiftSyntaxComparison
2 parents d3720a9 + b8f3907 commit 4bb7761

File tree

3 files changed

+62
-20
lines changed

3 files changed

+62
-20
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ let package = Package(
9191
),
9292
.target(
9393
name: "_SwiftSyntaxTestSupport",
94-
dependencies: ["SwiftSyntax", "SwiftSyntaxParser"]
94+
dependencies: ["SwiftSyntax"]
9595
),
9696
.executableTarget(
9797
name: "lit-test-helper",

Sources/_SwiftSyntaxTestSupport/Syntax+Assertions.swift

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
import SwiftSyntax
18-
import SwiftSyntaxParser
1918
import XCTest
2019

2120
/// Verifies that there is a next item returned by the iterator and that it
@@ -35,22 +34,55 @@ public func XCTAssertNextIsNil<Iterator: IteratorProtocol>(_ iterator: inout Ite
3534
}
3635

3736
/// Verifies that the tree parsed from `actual` has the same structure as
38-
/// `expected`, ie. it has the same structure and optionally the same trivia
39-
/// (if `includeTrivia` is set).
40-
public func XCTAssertSameStructure(_ actual: String, _ expected: Syntax, includeTrivia: Bool = false,
41-
file: StaticString = #filePath, line: UInt = #line) throws {
42-
let actualTree = try Syntax(SyntaxParser.parse(source: actual))
37+
/// `expected` when parsed with `parse`, ie. it has the same structure and
38+
/// optionally the same trivia (if `includeTrivia` is set).
39+
public func XCTAssertSameStructure(
40+
_ actual: String,
41+
parse: (String) throws -> Syntax,
42+
_ expected: Syntax,
43+
includeTrivia: Bool = false,
44+
file: StaticString = #filePath, line: UInt = #line
45+
) throws {
46+
let actualTree = try parse(actual)
4347
XCTAssertSameStructure(actualTree, expected, includeTrivia: includeTrivia, file: file, line: line)
4448
}
4549

4650
/// Verifies that two trees are equivalent, ie. they have the same structure
4751
/// and optionally the same trivia if `includeTrivia` is set.
48-
public func XCTAssertSameStructure(_ actual: Syntax, _ expected: Syntax, includeTrivia: Bool = false,
49-
file: StaticString = #filePath, line: UInt = #line) {
52+
public func XCTAssertSameStructure(
53+
_ actual: SyntaxProtocol,
54+
_ expected: SyntaxProtocol,
55+
includeTrivia: Bool = false,
56+
file: StaticString = #filePath, line: UInt = #line
57+
) {
5058
let diff = actual.findFirstDifference(baseline: expected, includeTrivia: includeTrivia)
5159
XCTAssertNil(diff, diff!.debugDescription, file: file, line: line)
5260
}
5361

62+
/// See `SubtreeMatcher.assertSameStructure`.
63+
public func XCTAssertHasSubstructure(
64+
_ markedText: String,
65+
parse: (String) throws -> Syntax,
66+
afterMarker: String? = nil,
67+
_ expected: SyntaxProtocol,
68+
includeTrivia: Bool = false,
69+
file: StaticString = #filePath, line: UInt = #line
70+
) throws {
71+
let subtreeMatcher = try SubtreeMatcher(markedText, parse: parse)
72+
try subtreeMatcher.assertSameStructure(afterMarker: afterMarker, Syntax(expected), file: file, line: line)
73+
}
74+
75+
/// See `SubtreeMatcher.assertSameStructure`.
76+
public func XCTAssertHasSubstructure(
77+
_ actualTree: SyntaxProtocol,
78+
_ expected: SyntaxProtocol,
79+
includeTrivia: Bool = false,
80+
file: StaticString = #filePath, line: UInt = #line
81+
) throws {
82+
let subtreeMatcher = SubtreeMatcher(Syntax(actualTree))
83+
try subtreeMatcher.assertSameStructure(Syntax(expected), file: file, line: line)
84+
}
85+
5486
/// Allows matching a subtrees of the given `markedText` against
5587
/// `baseline`/`expected` trees, where a combination of markers and the type
5688
/// of the `expected` tree is used to first find the subtree to match. Note
@@ -98,7 +130,7 @@ public struct SubtreeMatcher {
98130
/// The syntax tree from parsing source *with markers removed*.
99131
private var actualTree: Syntax
100132

101-
public init(_ markedText: String) throws {
133+
public init(_ markedText: String, parse: (String) throws -> Syntax) throws {
102134
var text = ""
103135
var markers = [String: Int]()
104136
var lastIndex = markedText.startIndex
@@ -112,7 +144,12 @@ public struct SubtreeMatcher {
112144
text += markedText[lastIndex ..< markedText.endIndex]
113145

114146
self.markers = markers.isEmpty ? ["DEFAULT": 0] : markers
115-
self.actualTree = try Syntax(SyntaxParser.parse(source: text))
147+
self.actualTree = try parse(text)
148+
}
149+
150+
public init(_ actualTree: Syntax) {
151+
self.markers = ["DEFAULT": 0]
152+
self.actualTree = actualTree
116153
}
117154

118155
/// Same as `Syntax.findFirstDifference(baseline:includeTrivia:)`, but
@@ -149,7 +186,7 @@ public enum SubtreeError: Error, CustomStringConvertible {
149186
case let .invalidMarker(name):
150187
return "Could not find marker with name '\(name)'"
151188
case let .invalidSubtree(tree, afterUTF8Offset, type):
152-
return "Could not find subtree after UTF8 offset \(afterUTF8Offset) with type \(type) in:\n\(tree.debugDescription)"
189+
return "Could not find subtree after UTF8 offset \(afterUTF8Offset) with type \(type) in:\n\(tree.debugDescription(includeChildren: true))"
153190
}
154191
}
155192
}

Tests/SwiftSyntaxTest/SyntaxComparisonTests.swift renamed to Tests/SwiftSyntaxParserTest/SyntaxComparisonTests.swift

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
import SwiftSyntax
22
import _SwiftSyntaxTestSupport
3+
import SwiftSyntaxParser
34
import XCTest
45

6+
private func parse(source: String) throws -> Syntax {
7+
return try Syntax(SyntaxParser.parse(source: source))
8+
}
9+
510
public class SyntaxComparisonTests: XCTestCase {
611
public func testSame() throws {
712
let expected = Syntax(makeFunc(identifier: SyntaxFactory.makeIdentifier("f")))
813

914
let actual = Syntax(makeFunc(identifier: SyntaxFactory.makeIdentifier("f")))
1015
XCTAssertNil(actual.findFirstDifference(baseline: expected))
1116

12-
let matcher = try SubtreeMatcher("struct A { func f() { } }")
17+
let matcher = try SubtreeMatcher("struct A { func f() { } }", parse: parse)
1318
try XCTAssertNil(matcher.findFirstDifference(baseline: expected))
1419
}
1520

@@ -36,7 +41,7 @@ public class SyntaxComparisonTests: XCTestCase {
3641
let actual = Syntax(makeFunc(identifier: SyntaxFactory.makeIdentifier("f")))
3742
try expectations(actual.findFirstDifference(baseline: expected))
3843

39-
let matcher = try SubtreeMatcher("struct A { #^FUNC^#func f() { } }")
44+
let matcher = try SubtreeMatcher("struct A { #^FUNC^#func f() { } }", parse: parse)
4045
try expectations(matcher.findFirstDifference(baseline: expected))
4146
}
4247

@@ -52,7 +57,7 @@ public class SyntaxComparisonTests: XCTestCase {
5257
let actual = Syntax(makeFunc(identifier: SyntaxFactory.makeIdentifier("g")))
5358
try expectations(actual.findFirstDifference(baseline: expected))
5459

55-
let matcher = try SubtreeMatcher("struct A { #^FUNC^#func g() { } }")
60+
let matcher = try SubtreeMatcher("struct A { #^FUNC^#func g() { } }", parse: parse)
5661
try expectations(matcher.findFirstDifference(afterMarker: "FUNC", baseline: expected))
5762
}
5863

@@ -69,7 +74,7 @@ public class SyntaxComparisonTests: XCTestCase {
6974
XCTAssertNil(actual.findFirstDifference(baseline: expected))
7075
try expectations(actual.findFirstDifference(baseline: expected, includeTrivia: true))
7176

72-
let matcher = try SubtreeMatcher("struct A {func f() { }}")
77+
let matcher = try SubtreeMatcher("struct A {func f() { }}", parse: parse)
7378
try XCTAssertNil(matcher.findFirstDifference(baseline: expected))
7479
try expectations(matcher.findFirstDifference(baseline: expected, includeTrivia: true))
7580
}
@@ -86,7 +91,7 @@ public class SyntaxComparisonTests: XCTestCase {
8691
let actual = Syntax(makeFunc(identifier: SyntaxFactory.makeIdentifier("f")))
8792
try expectations(actual.findFirstDifference(baseline: expected))
8893

89-
let matcher = try SubtreeMatcher("struct A { func f() { } }")
94+
let matcher = try SubtreeMatcher("struct A { func f() { } }", parse: parse)
9095
try expectations(matcher.findFirstDifference(baseline: expected))
9196
}
9297

@@ -100,7 +105,7 @@ public class SyntaxComparisonTests: XCTestCase {
100105
let actual = Syntax(makeFunc(identifier: SyntaxFactory.makeIdentifier("f")))
101106
try expectations(actual.findFirstDifference(baseline: expected))
102107

103-
let matcher = try SubtreeMatcher("struct A { func f() { } }")
108+
let matcher = try SubtreeMatcher("struct A { func f() { } }", parse: parse)
104109
try expectations(matcher.findFirstDifference(baseline: expected))
105110
}
106111

@@ -120,7 +125,7 @@ public class SyntaxComparisonTests: XCTestCase {
120125
0
121126
}
122127
}
123-
""")
128+
""", parse: parse)
124129
try expectations(matcher.findFirstDifference(baseline: expected))
125130
}
126131

@@ -137,7 +142,7 @@ public class SyntaxComparisonTests: XCTestCase {
137142
0
138143
}
139144
}
140-
""")
145+
""", parse: parse)
141146
let funcDiff = try XCTUnwrap(matcher.findFirstDifference(afterMarker: "FUNC", baseline: expectedFunc))
142147
XCTAssertEqual(funcDiff.reason, .additionalNode)
143148

0 commit comments

Comments
 (0)