From 3cff8d7dc4df11b8c7107a1b31660ef538b24bf9 Mon Sep 17 00:00:00 2001 From: Kim de Vos Date: Mon, 4 Sep 2023 20:45:23 +0200 Subject: [PATCH 1/2] Add editor place holder pattern --- .../Sources/SyntaxSupport/PatternNodes.swift | 18 +++++ .../SyntaxSupport/SyntaxNodeKind.swift | 1 + Release Notes/510.md | 5 ++ Sources/SwiftParser/Patterns.swift | 19 +++-- .../SyntaxKindNameForDiagnostics.swift | 2 + .../generated/SwiftSyntax.md | 1 + .../generated/ChildNameForKeyPath.swift | 6 ++ .../generated/SyntaxAnyVisitor.swift | 8 ++ .../generated/SyntaxBaseNodes.swift | 4 +- .../SwiftSyntax/generated/SyntaxEnum.swift | 3 + .../SwiftSyntax/generated/SyntaxKind.swift | 3 + .../generated/SyntaxRewriter.swift | 13 ++++ .../generated/SyntaxTransform.swift | 14 ++++ .../SwiftSyntax/generated/SyntaxVisitor.swift | 18 +++++ .../generated/raw/RawSyntaxNodesEF.swift | 58 ++++++++++++++ .../generated/raw/RawSyntaxNodesOP.swift | 2 +- .../generated/raw/RawSyntaxValidation.swift | 5 ++ .../generated/syntaxNodes/SyntaxNodesEF.swift | 78 +++++++++++++++++++ Tests/SwiftParserTest/LexerTests.swift | 10 +++ .../translated/IdentifiersTests.swift | 26 +++++++ 20 files changed, 287 insertions(+), 7 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/PatternNodes.swift b/CodeGeneration/Sources/SyntaxSupport/PatternNodes.swift index 6c751d8de7d..aab375ec4ad 100644 --- a/CodeGeneration/Sources/SyntaxSupport/PatternNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/PatternNodes.swift @@ -182,4 +182,22 @@ public let PATTERN_NODES: [Node] = [ ] ), + Node( + kind: .editorPlaceholderPattern, + base: .pattern, + nameForDiagnostics: "editor placeholder", + documentation: """ + An editor placeholder, e.g. `<#pattern#>` that is used in a position that expects a pattern. + """, + children: [ + Child( + name: "placeholder", + kind: .token(choices: [.token(.identifier)]), + documentation: """ + The actual editor placeholder that starts with `<#` and ends with `#>`. + """ + ) + ] + ), + ] diff --git a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift index c5613534ec8..5f89a63ffa6 100644 --- a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift +++ b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift @@ -111,6 +111,7 @@ public enum SyntaxNodeKind: String, CaseIterable { case dynamicReplacementAttributeArguments case editorPlaceholderDecl case editorPlaceholderExpr + case editorPlaceholderPattern case effectsAttributeArgumentList case enumCaseDecl case enumCaseElement diff --git a/Release Notes/510.md b/Release Notes/510.md index 9adf09c29ce..231d36ea230 100644 --- a/Release Notes/510.md +++ b/Release Notes/510.md @@ -21,6 +21,11 @@ - Description: Remarks are used by the Swift compiler and other tools to describe some aspect of translation that doesn't reflect correctness, but may be useful for the user. Remarks have been added to the diagnostic severity enums to align with the Swift compiler. - Pull Request: https://github.com/apple/swift-syntax/pull/2143 +- New pattern node `EditorPlaceholderPatternSyntax` + - Description: This node type will be placeholder that is used in a position that expects a pattern. + - Issue: https://github.com/apple/swift-syntax/issues/2147 + - Pull Request: https://github.com/apple/swift-syntax/pull/2150 + ## API Behavior Changes ## Deprecations diff --git a/Sources/SwiftParser/Patterns.swift b/Sources/SwiftParser/Patterns.swift index 159e18543e0..c304ecffb53 100644 --- a/Sources/SwiftParser/Patterns.swift +++ b/Sources/SwiftParser/Patterns.swift @@ -70,12 +70,21 @@ extension Parser { ) case (.lhs(.identifier), let handle)?: let identifier = self.eat(handle) - return RawPatternSyntax( - RawIdentifierPatternSyntax( - identifier: identifier, - arena: self.arena + if identifier.tokenText.isEditorPlaceholder { + return RawPatternSyntax( + RawEditorPlaceholderPatternSyntax( + placeholder: identifier, + arena: self.arena + ) ) - ) + } else { + return RawPatternSyntax( + RawIdentifierPatternSyntax( + identifier: identifier, + arena: self.arena + ) + ) + } case (.lhs(.dollarIdentifier), let handle)?: let dollarIdent = self.eat(handle) let unexpectedBeforeIdentifier = RawUnexpectedNodesSyntax(elements: [RawSyntax(dollarIdent)], arena: self.arena) diff --git a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift index 64ff8b4cadd..5b022bda285 100644 --- a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift @@ -143,6 +143,8 @@ extension SyntaxKind { return "editor placeholder" case .editorPlaceholderExpr: return "editor placeholder" + case .editorPlaceholderPattern: + return "editor placeholder" case .effectsAttributeArgumentList: return "@_effects arguments" case .enumCaseDecl: diff --git a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md index 98689c309eb..5410cabf81b 100644 --- a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md +++ b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md @@ -151,6 +151,7 @@ These articles are intended for developers wishing to contribute to SwiftSyntax - - - +- - - - diff --git a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift index 4cc8070057c..7eff15a4ca7 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -1077,6 +1077,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "placeholder" case \EditorPlaceholderExprSyntax.unexpectedAfterPlaceholder: return "unexpectedAfterPlaceholder" + case \EditorPlaceholderPatternSyntax.unexpectedBeforePlaceholder: + return "unexpectedBeforePlaceholder" + case \EditorPlaceholderPatternSyntax.placeholder: + return "placeholder" + case \EditorPlaceholderPatternSyntax.unexpectedAfterPlaceholder: + return "unexpectedAfterPlaceholder" case \EnumCaseDeclSyntax.unexpectedBeforeAttributes: return "unexpectedBeforeAttributes" case \EnumCaseDeclSyntax.attributes: diff --git a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift index 518cb834c89..3c0f87beb14 100644 --- a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift @@ -776,6 +776,14 @@ open class SyntaxAnyVisitor: SyntaxVisitor { visitAnyPost(node._syntaxNode) } + override open func visit(_ node: EditorPlaceholderPatternSyntax) -> SyntaxVisitorContinueKind { + return visitAny(node._syntaxNode) + } + + override open func visitPost(_ node: EditorPlaceholderPatternSyntax) { + visitAnyPost(node._syntaxNode) + } + override open func visit(_ node: EffectsAttributeArgumentListSyntax) -> SyntaxVisitorContinueKind { return visitAny(node._syntaxNode) } diff --git a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift index ab916c743b3..18f9fbdd809 100644 --- a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift +++ b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift @@ -770,7 +770,7 @@ public struct PatternSyntax: PatternSyntaxProtocol, SyntaxHashable { public init?(_ node: some SyntaxProtocol) { switch node.raw.kind { - case .expressionPattern, .identifierPattern, .isTypePattern, .missingPattern, .tuplePattern, .valueBindingPattern, .wildcardPattern: + case .editorPlaceholderPattern, .expressionPattern, .identifierPattern, .isTypePattern, .missingPattern, .tuplePattern, .valueBindingPattern, .wildcardPattern: self._syntaxNode = node._syntaxNode default: return nil @@ -795,6 +795,7 @@ public struct PatternSyntax: PatternSyntaxProtocol, SyntaxHashable { public static var structure: SyntaxNodeStructure { return .choices([ + .node(EditorPlaceholderPatternSyntax.self), .node(ExpressionPatternSyntax.self), .node(IdentifierPatternSyntax.self), .node(IsTypePatternSyntax.self), @@ -1486,6 +1487,7 @@ extension Syntax { .node(DynamicReplacementAttributeArgumentsSyntax.self), .node(EditorPlaceholderDeclSyntax.self), .node(EditorPlaceholderExprSyntax.self), + .node(EditorPlaceholderPatternSyntax.self), .node(EffectsAttributeArgumentListSyntax.self), .node(EnumCaseDeclSyntax.self), .node(EnumCaseElementListSyntax.self), diff --git a/Sources/SwiftSyntax/generated/SyntaxEnum.swift b/Sources/SwiftSyntax/generated/SyntaxEnum.swift index 6ea43ee2b8b..f502eb436db 100644 --- a/Sources/SwiftSyntax/generated/SyntaxEnum.swift +++ b/Sources/SwiftSyntax/generated/SyntaxEnum.swift @@ -105,6 +105,7 @@ public enum SyntaxEnum { case dynamicReplacementAttributeArguments(DynamicReplacementAttributeArgumentsSyntax) case editorPlaceholderDecl(EditorPlaceholderDeclSyntax) case editorPlaceholderExpr(EditorPlaceholderExprSyntax) + case editorPlaceholderPattern(EditorPlaceholderPatternSyntax) case effectsAttributeArgumentList(EffectsAttributeArgumentListSyntax) case enumCaseDecl(EnumCaseDeclSyntax) case enumCaseElementList(EnumCaseElementListSyntax) @@ -479,6 +480,8 @@ public extension Syntax { return .editorPlaceholderDecl(EditorPlaceholderDeclSyntax(self)!) case .editorPlaceholderExpr: return .editorPlaceholderExpr(EditorPlaceholderExprSyntax(self)!) + case .editorPlaceholderPattern: + return .editorPlaceholderPattern(EditorPlaceholderPatternSyntax(self)!) case .effectsAttributeArgumentList: return .effectsAttributeArgumentList(EffectsAttributeArgumentListSyntax(self)!) case .enumCaseDecl: diff --git a/Sources/SwiftSyntax/generated/SyntaxKind.swift b/Sources/SwiftSyntax/generated/SyntaxKind.swift index d0e659351ec..57bc3f801f7 100644 --- a/Sources/SwiftSyntax/generated/SyntaxKind.swift +++ b/Sources/SwiftSyntax/generated/SyntaxKind.swift @@ -105,6 +105,7 @@ public enum SyntaxKind: CaseIterable { case dynamicReplacementAttributeArguments case editorPlaceholderDecl case editorPlaceholderExpr + case editorPlaceholderPattern case effectsAttributeArgumentList case enumCaseDecl case enumCaseElementList @@ -600,6 +601,8 @@ public enum SyntaxKind: CaseIterable { return EditorPlaceholderDeclSyntax.self case .editorPlaceholderExpr: return EditorPlaceholderExprSyntax.self + case .editorPlaceholderPattern: + return EditorPlaceholderPatternSyntax.self case .effectsAttributeArgumentList: return EffectsAttributeArgumentListSyntax.self case .enumCaseDecl: diff --git a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift index 96e089034bb..82048b9ddd2 100644 --- a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift +++ b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift @@ -710,6 +710,13 @@ open class SyntaxRewriter { return ExprSyntax(visitChildren(node)) } + /// Visit a ``EditorPlaceholderPatternSyntax``. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + open func visit(_ node: EditorPlaceholderPatternSyntax) -> PatternSyntax { + return PatternSyntax(visitChildren(node)) + } + /// Visit a ``EffectsAttributeArgumentListSyntax``. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node @@ -2456,6 +2463,10 @@ open class SyntaxRewriter { return { self.visitImpl($0, EditorPlaceholderExprSyntax.self, self.visit) } + case .editorPlaceholderPattern: + return { + self.visitImpl($0, EditorPlaceholderPatternSyntax.self, self.visit) + } case .effectsAttributeArgumentList: return { self.visitImpl($0, EffectsAttributeArgumentListSyntax.self, self.visit) @@ -3390,6 +3401,8 @@ open class SyntaxRewriter { return visitImpl(node, EditorPlaceholderDeclSyntax.self, visit) case .editorPlaceholderExpr: return visitImpl(node, EditorPlaceholderExprSyntax.self, visit) + case .editorPlaceholderPattern: + return visitImpl(node, EditorPlaceholderPatternSyntax.self, visit) case .effectsAttributeArgumentList: return visitImpl(node, EffectsAttributeArgumentListSyntax.self, visit) case .enumCaseDecl: diff --git a/Sources/SwiftSyntax/generated/SyntaxTransform.swift b/Sources/SwiftSyntax/generated/SyntaxTransform.swift index 27c7d8e2bbd..9efda11a237 100644 --- a/Sources/SwiftSyntax/generated/SyntaxTransform.swift +++ b/Sources/SwiftSyntax/generated/SyntaxTransform.swift @@ -470,6 +470,11 @@ public protocol SyntaxTransformVisitor { /// - Returns: the sum of whatever the child visitors return. func visit(_ node: EditorPlaceholderExprSyntax) -> ResultType + /// Visiting ``EditorPlaceholderPatternSyntax`` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: the sum of whatever the child visitors return. + func visit(_ node: EditorPlaceholderPatternSyntax) -> ResultType + /// Visiting ``EffectsAttributeArgumentListSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: the sum of whatever the child visitors return. @@ -2036,6 +2041,13 @@ extension SyntaxTransformVisitor { visitAny(Syntax(node)) } + /// Visiting ``EditorPlaceholderPatternSyntax`` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: nil by default. + public func visit(_ node: EditorPlaceholderPatternSyntax) -> ResultType { + visitAny(Syntax(node)) + } + /// Visiting ``EffectsAttributeArgumentListSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: nil by default. @@ -3522,6 +3534,8 @@ extension SyntaxTransformVisitor { return visit(derived) case .editorPlaceholderExpr(let derived): return visit(derived) + case .editorPlaceholderPattern(let derived): + return visit(derived) case .effectsAttributeArgumentList(let derived): return visit(derived) case .enumCaseDecl(let derived): diff --git a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift index 92824a24c11..c735bffb513 100644 --- a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift @@ -1114,6 +1114,18 @@ open class SyntaxVisitor { open func visitPost(_ node: EditorPlaceholderExprSyntax) { } + /// Visiting ``EditorPlaceholderPatternSyntax`` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: how should we continue visiting. + open func visit(_ node: EditorPlaceholderPatternSyntax) -> SyntaxVisitorContinueKind { + return .visitChildren + } + + /// The function called after visiting ``EditorPlaceholderPatternSyntax`` and its descendants. + /// - node: the node we just finished visiting. + open func visitPost(_ node: EditorPlaceholderPatternSyntax) { + } + /// Visiting ``EffectsAttributeArgumentListSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: how should we continue visiting. @@ -3768,6 +3780,10 @@ open class SyntaxVisitor { return { self.visitImpl($0, EditorPlaceholderExprSyntax.self, self.visit, self.visitPost) } + case .editorPlaceholderPattern: + return { + self.visitImpl($0, EditorPlaceholderPatternSyntax.self, self.visit, self.visitPost) + } case .effectsAttributeArgumentList: return { self.visitImpl($0, EffectsAttributeArgumentListSyntax.self, self.visit, self.visitPost) @@ -4705,6 +4721,8 @@ open class SyntaxVisitor { visitImpl(node, EditorPlaceholderDeclSyntax.self, visit, visitPost) case .editorPlaceholderExpr: visitImpl(node, EditorPlaceholderExprSyntax.self, visit, visitPost) + case .editorPlaceholderPattern: + visitImpl(node, EditorPlaceholderPatternSyntax.self, visit, visitPost) case .effectsAttributeArgumentList: visitImpl(node, EffectsAttributeArgumentListSyntax.self, visit, visitPost) case .enumCaseDecl: diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesEF.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesEF.swift index da079023bdc..98f72931b4f 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesEF.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesEF.swift @@ -141,6 +141,64 @@ public struct RawEditorPlaceholderExprSyntax: RawExprSyntaxNodeProtocol { } } +@_spi(RawSyntax) +public struct RawEditorPlaceholderPatternSyntax: RawPatternSyntaxNodeProtocol { + @_spi(RawSyntax) + public var layoutView: RawSyntaxLayoutView { + return raw.layoutView! + } + + public static func isKindOf(_ raw: RawSyntax) -> Bool { + return raw.kind == .editorPlaceholderPattern + } + + public var raw: RawSyntax + + init(raw: RawSyntax) { + precondition(Self.isKindOf(raw)) + self.raw = raw + } + + private init(unchecked raw: RawSyntax) { + self.raw = raw + } + + public init?(_ other: some RawSyntaxNodeProtocol) { + guard Self.isKindOf(other.raw) else { + return nil + } + self.init(unchecked: other.raw) + } + + public init( + _ unexpectedBeforePlaceholder: RawUnexpectedNodesSyntax? = nil, + placeholder: RawTokenSyntax, + _ unexpectedAfterPlaceholder: RawUnexpectedNodesSyntax? = nil, + arena: __shared SyntaxArena + ) { + let raw = RawSyntax.makeLayout( + kind: .editorPlaceholderPattern, uninitializedCount: 3, arena: arena) { layout in + layout.initialize(repeating: nil) + layout[0] = unexpectedBeforePlaceholder?.raw + layout[1] = placeholder.raw + layout[2] = unexpectedAfterPlaceholder?.raw + } + self.init(unchecked: raw) + } + + public var unexpectedBeforePlaceholder: RawUnexpectedNodesSyntax? { + layoutView.children[0].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var placeholder: RawTokenSyntax { + layoutView.children[1].map(RawTokenSyntax.init(raw:))! + } + + public var unexpectedAfterPlaceholder: RawUnexpectedNodesSyntax? { + layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + } +} + @_spi(RawSyntax) public struct RawEffectsAttributeArgumentListSyntax: RawSyntaxNodeProtocol { @_spi(RawSyntax) diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesOP.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesOP.swift index 5afbf37a235..3a9b2177a26 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesOP.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesOP.swift @@ -1222,7 +1222,7 @@ public struct RawPatternSyntax: RawPatternSyntaxNodeProtocol { public static func isKindOf(_ raw: RawSyntax) -> Bool { switch raw.kind { - case .expressionPattern, .identifierPattern, .isTypePattern, .missingPattern, .tuplePattern, .valueBindingPattern, .wildcardPattern: + case .editorPlaceholderPattern, .expressionPattern, .identifierPattern, .isTypePattern, .missingPattern, .tuplePattern, .valueBindingPattern, .wildcardPattern: return true default: return false diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index b226fdd1edd..9daac06b376 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -1035,6 +1035,11 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier)])) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + case .editorPlaceholderPattern: + assert(layout.count == 3) + assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier)])) + assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) case .effectsAttributeArgumentList: for (index, element) in layout.enumerated() { assertNoError(kind, index, verify(element, as: RawTokenSyntax.self)) diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift index 6715763970b..9f625ea6aaf 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift @@ -288,6 +288,84 @@ public struct EditorPlaceholderExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _ } } +// MARK: - EditorPlaceholderPatternSyntax + +/// An editor placeholder, e.g. `<#pattern#>` that is used in a position that expects a pattern. +/// +/// ### Children +/// +/// - `placeholder`: `` +public struct EditorPlaceholderPatternSyntax: PatternSyntaxProtocol, SyntaxHashable, _LeafPatternSyntaxNodeProtocol { + public let _syntaxNode: Syntax + + public init?(_ node: some SyntaxProtocol) { + guard node.raw.kind == .editorPlaceholderPattern else { + return nil + } + self._syntaxNode = node._syntaxNode + } + + /// - Parameters: + /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. + /// - placeholder: The actual editor placeholder that starts with `<#` and ends with `#>`. + /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforePlaceholder: UnexpectedNodesSyntax? = nil, + placeholder: TokenSyntax, + _ unexpectedAfterPlaceholder: UnexpectedNodesSyntax? = nil, + trailingTrivia: Trivia? = nil + + ) { + // Extend the lifetime of all parameters so their arenas don't get destroyed + // before they can be added as children of the new arena. + self = withExtendedLifetime((SyntaxArena(), (unexpectedBeforePlaceholder, placeholder, unexpectedAfterPlaceholder))) { (arena, _) in + let layout: [RawSyntax?] = [unexpectedBeforePlaceholder?.raw, placeholder.raw, unexpectedAfterPlaceholder?.raw] + let raw = RawSyntax.makeLayout( + kind: SyntaxKind.editorPlaceholderPattern, + from: layout, + arena: arena, + leadingTrivia: leadingTrivia, + trailingTrivia: trailingTrivia + + ) + return Syntax.forRoot(raw, rawNodeArena: arena).cast(Self.self) + } + } + + public var unexpectedBeforePlaceholder: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 0)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 0, with: Syntax(value), arena: SyntaxArena()).cast(EditorPlaceholderPatternSyntax.self) + } + } + + /// The actual editor placeholder that starts with `<#` and ends with `#>`. + public var placeholder: TokenSyntax { + get { + return Syntax(self).child(at: 1)!.cast(TokenSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 1, with: Syntax(value), arena: SyntaxArena()).cast(EditorPlaceholderPatternSyntax.self) + } + } + + public var unexpectedAfterPlaceholder: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 2, with: Syntax(value), arena: SyntaxArena()).cast(EditorPlaceholderPatternSyntax.self) + } + } + + public static var structure: SyntaxNodeStructure { + return .layout([\Self.unexpectedBeforePlaceholder, \Self.placeholder, \Self.unexpectedAfterPlaceholder]) + } +} + // MARK: - EnumCaseDeclSyntax /// A `case` declaration of a Swift `enum`. It can have 1 or more `EnumCaseElement`s inside, each declaring a different case of the enum. diff --git a/Tests/SwiftParserTest/LexerTests.swift b/Tests/SwiftParserTest/LexerTests.swift index f56a76f16a2..38d62424434 100644 --- a/Tests/SwiftParserTest/LexerTests.swift +++ b/Tests/SwiftParserTest/LexerTests.swift @@ -846,6 +846,16 @@ public class LexerTests: ParserTestCase { LexemeSpec(.identifier, text: "<##>", trailing: "", diagnostic: "editor placeholder in source file") ] ) + + assertLexemes( + "let 1️⃣<#name#> = 2️⃣<#value#>", + lexemes: [ + LexemeSpec(.keyword, text: "let", trailing: " "), + LexemeSpec(.identifier, text: "<#name#>", trailing: " ", errorLocationMarker: "1️⃣", diagnostic: "editor placeholder in source file"), + LexemeSpec(.equal, text: "=", trailing: " "), + LexemeSpec(.identifier, text: "<#value#>", errorLocationMarker: "2️⃣", diagnostic: "editor placeholder in source file"), + ] + ) } func testCommentAttribution() { diff --git a/Tests/SwiftParserTest/translated/IdentifiersTests.swift b/Tests/SwiftParserTest/translated/IdentifiersTests.swift index edbee78a25e..420af310199 100644 --- a/Tests/SwiftParserTest/translated/IdentifiersTests.swift +++ b/Tests/SwiftParserTest/translated/IdentifiersTests.swift @@ -12,6 +12,8 @@ // This test file has been translated from swift/test/Parse/identifiers.swift +import SwiftSyntax +import SwiftSyntaxBuilder import XCTest final class IdentifiersTests: ParserTestCase { @@ -230,4 +232,28 @@ final class IdentifiersTests: ParserTestCase { ) } + func testPatternAsPlaceholderExpr() { + assertParse( + "let 1️⃣<#name#> = 2️⃣<#value#>", + substructure: VariableDeclSyntax( + bindingSpecifier: .keyword(.let), + bindings: [ + PatternBindingSyntax( + pattern: EditorPlaceholderPatternSyntax( + placeholder: .identifier("<#name#>") + ), + initializer: InitializerClauseSyntax( + value: EditorPlaceholderExprSyntax( + placeholder: .identifier("<#value#>") + ) + ) + ) + ] + ), + diagnostics: [ + DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file"), + DiagnosticSpec(locationMarker: "2️⃣", message: "editor placeholder in source file"), + ] + ) + } } From 6d507ecdf0c2d2758cc69f6f10e7c7f89d22600b Mon Sep 17 00:00:00 2001 From: Kim de Vos Date: Thu, 7 Sep 2023 21:31:53 +0200 Subject: [PATCH 2/2] Add editor place holder type --- .../SyntaxSupport/SyntaxNodeKind.swift | 1 + .../Sources/SyntaxSupport/TypeNodes.swift | 24 ++++ Release Notes/510.md | 5 + Sources/SwiftParser/Types.swift | 29 +++-- .../SyntaxKindNameForDiagnostics.swift | 2 + .../generated/SwiftSyntax.md | 1 + .../generated/ChildNameForKeyPath.swift | 10 ++ .../generated/SyntaxAnyVisitor.swift | 8 ++ .../generated/SyntaxBaseNodes.swift | 4 +- .../SwiftSyntax/generated/SyntaxEnum.swift | 3 + .../SwiftSyntax/generated/SyntaxKind.swift | 3 + .../generated/SyntaxRewriter.swift | 13 ++ .../generated/SyntaxTransform.swift | 14 +++ .../SwiftSyntax/generated/SyntaxVisitor.swift | 18 +++ .../generated/raw/RawSyntaxNodesEF.swift | 70 +++++++++++ .../generated/raw/RawSyntaxNodesTUVWXYZ.swift | 2 +- .../generated/raw/RawSyntaxValidation.swift | 7 ++ .../generated/syntaxNodes/SyntaxNodesEF.swift | 119 ++++++++++++++++++ .../syntaxNodes/SyntaxNodesGHI.swift | 1 + Tests/SwiftParserTest/TypeTests.swift | 61 +++++++++ 20 files changed, 385 insertions(+), 10 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift index 5f89a63ffa6..d8e35377a5f 100644 --- a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift +++ b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift @@ -112,6 +112,7 @@ public enum SyntaxNodeKind: String, CaseIterable { case editorPlaceholderDecl case editorPlaceholderExpr case editorPlaceholderPattern + case editorPlaceholderType case effectsAttributeArgumentList case enumCaseDecl case enumCaseElement diff --git a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift index eaf2f5906b4..1147dfbc140 100644 --- a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift @@ -530,4 +530,28 @@ public let TYPE_NODES: [Node] = [ ] ), + Node( + kind: .editorPlaceholderType, + base: .type, + nameForDiagnostics: "editor placeholder", + documentation: """ + An editor placeholder, e.g. `<#Type#>` that is used in a position that expects a type. + """, + children: [ + Child( + name: "placeholder", + kind: .token(choices: [.token(.identifier)]), + documentation: """ + The actual editor placeholder that starts with `<#` and ends with `#>`. + """ + ), + Child( + name: "genericArgumentClause", + kind: .node(kind: .genericArgumentClause), + documentation: "Generic arguments that is attatched to the type.", + isOptional: true + ), + ] + ), + ] diff --git a/Release Notes/510.md b/Release Notes/510.md index 231d36ea230..6136888a67b 100644 --- a/Release Notes/510.md +++ b/Release Notes/510.md @@ -26,6 +26,11 @@ - Issue: https://github.com/apple/swift-syntax/issues/2147 - Pull Request: https://github.com/apple/swift-syntax/pull/2150 +- New type node `EditorPlaceholderTypeSyntax` + - Description: This node type will be placeholder that is used in a position that expects a type. + - Issue: https://github.com/apple/swift-syntax/issues/2156 + - Pull Request: https://github.com/apple/swift-syntax/pull/2150 + ## API Behavior Changes ## Deprecations diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 36bfb2c7a9e..0ee67433e91 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -349,14 +349,25 @@ extension Parser { generics = nil } - return RawTypeSyntax( - RawIdentifierTypeSyntax( - unexpectedBeforeName, - name: name, - genericArgumentClause: generics, - arena: self.arena + if name.tokenText.isEditorPlaceholder { + return RawTypeSyntax( + RawEditorPlaceholderTypeSyntax( + placeholder: name, + genericArgumentClause: generics, + arena: self.arena + ) ) - ) + } else { + return RawTypeSyntax( + RawIdentifierTypeSyntax( + unexpectedBeforeName, + name: name, + genericArgumentClause: generics, + arena: self.arena + ) + ) + } + } /// Parse the existential `Any` type. @@ -938,7 +949,9 @@ extension Parser { extension Parser { mutating func parseResultType() -> RawTypeSyntax { - if self.at(prefix: "<") { + if self.at(prefix: "<#") { + return self.parseTypeIdentifier() + } else if self.at(prefix: "<") { let generics = self.parseGenericParameters() let baseType = self.parseType() return RawTypeSyntax( diff --git a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift index 5b022bda285..540bad6ddf7 100644 --- a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift @@ -145,6 +145,8 @@ extension SyntaxKind { return "editor placeholder" case .editorPlaceholderPattern: return "editor placeholder" + case .editorPlaceholderType: + return "editor placeholder" case .effectsAttributeArgumentList: return "@_effects arguments" case .enumCaseDecl: diff --git a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md index 5410cabf81b..bc142649966 100644 --- a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md +++ b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md @@ -191,6 +191,7 @@ These articles are intended for developers wishing to contribute to SwiftSyntax - - - +- - - - diff --git a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift index 7eff15a4ca7..dbf1504fe2a 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -1083,6 +1083,16 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "placeholder" case \EditorPlaceholderPatternSyntax.unexpectedAfterPlaceholder: return "unexpectedAfterPlaceholder" + case \EditorPlaceholderTypeSyntax.unexpectedBeforePlaceholder: + return "unexpectedBeforePlaceholder" + case \EditorPlaceholderTypeSyntax.placeholder: + return "placeholder" + case \EditorPlaceholderTypeSyntax.unexpectedBetweenPlaceholderAndGenericArgumentClause: + return "unexpectedBetweenPlaceholderAndGenericArgumentClause" + case \EditorPlaceholderTypeSyntax.genericArgumentClause: + return "genericArgumentClause" + case \EditorPlaceholderTypeSyntax.unexpectedAfterGenericArgumentClause: + return "unexpectedAfterGenericArgumentClause" case \EnumCaseDeclSyntax.unexpectedBeforeAttributes: return "unexpectedBeforeAttributes" case \EnumCaseDeclSyntax.attributes: diff --git a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift index 3c0f87beb14..e7b991de886 100644 --- a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift @@ -784,6 +784,14 @@ open class SyntaxAnyVisitor: SyntaxVisitor { visitAnyPost(node._syntaxNode) } + override open func visit(_ node: EditorPlaceholderTypeSyntax) -> SyntaxVisitorContinueKind { + return visitAny(node._syntaxNode) + } + + override open func visitPost(_ node: EditorPlaceholderTypeSyntax) { + visitAnyPost(node._syntaxNode) + } + override open func visit(_ node: EffectsAttributeArgumentListSyntax) -> SyntaxVisitorContinueKind { return visitAny(node._syntaxNode) } diff --git a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift index 18f9fbdd809..17a17d7eacc 100644 --- a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift +++ b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift @@ -1299,7 +1299,7 @@ public struct TypeSyntax: TypeSyntaxProtocol, SyntaxHashable { public init?(_ node: some SyntaxProtocol) { switch node.raw.kind { - case .arrayType, .attributedType, .classRestrictionType, .compositionType, .dictionaryType, .functionType, .identifierType, .implicitlyUnwrappedOptionalType, .memberType, .metatypeType, .missingType, .namedOpaqueReturnType, .optionalType, .packElementType, .packExpansionType, .someOrAnyType, .suppressedType, .tupleType: + case .arrayType, .attributedType, .classRestrictionType, .compositionType, .dictionaryType, .editorPlaceholderType, .functionType, .identifierType, .implicitlyUnwrappedOptionalType, .memberType, .metatypeType, .missingType, .namedOpaqueReturnType, .optionalType, .packElementType, .packExpansionType, .someOrAnyType, .suppressedType, .tupleType: self._syntaxNode = node._syntaxNode default: return nil @@ -1329,6 +1329,7 @@ public struct TypeSyntax: TypeSyntaxProtocol, SyntaxHashable { .node(ClassRestrictionTypeSyntax.self), .node(CompositionTypeSyntax.self), .node(DictionaryTypeSyntax.self), + .node(EditorPlaceholderTypeSyntax.self), .node(FunctionTypeSyntax.self), .node(IdentifierTypeSyntax.self), .node(ImplicitlyUnwrappedOptionalTypeSyntax.self), @@ -1488,6 +1489,7 @@ extension Syntax { .node(EditorPlaceholderDeclSyntax.self), .node(EditorPlaceholderExprSyntax.self), .node(EditorPlaceholderPatternSyntax.self), + .node(EditorPlaceholderTypeSyntax.self), .node(EffectsAttributeArgumentListSyntax.self), .node(EnumCaseDeclSyntax.self), .node(EnumCaseElementListSyntax.self), diff --git a/Sources/SwiftSyntax/generated/SyntaxEnum.swift b/Sources/SwiftSyntax/generated/SyntaxEnum.swift index f502eb436db..a2c1ccdb31e 100644 --- a/Sources/SwiftSyntax/generated/SyntaxEnum.swift +++ b/Sources/SwiftSyntax/generated/SyntaxEnum.swift @@ -106,6 +106,7 @@ public enum SyntaxEnum { case editorPlaceholderDecl(EditorPlaceholderDeclSyntax) case editorPlaceholderExpr(EditorPlaceholderExprSyntax) case editorPlaceholderPattern(EditorPlaceholderPatternSyntax) + case editorPlaceholderType(EditorPlaceholderTypeSyntax) case effectsAttributeArgumentList(EffectsAttributeArgumentListSyntax) case enumCaseDecl(EnumCaseDeclSyntax) case enumCaseElementList(EnumCaseElementListSyntax) @@ -482,6 +483,8 @@ public extension Syntax { return .editorPlaceholderExpr(EditorPlaceholderExprSyntax(self)!) case .editorPlaceholderPattern: return .editorPlaceholderPattern(EditorPlaceholderPatternSyntax(self)!) + case .editorPlaceholderType: + return .editorPlaceholderType(EditorPlaceholderTypeSyntax(self)!) case .effectsAttributeArgumentList: return .effectsAttributeArgumentList(EffectsAttributeArgumentListSyntax(self)!) case .enumCaseDecl: diff --git a/Sources/SwiftSyntax/generated/SyntaxKind.swift b/Sources/SwiftSyntax/generated/SyntaxKind.swift index 57bc3f801f7..c5cd3ee5725 100644 --- a/Sources/SwiftSyntax/generated/SyntaxKind.swift +++ b/Sources/SwiftSyntax/generated/SyntaxKind.swift @@ -106,6 +106,7 @@ public enum SyntaxKind: CaseIterable { case editorPlaceholderDecl case editorPlaceholderExpr case editorPlaceholderPattern + case editorPlaceholderType case effectsAttributeArgumentList case enumCaseDecl case enumCaseElementList @@ -603,6 +604,8 @@ public enum SyntaxKind: CaseIterable { return EditorPlaceholderExprSyntax.self case .editorPlaceholderPattern: return EditorPlaceholderPatternSyntax.self + case .editorPlaceholderType: + return EditorPlaceholderTypeSyntax.self case .effectsAttributeArgumentList: return EffectsAttributeArgumentListSyntax.self case .enumCaseDecl: diff --git a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift index 82048b9ddd2..d391404aeed 100644 --- a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift +++ b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift @@ -717,6 +717,13 @@ open class SyntaxRewriter { return PatternSyntax(visitChildren(node)) } + /// Visit a ``EditorPlaceholderTypeSyntax``. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + open func visit(_ node: EditorPlaceholderTypeSyntax) -> TypeSyntax { + return TypeSyntax(visitChildren(node)) + } + /// Visit a ``EffectsAttributeArgumentListSyntax``. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node @@ -2467,6 +2474,10 @@ open class SyntaxRewriter { return { self.visitImpl($0, EditorPlaceholderPatternSyntax.self, self.visit) } + case .editorPlaceholderType: + return { + self.visitImpl($0, EditorPlaceholderTypeSyntax.self, self.visit) + } case .effectsAttributeArgumentList: return { self.visitImpl($0, EffectsAttributeArgumentListSyntax.self, self.visit) @@ -3403,6 +3414,8 @@ open class SyntaxRewriter { return visitImpl(node, EditorPlaceholderExprSyntax.self, visit) case .editorPlaceholderPattern: return visitImpl(node, EditorPlaceholderPatternSyntax.self, visit) + case .editorPlaceholderType: + return visitImpl(node, EditorPlaceholderTypeSyntax.self, visit) case .effectsAttributeArgumentList: return visitImpl(node, EffectsAttributeArgumentListSyntax.self, visit) case .enumCaseDecl: diff --git a/Sources/SwiftSyntax/generated/SyntaxTransform.swift b/Sources/SwiftSyntax/generated/SyntaxTransform.swift index 9efda11a237..39df24c44bc 100644 --- a/Sources/SwiftSyntax/generated/SyntaxTransform.swift +++ b/Sources/SwiftSyntax/generated/SyntaxTransform.swift @@ -475,6 +475,11 @@ public protocol SyntaxTransformVisitor { /// - Returns: the sum of whatever the child visitors return. func visit(_ node: EditorPlaceholderPatternSyntax) -> ResultType + /// Visiting ``EditorPlaceholderTypeSyntax`` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: the sum of whatever the child visitors return. + func visit(_ node: EditorPlaceholderTypeSyntax) -> ResultType + /// Visiting ``EffectsAttributeArgumentListSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: the sum of whatever the child visitors return. @@ -2048,6 +2053,13 @@ extension SyntaxTransformVisitor { visitAny(Syntax(node)) } + /// Visiting ``EditorPlaceholderTypeSyntax`` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: nil by default. + public func visit(_ node: EditorPlaceholderTypeSyntax) -> ResultType { + visitAny(Syntax(node)) + } + /// Visiting ``EffectsAttributeArgumentListSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: nil by default. @@ -3536,6 +3548,8 @@ extension SyntaxTransformVisitor { return visit(derived) case .editorPlaceholderPattern(let derived): return visit(derived) + case .editorPlaceholderType(let derived): + return visit(derived) case .effectsAttributeArgumentList(let derived): return visit(derived) case .enumCaseDecl(let derived): diff --git a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift index c735bffb513..44753adfd0e 100644 --- a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift @@ -1126,6 +1126,18 @@ open class SyntaxVisitor { open func visitPost(_ node: EditorPlaceholderPatternSyntax) { } + /// Visiting ``EditorPlaceholderTypeSyntax`` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: how should we continue visiting. + open func visit(_ node: EditorPlaceholderTypeSyntax) -> SyntaxVisitorContinueKind { + return .visitChildren + } + + /// The function called after visiting ``EditorPlaceholderTypeSyntax`` and its descendants. + /// - node: the node we just finished visiting. + open func visitPost(_ node: EditorPlaceholderTypeSyntax) { + } + /// Visiting ``EffectsAttributeArgumentListSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: how should we continue visiting. @@ -3784,6 +3796,10 @@ open class SyntaxVisitor { return { self.visitImpl($0, EditorPlaceholderPatternSyntax.self, self.visit, self.visitPost) } + case .editorPlaceholderType: + return { + self.visitImpl($0, EditorPlaceholderTypeSyntax.self, self.visit, self.visitPost) + } case .effectsAttributeArgumentList: return { self.visitImpl($0, EffectsAttributeArgumentListSyntax.self, self.visit, self.visitPost) @@ -4723,6 +4739,8 @@ open class SyntaxVisitor { visitImpl(node, EditorPlaceholderExprSyntax.self, visit, visitPost) case .editorPlaceholderPattern: visitImpl(node, EditorPlaceholderPatternSyntax.self, visit, visitPost) + case .editorPlaceholderType: + visitImpl(node, EditorPlaceholderTypeSyntax.self, visit, visitPost) case .effectsAttributeArgumentList: visitImpl(node, EffectsAttributeArgumentListSyntax.self, visit, visitPost) case .enumCaseDecl: diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesEF.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesEF.swift index 98f72931b4f..7740e6e50a4 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesEF.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesEF.swift @@ -199,6 +199,76 @@ public struct RawEditorPlaceholderPatternSyntax: RawPatternSyntaxNodeProtocol { } } +@_spi(RawSyntax) +public struct RawEditorPlaceholderTypeSyntax: RawTypeSyntaxNodeProtocol { + @_spi(RawSyntax) + public var layoutView: RawSyntaxLayoutView { + return raw.layoutView! + } + + public static func isKindOf(_ raw: RawSyntax) -> Bool { + return raw.kind == .editorPlaceholderType + } + + public var raw: RawSyntax + + init(raw: RawSyntax) { + precondition(Self.isKindOf(raw)) + self.raw = raw + } + + private init(unchecked raw: RawSyntax) { + self.raw = raw + } + + public init?(_ other: some RawSyntaxNodeProtocol) { + guard Self.isKindOf(other.raw) else { + return nil + } + self.init(unchecked: other.raw) + } + + public init( + _ unexpectedBeforePlaceholder: RawUnexpectedNodesSyntax? = nil, + placeholder: RawTokenSyntax, + _ unexpectedBetweenPlaceholderAndGenericArgumentClause: RawUnexpectedNodesSyntax? = nil, + genericArgumentClause: RawGenericArgumentClauseSyntax?, + _ unexpectedAfterGenericArgumentClause: RawUnexpectedNodesSyntax? = nil, + arena: __shared SyntaxArena + ) { + let raw = RawSyntax.makeLayout( + kind: .editorPlaceholderType, uninitializedCount: 5, arena: arena) { layout in + layout.initialize(repeating: nil) + layout[0] = unexpectedBeforePlaceholder?.raw + layout[1] = placeholder.raw + layout[2] = unexpectedBetweenPlaceholderAndGenericArgumentClause?.raw + layout[3] = genericArgumentClause?.raw + layout[4] = unexpectedAfterGenericArgumentClause?.raw + } + self.init(unchecked: raw) + } + + public var unexpectedBeforePlaceholder: RawUnexpectedNodesSyntax? { + layoutView.children[0].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var placeholder: RawTokenSyntax { + layoutView.children[1].map(RawTokenSyntax.init(raw:))! + } + + public var unexpectedBetweenPlaceholderAndGenericArgumentClause: RawUnexpectedNodesSyntax? { + layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var genericArgumentClause: RawGenericArgumentClauseSyntax? { + layoutView.children[3].map(RawGenericArgumentClauseSyntax.init(raw:)) + } + + public var unexpectedAfterGenericArgumentClause: RawUnexpectedNodesSyntax? { + layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) + } +} + @_spi(RawSyntax) public struct RawEffectsAttributeArgumentListSyntax: RawSyntaxNodeProtocol { @_spi(RawSyntax) diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesTUVWXYZ.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesTUVWXYZ.swift index 21693ed8fdc..bbefabe4cc7 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesTUVWXYZ.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesTUVWXYZ.swift @@ -1306,7 +1306,7 @@ public struct RawTypeSyntax: RawTypeSyntaxNodeProtocol { public static func isKindOf(_ raw: RawSyntax) -> Bool { switch raw.kind { - case .arrayType, .attributedType, .classRestrictionType, .compositionType, .dictionaryType, .functionType, .identifierType, .implicitlyUnwrappedOptionalType, .memberType, .metatypeType, .missingType, .namedOpaqueReturnType, .optionalType, .packElementType, .packExpansionType, .someOrAnyType, .suppressedType, .tupleType: + case .arrayType, .attributedType, .classRestrictionType, .compositionType, .dictionaryType, .editorPlaceholderType, .functionType, .identifierType, .implicitlyUnwrappedOptionalType, .memberType, .metatypeType, .missingType, .namedOpaqueReturnType, .optionalType, .packElementType, .packExpansionType, .someOrAnyType, .suppressedType, .tupleType: return true default: return false diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index 9daac06b376..8684bb977ee 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -1040,6 +1040,13 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier)])) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + case .editorPlaceholderType: + assert(layout.count == 5) + assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier)])) + assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 3, verify(layout[3], as: RawGenericArgumentClauseSyntax?.self)) + assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) case .effectsAttributeArgumentList: for (index, element) in layout.enumerated() { assertNoError(kind, index, verify(element, as: RawTokenSyntax.self)) diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift index 9f625ea6aaf..c46c6711f64 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift @@ -366,6 +366,125 @@ public struct EditorPlaceholderPatternSyntax: PatternSyntaxProtocol, SyntaxHasha } } +// MARK: - EditorPlaceholderTypeSyntax + +/// An editor placeholder, e.g. `<#Type#>` that is used in a position that expects a type. +/// +/// ### Children +/// +/// - `placeholder`: `` +/// - `genericArgumentClause`: ``GenericArgumentClauseSyntax``? +public struct EditorPlaceholderTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyntaxNodeProtocol { + public let _syntaxNode: Syntax + + public init?(_ node: some SyntaxProtocol) { + guard node.raw.kind == .editorPlaceholderType else { + return nil + } + self._syntaxNode = node._syntaxNode + } + + /// - Parameters: + /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. + /// - placeholder: The actual editor placeholder that starts with `<#` and ends with `#>`. + /// - genericArgumentClause: Generic arguments that is attatched to the type. + /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforePlaceholder: UnexpectedNodesSyntax? = nil, + placeholder: TokenSyntax, + _ unexpectedBetweenPlaceholderAndGenericArgumentClause: UnexpectedNodesSyntax? = nil, + genericArgumentClause: GenericArgumentClauseSyntax? = nil, + _ unexpectedAfterGenericArgumentClause: UnexpectedNodesSyntax? = nil, + trailingTrivia: Trivia? = nil + + ) { + // Extend the lifetime of all parameters so their arenas don't get destroyed + // before they can be added as children of the new arena. + self = withExtendedLifetime((SyntaxArena(), ( + unexpectedBeforePlaceholder, + placeholder, + unexpectedBetweenPlaceholderAndGenericArgumentClause, + genericArgumentClause, + unexpectedAfterGenericArgumentClause + ))) { (arena, _) in + let layout: [RawSyntax?] = [ + unexpectedBeforePlaceholder?.raw, + placeholder.raw, + unexpectedBetweenPlaceholderAndGenericArgumentClause?.raw, + genericArgumentClause?.raw, + unexpectedAfterGenericArgumentClause?.raw + ] + let raw = RawSyntax.makeLayout( + kind: SyntaxKind.editorPlaceholderType, + from: layout, + arena: arena, + leadingTrivia: leadingTrivia, + trailingTrivia: trailingTrivia + + ) + return Syntax.forRoot(raw, rawNodeArena: arena).cast(Self.self) + } + } + + public var unexpectedBeforePlaceholder: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 0)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 0, with: Syntax(value), arena: SyntaxArena()).cast(EditorPlaceholderTypeSyntax.self) + } + } + + /// The actual editor placeholder that starts with `<#` and ends with `#>`. + public var placeholder: TokenSyntax { + get { + return Syntax(self).child(at: 1)!.cast(TokenSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 1, with: Syntax(value), arena: SyntaxArena()).cast(EditorPlaceholderTypeSyntax.self) + } + } + + public var unexpectedBetweenPlaceholderAndGenericArgumentClause: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 2, with: Syntax(value), arena: SyntaxArena()).cast(EditorPlaceholderTypeSyntax.self) + } + } + + /// Generic arguments that is attatched to the type. + public var genericArgumentClause: GenericArgumentClauseSyntax? { + get { + return Syntax(self).child(at: 3)?.cast(GenericArgumentClauseSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 3, with: Syntax(value), arena: SyntaxArena()).cast(EditorPlaceholderTypeSyntax.self) + } + } + + public var unexpectedAfterGenericArgumentClause: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 4, with: Syntax(value), arena: SyntaxArena()).cast(EditorPlaceholderTypeSyntax.self) + } + } + + public static var structure: SyntaxNodeStructure { + return .layout([ + \Self.unexpectedBeforePlaceholder, + \Self.placeholder, + \Self.unexpectedBetweenPlaceholderAndGenericArgumentClause, + \Self.genericArgumentClause, + \Self.unexpectedAfterGenericArgumentClause + ]) + } +} + // MARK: - EnumCaseDeclSyntax /// A `case` declaration of a Swift `enum`. It can have 1 or more `EnumCaseElement`s inside, each declaring a different case of the enum. diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift index 30d3572a9fb..9c972f62156 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift @@ -22,6 +22,7 @@ /// /// ### Contained in /// +/// - ``EditorPlaceholderTypeSyntax``.``EditorPlaceholderTypeSyntax/genericArgumentClause`` /// - ``GenericSpecializationExprSyntax``.``GenericSpecializationExprSyntax/genericArgumentClause`` /// - ``IdentifierTypeSyntax``.``IdentifierTypeSyntax/genericArgumentClause`` /// - ``KeyPathPropertyComponentSyntax``.``KeyPathPropertyComponentSyntax/genericArgumentClause`` diff --git a/Tests/SwiftParserTest/TypeTests.swift b/Tests/SwiftParserTest/TypeTests.swift index 5be48f065fe..853ce278806 100644 --- a/Tests/SwiftParserTest/TypeTests.swift +++ b/Tests/SwiftParserTest/TypeTests.swift @@ -216,4 +216,65 @@ final class TypeTests: ParserTestCase { substructureAfterMarker: "1️⃣" ) } + + func testTypeWithPlaceholder() { + assertParse( + "let a: 1️⃣<#T#> = x", + substructure: VariableDeclSyntax( + bindingSpecifier: .keyword(.let), + bindings: [ + PatternBindingSyntax( + pattern: IdentifierPatternSyntax(identifier: .identifier("a")), + typeAnnotation: TypeAnnotationSyntax( + type: EditorPlaceholderTypeSyntax( + placeholder: .identifier("<#T#>") + ) + ), + initializer: InitializerClauseSyntax( + value: DeclReferenceExprSyntax( + baseName: .identifier("x") + ) + ) + ) + ] + ), + diagnostics: [ + DiagnosticSpec(message: "editor placeholder in source file") + ] + ) + + assertParse( + "let a: 1️⃣<#T#> = x", + substructure: VariableDeclSyntax( + bindingSpecifier: .keyword(.let), + bindings: [ + PatternBindingSyntax( + pattern: IdentifierPatternSyntax(identifier: .identifier("a")), + typeAnnotation: TypeAnnotationSyntax( + type: EditorPlaceholderTypeSyntax( + placeholder: .identifier("<#T#>"), + genericArgumentClause: GenericArgumentClauseSyntax( + arguments: GenericArgumentListSyntax([ + GenericArgumentSyntax( + argument: IdentifierTypeSyntax( + name: .identifier("Foo") + ) + ) + ]) + ) + ) + ), + initializer: InitializerClauseSyntax( + value: DeclReferenceExprSyntax( + baseName: .identifier("x") + ) + ) + ) + ] + ), + diagnostics: [ + DiagnosticSpec(message: "editor placeholder in source file") + ] + ) + } }