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..d8e35377a5f 100644 --- a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift +++ b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift @@ -111,6 +111,8 @@ public enum SyntaxNodeKind: String, CaseIterable { case dynamicReplacementAttributeArguments 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 9adf09c29ce..6136888a67b 100644 --- a/Release Notes/510.md +++ b/Release Notes/510.md @@ -21,6 +21,16 @@ - 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 + +- 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/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/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 64ff8b4cadd..540bad6ddf7 100644 --- a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift @@ -143,6 +143,10 @@ extension SyntaxKind { return "editor placeholder" case .editorPlaceholderExpr: 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 98689c309eb..bc142649966 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 - - - +- - - - @@ -190,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 4cc8070057c..dbf1504fe2a 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -1077,6 +1077,22 @@ 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 \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 518cb834c89..e7b991de886 100644 --- a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift @@ -776,6 +776,22 @@ 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: 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 ab916c743b3..17a17d7eacc 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), @@ -1298,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 @@ -1328,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), @@ -1486,6 +1488,8 @@ extension Syntax { .node(DynamicReplacementAttributeArgumentsSyntax.self), .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 6ea43ee2b8b..a2c1ccdb31e 100644 --- a/Sources/SwiftSyntax/generated/SyntaxEnum.swift +++ b/Sources/SwiftSyntax/generated/SyntaxEnum.swift @@ -105,6 +105,8 @@ public enum SyntaxEnum { case dynamicReplacementAttributeArguments(DynamicReplacementAttributeArgumentsSyntax) case editorPlaceholderDecl(EditorPlaceholderDeclSyntax) case editorPlaceholderExpr(EditorPlaceholderExprSyntax) + case editorPlaceholderPattern(EditorPlaceholderPatternSyntax) + case editorPlaceholderType(EditorPlaceholderTypeSyntax) case effectsAttributeArgumentList(EffectsAttributeArgumentListSyntax) case enumCaseDecl(EnumCaseDeclSyntax) case enumCaseElementList(EnumCaseElementListSyntax) @@ -479,6 +481,10 @@ public extension Syntax { return .editorPlaceholderDecl(EditorPlaceholderDeclSyntax(self)!) case .editorPlaceholderExpr: 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 d0e659351ec..c5cd3ee5725 100644 --- a/Sources/SwiftSyntax/generated/SyntaxKind.swift +++ b/Sources/SwiftSyntax/generated/SyntaxKind.swift @@ -105,6 +105,8 @@ public enum SyntaxKind: CaseIterable { case dynamicReplacementAttributeArguments case editorPlaceholderDecl case editorPlaceholderExpr + case editorPlaceholderPattern + case editorPlaceholderType case effectsAttributeArgumentList case enumCaseDecl case enumCaseElementList @@ -600,6 +602,10 @@ public enum SyntaxKind: CaseIterable { return EditorPlaceholderDeclSyntax.self case .editorPlaceholderExpr: 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 96e089034bb..d391404aeed 100644 --- a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift +++ b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift @@ -710,6 +710,20 @@ 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 ``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 @@ -2456,6 +2470,14 @@ open class SyntaxRewriter { return { self.visitImpl($0, EditorPlaceholderExprSyntax.self, self.visit) } + case .editorPlaceholderPattern: + 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) @@ -3390,6 +3412,10 @@ 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 .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 27c7d8e2bbd..39df24c44bc 100644 --- a/Sources/SwiftSyntax/generated/SyntaxTransform.swift +++ b/Sources/SwiftSyntax/generated/SyntaxTransform.swift @@ -470,6 +470,16 @@ 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 ``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. @@ -2036,6 +2046,20 @@ 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 ``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. @@ -3522,6 +3546,10 @@ extension SyntaxTransformVisitor { return visit(derived) case .editorPlaceholderExpr(let derived): 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 92824a24c11..44753adfd0e 100644 --- a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift @@ -1114,6 +1114,30 @@ 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 ``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. @@ -3768,6 +3792,14 @@ 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 .editorPlaceholderType: + return { + self.visitImpl($0, EditorPlaceholderTypeSyntax.self, self.visit, self.visitPost) + } case .effectsAttributeArgumentList: return { self.visitImpl($0, EffectsAttributeArgumentListSyntax.self, self.visit, self.visitPost) @@ -4705,6 +4737,10 @@ 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 .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 da079023bdc..7740e6e50a4 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesEF.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesEF.swift @@ -141,6 +141,134 @@ 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 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/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/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 b226fdd1edd..8684bb977ee 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -1035,6 +1035,18 @@ 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 .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 6715763970b..c46c6711f64 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift @@ -288,6 +288,203 @@ 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: - 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/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/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") + ] + ) + } } 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"), + ] + ) + } }