Skip to content
15 changes: 14 additions & 1 deletion CodeGeneration/Sources/SyntaxSupport/CommonNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public let COMMON_NODES: [Node] = [
kind: .decl,
base: .syntax,
nameForDiagnostics: "declaration",
parserFunction: "parseDeclaration"
parserFunction: "parseDeclarationOrIfConfig"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseDeclaration() don't parse #if ... #endif. Newly introduced parseDeclarationOrIfConfig() just for DeclSyntax.parse(from:)

),

Node(
Expand Down Expand Up @@ -401,4 +401,17 @@ public let COMMON_NODES: [Node] = [
elementChoices: [.syntax]
),

Node(
kind: .unexpectedCodeDecl,
base: .decl,
nameForDiagnostics: nil,
documentation: "Unexpected code at declaration position",
children: [
Child(
name: "unexpectedCode",
// NOTE: This is not .collection() on purpose. We don't need collection related functions for this.
kind: .node(kind: .unexpectedNodes)
)
]
),
]
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
case typeSpecifier
case lifetimeSpecifierArguments
case typeSpecifierList
case unexpectedCodeDecl
case unexpectedNodes
case unresolvedAsExpr
case unresolvedIsExpr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ let layoutNodesParsableFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
DeclSyntax(
"""
mutating func parseNonOptionalCodeBlockItem() -> RawCodeBlockItemSyntax {
guard let node = self.parseCodeBlockItem(isAtTopLevel: false, allowInitDecl: true) else {
guard let node = self.parseCodeBlockItem(allowInitDecl: true, until: { _ in false }) else {
// The missing item is not necessary to be a declaration,
// which is just a placeholder here
return RawCodeBlockItemSyntax(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,12 @@ class ValidateSyntaxNodes: XCTestCase {

assertFailuresMatchXFails(
failures,
expectedFailures: []
expectedFailures: [
ValidationFailure(
node: .unexpectedCodeDecl,
message: "child 'unexpectedCode' is a SyntaxCollection but child is not marked as a collection"
)
]
)
}

Expand Down
33 changes: 27 additions & 6 deletions Sources/SwiftParser/Attributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ extension Parser {
//
// In such cases, the second `#if` is not `consumeIfConfigOfAttributes()`.
return .ifConfigDecl(
self.parsePoundIfDirective { (parser, _) -> RawAttributeListSyntax.Element in
return parser.parseAttributeListElement()
} syntax: { parser, attributes in
return .attributes(RawAttributeListSyntax(elements: attributes, arena: parser.arena))
}
self.parsePoundIfDirective({ .attributes($0.parseAttributeList()) })
)
} else {
return .attribute(self.parseAttribute())
Expand Down Expand Up @@ -896,7 +892,32 @@ extension Parser {
return makeMissingProviderArguments(unexpectedBefore: [])
}

let decl = parseDeclaration(in: .argumentList)
let decl: RawDeclSyntax
if self.at(.poundIf) {
// '#if' is not accepted in '@abi' attribute, but for recovery, parse it
// parse it and wrap the first decl init with unexpected nodes.
let ifConfig = self.parsePoundIfDirective({ parser in
let decl = parser.parseDeclaration(in: .argumentList)
let member = RawMemberBlockItemSyntax(decl: decl, semicolon: nil, arena: parser.arena)
return .decls(RawMemberBlockItemListSyntax(elements: [member], arena: parser.arena))
})
decl = ifConfig.makeUnexpectedKeepingFirstNode(
of: RawDeclSyntax.self,
arena: self.arena,
where: { !$0.is(RawIfConfigDeclSyntax.self) },
makeMissing: {
RawDeclSyntax(
RawMissingDeclSyntax(
attributes: self.emptyCollection(RawAttributeListSyntax.self),
modifiers: self.emptyCollection(RawDeclModifierListSyntax.self),
arena: self.arena
)
)
}
)
} else {
decl = self.parseDeclaration(in: .argumentList)
}

guard let provider = RawABIAttributeArgumentsSyntax.Provider(decl) else {
return makeMissingProviderArguments(unexpectedBefore: [decl.raw])
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftParser/CollectionNodes+Parsable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ extension CodeBlockItemListSyntax: SyntaxParseable {
extension MemberBlockItemListSyntax: SyntaxParseable {
public static func parse(from parser: inout Parser) -> Self {
return parse(from: &parser) { parser in
return parser.parseMemberDeclList()
return parser.parseMemberDeclList(until: { _ in false })
} makeMissing: { remainingTokens, arena in
let missingDecl = RawMissingDeclSyntax(
attributes: RawAttributeListSyntax(elements: [], arena: arena),
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftParser/CompilerFiles.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ extension Parser {

/// Parse a declaration macro expansions in type contexts.
mutating func parseMemberBlockItemListFile() -> RawMemberBlockItemListFileSyntax {
let members = self.parseMemberDeclList()
let members = self.parseMemberDeclList(until: { _ in false })
let (unexpectedBeforeEndOfFileToken, endOfFile) = self.expectEndOfFile()

return RawMemberBlockItemListFileSyntax(
Expand Down
Loading
Loading