Skip to content

Add SwiftSyntaxBuilder convenience initializers that mix parser integration and result builders #1012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 100 additions & 95 deletions Sources/SwiftParser/Declarations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,6 @@ extension Parser {
}

extension Parser {
@_spi(RawSyntax)
public enum ParameterSubject {
case closure
case enumCase
Expand Down Expand Up @@ -946,6 +945,103 @@ extension Parser {
}
}

@_spi(RawSyntax)
public mutating func parseFunctionParameter(for subject: ParameterSubject) -> RawFunctionParameterSyntax {
// Parse any declaration attributes. The exception here is enum cases
// which only allow types, so we do not consume attributes to allow the
// type attribute grammar a chance to examine them.
let attrs: RawAttributeListSyntax?
if case .enumCase = subject {
attrs = nil
} else {
attrs = self.parseAttributeList()
}

let modifiers = parseParameterModifiers(for: subject)

var misplacedSpecifiers: [RawTokenSyntax] = []
while let specifier = self.consume(ifAnyIn: TypeSpecifier.self) {
misplacedSpecifiers.append(specifier)
}

let unexpectedBeforeFirstName: RawUnexpectedNodesSyntax?
let firstName: RawTokenSyntax?
let unexpectedBeforeSecondName: RawUnexpectedNodesSyntax?
let secondName: RawTokenSyntax?
let unexpectedBeforeColon: RawUnexpectedNodesSyntax?
let colon: RawTokenSyntax?
let shouldParseType: Bool

if self.withLookahead({ $0.startsParameterName(isClosure: subject.isClosure, allowMisplacedSpecifierRecovery: false) }) {
if self.currentToken.canBeArgumentLabel(allowDollarIdentifier: true) {
(unexpectedBeforeFirstName, firstName) = self.parseArgumentLabel()
} else {
unexpectedBeforeFirstName = nil
firstName = nil
}

if self.currentToken.canBeArgumentLabel(allowDollarIdentifier: true) {
(unexpectedBeforeSecondName, secondName) = self.parseArgumentLabel()
} else {
unexpectedBeforeSecondName = nil
secondName = nil
}
if subject.isClosure {
unexpectedBeforeColon = nil
colon = self.consume(if: .colon)
shouldParseType = (colon != nil)
} else {
(unexpectedBeforeColon, colon) = self.expect(.colon)
shouldParseType = true
}
} else {
unexpectedBeforeFirstName = nil
firstName = nil
unexpectedBeforeSecondName = nil
secondName = nil
unexpectedBeforeColon = nil
colon = nil
shouldParseType = true
}

let type: RawTypeSyntax?
if shouldParseType {
type = self.parseType(misplacedSpecifiers: misplacedSpecifiers)
} else {
type = nil
}

let ellipsis: RawTokenSyntax?
if self.atContextualPunctuator("...") {
ellipsis = self.consumeAnyToken(remapping: .ellipsis)
} else {
ellipsis = nil
}

let defaultArgument: RawInitializerClauseSyntax?
if self.at(.equal) {
defaultArgument = self.parseDefaultArgument()
} else {
defaultArgument = nil
}

let trailingComma = self.consume(if: .comma)
return RawFunctionParameterSyntax(
attributes: attrs,
modifiers: modifiers,
RawUnexpectedNodesSyntax(misplacedSpecifiers.map(RawSyntax.init) + (unexpectedBeforeFirstName?.elements ?? []), arena: self.arena),
firstName: firstName,
unexpectedBeforeSecondName,
secondName: secondName,
unexpectedBeforeColon,
colon: colon,
type: type,
ellipsis: ellipsis,
defaultArgument: defaultArgument,
trailingComma: trailingComma,
arena: self.arena)
}

@_spi(RawSyntax)
public mutating func parseParameterClause(for subject: ParameterSubject) -> RawParameterClauseSyntax {
let (unexpectedBeforeLParen, lparen) = self.expect(.leftParen)
Expand All @@ -959,100 +1055,9 @@ extension Parser {
while !self.at(any: [.eof, .rightParen])
&& keepGoing
&& loopProgress.evaluate(currentToken) {
// Parse any declaration attributes. The exception here is enum cases
// which only allow types, so we do not consume attributes to allow the
// type attribute grammar a chance to examine them.
let attrs: RawAttributeListSyntax?
if case .enumCase = subject {
attrs = nil
} else {
attrs = self.parseAttributeList()
}

let modifiers = parseParameterModifiers(for: subject)

var misplacedSpecifiers: [RawTokenSyntax] = []
while let specifier = self.consume(ifAnyIn: TypeSpecifier.self) {
misplacedSpecifiers.append(specifier)
}

let unexpectedBeforeFirstName: RawUnexpectedNodesSyntax?
let firstName: RawTokenSyntax?
let unexpectedBeforeSecondName: RawUnexpectedNodesSyntax?
let secondName: RawTokenSyntax?
let unexpectedBeforeColon: RawUnexpectedNodesSyntax?
let colon: RawTokenSyntax?
let shouldParseType: Bool

if self.withLookahead({ $0.startsParameterName(isClosure: subject.isClosure, allowMisplacedSpecifierRecovery: false) }) {
if self.currentToken.canBeArgumentLabel(allowDollarIdentifier: true) {
(unexpectedBeforeFirstName, firstName) = self.parseArgumentLabel()
} else {
unexpectedBeforeFirstName = nil
firstName = nil
}

if self.currentToken.canBeArgumentLabel(allowDollarIdentifier: true) {
(unexpectedBeforeSecondName, secondName) = self.parseArgumentLabel()
} else {
unexpectedBeforeSecondName = nil
secondName = nil
}
if subject.isClosure {
unexpectedBeforeColon = nil
colon = self.consume(if: .colon)
shouldParseType = (colon != nil)
} else {
(unexpectedBeforeColon, colon) = self.expect(.colon)
shouldParseType = true
}
} else {
unexpectedBeforeFirstName = nil
firstName = nil
unexpectedBeforeSecondName = nil
secondName = nil
unexpectedBeforeColon = nil
colon = nil
shouldParseType = true
}

let type: RawTypeSyntax?
if shouldParseType {
type = self.parseType(misplacedSpecifiers: misplacedSpecifiers)
} else {
type = nil
}

let ellipsis: RawTokenSyntax?
if self.atContextualPunctuator("...") {
ellipsis = self.consumeAnyToken(remapping: .ellipsis)
} else {
ellipsis = nil
}

let defaultArgument: RawInitializerClauseSyntax?
if self.at(.equal) {
defaultArgument = self.parseDefaultArgument()
} else {
defaultArgument = nil
}

let trailingComma = self.consume(if: .comma)
keepGoing = trailingComma != nil
elements.append(RawFunctionParameterSyntax(
attributes: attrs,
modifiers: modifiers,
RawUnexpectedNodesSyntax(misplacedSpecifiers.map(RawSyntax.init) + (unexpectedBeforeFirstName?.elements ?? []), arena: self.arena),
firstName: firstName,
unexpectedBeforeSecondName,
secondName: secondName,
unexpectedBeforeColon,
colon: colon,
type: type,
ellipsis: ellipsis,
defaultArgument: defaultArgument,
trailingComma: trailingComma,
arena: self.arena))
let parameter = parseFunctionParameter(for: subject)
keepGoing = parameter.trailingComma != nil
elements.append(parameter)
}
}
let (unexpectedBeforeRParen, rparen) = self.expect(.rightParen)
Expand Down
16 changes: 2 additions & 14 deletions Sources/SwiftSyntaxBuilder/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,13 @@
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors

add_library(SwiftSyntaxBuilder STATIC
ConvenienceInitializers.swift
HasTrailingComma.swift
Indenter.swift
ResultBuilderExtensions.swift
Syntax+StringInterpolation.swift
SyntaxNodeWithBody.swift

ConvenienceInitializers/BinaryOperatorExprConvenienceInitializers.swift
ConvenienceInitializers/BooleanLiteralExprConvenienceInitializers.swift
ConvenienceInitializers/CatchClauseConvenienceInitializer.swift
ConvenienceInitializers/CustomAttributeConvenienceInitializers.swift
ConvenienceInitializers/DictionaryExprConvenienceInitializers.swift
ConvenienceInitializers/FloatLiteralExprConvenienceInitializers.swift
ConvenienceInitializers/FunctionCallExprConvenienceInitializers.swift
ConvenienceInitializers/IfStmtConvenienceInitializers.swift
ConvenienceInitializers/IntegerLiteralExprConvenienceInitializers.swift
ConvenienceInitializers/MemberAccessExprConvenienceInitializers.swift
ConvenienceInitializers/StringLiteralExprConvenienceInitializers.swift
ConvenienceInitializers/TernaryExprConvenienceInitializers.swift
ConvenienceInitializers/TupleExprElementConvenienceInitializers.swift
ConvenienceInitializers/VariableDeclConvenienceInitializers.swift

generated/BuildableCollectionNodes.swift
generated/BuildableNodes.swift
Expand Down
Loading