@@ -19,6 +19,36 @@ import _SwiftSyntaxTestSupport
19
19
20
20
// MARK: Lexing Assertions
21
21
22
+ struct LexemeSpec {
23
+ let tokenKind : RawTokenKind
24
+ let leadingTrivia : SyntaxText
25
+ let tokenText : SyntaxText
26
+ let trailingTrivia : SyntaxText
27
+ let flags : Lexer . Lexeme . Flags
28
+
29
+ /// The file and line at which this `LexemeSpec` was created, so that assertion failures can be reported at its location.
30
+ let file : StaticString
31
+ let line : UInt
32
+
33
+ init (
34
+ _ tokenKind: RawTokenKind ,
35
+ leading: SyntaxText = " " ,
36
+ text: SyntaxText ,
37
+ trailing: SyntaxText = " " ,
38
+ flags: Lexer . Lexeme . Flags = [ ] ,
39
+ file: StaticString = #file,
40
+ line: UInt = #line
41
+ ) {
42
+ self . tokenKind = tokenKind
43
+ self . leadingTrivia = leading
44
+ self . tokenText = text
45
+ self . trailingTrivia = trailing
46
+ self . flags = flags
47
+ self . file = file
48
+ self . line = line
49
+ }
50
+ }
51
+
22
52
/// Asserts that two lexical streams are structurally equal, including their trivia and any
23
53
/// text.
24
54
///
@@ -29,45 +59,85 @@ import _SwiftSyntaxTestSupport
29
59
/// which this function was called.
30
60
/// - line: The line number on which failure occurred. Defaults to the line number on which this
31
61
/// function was called.
32
- func AssertEqualTokens ( _ actual: [ Lexer . Lexeme ] , _ expected: [ Lexer . Lexeme ] , file: StaticString = #file, line: UInt = #line) {
62
+ private func AssertTokens ( _ actual: [ Lexer . Lexeme ] , _ expected: [ LexemeSpec ] , file: StaticString = #file, line: UInt = #line) {
33
63
guard actual. count == expected. count else {
34
- return XCTFail ( " Number of tokens does not match! \( actual. count) != \( expected. count) " , file: file, line: line)
64
+ return XCTFail (
65
+ " Expected \( expected. count) tokens but got \( actual. count) " ,
66
+ file: file,
67
+ line: line
68
+ )
35
69
}
36
70
37
- for (idx, ( l, r) ) in zip ( actual, expected) . enumerated ( ) {
38
- guard l. tokenKind == r. tokenKind else {
39
- return XCTFail ( " Token at index \( idx) does not match! \( l. tokenKind) != \( r. tokenKind) " , file: file, line: line)
71
+ for (actualLexeme, expectedLexeme) in zip ( actual, expected) {
72
+ if actualLexeme. tokenKind != expectedLexeme. tokenKind {
73
+ XCTFail (
74
+ " Expected token kind \( expectedLexeme. tokenKind) but got \( actualLexeme. tokenKind) " ,
75
+ file: expectedLexeme. file,
76
+ line: expectedLexeme. line
77
+ )
40
78
}
41
79
42
- guard l . leadingTriviaText == r . leadingTriviaText else {
43
- return FailStringsEqualWithDiff (
44
- String ( syntaxText: l . leadingTriviaText) ,
45
- String ( syntaxText: r . leadingTriviaText ) ,
46
- " Token at index \( idx ) does not have matching leading trivia " ,
47
- file: file,
48
- line: line
80
+ if actualLexeme . leadingTriviaText != expectedLexeme . leadingTrivia {
81
+ FailStringsEqualWithDiff (
82
+ String ( syntaxText: actualLexeme . leadingTriviaText) ,
83
+ String ( syntaxText: expectedLexeme . leadingTrivia ) ,
84
+ " Leading trivia does not match " ,
85
+ file: expectedLexeme . file,
86
+ line: expectedLexeme . line
49
87
)
50
88
}
51
89
52
- guard l . tokenText. debugDescription == r . tokenText. debugDescription else {
53
- return FailStringsEqualWithDiff (
54
- l . tokenText. debugDescription,
55
- r . tokenText. debugDescription,
56
- " Text at index \( idx ) does not have matching text " ,
57
- file: file,
58
- line: line
90
+ if actualLexeme . tokenText. debugDescription != expectedLexeme . tokenText. debugDescription {
91
+ FailStringsEqualWithDiff (
92
+ actualLexeme . tokenText. debugDescription,
93
+ expectedLexeme . tokenText. debugDescription,
94
+ " Token text does not match " ,
95
+ file: expectedLexeme . file,
96
+ line: expectedLexeme . line
59
97
)
60
98
}
61
99
62
- guard l . trailingTriviaText == r . trailingTriviaText else {
63
- return FailStringsEqualWithDiff (
64
- String ( syntaxText: l . trailingTriviaText) ,
65
- String ( syntaxText: r . trailingTriviaText ) ,
66
- " Token at index \( idx ) does not have matching trailing trivia " ,
67
- file: file,
68
- line: line
100
+ if actualLexeme . trailingTriviaText != expectedLexeme . trailingTrivia {
101
+ FailStringsEqualWithDiff (
102
+ String ( syntaxText: actualLexeme . trailingTriviaText) ,
103
+ String ( syntaxText: expectedLexeme . trailingTrivia ) ,
104
+ " Trailing trivia does not match " ,
105
+ file: expectedLexeme . file,
106
+ line: expectedLexeme . line
69
107
)
70
108
}
109
+
110
+ if actualLexeme. flags != expectedLexeme. flags {
111
+ XCTFail (
112
+ " Expected flags \( expectedLexeme. flags. debugDescription) but got \( actualLexeme. flags. debugDescription) " ,
113
+ file: expectedLexeme. file,
114
+ line: expectedLexeme. line
115
+ )
116
+ }
117
+ }
118
+ }
119
+
120
+ func AssertLexemes(
121
+ _ source: String ,
122
+ lexemes expectedLexemes: [ LexemeSpec ] ,
123
+ file: StaticString = #file,
124
+ line: UInt = #line
125
+ ) {
126
+ var expectedLexemes = expectedLexemes
127
+ if expectedLexemes. last? . tokenKind != . eof {
128
+ expectedLexemes. append ( LexemeSpec ( . eof, text: " " ) )
129
+ }
130
+ var source = source
131
+ source. withUTF8 { buf in
132
+ var lexemes = [ Lexer . Lexeme] ( )
133
+ for token in Lexer . tokenize ( buf, from: 0 ) {
134
+ lexemes. append ( token)
135
+
136
+ guard token. tokenKind != . eof else {
137
+ break
138
+ }
139
+ }
140
+ AssertTokens ( lexemes, expectedLexemes, file: file, line: line)
71
141
}
72
142
}
73
143
@@ -271,7 +341,9 @@ func AssertDiagnostic<T: SyntaxProtocol>(
271
341
"""
272
342
Diagnostic message should only span a single line. Message was:
273
343
\( diag. message)
274
- """
344
+ """ ,
345
+ file: file,
346
+ line: line
275
347
)
276
348
}
277
349
if let highlight = spec. highlight {
0 commit comments