diff --git a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift index c70c67b9072..60a07d9e52a 100644 --- a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift @@ -349,6 +349,23 @@ public let TYPE_NODES: [Node] = [ ] ), + // suppressed-type -> '~' type + Node( + name: "SuppressedType", + nameForDiagnostics: "suppressed type conformance", + kind: "Type", + children: [ + Child( + name: "WithoutTilde", + kind: .token(choices: [.token(tokenKind: "PrefixOperatorToken")]) + ), + Child( + name: "PatternType", + kind: .node(kind: "Type") + ), + ] + ), + // pack-expansion-type -> type '...' Node( name: "PackExpansionType", diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 9c1e5dceff4..f506deaa5ef 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -497,7 +497,7 @@ extension Parser { let unexpectedBeforeInherited: RawUnexpectedNodesSyntax? let inherited: RawTypeSyntax? if colon != nil { - if self.at(.identifier, .keyword(.protocol), .keyword(.Any)) { + if self.at(.identifier, .keyword(.protocol), .keyword(.Any)) || self.atContextualPunctuator("~") { unexpectedBeforeInherited = nil inherited = self.parseType() } else if let classKeyword = self.consume(if: .keyword(.class)) { diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 8ddab9caa8b..9f2c526951f 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -37,6 +37,18 @@ extension Parser { ) } + // Parse without operator preceding a type '~ T'. + if let withoutTilde = self.consumeIfContextualPunctuator("~", remapping: .prefixOperator) { + let type = self.parseTypeScalar(misplacedSpecifiers: misplacedSpecifiers) + return RawTypeSyntax( + RawSuppressedTypeSyntax( + withoutTilde: withoutTilde, + patternType: type, + arena: self.arena + ) + ) + } + return self.parseTypeScalar(misplacedSpecifiers: misplacedSpecifiers) } diff --git a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift index b35327cad6d..d0cee23cd41 100644 --- a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift @@ -341,6 +341,8 @@ extension SyntaxKind { return "subscript" case .subscriptExpr: return "subscript" + case .suppressedType: + return "suppressed type conformance" case .switchCase: return "switch case" case .switchExpr: diff --git a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md index c3924e1afc6..5a9987700bf 100644 --- a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md +++ b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md @@ -186,6 +186,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code. - - - +- - ### Collections diff --git a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift index 35215544ca8..a1b06fc3c51 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -2869,6 +2869,16 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "superKeyword" case \SuperRefExprSyntax.unexpectedAfterSuperKeyword: return "unexpectedAfterSuperKeyword" + case \SuppressedTypeSyntax.unexpectedBeforeWithoutTilde: + return "unexpectedBeforeWithoutTilde" + case \SuppressedTypeSyntax.withoutTilde: + return "withoutTilde" + case \SuppressedTypeSyntax.unexpectedBetweenWithoutTildeAndPatternType: + return "unexpectedBetweenWithoutTildeAndPatternType" + case \SuppressedTypeSyntax.patternType: + return "patternType" + case \SuppressedTypeSyntax.unexpectedAfterPatternType: + return "unexpectedAfterPatternType" case \SwitchCaseLabelSyntax.unexpectedBeforeCaseKeyword: return "unexpectedBeforeCaseKeyword" case \SwitchCaseLabelSyntax.caseKeyword: diff --git a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift index 08f7d2307a1..783e957d60a 100644 --- a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift @@ -1869,6 +1869,14 @@ open class SyntaxAnyVisitor: SyntaxVisitor { visitAnyPost(node._syntaxNode) } + override open func visit(_ node: SuppressedTypeSyntax) -> SyntaxVisitorContinueKind { + return visitAny(node._syntaxNode) + } + + override open func visitPost(_ node: SuppressedTypeSyntax) { + visitAnyPost(node._syntaxNode) + } + override open func visit(_ node: SwitchCaseLabelSyntax) -> SyntaxVisitorContinueKind { return visitAny(node._syntaxNode) } diff --git a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift index a91643e1fe9..d1b37a196fa 100644 --- a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift +++ b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift @@ -610,7 +610,7 @@ public struct TypeSyntax: TypeSyntaxProtocol, SyntaxHashable { public init?(_ node: S) { switch node.raw.kind { - case .arrayType, .attributedType, .classRestrictionType, .compositionType, .constrainedSugarType, .dictionaryType, .functionType, .implicitlyUnwrappedOptionalType, .memberTypeIdentifier, .metatypeType, .missingType, .namedOpaqueReturnType, .optionalType, .packExpansionType, .packReferenceType, .simpleTypeIdentifier, .tupleType: + case .arrayType, .attributedType, .classRestrictionType, .compositionType, .constrainedSugarType, .dictionaryType, .functionType, .implicitlyUnwrappedOptionalType, .memberTypeIdentifier, .metatypeType, .missingType, .namedOpaqueReturnType, .optionalType, .packExpansionType, .packReferenceType, .simpleTypeIdentifier, .suppressedType, .tupleType: self._syntaxNode = node._syntaxNode default: return nil @@ -622,7 +622,7 @@ public struct TypeSyntax: TypeSyntaxProtocol, SyntaxHashable { /// is undefined. internal init(_ data: SyntaxData) { switch data.raw.kind { - case .arrayType, .attributedType, .classRestrictionType, .compositionType, .constrainedSugarType, .dictionaryType, .functionType, .implicitlyUnwrappedOptionalType, .memberTypeIdentifier, .metatypeType, .missingType, .namedOpaqueReturnType, .optionalType, .packExpansionType, .packReferenceType, .simpleTypeIdentifier, .tupleType: + case .arrayType, .attributedType, .classRestrictionType, .compositionType, .constrainedSugarType, .dictionaryType, .functionType, .implicitlyUnwrappedOptionalType, .memberTypeIdentifier, .metatypeType, .missingType, .namedOpaqueReturnType, .optionalType, .packExpansionType, .packReferenceType, .simpleTypeIdentifier, .suppressedType, .tupleType: break default: preconditionFailure("Unable to create TypeSyntax from \(data.raw.kind)") @@ -674,6 +674,7 @@ public struct TypeSyntax: TypeSyntaxProtocol, SyntaxHashable { .node(PackExpansionTypeSyntax.self), .node(PackReferenceTypeSyntax.self), .node(SimpleTypeIdentifierSyntax.self), + .node(SuppressedTypeSyntax.self), .node(TupleTypeSyntax.self) ]) } @@ -910,6 +911,7 @@ extension Syntax { .node(SubscriptDeclSyntax.self), .node(SubscriptExprSyntax.self), .node(SuperRefExprSyntax.self), + .node(SuppressedTypeSyntax.self), .node(SwitchCaseLabelSyntax.self), .node(SwitchCaseListSyntax.self), .node(SwitchCaseSyntax.self), diff --git a/Sources/SwiftSyntax/generated/SyntaxEnum.swift b/Sources/SwiftSyntax/generated/SyntaxEnum.swift index 8e9144700ab..390943e141c 100644 --- a/Sources/SwiftSyntax/generated/SyntaxEnum.swift +++ b/Sources/SwiftSyntax/generated/SyntaxEnum.swift @@ -243,6 +243,7 @@ public enum SyntaxEnum { case subscriptDecl(SubscriptDeclSyntax) case subscriptExpr(SubscriptExprSyntax) case superRefExpr(SuperRefExprSyntax) + case suppressedType(SuppressedTypeSyntax) case switchCaseLabel(SwitchCaseLabelSyntax) case switchCaseList(SwitchCaseListSyntax) case switchCase(SwitchCaseSyntax) @@ -746,6 +747,8 @@ public extension Syntax { return .subscriptExpr(SubscriptExprSyntax(self)!) case .superRefExpr: return .superRefExpr(SuperRefExprSyntax(self)!) + case .suppressedType: + return .suppressedType(SuppressedTypeSyntax(self)!) case .switchCaseLabel: return .switchCaseLabel(SwitchCaseLabelSyntax(self)!) case .switchCaseList: diff --git a/Sources/SwiftSyntax/generated/SyntaxKind.swift b/Sources/SwiftSyntax/generated/SyntaxKind.swift index 518f1f43a0f..aa199255f7b 100644 --- a/Sources/SwiftSyntax/generated/SyntaxKind.swift +++ b/Sources/SwiftSyntax/generated/SyntaxKind.swift @@ -243,6 +243,7 @@ public enum SyntaxKind { case subscriptDecl case subscriptExpr case superRefExpr + case suppressedType case switchCaseLabel case switchCaseList case switchCase @@ -861,6 +862,8 @@ public enum SyntaxKind { return SubscriptExprSyntax.self case .superRefExpr: return SuperRefExprSyntax.self + case .suppressedType: + return SuppressedTypeSyntax.self case .switchCaseLabel: return SwitchCaseLabelSyntax.self case .switchCaseList: diff --git a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift index 3fdb902fd64..909cee80a34 100644 --- a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift +++ b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift @@ -1614,6 +1614,13 @@ open class SyntaxRewriter { return ExprSyntax(visitChildren(node)) } + /// Visit a `SuppressedTypeSyntax`. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + open func visit(_ node: SuppressedTypeSyntax) -> TypeSyntax { + return TypeSyntax(visitChildren(node)) + } + /// Visit a `SwitchCaseLabelSyntax`. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node @@ -5153,6 +5160,20 @@ open class SyntaxRewriter { return Syntax(visit(node)) } + /// Implementation detail of visit(_:). Do not call directly. + private func visitImplSuppressedTypeSyntax(_ data: SyntaxData) -> Syntax { + let node = SuppressedTypeSyntax(data) + // Accessing _syntaxNode directly is faster than calling Syntax(node) + visitPre(node._syntaxNode) + defer { + visitPost(node._syntaxNode) + } + if let newNode = visitAny(node._syntaxNode) { + return newNode + } + return Syntax(visit(node)) + } + /// Implementation detail of visit(_:). Do not call directly. private func visitImplSwitchCaseLabelSyntax(_ data: SyntaxData) -> Syntax { let node = SwitchCaseLabelSyntax(data) @@ -6223,6 +6244,8 @@ open class SyntaxRewriter { return visitImplSubscriptExprSyntax case .superRefExpr: return visitImplSuperRefExprSyntax + case .suppressedType: + return visitImplSuppressedTypeSyntax case .switchCaseLabel: return visitImplSwitchCaseLabelSyntax case .switchCaseList: @@ -6769,6 +6792,8 @@ open class SyntaxRewriter { return visitImplSubscriptExprSyntax(data) case .superRefExpr: return visitImplSuperRefExprSyntax(data) + case .suppressedType: + return visitImplSuppressedTypeSyntax(data) case .switchCaseLabel: return visitImplSwitchCaseLabelSyntax(data) case .switchCaseList: diff --git a/Sources/SwiftSyntax/generated/SyntaxTransform.swift b/Sources/SwiftSyntax/generated/SyntaxTransform.swift index 4d84a26cc30..cbbeb096f34 100644 --- a/Sources/SwiftSyntax/generated/SyntaxTransform.swift +++ b/Sources/SwiftSyntax/generated/SyntaxTransform.swift @@ -1154,6 +1154,11 @@ public protocol SyntaxTransformVisitor { /// - Returns: the sum of whatever the child visitors return. func visit(_ node: SuperRefExprSyntax) -> ResultType + /// Visiting `SuppressedTypeSyntax` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: the sum of whatever the child visitors return. + func visit(_ node: SuppressedTypeSyntax) -> ResultType + /// Visiting `SwitchCaseLabelSyntax` specifically. /// - Parameter node: the node we are visiting. /// - Returns: the sum of whatever the child visitors return. @@ -2954,6 +2959,13 @@ extension SyntaxTransformVisitor { visitAny(Syntax(node)) } + /// Visiting `SuppressedTypeSyntax` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: nil by default. + public func visit(_ node: SuppressedTypeSyntax) -> ResultType { + visitAny(Syntax(node)) + } + /// Visiting `SwitchCaseLabelSyntax` specifically. /// - Parameter node: the node we are visiting. /// - Returns: nil by default. @@ -3699,6 +3711,8 @@ extension SyntaxTransformVisitor { return visit(derived) case .superRefExpr(let derived): return visit(derived) + case .suppressedType(let derived): + return visit(derived) case .switchCaseLabel(let derived): return visit(derived) case .switchCaseList(let derived): diff --git a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift index 0e9e589d93c..b7124bbd68e 100644 --- a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift @@ -2758,6 +2758,18 @@ open class SyntaxVisitor { open func visitPost(_ node: SuperRefExprSyntax) { } + /// Visiting `SuppressedTypeSyntax` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: how should we continue visiting. + open func visit(_ node: SuppressedTypeSyntax) -> SyntaxVisitorContinueKind { + return .visitChildren + } + + /// The function called after visiting `SuppressedTypeSyntax` and its descendents. + /// - node: the node we just finished visiting. + open func visitPost(_ node: SuppressedTypeSyntax) { + } + /// Visiting `SwitchCaseLabelSyntax` specifically. /// - Parameter node: the node we are visiting. /// - Returns: how should we continue visiting. @@ -5759,6 +5771,17 @@ open class SyntaxVisitor { visitPost(node) } + /// Implementation detail of doVisit(_:_:). Do not call directly. + private func visitImplSuppressedTypeSyntax(_ data: SyntaxData) { + let node = SuppressedTypeSyntax(data) + let needsChildren = (visit(node) == .visitChildren) + // Avoid calling into visitChildren if possible. + if needsChildren && !node.raw.layoutView!.children.isEmpty { + visitChildren(node) + } + visitPost(node) + } + /// Implementation detail of doVisit(_:_:). Do not call directly. private func visitImplSwitchCaseLabelSyntax(_ data: SyntaxData) { let node = SwitchCaseLabelSyntax(data) @@ -6671,6 +6694,8 @@ open class SyntaxVisitor { visitImplSubscriptExprSyntax(data) case .superRefExpr: visitImplSuperRefExprSyntax(data) + case .suppressedType: + visitImplSuppressedTypeSyntax(data) case .switchCaseLabel: visitImplSwitchCaseLabelSyntax(data) case .switchCaseList: diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodes.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodes.swift index a21a469aebf..ac0210ca88c 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodes.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodes.swift @@ -19028,6 +19028,76 @@ public struct RawSuperRefExprSyntax: RawExprSyntaxNodeProtocol { } } +@_spi(RawSyntax) +public struct RawSuppressedTypeSyntax: RawTypeSyntaxNodeProtocol { + @_spi(RawSyntax) + public var layoutView: RawSyntaxLayoutView { + return raw.layoutView! + } + + public static func isKindOf(_ raw: RawSyntax) -> Bool { + return raw.kind == .suppressedType + } + + 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: Node) { + guard Self.isKindOf(other.raw) else { + return nil + } + self.init(unchecked: other.raw) + } + + public init( + _ unexpectedBeforeWithoutTilde: RawUnexpectedNodesSyntax? = nil, + withoutTilde: RawTokenSyntax, + _ unexpectedBetweenWithoutTildeAndPatternType: RawUnexpectedNodesSyntax? = nil, + patternType: RawTypeSyntax, + _ unexpectedAfterPatternType: RawUnexpectedNodesSyntax? = nil, + arena: __shared SyntaxArena + ) { + let raw = RawSyntax.makeLayout( + kind: .suppressedType, uninitializedCount: 5, arena: arena) { layout in + layout.initialize(repeating: nil) + layout[0] = unexpectedBeforeWithoutTilde?.raw + layout[1] = withoutTilde.raw + layout[2] = unexpectedBetweenWithoutTildeAndPatternType?.raw + layout[3] = patternType.raw + layout[4] = unexpectedAfterPatternType?.raw + } + self.init(unchecked: raw) + } + + public var unexpectedBeforeWithoutTilde: RawUnexpectedNodesSyntax? { + layoutView.children[0].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var withoutTilde: RawTokenSyntax { + layoutView.children[1].map(RawTokenSyntax.init(raw:))! + } + + public var unexpectedBetweenWithoutTildeAndPatternType: RawUnexpectedNodesSyntax? { + layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var patternType: RawTypeSyntax { + layoutView.children[3].map(RawTypeSyntax.init(raw:))! + } + + public var unexpectedAfterPatternType: RawUnexpectedNodesSyntax? { + layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) + } +} + @_spi(RawSyntax) public struct RawSwitchCaseLabelSyntax: RawSyntaxNodeProtocol { @_spi(RawSyntax) @@ -20905,7 +20975,7 @@ public struct RawTypeSyntax: RawTypeSyntaxNodeProtocol { public static func isKindOf(_ raw: RawSyntax) -> Bool { switch raw.kind { - case .arrayType, .attributedType, .classRestrictionType, .compositionType, .constrainedSugarType, .dictionaryType, .functionType, .implicitlyUnwrappedOptionalType, .memberTypeIdentifier, .metatypeType, .missingType, .namedOpaqueReturnType, .optionalType, .packExpansionType, .packReferenceType, .simpleTypeIdentifier, .tupleType: + case .arrayType, .attributedType, .classRestrictionType, .compositionType, .constrainedSugarType, .dictionaryType, .functionType, .implicitlyUnwrappedOptionalType, .memberTypeIdentifier, .metatypeType, .missingType, .namedOpaqueReturnType, .optionalType, .packExpansionType, .packReferenceType, .simpleTypeIdentifier, .suppressedType, .tupleType: return true default: return false diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index e1b5716c132..8475d49a92a 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -2309,6 +2309,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: [.keyword("super")])) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + case .suppressedType: + assert(layout.count == 5) + assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.prefixOperator)])) + assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 3, verify(layout[3], as: RawTypeSyntax.self)) + assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) case .switchCaseLabel: assert(layout.count == 7) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxTypeNodes.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxTypeNodes.swift index b3c42bda968..681a100811f 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxTypeNodes.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxTypeNodes.swift @@ -2098,6 +2098,122 @@ public struct SimpleTypeIdentifierSyntax: TypeSyntaxProtocol, SyntaxHashable { } } +// MARK: - SuppressedTypeSyntax + + +public struct SuppressedTypeSyntax: TypeSyntaxProtocol, SyntaxHashable { + public let _syntaxNode: Syntax + + public init?(_ node: S) { + guard node.raw.kind == .suppressedType else { + return nil + } + self._syntaxNode = node._syntaxNode + } + + /// Creates a `SuppressedTypeSyntax` node from the given `SyntaxData`. This assumes + /// that the `SyntaxData` is of the correct kind. If it is not, the behaviour + /// is undefined. + internal init(_ data: SyntaxData) { + precondition(data.raw.kind == .suppressedType) + self._syntaxNode = Syntax(data) + } + + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforeWithoutTilde: UnexpectedNodesSyntax? = nil, + withoutTilde: TokenSyntax, + _ unexpectedBetweenWithoutTildeAndPatternType: UnexpectedNodesSyntax? = nil, + patternType: P, + _ unexpectedAfterPatternType: 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. + let data: SyntaxData = withExtendedLifetime((SyntaxArena(), ( + unexpectedBeforeWithoutTilde, + withoutTilde, + unexpectedBetweenWithoutTildeAndPatternType, + patternType, + unexpectedAfterPatternType + ))) {(arena, _) in + let layout: [RawSyntax?] = [ + unexpectedBeforeWithoutTilde?.raw, + withoutTilde.raw, + unexpectedBetweenWithoutTildeAndPatternType?.raw, + patternType.raw, + unexpectedAfterPatternType?.raw + ] + let raw = RawSyntax.makeLayout( + kind: SyntaxKind.suppressedType, + from: layout, + arena: arena, + leadingTrivia: leadingTrivia, + trailingTrivia: trailingTrivia + + ) + return SyntaxData.forRoot(raw) + } + self.init(data) + } + + public var unexpectedBeforeWithoutTilde: UnexpectedNodesSyntax? { + get { + return data.child(at: 0, parent: Syntax(self)).map(UnexpectedNodesSyntax.init) + } + set(value) { + self = SuppressedTypeSyntax(data.replacingChild(at: 0, with: value?.raw, arena: SyntaxArena())) + } + } + + public var withoutTilde: TokenSyntax { + get { + return TokenSyntax(data.child(at: 1, parent: Syntax(self))!) + } + set(value) { + self = SuppressedTypeSyntax(data.replacingChild(at: 1, with: value.raw, arena: SyntaxArena())) + } + } + + public var unexpectedBetweenWithoutTildeAndPatternType: UnexpectedNodesSyntax? { + get { + return data.child(at: 2, parent: Syntax(self)).map(UnexpectedNodesSyntax.init) + } + set(value) { + self = SuppressedTypeSyntax(data.replacingChild(at: 2, with: value?.raw, arena: SyntaxArena())) + } + } + + public var patternType: TypeSyntax { + get { + return TypeSyntax(data.child(at: 3, parent: Syntax(self))!) + } + set(value) { + self = SuppressedTypeSyntax(data.replacingChild(at: 3, with: value.raw, arena: SyntaxArena())) + } + } + + public var unexpectedAfterPatternType: UnexpectedNodesSyntax? { + get { + return data.child(at: 4, parent: Syntax(self)).map(UnexpectedNodesSyntax.init) + } + set(value) { + self = SuppressedTypeSyntax(data.replacingChild(at: 4, with: value?.raw, arena: SyntaxArena())) + } + } + + public static var structure: SyntaxNodeStructure { + return .layout([ + \Self.unexpectedBeforeWithoutTilde, + \Self.withoutTilde, + \Self.unexpectedBetweenWithoutTildeAndPatternType, + \Self.patternType, + \Self.unexpectedAfterPatternType + ]) + } +} + // MARK: - TupleTypeSyntax diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index 8780eb3cc01..754381e4fdf 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -1561,6 +1561,82 @@ final class DeclarationTests: XCTestCase { ] ) } + + func testSuppressedImplicitConformance() { + assertParse( + """ + struct Hello: ~Copyable {} + """, + substructure: Syntax( + InheritedTypeSyntax( + typeName: SuppressedTypeSyntax( + withoutTilde: .prefixOperator("~"), + patternType: TypeSyntax(stringLiteral: "Copyable") + ) + ) + ) + ) + + assertParse( + """ + enum Whatever: Int, ~ Hashable, Equatable {} + """, + substructure: + Syntax( + TypeInheritanceClauseSyntax( + colon: .colonToken(), + inheritedTypeCollection: InheritedTypeListSyntax([ + InheritedTypeSyntax( + typeName: TypeSyntax(stringLiteral: "Int"), + trailingComma: .commaToken() + ), + InheritedTypeSyntax( + typeName: SuppressedTypeSyntax( + withoutTilde: .prefixOperator("~"), + patternType: TypeSyntax(stringLiteral: "Hashable") + ), + trailingComma: .commaToken() + ), + InheritedTypeSyntax(typeName: TypeSyntax(stringLiteral: "Equatable")), + ]) + ) + ) + ) + + assertParse( + """ + typealias T = ~1️⃣Int 2️⃣-> Bool + """, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected '(' to start function type", + fixIts: ["insert '('"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ')' in function type", + fixIts: ["insert ')'"] + ), + ], + fixedSource: """ + typealias T = ~(Int) -> Bool + """ + ) + + assertParse( + """ + typealias T = ~(Int) -> Bool + """, + substructure: + Syntax( + SuppressedTypeSyntax( + withoutTilde: .prefixOperator("~"), + patternType: FunctionTypeSyntax(arguments: [TupleTypeElementSyntax(type: TypeSyntax("Int"))], output: ReturnClauseSyntax(returnType: TypeSyntax("Bool"))) + ) + ) + ) + } } extension Parser.DeclAttributes { diff --git a/Tests/SwiftSyntaxTest/SyntaxVisitorTests.swift b/Tests/SwiftSyntaxTest/SyntaxVisitorTests.swift index b408b1aa073..9dff638264c 100644 --- a/Tests/SwiftSyntaxTest/SyntaxVisitorTests.swift +++ b/Tests/SwiftSyntaxTest/SyntaxVisitorTests.swift @@ -29,6 +29,27 @@ public class SyntaxVisitorTests: XCTestCase { /// /// The source file is hard-coded so this test case doesn't need to depend on the parser. static var nestedFunctionsFile: SourceFileSyntax { + let innerBody = CodeBlockSyntax( + leftBrace: .leftBraceToken(), + statements: CodeBlockItemListSyntax([ + CodeBlockItemSyntax( + item: CodeBlockItemSyntax.Item( + IntegerLiteralExprSyntax( + digits: .integerLiteral( + "0xG", + leadingTrivia: [ + .newlines(1), + .spaces(6), + .blockComment("/*Unknown token */"), + ] + ) + ) + ) + ) + ]), + rightBrace: .rightBraceToken(leadingTrivia: [.newlines(1), .spaces(4)]) + ) + let source = SourceFileSyntax( statements: CodeBlockItemListSyntax([ CodeBlockItemSyntax( @@ -76,26 +97,7 @@ public class SyntaxVisitorTests: XCTestCase { rightParen: .rightParenToken(trailingTrivia: .space) ) ), - body: CodeBlockSyntax( - leftBrace: .leftBraceToken(), - statements: CodeBlockItemListSyntax([ - CodeBlockItemSyntax( - item: CodeBlockItemSyntax.Item( - IntegerLiteralExprSyntax( - digits: .integerLiteral( - "0xG", - leadingTrivia: [ - .newlines(1), - .spaces(6), - .blockComment("/*Unknown token */"), - ] - ) - ) - ) - ) - ]), - rightBrace: .rightBraceToken(leadingTrivia: [.newlines(1), .spaces(4)]) - ) + body: innerBody ) ) )