Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/apple/swift-syntax into pac…
Browse files Browse the repository at this point in the history
…kage-attr
  • Loading branch information
stevapple committed Feb 7, 2023
2 parents 10e8853 + 3ac962d commit af2977a
Show file tree
Hide file tree
Showing 49 changed files with 913 additions and 10,279 deletions.
6 changes: 4 additions & 2 deletions CodeGeneration/Sources/SyntaxSupport/Child.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ public enum ChildKind {
/// The child is a collection of `kind`.
case collection(kind: String, collectionElementName: String)
/// The child is a token that matches one of the given `choices`.
case token(choices: [TokenChoice])
/// If `requiresLeadingSpace` or `requiresTrailingSpace` is not `nil`, it
/// overrides the default leading/trailing space behavior of the token.
case token(choices: [TokenChoice], requiresLeadingSpace: Bool? = nil, requiresTrailingSpace: Bool? = nil)

public var isNodeChoices: Bool {
if case .nodeChoices = self {
Expand Down Expand Up @@ -67,7 +69,7 @@ public class Child {
return "syntax"
case .collection(kind: let kind, collectionElementName: _):
return kind
case .token(choices: let choices):
case .token(choices: let choices, requiresLeadingSpace: _, requiresTrailingSpace: _):
if choices.count == 1 {
switch choices.first! {
case .keyword: return "KeywordToken"
Expand Down
4 changes: 2 additions & 2 deletions CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public let KEYWORDS: [KeywordSpec] = [
KeywordSpec("cType"),
KeywordSpec("default", isLexerClassified: true),
KeywordSpec("defer", isLexerClassified: true, requiresTrailingSpace: true),
KeywordSpec("deinit", isLexerClassified: true, requiresTrailingSpace: true),
KeywordSpec("deinit", isLexerClassified: true),
KeywordSpec("deprecated"),
KeywordSpec("derivative"),
KeywordSpec("didSet"),
Expand Down Expand Up @@ -146,7 +146,7 @@ public let KEYWORDS: [KeywordSpec] = [
KeywordSpec("in", isLexerClassified: true, requiresLeadingSpace: true, requiresTrailingSpace: true),
KeywordSpec("indirect"),
KeywordSpec("infix"),
KeywordSpec("init", isLexerClassified: true, requiresTrailingSpace: true),
KeywordSpec("init", isLexerClassified: true),
KeywordSpec("inline"),
KeywordSpec("inout", isLexerClassified: true, requiresTrailingSpace: true),
KeywordSpec("internal", isLexerClassified: true, requiresTrailingSpace: true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ public let ATTRIBUTE_NODES: [Node] = [
kind: "Syntax",
children: [
Child(name: "ForLabel",
kind: .token(choices: [.keyword(text: "for")])),
kind: .token(choices: [.keyword(text: "for")], requiresTrailingSpace: false)),
Child(name: "Colon",
kind: .token(choices: [.token(tokenKind: "ColonToken")])),
Child(name: "Declname",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public let AVAILABILITY_NODES: [Node] = [
Child(name: "Entry",
kind: .nodeChoices(choices: [
Child(name: "Token",
kind: .token(choices: [.token(tokenKind: "BinaryOperatorToken"), .token(tokenKind: "IdentifierToken")])),
kind: .token(choices: [.token(tokenKind: "BinaryOperatorToken"), .token(tokenKind: "IdentifierToken")], requiresLeadingSpace: false, requiresTrailingSpace: false)),
Child(name: "AvailabilityVersionRestriction",
kind: .node(kind: "AvailabilityVersionRestriction")),
Child(name: "AvailabilityLabeledArgument",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public let EXPR_NODES: [Node] = [
Child(name: "TryKeyword",
kind: .token(choices: [.keyword(text: "try")])),
Child(name: "QuestionOrExclamationMark",
kind: .token(choices: [.token(tokenKind: "PostfixQuestionMarkToken"), .token(tokenKind: "ExclamationMarkToken")]),
kind: .token(choices: [.token(tokenKind: "PostfixQuestionMarkToken"), .token(tokenKind: "ExclamationMarkToken")], requiresTrailingSpace: true),
isOptional: true),
Child(name: "Expression",
kind: .node(kind: "Expr"))
Expand Down Expand Up @@ -284,7 +284,7 @@ public let EXPR_NODES: [Node] = [
Child(name: "Content",
kind: .nodeChoices(choices: [
Child(name: "Colon",
kind: .token(choices: [.token(tokenKind: "ColonToken")])),
kind: .token(choices: [.token(tokenKind: "ColonToken")], requiresTrailingSpace: false)),
Child(name: "Elements",
kind: .node(kind: "DictionaryElementList"))
]),
Expand Down
8 changes: 7 additions & 1 deletion CodeGeneration/Sources/SyntaxSupport/gyb_helpers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,13 @@ def make_swift_child(child, spaces):
mapped_choices = [f'.token(tokenKind: "{choice.name}Token")' for (choice, text) in child.token_choices if text is None]
mapped_choices += [f'.keyword(text: "{text}")' for (choice, text) in child.token_choices if text is not None]
joined_choices = ', '.join(mapped_choices)
kind = f'.token(choices: [{joined_choices}])'
token_arguments = [f'choices: [{joined_choices}]']
if child.requires_leading_space is not None:
token_arguments += ['requiresLeadingSpace: ' + ('true' if child.requires_leading_space else 'false')]
if child.requires_trailing_space is not None:
token_arguments += ['requiresTrailingSpace: ' + ('true' if child.requires_trailing_space else 'false')]
arguments = ', '.join(token_arguments)
kind = f'.token({arguments})'
elif child.collection_element_name:
kind = f'.collection(kind: "{child.syntax_kind}", collectionElementName: "{child.collection_element_name}")'
elif child.node_choices:
Expand Down
4 changes: 2 additions & 2 deletions CodeGeneration/Sources/Utils/SyntaxBuildableChild.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public extension Child {

var defaultInitialization: ExprSyntax? {
switch kind {
case .token(choices: let choices):
case .token(choices: let choices, requiresLeadingSpace: _, requiresTrailingSpace: _):
if choices.count == 1, case .keyword(text: let text) = choices.first {
var textChoice = text
if textChoice == "init" {
Expand All @@ -66,7 +66,7 @@ public extension Child {
/// `assert` statement that verifies the variable with name var_name and of type
/// `TokenSyntax` contains one of the supported text options. Otherwise return `nil`.
func generateAssertStmtTextChoices(varName: String) -> FunctionCallExprSyntax? {
guard case .token(choices: let choices) = kind else {
guard case .token(choices: let choices, requiresLeadingSpace: _, requiresTrailingSpace: _) = kind else {
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,40 @@ import SwiftSyntaxBuilder
import SyntaxSupport
import Utils

extension Child {
var requiresLeadingSpace: Bool? {
switch self.kind {
case .token(choices: _, requiresLeadingSpace: let requiresLeadingSpace, requiresTrailingSpace: _):
return requiresLeadingSpace
case .nodeChoices(choices: let choices):
for choice in choices {
if let requiresLeadingSpace = choice.requiresLeadingSpace {
return requiresLeadingSpace
}
}
default:
break
}
return nil
}

var requiresTrailingSpace: Bool? {
switch self.kind {
case .token(choices: _, requiresLeadingSpace: _, requiresTrailingSpace: let requiresTrailingSpace):
return requiresTrailingSpace
case .nodeChoices(choices: let choices):
for choice in choices {
if let requiresTrailingSpace = choice.requiresTrailingSpace {
return requiresTrailingSpace
}
}
default:
break
}
return nil
}
}

let basicFormatFile = SourceFileSyntax {
DeclSyntax(
"""
Expand Down Expand Up @@ -126,14 +160,34 @@ let basicFormatFile = SourceFileSyntax {
}
}

try FunctionDeclSyntax(
"""
/// If this returns a value that is not `nil`, it overrides the default
/// leading space behavior of a token.
open func requiresLeadingSpace(_ keyPath: AnyKeyPath) -> Bool?
"""
) {
try SwitchStmtSyntax("switch keyPath") {
for node in SYNTAX_NODES where !node.isBase {
for child in node.children {
if let requiresLeadingSpace = child.requiresLeadingSpace {
SwitchCaseSyntax("case \\\(raw: node.type.syntaxBaseName).\(raw: child.swiftName):") {
StmtSyntax("return \(literal: requiresLeadingSpace)")
}
}
}
}
SwitchCaseSyntax("default:") {
StmtSyntax("return nil")
}
}
}

try FunctionDeclSyntax("open func requiresLeadingSpace(_ token: TokenSyntax) -> Bool") {
StmtSyntax(
"""
switch (token.previousToken(viewMode: .sourceAccurate)?.tokenKind, token.tokenKind) {
case (.leftParen, .binaryOperator): // Ensures there is no space in @available(*, deprecated)
return false
default:
break
if let keyPath = getKeyPath(token), let requiresLeadingSpace = requiresLeadingSpace(keyPath) {
return requiresLeadingSpace
}
"""
)
Expand All @@ -157,17 +211,34 @@ let basicFormatFile = SourceFileSyntax {
}
}

try FunctionDeclSyntax(
"""
/// If this returns a value that is not `nil`, it overrides the default
/// trailing space behavior of a token.
open func requiresTrailingSpace(_ keyPath: AnyKeyPath) -> Bool?
"""
) {
try SwitchStmtSyntax("switch keyPath") {
for node in SYNTAX_NODES where !node.isBase {
for child in node.children {
if let requiresTrailingSpace = child.requiresTrailingSpace {
SwitchCaseSyntax("case \\\(raw: node.type.syntaxBaseName).\(raw: child.swiftName):") {
StmtSyntax("return \(literal: requiresTrailingSpace)")
}
}
}
}
SwitchCaseSyntax("default:") {
StmtSyntax("return nil")
}
}
}

try FunctionDeclSyntax("open func requiresTrailingSpace(_ token: TokenSyntax) -> Bool") {
StmtSyntax(
"""
switch (token.tokenKind, token.parent?.kind) {
case (.colon, .dictionaryExpr): // Ensures there is not space in `[:]`
return false
case (.exclamationMark, .tryExpr), // Ensures there is a space in `try! foo`
(.postfixQuestionMark, .tryExpr): // Ensures there is a space in `try? foo`
return true
default:
break
if let keyPath = getKeyPath(token), let requiresTrailingSpace = requiresTrailingSpace(keyPath) {
return requiresTrailingSpace
}
"""
)
Expand All @@ -179,14 +250,11 @@ let basicFormatFile = SourceFileSyntax {
(.keyword(.as), .postfixQuestionMark), // Ensures there is not space in `as?`
(.exclamationMark, .leftParen), // Ensures there is not space in `myOptionalClosure!()`
(.exclamationMark, .period), // Ensures there is not space in `myOptionalBar!.foo()`
(.keyword(.`init`), .leftParen), // Ensures there is not space in `init()`
(.keyword(.`init`), .postfixQuestionMark), // Ensures there is not space in `init?`
(.postfixQuestionMark, .leftParen), // Ensures there is not space in `init?()`
(.postfixQuestionMark, .leftParen), // Ensures there is not space in `init?()` or `myOptionalClosure?()`s
(.postfixQuestionMark, .rightAngle), // Ensures there is not space in `ContiguousArray<RawSyntax?>`
(.postfixQuestionMark, .rightParen), // Ensures there is not space in `myOptionalClosure?()`
(.keyword(.try), .exclamationMark), // Ensures there is not space in `try!`
(.keyword(.try), .postfixQuestionMark), // Ensures there is not space in `try?`
(.binaryOperator, .comma): // Ensures there is no space in `@available(*, deprecated)`
(.keyword(.try), .postfixQuestionMark): // Ensures there is not space in `try?`:
return false
default:
break
Expand Down Expand Up @@ -215,7 +283,7 @@ let basicFormatFile = SourceFileSyntax {

DeclSyntax(
"""
private func getKeyPath(_ node: Syntax) -> AnyKeyPath? {
private func getKeyPath<T: SyntaxProtocol>(_ node: T) -> AnyKeyPath? {
guard let parent = node.parent else {
return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ let syntaxCollectionsFile = SourceFileSyntax(leadingTrivia: [.blockComment(gener
for node in SYNTAX_NODES where node.isSyntaxCollection {
let documentation =
node.description.map { "/// " + $0 }
?? """
/// `\(node.name)` represents a collection of one or more
/// `\(node.collectionElement)` nodes. \(node.name) behaves
/// as a regular Swift collection, and has accessors that return new
/// versions of the collection with different children.
"""
?? """
/// `\(node.name)` represents a collection of one or more
/// `\(node.collectionElement)` nodes. \(node.name) behaves
/// as a regular Swift collection, and has accessors that return new
/// versions of the collection with different children.
"""

try! StructDeclSyntax(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,6 @@ let syntaxVisitorFile = SourceFileSyntax {
try! ClassDeclSyntax("open class SyntaxVisitor") {
DeclSyntax("public let viewMode: SyntaxTreeViewMode")

DeclSyntax(
"""
@available(*, deprecated, message: "Use init(viewMode:) instead")
public convenience init() {
self.init(viewMode: .sourceAccurate)
}
"""
)

DeclSyntax(
"""
public init(viewMode: SyntaxTreeViewMode) {
Expand Down
1 change: 0 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ let package = Package(
"CMakeLists.txt",
"Raw/RawSyntaxNodes.swift.gyb",
"Raw/RawSyntaxValidation.swift.gyb",
"SyntaxFactory.swift.gyb",
"SyntaxNodes.swift.gyb.template",
],
swiftSettings: swiftSyntaxSwiftSettings
Expand Down
Loading

0 comments on commit af2977a

Please sign in to comment.