Skip to content

Commit 5cfd750

Browse files
committed
Extend parser consistency checking to check for failed parses.
Optionally diagnose unexpected and missing tokens as part of the parser consistency checking. Ignore diagnostics within `#if`, because we cannot reason about those yet.
1 parent 5707ce3 commit 5cfd750

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

Sources/SwiftParser/CompilerSupport.swift

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@
99
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1010
//
1111
//===----------------------------------------------------------------------===//
12+
@_spi(RawSyntax) import SwiftSyntax
13+
14+
extension Syntax {
15+
/// Whether this syntax node is or is enclosed within a #if.
16+
fileprivate var isInIfConfig: Bool {
17+
if self.is(IfConfigDeclSyntax.self) {
18+
return true
19+
}
20+
21+
return parent?.isInIfConfig ?? false
22+
}
23+
}
1224

1325
/// Entry point for the Swift compiler to use for consistency checking.
1426
///
@@ -18,6 +30,7 @@
1830
/// - filename: The name of the source file, which is used only for diagnostics
1931
/// - flags: Flags that indicate what checks should be performed.
2032
/// 0x01: Perform round-trip checking.
33+
/// 0x02: Check for parser diagnostics.
2134
/// - Returns: 0 if all requested consistency checks passed, nonzero otherwise.
2235
@_cdecl("swift_parser_consistencyCheck")
2336
@_spi(SwiftCompiler)
@@ -30,19 +43,44 @@ public func _parserConsistencyCheck(
3043
var parser = Parser(buffer)
3144
return withExtendedLifetime(parser) { () -> CInt in
3245
// Parse the source file
33-
let sourceFile = parser.parseSourceFile()
46+
let rawSourceFile = parser.parseSourceFile()
3447

3548
// Round-trip test.
3649
if flags & 0x01 != 0 {
3750
var bufferArray = [UInt8](buffer)
3851
bufferArray.append(0)
39-
if "\(sourceFile)" != String(cString: bufferArray) {
52+
if "\(rawSourceFile)" != String(cString: bufferArray) {
4053
print(
4154
"\(String(cString: filename)): error: file failed to round-trip")
4255
return 1
4356
}
4457
}
4558

59+
// Diagnostics test.
60+
if flags & 0x02 != 0 {
61+
var anyDiags = false
62+
63+
let sourceFile = Syntax(raw: rawSourceFile.raw).as(SourceFileSyntax.self)!
64+
65+
let diags = ParseDiagnosticsGenerator.diagnostics(
66+
for: sourceFile)
67+
for diag in diags {
68+
// Skip over diagnostics within #if, because we don't know whether
69+
// we are in an active region or not.
70+
// FIXME: This heuristic could be improved.
71+
if diag.node.isInIfConfig {
72+
continue
73+
}
74+
75+
print("\(diag.debugDescription)")
76+
anyDiags = true
77+
}
78+
79+
if anyDiags {
80+
return 1
81+
}
82+
}
83+
4684
return 0
4785
}
4886
}

Sources/SwiftParser/SwiftParserCompilerSupport.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ extern "C" {
2121
enum SwiftParserConsistencyCheckFlags {
2222
/// Ensure that the syntax tree produced by the parser fully reproduces the
2323
/// input source.
24-
SPCC_RoundTrip = 0x01
24+
SPCC_RoundTrip = 0x01,
25+
26+
/// Check for the presence of parsing diagnostics.
27+
SPCC_ParseDiagnostics = 0x02
2528
};
2629

2730
/// Entry point for the Swift compiler to use for consistency checking.

0 commit comments

Comments
 (0)