diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 96e24e703e1..2d063195ca8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,7 +8,7 @@ # Order is important. The last matching pattern has the most precedence. # Owner of anything in SwiftSyntax not owned by anyone else. -* @ahoppen @bnbarham +* @ahoppen @bnbarham @hamishknight @rintaro # Macros /Sources/SwiftSyntaxMacros @DougGregor diff --git a/.github/workflows/publish_release.yml b/.github/workflows/publish_release.yml index 44f68cce276..715bdcbcc8b 100644 --- a/.github/workflows/publish_release.yml +++ b/.github/workflows/publish_release.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - run: | - if [[ "${{ github.triggering_actor }}" != "ahoppen" ]]; then + if [[ "${{ github.triggering_actor }}" != "bnbarham" ]]; then echo "${{ github.triggering_actor }} is not allowed to create a release" exit 1 fi diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index fd8e6f14272..62868ba50eb 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -1,5 +1,7 @@ name: Pull request +# PRs created by GitHub Actions don't kick off further actions (https://github.com/peter-evans/create-pull-request/blob/d57e551ebc1a16dee0b8c9ea6d24dba7627a6e35/docs/concepts-guidelines.md#triggering-further-workflow-runs). +# As a workaround, we mark automerge PRs that are created by GitHub actions as draft and trigger the GitHub actions by marking the PR as ready for review. We'd prefer not re-triggering testing on a normal user's PR in this case, but skipping them causes the checks to reset. on: pull_request: types: [opened, reopened, synchronize, ready_for_review] @@ -11,20 +13,15 @@ concurrency: jobs: tests: name: Test - # PRs created by GitHub Actions don't kick off further actions (https://github.com/peter-evans/create-pull-request/blob/d57e551ebc1a16dee0b8c9ea6d24dba7627a6e35/docs/concepts-guidelines.md#triggering-further-workflow-runs). - # As a workaround, we mark automerge PRs that are created by GitHub actions as draft and trigger the GitHub actions by marking the PR as ready for review. But we don't want to re-trigger testing this when a normal user's PR is marked as ready for review. - if: (github.event.action != 'ready_for_review') || (github.event.action == 'ready_for_review' && github.event.pull_request.user.login == 'github-actions[bot]') uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main soundness: name: Soundness - if: (github.event.action != 'ready_for_review') || (github.event.action == 'ready_for_review' && github.event.pull_request.user.login == 'github-actions[bot]') uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main with: api_breakage_check_enabled: false # https://github.com/swiftlang/swift-syntax/issues/3010 docs_check_additional_arguments: "--disable-parameters-and-returns-validation" verify_source_code: name: Validate generated code - if: (github.event.action != 'ready_for_review') || (github.event.action == 'ready_for_review' && github.event.pull_request.user.login == 'github-actions[bot]') runs-on: ubuntu-latest container: image: swift:latest @@ -37,7 +34,6 @@ jobs: run: "./swift-syntax-dev-utils verify-source-code --toolchain /usr" test_using_swift_syntax_dev_utils_linux: name: Run tests using swift-syntax-dev-utils (Linux) - if: (github.event.action != 'ready_for_review') || (github.event.action == 'ready_for_review' && github.event.pull_request.user.login == 'github-actions[bot]') runs-on: ubuntu-latest container: image: swift:latest @@ -50,7 +46,6 @@ jobs: run: "./swift-syntax-dev-utils test --enable-rawsyntax-validation --enable-test-fuzzing --toolchain /usr" test_using_swift_syntax_dev_utils_windows: name: Run tests using swift-syntax-dev-utils (Windows) - if: (github.event.action != 'ready_for_review') || (github.event.action == 'ready_for_review' && github.event.pull_request.user.login == 'github-actions[bot]') runs-on: windows-2022 steps: - name: Pull Docker image diff --git a/.swift-format b/.swift-format index 41a022f2627..176687e2845 100644 --- a/.swift-format +++ b/.swift-format @@ -13,6 +13,8 @@ "NoBlockComments": false, "OrderedImports": true, "UseLetInEveryBoundCaseVariable": false, - "UseSynthesizedInitializer": false + "UseSynthesizedInitializer": false, + "ReturnVoidInsteadOfEmptyTuple": true, + "NoVoidReturnOnFunctionSignature": true, } } diff --git a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift index 26041a0cf89..d960ec5db26 100644 --- a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift @@ -74,6 +74,11 @@ public let ATTRIBUTE_NODES: [Node] = [ // Special arguments for keyword decl name e.g. 'subscript(_:)', and availability arguments. kind: .node(kind: .specializeAttributeArgumentList) ), + Child( + name: "specializedArguments", + // Special arguments for generic where clause. + kind: .node(kind: .specializedAttributeArgument) + ), Child( name: "objCName", // Special arguments for Objective-C names. e.g. 'methodNameWithArg1:Arg2:' @@ -122,8 +127,7 @@ public let ATTRIBUTE_NODES: [Node] = [ Child( name: "abiArguments", // Special arguments for declaration syntax. e.g. @abi(func abiName() -> Int) - kind: .node(kind: .abiAttributeArguments), - experimentalFeature: .abiAttribute + kind: .node(kind: .abiAttributeArguments) ), ]), documentation: """ @@ -256,7 +260,6 @@ public let ATTRIBUTE_NODES: [Node] = [ Node( kind: .abiAttributeArguments, base: .syntax, - experimentalFeature: .abiAttribute, nameForDiagnostics: "ABI-providing declaration", documentation: "The arguments of the '@abi' attribute", children: [ @@ -719,6 +722,19 @@ public let ATTRIBUTE_NODES: [Node] = [ ] ), + Node( + kind: .specializedAttributeArgument, + base: .syntax, + nameForDiagnostics: "argument to '@specialized", + documentation: "The generic where clause for the `@specialized` attribute", + children: [ + Child( + name: "genericWhereClause", + kind: .node(kind: .genericWhereClause) + ) + ] + ), + Node( kind: .specializeTargetFunctionArgument, base: .syntax, diff --git a/CodeGeneration/Sources/SyntaxSupport/Child.swift b/CodeGeneration/Sources/SyntaxSupport/Child.swift index 683c0441953..ce631b5950e 100644 --- a/CodeGeneration/Sources/SyntaxSupport/Child.swift +++ b/CodeGeneration/Sources/SyntaxSupport/Child.swift @@ -47,7 +47,8 @@ public enum ChildKind { kind: SyntaxNodeKind, collectionElementName: String? = nil, defaultsToEmpty: Bool = false, - deprecatedCollectionElementName: String? = nil + deprecatedCollectionElementName: String? = nil, + generateDeprecatedAddFunction: Bool = true ) /// The child is a token that matches one of the given `choices`. /// If `requiresLeadingSpace` or `requiresTrailingSpace` is not `nil`, it @@ -132,7 +133,7 @@ public class Child: NodeChoiceConvertible { return kind case .nodeChoices: return .syntax - case .collection(kind: let kind, _, _, _): + case .collection(kind: let kind, _, _, _, _): return kind case .token: return .token @@ -268,7 +269,7 @@ public class Child: NodeChoiceConvertible { /// Whether this child has syntax kind `UnexpectedNodes`. public var isUnexpectedNodes: Bool { switch kind { - case .collection(kind: .unexpectedNodes, _, _, _): + case .collection(kind: .unexpectedNodes, _, _, _, _): return true default: return false @@ -283,7 +284,7 @@ public class Child: NodeChoiceConvertible { return choices.isEmpty case .node(let kind): return kind.isBase - case .collection(kind: let kind, _, _, _): + case .collection(kind: let kind, _, _, _, _): return kind.isBase case .token: return false diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index 0dea2d63426..25ecbf84785 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -1307,6 +1307,37 @@ public let DECL_NODES: [Node] = [ ] ), + Node( + kind: .usingDecl, + base: .decl, + experimentalFeature: .defaultIsolationPerFile, + nameForDiagnostics: "using", + documentation: """ + A `using` declaration, currently used to control actor isolation within the current file. + + An example of a `using` declaration is + + ```swift + using @MainActor + ``` + """, + children: [ + Child( + name: "usingKeyword", + kind: .token(choices: [.keyword(.using)]), + documentation: "The `using` keyword for this declaration." + ), + Child( + name: "specifier", + kind: .nodeChoices(choices: [ + Child(name: "attribute", kind: .node(kind: .attribute)), + Child(name: "modifier", kind: .token(choices: [.token(.identifier)])), + ]), + documentation: "The specifier that could be either an attribute or a modifier." + ), + ] + ), + Node( kind: .inheritedTypeList, base: .syntaxCollection, diff --git a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift index bdc09c1f462..70cd36c9a7d 100644 --- a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift +++ b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift @@ -19,10 +19,10 @@ public enum ExperimentalFeature: String, CaseIterable { case nonescapableTypes case trailingComma case coroutineAccessors - case abiAttribute case keypathWithMethodMembers case oldOwnershipOperatorSpellings case inlineArrayTypeSugar + case defaultIsolationPerFile /// The name of the feature as it is written in the compiler's `Features.def` file. public var featureName: String { @@ -39,14 +39,14 @@ public enum ExperimentalFeature: String, CaseIterable { return "TrailingComma" case .coroutineAccessors: return "CoroutineAccessors" - case .abiAttribute: - return "ABIAttribute" case .keypathWithMethodMembers: return "KeypathWithMethodMembers" case .oldOwnershipOperatorSpellings: return "OldOwnershipOperatorSpellings" case .inlineArrayTypeSugar: return "InlineArrayTypeSugar" + case .defaultIsolationPerFile: + return "DefaultIsolationPerFile" } } @@ -65,14 +65,14 @@ public enum ExperimentalFeature: String, CaseIterable { return "trailing commas" case .coroutineAccessors: return "coroutine accessors" - case .abiAttribute: - return "@abi attribute" case .keypathWithMethodMembers: return "keypaths with method members" case .oldOwnershipOperatorSpellings: return "`_move` and `_borrow` as ownership operators" case .inlineArrayTypeSugar: return "sugar type for InlineArray" + case .defaultIsolationPerFile: + return "set default actor isolation for a file" } } diff --git a/CodeGeneration/Sources/SyntaxSupport/GrammarGenerator.swift b/CodeGeneration/Sources/SyntaxSupport/GrammarGenerator.swift index ae84735dbf9..4d28dff2564 100644 --- a/CodeGeneration/Sources/SyntaxSupport/GrammarGenerator.swift +++ b/CodeGeneration/Sources/SyntaxSupport/GrammarGenerator.swift @@ -41,7 +41,7 @@ struct GrammarGenerator { case .nodeChoices(let choices, _): let choicesDescriptions = choices.map { grammar(for: $0) } return "(\(choicesDescriptions.joined(separator: " | ")))\(optionality)" - case .collection(kind: let kind, _, _, _): + case .collection(kind: let kind, _, _, _, _): return "\(kind.doccLink)\(optionality)" case .token(let choices, _, _): if choices.count == 1 { diff --git a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift index 7c4b72eeafb..e4a66399721 100644 --- a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift @@ -104,6 +104,7 @@ public enum Keyword: CaseIterable { case _PackageDescription case _read case _RefCountedObject + case specialized case _specialize case _spi_available case _Trivial @@ -268,6 +269,7 @@ public enum Keyword: CaseIterable { case unsafe case unsafeAddress case unsafeMutableAddress + case using case `var` case visibility case weak @@ -275,7 +277,6 @@ public enum Keyword: CaseIterable { case `while` case willSet case wrt - case x case yield public var spec: KeywordSpec { @@ -340,6 +341,8 @@ public enum Keyword: CaseIterable { return KeywordSpec("_read") case ._RefCountedObject: return KeywordSpec("_RefCountedObject") + case .specialized: + return KeywordSpec("specialized") case ._specialize: return KeywordSpec("_specialize") case ._spi_available: @@ -357,7 +360,7 @@ public enum Keyword: CaseIterable { case ._version: return KeywordSpec("_version") case .abi: - return KeywordSpec("abi", experimentalFeature: .abiAttribute) + return KeywordSpec("abi") case .accesses: return KeywordSpec("accesses") case .actor: @@ -668,6 +671,8 @@ public enum Keyword: CaseIterable { return KeywordSpec("unsafeAddress") case .unsafeMutableAddress: return KeywordSpec("unsafeMutableAddress") + case .using: + return KeywordSpec("using") case .var: return KeywordSpec("var", isLexerClassified: true) case .visibility: @@ -682,8 +687,6 @@ public enum Keyword: CaseIterable { return KeywordSpec("willSet") case .wrt: return KeywordSpec("wrt") - case .x: - return KeywordSpec("x", experimentalFeature: .inlineArrayTypeSugar) case .yield: return KeywordSpec("yield") } diff --git a/CodeGeneration/Sources/SyntaxSupport/Node.swift b/CodeGeneration/Sources/SyntaxSupport/Node.swift index 913473c1c85..f1341f7e355 100644 --- a/CodeGeneration/Sources/SyntaxSupport/Node.swift +++ b/CodeGeneration/Sources/SyntaxSupport/Node.swift @@ -391,7 +391,7 @@ fileprivate extension Child { return [kind] case .nodeChoices(let choices, _): return choices.flatMap(\.kinds) - case .collection(kind: let kind, _, _, _): + case .collection(kind: let kind, _, _, _, _): return [kind] case .token: return [.token] diff --git a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift index 6e50fe39500..011058348cd 100644 --- a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift +++ b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift @@ -259,6 +259,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon case simpleStringLiteralSegmentList case someOrAnyType case sourceFile + case specializedAttributeArgument case specializeAttributeArgumentList case specializeAvailabilityArgument case specializeTargetFunctionArgument @@ -304,6 +305,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon case unresolvedIsExpr case unresolvedTernaryExpr case unsafeExpr + case usingDecl case valueBindingPattern case variableDecl case versionComponent @@ -454,6 +456,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon case .someOrAnyType: return "constrainedSugarType" case .simpleTypeSpecifier: return "typeSpecifier" case .specializeAttributeArgumentList: return "specializeAttributeSpecList" + case .specializedAttributeArgument: return "specializedAttribute" case .specializeAvailabilityArgument: return "availabilityEntry" case .specializeTargetFunctionArgument: return "targetFunctionEntry" case .stringLiteralSegmentList: return "stringLiteralSegments" diff --git a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift index 3d65755fa45..12dd1d385cc 100644 --- a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift @@ -57,6 +57,17 @@ public let TYPE_NODES: [Node] = [ kind: .collection(kind: .attributeList, collectionElementName: "Attribute", defaultsToEmpty: true), documentation: "A list of attributes that can be attached to the type, such as `@escaping`." ), + Child( + name: "lateSpecifiers", + kind: .collection( + kind: .typeSpecifierList, + collectionElementName: "Specifier", + defaultsToEmpty: true, + generateDeprecatedAddFunction: false + ), + documentation: + "A list of specifiers that can be attached to the type after the attributes, such as 'nonisolated'." + ), Child( name: "baseType", kind: .node(kind: .type), @@ -304,7 +315,7 @@ public let TYPE_NODES: [Node] = [ base: .type, experimentalFeature: .inlineArrayTypeSugar, nameForDiagnostics: "inline array type", - documentation: "An inline array type `[3 x Int]`, sugar for `InlineArray<3, Int>`.", + documentation: "An inline array type `[3 of Int]`, sugar for `InlineArray<3, Int>`.", children: [ Child( name: "leftSquare", @@ -317,12 +328,12 @@ public let TYPE_NODES: [Node] = [ documentation: """ The `count` argument for the inline array type. - - Note: In semantically valid Swift code, this is always an integer or a wildcard type, e.g `_` in `[_ x Int]`. + - Note: In semantically valid Swift code, this is always an integer or a wildcard type, e.g `_` in `[_ of Int]`. """ ), Child( name: "separator", - kind: .token(choices: [.keyword(.x)]) + kind: .token(choices: [.keyword(.of)]) ), Child( name: "element", diff --git a/CodeGeneration/Sources/Utils/SyntaxBuildableChild.swift b/CodeGeneration/Sources/Utils/SyntaxBuildableChild.swift index 9ad78761e04..6e4fb79941a 100644 --- a/CodeGeneration/Sources/Utils/SyntaxBuildableChild.swift +++ b/CodeGeneration/Sources/Utils/SyntaxBuildableChild.swift @@ -33,7 +33,7 @@ extension Child { buildableKind = .node(kind: kind) case .nodeChoices: buildableKind = .node(kind: .syntax) - case .collection(kind: let kind, _, _, _): + case .collection(kind: let kind, _, _, _, _): buildableKind = .node(kind: kind) case .token: buildableKind = .token(self.tokenKind!) @@ -65,7 +65,7 @@ extension Child { return ExprSyntax("nil") } } - if case .collection(_, _, defaultsToEmpty: true, _) = kind { + if case .collection(_, _, defaultsToEmpty: true, _, _) = kind { return ExprSyntax("[]") } guard let token = token, isToken else { diff --git a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/RenamedChildrenCompatibilityFile.swift b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/RenamedChildrenCompatibilityFile.swift index aea1375e54c..77f4548117b 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/RenamedChildrenCompatibilityFile.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/RenamedChildrenCompatibilityFile.swift @@ -85,7 +85,8 @@ func makeCompatibilityAddMethod(for child: Child) -> DeclSyntax? { kind: _, collectionElementName: let collectionElementName?, defaultsToEmpty: _, - deprecatedCollectionElementName: let deprecatedCollectionElementName? + deprecatedCollectionElementName: let deprecatedCollectionElementName?, + generateDeprecatedAddFunction: _ ) = child.kind { let childEltType = childNode.collectionElementType.syntaxBaseName diff --git a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxNodesFile.swift b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxNodesFile.swift index 6c5bd8bad67..cb3a5f184eb 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxNodesFile.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxNodesFile.swift @@ -176,7 +176,8 @@ func syntaxNode(nodesStartingWith: [Character]) -> SourceFileSyntax { // If needed, this could be added in the future, but for now withUnexpected should be sufficient. if let childNode = SYNTAX_NODE_MAP[child.syntaxNodeKind]?.collectionNode, !child.isUnexpectedNodes, - case .collection(_, collectionElementName: let childElt?, _, _) = child.kind + case .collection(_, collectionElementName: let childElt?, _, _, generateDeprecatedAddFunction: true) = + child.kind { let childEltType = childNode.collectionElementType.syntaxBaseName diff --git a/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift b/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift index d2eceb9334f..e1b9a73df15 100644 --- a/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift +++ b/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift @@ -55,13 +55,13 @@ fileprivate extension ChildKind { return kind == otherKind case (.nodeChoices(let choices, _), .nodeChoices(let otherChoices, _)): return choices.count == otherChoices.count && zip(choices, otherChoices).allSatisfy { $0.hasSameType(as: $1) } - case (.collection(kind: let kind, _, _, _), .collection(kind: let otherKind, _, _, _)): + case (.collection(kind: let kind, _, _, _, _), .collection(kind: let otherKind, _, _, _, _)): return kind == otherKind case (.token(let choices, _, _), .token(let otherChoices, _, _)): return choices == otherChoices - case (.node(let kind), .collection(kind: let otherKind, _, _, _)): + case (.node(let kind), .collection(kind: let otherKind, _, _, _, _)): return kind == otherKind - case (.collection(kind: let kind, _, _, _), .node(let otherKind)): + case (.collection(kind: let kind, _, _, _, _), .node(let otherKind)): return kind == otherKind default: return false @@ -372,10 +372,11 @@ class ValidateSyntaxNodes: XCTestCase { message: "child 'defaultKeyword' has a single keyword as its only token choice and is followed by a colon. It should thus be named 'defaultLabel'" ), - // 'separator' is more descriptive than 'xKeyword' + // 'separator' is more descriptive than 'ofKeyword' ValidationFailure( node: .inlineArrayType, - message: "child 'separator' has a single keyword as its only token choice and should thus be named 'xKeyword'" + message: + "child 'separator' has a single keyword as its only token choice and should thus be named 'ofKeyword'" ), ] ) diff --git a/Examples/Sources/MacroExamples/Implementation/Peer/AddAsyncMacro.swift b/Examples/Sources/MacroExamples/Implementation/Peer/AddAsyncMacro.swift index 923f002c6c4..1ebe01a8a07 100644 --- a/Examples/Sources/MacroExamples/Implementation/Peer/AddAsyncMacro.swift +++ b/Examples/Sources/MacroExamples/Implementation/Peer/AddAsyncMacro.swift @@ -42,7 +42,9 @@ public struct AddAsyncMacro: PeerMacro { } // This only makes sense void functions - if funcDecl.signature.returnClause?.type.as(IdentifierTypeSyntax.self)?.name.text != "Void" { + if let returnClause = funcDecl.signature.returnClause, + returnClause.type.as(IdentifierTypeSyntax.self)?.name.text != "Void" + { throw CustomError.message( "@addAsync requires an function that returns void" ) diff --git a/Examples/Sources/MacroExamples/Playground/PeerMacrosPlayground.swift b/Examples/Sources/MacroExamples/Playground/PeerMacrosPlayground.swift index bc5ba242ca1..f4bfaf335fc 100644 --- a/Examples/Sources/MacroExamples/Playground/PeerMacrosPlayground.swift +++ b/Examples/Sources/MacroExamples/Playground/PeerMacrosPlayground.swift @@ -17,12 +17,12 @@ func runPeerMacrosPlayground() { struct MyStruct { @AddAsync - func c(a: Int, for b: String, _ value: Double, completionBlock: @escaping (Result) -> Void) -> Void { + func c(a: Int, for b: String, _ value: Double, completionBlock: @escaping (Result) -> Void) { completionBlock(.success("a: \(a), b: \(b), value: \(value)")) } @AddAsync - func d(a: Int, for b: String, _ value: Double, completionBlock: @escaping (Bool) -> Void) -> Void { + func d(a: Int, for b: String, _ value: Double, completionBlock: @escaping (Bool) -> Void) { completionBlock(true) } } diff --git a/Examples/Tests/MacroExamples/Implementation/Peer/AddAsyncMacroTests.swift b/Examples/Tests/MacroExamples/Implementation/Peer/AddAsyncMacroTests.swift index 79178633770..f936f425dd0 100644 --- a/Examples/Tests/MacroExamples/Implementation/Peer/AddAsyncMacroTests.swift +++ b/Examples/Tests/MacroExamples/Implementation/Peer/AddAsyncMacroTests.swift @@ -79,6 +79,32 @@ final class AddAsyncMacroTests: XCTestCase { ) } + func testImplicitVoidResult() { + assertMacroExpansion( + """ + @AddAsync + func d(a: Int, completionBlock: @escaping (Bool) -> Void) { + } + """, + expandedSource: """ + func d(a: Int, completionBlock: @escaping (Bool) -> Void) { + } + + func d(a: Int) async -> Bool { + await withCheckedContinuation { continuation in + d(a: a) { returnValue in + + continuation.resume(returning: returnValue) + } + } + + } + """, + macros: macros, + indentationWidth: .spaces(2) + ) + } + func testExpansionOnStoredPropertyEmitsError() { assertMacroExpansion( """ @@ -105,18 +131,18 @@ final class AddAsyncMacroTests: XCTestCase { ) } - func testExpansionOnAsyncFunctionEmitsError() { + func testNonVoidResult() { assertMacroExpansion( """ struct Test { @AddAsync - async func sayHello() { + func sayHello() -> Int { } } """, expandedSource: """ struct Test { - async func sayHello() { + func sayHello() -> Int { } } """, @@ -132,4 +158,50 @@ final class AddAsyncMacroTests: XCTestCase { indentationWidth: .spaces(2) ) } + + func testAlreadyAsync() { + assertMacroExpansion( + """ + @AddAsync + func d(a: Int, completionBlock: @escaping (Bool) -> Void) async { + } + """, + expandedSource: """ + func d(a: Int, completionBlock: @escaping (Bool) -> Void) async { + } + """, + diagnostics: [ + DiagnosticSpec( + message: "@addAsync requires an non async function", + line: 1, + column: 1, + severity: .error + ) + ], + macros: macros, + indentationWidth: .spaces(2) + ) + } + + func testNoCompletionHandler() { + assertMacroExpansion( + """ + @AddAsync + func sayHello(x: Int) {} + """, + expandedSource: """ + func sayHello(x: Int) {} + """, + diagnostics: [ + DiagnosticSpec( + message: "@addAsync requires an function that has a completion handler as last parameter", + line: 1, + column: 1, + severity: .error + ) + ], + macros: macros, + indentationWidth: .spaces(2) + ) + } } diff --git a/Release Notes/602.md b/Release Notes/602.md index 0d5750bdd2e..7ef16677d8f 100644 --- a/Release Notes/602.md +++ b/Release Notes/602.md @@ -54,7 +54,13 @@ - Pull Request: https://github.com/swiftlang/swift-syntax/pull/3028 - Migration steps: Use `AttributeSyntax.Arguments.argumentList(LabeledExprListSyntax)` instead. - Notes: Removed cases from `AttributeSyntax.Arguments`: `token(TokenSyntax)`, `string(StringLiteralExprSyntax)`, `conventionArguments(ConventionAttributeArgumentsSyntax)`, `conventionWitnessMethodArguments(ConventionWitnessMethodAttributeArgumentsSyntax)`, `opaqueReturnTypeOfAttributeArguments(OpaqueReturnTypeOfAttributeArgumentsSyntax)`, `exposeAttributeArguments(ExposeAttributeArgumentsSyntax)`, `underscorePrivateAttributeArguments(UnderscorePrivateAttributeArgumentsSyntax)`, and `unavailableFromAsyncArguments(UnavailableFromAsyncAttributeArgumentsSyntax)`. Removed Syntax kinds: `ConventionAttributeArgumentsSyntax`, `ConventionWitnessMethodAttributeArgumentsSyntax`, `OpaqueReturnTypeOfAttributeArgumentsSyntax`, `ExposeAttributeArgumentsSyntax`, `UnderscorePrivateAttributeArgumentsSyntax`, and `UnavailableFromAsyncAttributeArgumentsSyntax`. -, + +- `ExpandEditorPlaceholdersToLiteralClosures` & `CallToTrailingClosures` now take a `Syntax` parameter + - Description: These refactorings now take an arbitrary `Syntax` and return a `Syntax?`. If a non-function-like syntax node is passed, `nil` is returned. The previous `FunctionCallExprSyntax` overloads are deprecated. + - Pull Request: https://github.com/swiftlang/swift-syntax/pull/3092 + - Migration steps: Insert a `Syntax(...)` initializer call for the argument, and cast the result with `.as(...)` if necessary. + - Notes: This allows the refactorings to correctly handle macro expansion expressions and declarations. + ## Template - *Affected API or two word description* diff --git a/Sources/SwiftIDEUtils/FixItApplier.swift b/Sources/SwiftIDEUtils/FixItApplier.swift index de5785ff941..6253710930d 100644 --- a/Sources/SwiftIDEUtils/FixItApplier.swift +++ b/Sources/SwiftIDEUtils/FixItApplier.swift @@ -27,12 +27,15 @@ public enum FixItApplier { /// - filterByMessages: An optional array of message strings to filter which Fix-Its to apply. /// If `nil`, the first Fix-It from each diagnostic is applied. /// - tree: The syntax tree to which the Fix-Its will be applied. + /// - allowDuplicateInsertions: Whether to apply duplicate insertions. + /// Defaults to `true`. /// /// - Returns: A `String` representation of the modified syntax tree after applying the Fix-Its. public static func applyFixes( from diagnostics: [Diagnostic], filterByMessages messages: [String]?, - to tree: any SyntaxProtocol + to tree: some SyntaxProtocol, + allowDuplicateInsertions: Bool = true ) -> String { let messages = messages ?? diagnostics.compactMap { $0.fixIts.first?.message.message } @@ -43,51 +46,89 @@ public enum FixItApplier { .filter { messages.contains($0.message.message) } .flatMap(\.edits) - return self.apply(edits: edits, to: tree) + return self.apply(edits: edits, to: tree, allowDuplicateInsertions: allowDuplicateInsertions) } - /// Apply the given edits to the syntax tree. + /// Applies the given edits to the given syntax tree. /// /// - Parameters: - /// - edits: The edits to apply to the syntax tree - /// - tree: he syntax tree to which the edits should be applied. - /// - Returns: A `String` representation of the modified syntax tree after applying the edits. + /// - edits: The edits to apply. + /// - tree: The syntax tree to which the edits should be applied. + /// - allowDuplicateInsertions: Whether to apply duplicate insertions. + /// Defaults to `true`. + /// + /// - Returns: A `String` representation of the modified syntax tree. public static func apply( edits: [SourceEdit], - to tree: any SyntaxProtocol + to tree: some SyntaxProtocol, + allowDuplicateInsertions: Bool = true ) -> String { var edits = edits var source = tree.description - while let edit = edits.first { - edits = Array(edits.dropFirst()) + for var editIndex in edits.indices { + let edit = edits[editIndex] + + // Empty edits do nothing. + guard !edit.isEmpty else { + continue + } + + do { + let utf8 = source.utf8 + let startIndex = utf8.index(utf8.startIndex, offsetBy: edit.startUtf8Offset) + let endIndex = utf8.index(utf8.startIndex, offsetBy: edit.endUtf8Offset) + + source.replaceSubrange(startIndex.. Bool { + // Insertions never conflict between themselves, unless we were asked + // to drop duplicate insertions. + if edit.range.isEmpty && remainingEdit.range.isEmpty { + if allowDuplicateInsertions { + return false + } - let startIndex = source.utf8.index(source.utf8.startIndex, offsetBy: edit.startUtf8Offset) - let endIndex = source.utf8.index(source.utf8.startIndex, offsetBy: edit.endUtf8Offset) + return edit == remainingEdit + } - source.replaceSubrange(startIndex.. remainingEdit.startUtf8Offset + && edit.startUtf8Offset < remainingEdit.endUtf8Offset + } - edits = edits.compactMap { remainingEdit -> SourceEdit? in - if remainingEdit.replacementRange.overlaps(edit.replacementRange) { - // The edit overlaps with the previous edit. We can't apply both - // without conflicts. Apply the one that's listed first and drop the - // later edit. - return nil + guard !shouldDropRemainingEdit() else { + // Drop the edit by swapping it for an empty one. + edits[editIndex] = SourceEdit() + continue } // If the remaining edit starts after or at the end of the edit that we just applied, // shift it by the current edit's difference in length. if edit.endUtf8Offset <= remainingEdit.startUtf8Offset { - let startPosition = AbsolutePosition( - utf8Offset: remainingEdit.startUtf8Offset - edit.replacementRange.count + edit.replacementLength.utf8Length - ) - let endPosition = AbsolutePosition( - utf8Offset: remainingEdit.endUtf8Offset - edit.replacementRange.count + edit.replacementLength.utf8Length - ) - return SourceEdit(range: startPosition.. Index { + self.formIndex(after: &index) as Void + return index + } +} + private extension SourceEdit { var startUtf8Offset: Int { return range.lowerBound.utf8Offset @@ -104,7 +152,15 @@ private extension SourceEdit { return range.upperBound.utf8Offset } - var replacementRange: Range { - return startUtf8Offset.. RawSpecializedAttributeArgumentSyntax { + let whereClause = self.parseGenericWhereClause() + return RawSpecializedAttributeArgumentSyntax(genericWhereClause: whereClause, arena: self.arena) + } + mutating func parseSpecializeAttributeArgumentList() -> RawSpecializeAttributeArgumentListSyntax { var elements = [RawSpecializeAttributeArgumentListSyntax.Element]() // Parse optional "exported" and "kind" labeled parameters. @@ -794,9 +806,9 @@ extension Parser { /// - Parameter missingLParen: `true` if the opening paren for the argument list was missing. mutating func parseABIAttributeArguments( missingLParen: Bool = false - ) -> (RawUnexpectedNodesSyntax?, RawAttributeSyntax.Arguments) { - func makeMissingProviderArguments(unexpectedBefore: [RawSyntax]) -> RawAttributeSyntax.Arguments { - let args = RawABIAttributeArgumentsSyntax( + ) -> RawABIAttributeArgumentsSyntax { + func makeMissingProviderArguments(unexpectedBefore: [RawSyntax]) -> RawABIAttributeArgumentsSyntax { + return RawABIAttributeArgumentsSyntax( provider: .missing( RawMissingDeclSyntax( unexpectedBefore.isEmpty ? nil : RawUnexpectedNodesSyntax(elements: unexpectedBefore, arena: self.arena), @@ -808,7 +820,6 @@ extension Parser { ), arena: self.arena ) - return .abiArguments(args) } // Consider the three kinds of mistakes we might see here: @@ -824,23 +835,16 @@ extension Parser { // In lieu of that, we judge that recovering gracefully from #3 is more important than #2 and therefore do not even // attempt to parse the argument unless we've seen a left paren. guard !missingLParen && !self.at(.rightParen) else { - return (nil, makeMissingProviderArguments(unexpectedBefore: [])) + return makeMissingProviderArguments(unexpectedBefore: []) } let decl = parseDeclaration(in: .argumentList) - guard experimentalFeatures.contains(.abiAttribute) else { - return ( - RawUnexpectedNodesSyntax([decl], arena: self.arena), - .argumentList(RawLabeledExprListSyntax(elements: [], arena: self.arena)) - ) - } - guard let provider = RawABIAttributeArgumentsSyntax.Provider(decl) else { - return (nil, makeMissingProviderArguments(unexpectedBefore: [decl.raw])) + return makeMissingProviderArguments(unexpectedBefore: [decl.raw]) } - return (nil, .abiArguments(RawABIAttributeArgumentsSyntax(provider: provider, arena: self.arena))) + return RawABIAttributeArgumentsSyntax(provider: provider, arena: self.arena) } } diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index a9e4a01f449..6ffffd81438 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -140,6 +140,29 @@ extension TokenConsumer { // Otherwise, parse it as an expression. return false + case .lhs(.using): + // This declaration doesn't support attributes or modifiers + if hasAttribute || hasModifier { + return false + } + + var lookahead = subparser.lookahead() + + // Consume 'using' + lookahead.consumeAnyToken() + + // Allow parsing 'using' as declaration only if + // it's immediately followed by either `@` or + // an identifier. + if lookahead.atStartOfLine { + return false + } + + guard lookahead.at(.atSign) || lookahead.at(.identifier) else { + return false + } + + return true case .some(_): // All other decl start keywords unconditionally start a decl. return true @@ -338,6 +361,8 @@ extension Parser { return RawDeclSyntax(self.parseMacroDeclaration(attrs: attrs, introducerHandle: handle)) case (.lhs(.pound), let handle)?: return RawDeclSyntax(self.parseMacroExpansionDeclaration(attrs, handle)) + case (.lhs(.using), let handle)?: + return RawDeclSyntax(self.parseUsingDeclaration(attrs: attrs, introducerHandle: handle)) case (.rhs, let handle)?: return RawDeclSyntax(self.parseBindingDeclaration(attrs, handle, in: context)) case nil: @@ -439,6 +464,54 @@ extension Parser { } } +extension Parser { + mutating func parseUsingDeclaration( + attrs: DeclAttributes, + introducerHandle handle: RecoveryConsumptionHandle + ) -> RawUsingDeclSyntax { + let unexpectedAttributes: RawUnexpectedNodesSyntax? = + if !attrs.attributes.isEmpty { + RawUnexpectedNodesSyntax(attrs.attributes.elements, arena: self.arena) + } else { + nil + } + + let unexpectedModifiers: RawUnexpectedNodesSyntax? = + if !attrs.modifiers.isEmpty { + RawUnexpectedNodesSyntax(attrs.modifiers.elements, arena: self.arena) + } else { + nil + } + + let (unexpectedBeforeKeyword, usingKeyword) = self.eat(handle) + + let unexpectedBeforeUsingKeyword = RawUnexpectedNodesSyntax( + combining: unexpectedAttributes, + unexpectedModifiers, + unexpectedBeforeKeyword, + arena: self.arena + ) + + if self.at(.atSign), case .attribute(let attribute) = self.parseAttribute() { + return RawUsingDeclSyntax( + unexpectedBeforeUsingKeyword, + usingKeyword: usingKeyword, + specifier: .attribute(attribute), + arena: self.arena + ) + } + + let modifier = self.expectWithoutRecovery(.identifier) + + return RawUsingDeclSyntax( + unexpectedBeforeUsingKeyword, + usingKeyword: usingKeyword, + specifier: .modifier(modifier), + arena: self.arena + ) + } +} + extension Parser { /// Parse an extension declaration. mutating func parseExtensionDeclaration( diff --git a/Sources/SwiftParser/IncrementalParseTransition.swift b/Sources/SwiftParser/IncrementalParseTransition.swift index c2ebb127817..730f5112da0 100644 --- a/Sources/SwiftParser/IncrementalParseTransition.swift +++ b/Sources/SwiftParser/IncrementalParseTransition.swift @@ -47,7 +47,7 @@ extension Parser { /// /// This is also used for testing purposes to ensure incremental reparsing /// worked as expected. -public typealias ReusedNodeCallback = (_ node: Syntax) -> () +public typealias ReusedNodeCallback = (_ node: Syntax) -> Void /// Keeps track of a previously parsed syntax tree and the source edits that /// occurred since it was created. diff --git a/Sources/SwiftParser/Lexer/Cursor.swift b/Sources/SwiftParser/Lexer/Cursor.swift index 13d2af8c289..24262fbbbab 100644 --- a/Sources/SwiftParser/Lexer/Cursor.swift +++ b/Sources/SwiftParser/Lexer/Cursor.swift @@ -79,7 +79,7 @@ extension Lexer.Cursor { /// The lexer has finished lexing the contents of a string literal and is now /// looking for the closing quote. - case afterStringLiteral(isRawString: Bool) + case afterStringLiteral(kind: StringLiteralKind, isRawString: Bool) /// The lexer has lexed the closing quote of a string literal that had raw /// string delimiters and is now looking for the closing raw string delimiters. @@ -453,8 +453,8 @@ extension Lexer.Cursor { result = lexAfterRawStringDelimiter(delimiterLength: delimiterLength) case .inStringLiteral(kind: let stringLiteralKind, delimiterLength: let delimiterLength): result = lexInStringLiteral(stringLiteralKind: stringLiteralKind, delimiterLength: delimiterLength) - case .afterStringLiteral(isRawString: _): - result = lexAfterStringLiteral() + case .afterStringLiteral(kind: let stringLiteralKind, isRawString: _): + result = lexAfterStringLiteral(stringLiteralKind: stringLiteralKind) case .afterClosingStringQuote: result = lexAfterClosingStringQuote() case .inStringInterpolationStart(stringLiteralKind: let stringLiteralKind): @@ -998,7 +998,7 @@ extension Lexer.Cursor { case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9": return self.lexNumber() case #"'"#, #"""#: - return self.lexStringQuote(isOpening: true, leadingDelimiterLength: 0) + return self.lexStringQuote(matchingOpening: nil, leadingDelimiterLength: 0) case "`": return self.lexEscapedIdentifier() @@ -1029,7 +1029,7 @@ extension Lexer.Cursor { private mutating func lexAfterRawStringDelimiter(delimiterLength: Int) -> Lexer.Result { switch self.peek() { case #"'"#, #"""#: - return self.lexStringQuote(isOpening: true, leadingDelimiterLength: delimiterLength) + return self.lexStringQuote(matchingOpening: nil, leadingDelimiterLength: delimiterLength) case nil: return Lexer.Result(.endOfFile) default: @@ -1037,10 +1037,10 @@ extension Lexer.Cursor { } } - private mutating func lexAfterStringLiteral() -> Lexer.Result { + private mutating func lexAfterStringLiteral(stringLiteralKind: StringLiteralKind) -> Lexer.Result { switch self.peek() { case #"'"#, #"""#: - return self.lexStringQuote(isOpening: false, leadingDelimiterLength: 0) + return self.lexStringQuote(matchingOpening: stringLiteralKind, leadingDelimiterLength: 0) case nil: return Lexer.Result(.endOfFile) default: @@ -1796,9 +1796,9 @@ extension Lexer.Cursor { extension Lexer.Cursor { private func stateTransitionAfterLexingStringQuote(kind: StringLiteralKind) -> Lexer.StateTransition { switch currentState { - case .afterStringLiteral(isRawString: true): + case .afterStringLiteral(kind: _, isRawString: true): return .replace(newState: .afterClosingStringQuote) - case .afterStringLiteral(isRawString: false): + case .afterStringLiteral(kind: _, isRawString: false): return .pop case .afterRawStringDelimiter(delimiterLength: let delimiterLength): return .replace(newState: .inStringLiteral(kind: kind, delimiterLength: delimiterLength)) @@ -1809,9 +1809,12 @@ extension Lexer.Cursor { } } - /// `isOpening` is `true` if this string quote is the opening quote of a string - /// literal and `false` if we are lexing the closing quote of a string literal. - mutating func lexStringQuote(isOpening: Bool, leadingDelimiterLength: Int) -> Lexer.Result { + /// `matchingOpening` is the opening literal kind if this string quote is the + /// closing quote of a string literal, `nil` if it's the opening quote. + mutating func lexStringQuote( + matchingOpening: StringLiteralKind?, + leadingDelimiterLength: Int + ) -> Lexer.Result { if self.advance(matching: "'") { return Lexer.Result(.singleQuote, stateTransition: stateTransitionAfterLexingStringQuote(kind: .singleQuote)) } @@ -1819,52 +1822,57 @@ extension Lexer.Cursor { let firstQuoteConsumed = self.advance(matching: #"""#) precondition(firstQuoteConsumed) + // Check to see if we have a multi-line delimiter. If we're matching an + // opening '"' then we want to bail since e.g `"a"""` shouldn't try to eat + // the '"""' as its closing delimiter. var lookingForMultilineString = self - if lookingForMultilineString.advance(matching: #"""#), lookingForMultilineString.advance(matching: #"""#) { - if leadingDelimiterLength > 0 { - // If this is a string literal, check if we have the closing delimiter on the same line to correctly parse things like `#"""#` as a single line string containing a quote. - var isSingleLineString = lookingForMultilineString - - if isSingleLineString.advanceIfStringDelimiter(delimiterLength: leadingDelimiterLength) { - // If we have the correct number of delimiters now, we have something like `#"""#`. - // This is a single-line string. - return Lexer.Result(.stringQuote, stateTransition: stateTransitionAfterLexingStringQuote(kind: .singleLine)) - } + if matchingOpening == .singleLine + || !(lookingForMultilineString.advance(matching: #"""#) && lookingForMultilineString.advance(matching: #"""#)) + { + return Lexer.Result(.stringQuote, stateTransition: stateTransitionAfterLexingStringQuote(kind: .singleLine)) + } - // Scan ahead until the end of the line. Every time we see a closing - // quote, check if it is followed by the correct number of closing delimiters. - while isSingleLineString.is(notAt: "\r", "\n") { - if isSingleLineString.advance(if: { $0 == #"""# }) { - if isSingleLineString.advanceIfStringDelimiter(delimiterLength: leadingDelimiterLength) { - return Lexer.Result( - .stringQuote, - stateTransition: stateTransitionAfterLexingStringQuote(kind: .singleLine) - ) - } - continue - } - _ = isSingleLineString.advance() - } + if leadingDelimiterLength > 0 { + // If this is a string literal, check if we have the closing delimiter on the same line to correctly parse things like `#"""#` as a single line string containing a quote. + var isSingleLineString = lookingForMultilineString + + if isSingleLineString.advanceIfStringDelimiter(delimiterLength: leadingDelimiterLength) { + // If we have the correct number of delimiters now, we have something like `#"""#`. + // This is a single-line string. + return Lexer.Result(.stringQuote, stateTransition: stateTransitionAfterLexingStringQuote(kind: .singleLine)) } - self = lookingForMultilineString - let trailingTriviaLexingMode: TriviaLexingMode? - if isOpening && self.is(at: "\n", "\r") { - // The opening quote of a multi-line string literal must be followed by - // a newline that's not part of the represented string. - trailingTriviaLexingMode = .escapedNewlineInMultiLineStringLiteral - } else { - trailingTriviaLexingMode = nil + // Scan ahead until the end of the line. Every time we see a closing + // quote, check if it is followed by the correct number of closing delimiters. + while isSingleLineString.is(notAt: "\r", "\n") { + if isSingleLineString.advance(if: { $0 == #"""# }) { + if isSingleLineString.advanceIfStringDelimiter(delimiterLength: leadingDelimiterLength) { + return Lexer.Result( + .stringQuote, + stateTransition: stateTransitionAfterLexingStringQuote(kind: .singleLine) + ) + } + continue + } + _ = isSingleLineString.advance() } + } - return Lexer.Result( - .multilineStringQuote, - stateTransition: stateTransitionAfterLexingStringQuote(kind: .multiLine), - trailingTriviaLexingMode: trailingTriviaLexingMode - ) + self = lookingForMultilineString + let trailingTriviaLexingMode: TriviaLexingMode? + if matchingOpening == nil && self.is(at: "\n", "\r") { + // The opening quote of a multi-line string literal must be followed by + // a newline that's not part of the represented string. + trailingTriviaLexingMode = .escapedNewlineInMultiLineStringLiteral } else { - return Lexer.Result(.stringQuote, stateTransition: stateTransitionAfterLexingStringQuote(kind: .singleLine)) + trailingTriviaLexingMode = nil } + + return Lexer.Result( + .multilineStringQuote, + stateTransition: stateTransitionAfterLexingStringQuote(kind: .multiLine), + trailingTriviaLexingMode: trailingTriviaLexingMode + ) } /// Returns `true` if the cursor is positioned at `\##(` with `delimiterLength` @@ -1935,7 +1943,9 @@ extension Lexer.Cursor { return Lexer.Result( .stringSegment, error: error, - stateTransition: .replace(newState: .afterStringLiteral(isRawString: delimiterLength > 0)) + stateTransition: .replace( + newState: .afterStringLiteral(kind: stringLiteralKind, isRawString: delimiterLength > 0) + ) ) default: break @@ -1967,7 +1977,9 @@ extension Lexer.Cursor { return Lexer.Result( .stringSegment, error: error, - stateTransition: .replace(newState: .afterStringLiteral(isRawString: delimiterLength > 0)) + stateTransition: .replace( + newState: .afterStringLiteral(kind: stringLiteralKind, isRawString: delimiterLength > 0) + ) ) } } diff --git a/Sources/SwiftParser/Nominals.swift b/Sources/SwiftParser/Nominals.swift index bbd15cf5618..eebdcd6fa0c 100644 --- a/Sources/SwiftParser/Nominals.swift +++ b/Sources/SwiftParser/Nominals.swift @@ -361,6 +361,11 @@ extension Parser { arena: self.arena ) ) + + // If this was a trailing comma, there are no more elements + if at(prefix: ">") { + break + } } while keepGoing != nil && self.hasProgressed(&loopProgress) } let rangle = self.expectWithoutRecovery(prefix: ">", as: .rightAngle) diff --git a/Sources/SwiftParser/StringLiterals.swift b/Sources/SwiftParser/StringLiterals.swift index b03c8877def..d3b9c8adc4d 100644 --- a/Sources/SwiftParser/StringLiterals.swift +++ b/Sources/SwiftParser/StringLiterals.swift @@ -340,22 +340,6 @@ extension Parser { unexpectedBeforeClosingQuote: [RawTokenSyntax], closingQuote: RawTokenSyntax ) { - // ------------------------------------------------------------------------- - // Precondition - - precondition( - allSegments.allSatisfy { - if case .stringSegment(let segment) = $0 { - return segment.unexpectedBeforeContent == nil - && segment.unexpectedAfterContent == nil - && segment.content.leadingTriviaByteLength == 0 - } else { - return true - } - }, - "String segment produced by the lexer should not have unexpected text or trivia because we would drop it during post-processing" - ) - // ------------------------------------------------------------------------- // Variables @@ -395,6 +379,9 @@ extension Parser { // Parse indentation of the closing quote if let lastSegment, + lastSegment.unexpectedBeforeContent == nil, + lastSegment.unexpectedAfterContent == nil, + lastSegment.content.leadingTriviaByteLength == 0, let parsedTrivia = parseIndentationTrivia(text: lastSegment.content.tokenText) { indentationTrivia = parsedTrivia @@ -409,10 +396,9 @@ extension Parser { arena: self.arena ) } else { - if let lastSegment = lastSegment { - indentationTrivia = TriviaParser.parseTrivia(lastSegment.content.tokenText, position: .leading).prefix(while: { - $0.isIndentationWhitespace - }) + if let lastSegment { + indentationTrivia = TriviaParser.parseTrivia(lastSegment.content.tokenText, position: .leading) + .prefix(while: \.isIndentationWhitespace) let indentationByteLength = indentationTrivia.reduce(0, { $0 + $1.byteLength }) indentation = SyntaxText(rebasing: lastSegment.content.tokenText[0..") { + break + } } while keepGoing != nil && self.hasProgressed(&loopProgress) } @@ -644,11 +650,11 @@ extension Parser { precondition(self.experimentalFeatures.contains(.inlineArrayTypeSugar)) // We allow both values and types here and for the element type for - // better recovery in cases where the user writes e.g '[Int x 3]'. + // better recovery in cases where the user writes e.g '[Int of 3]'. let count = self.parseGenericArgumentType() let (unexpectedBeforeSeparator, separator) = self.expect( - TokenSpec(.x, allowAtStartOfLine: false) + TokenSpec(.of, allowAtStartOfLine: false) ) let element = self.parseGenericArgumentType() @@ -874,18 +880,18 @@ extension Parser.Lookahead { return false } - // We must have at least '[ x', which cannot be any other + // We must have at least '[ of', which cannot be any other // kind of expression or type. We specifically look for both types and // integers for better recovery in e.g cases where the user writes e.g - // '[Int x 2]'. We only do type-scalar since variadics would be ambiguous - // e.g 'Int...x'. + // '[Int of 2]'. We only do type-scalar since variadics would be ambiguous + // e.g 'Int...of'. guard self.canParseTypeScalar() || self.canParseIntegerLiteral() else { return false } // We don't currently allow multi-line since that would require // disambiguation with array literals. - return self.consume(if: TokenSpec(.x, allowAtStartOfLine: false)) != nil + return self.consume(if: TokenSpec(.of, allowAtStartOfLine: false)) != nil } mutating func canParseInlineArrayTypeBody() -> Bool { @@ -893,7 +899,7 @@ extension Parser.Lookahead { return false } // Note we look for both types and integers for better recovery in e.g cases - // where the user writes e.g '[Int x 2]'. + // where the user writes e.g '[Int of 2]'. guard self.canParseGenericArgument() else { return false } @@ -939,13 +945,13 @@ extension Parser.Lookahead { // by a type annotation. if self.startsParameterName(isClosure: false, allowMisplacedSpecifierRecovery: false) { self.consumeAnyToken() + // If we have a secondary argument label, consume it. if self.atArgumentLabel() { self.consumeAnyToken() - guard self.at(.colon) else { - return false - } } - self.eat(.colon) + guard self.consume(if: .colon) != nil else { + return false + } // Parse a type. guard self.canParseType() else { @@ -1052,7 +1058,8 @@ extension Parser.Lookahead { return false } // Parse the comma, if the list continues. - } while self.consume(if: .comma) != nil && self.hasProgressed(&loopProgress) + // This could be the trailing comma. + } while self.consume(if: .comma) != nil && !self.at(prefix: ">") && self.hasProgressed(&loopProgress) } guard self.consume(ifPrefix: ">", as: .rightAngle) != nil else { @@ -1215,7 +1222,8 @@ extension Parser { misplacedSpecifiers: [RawTokenSyntax] = [] ) -> ( specifiers: RawTypeSpecifierListSyntax, - attributes: RawAttributeListSyntax + attributes: RawAttributeListSyntax, + lateSpecifiers: RawTypeSpecifierListSyntax )? { var specifiers: [RawTypeSpecifierListSyntax.Element] = [] SPECIFIER_PARSING: while canHaveParameterSpecifier { @@ -1254,7 +1262,15 @@ extension Parser { attributes = nil } - guard !specifiers.isEmpty || attributes != nil else { + // Only handle `nonisolated` as a late specifier. + var lateSpecifiers: [RawTypeSpecifierListSyntax.Element] = [] + if self.at(.keyword(.nonisolated)) && !(self.peek(isAt: .leftParen) && self.peek().isAtStartOfLine) + && canHaveParameterSpecifier + { + lateSpecifiers.append(parseNonisolatedTypeSpecifier()) + } + + guard !specifiers.isEmpty || attributes != nil || !lateSpecifiers.isEmpty else { // No specifiers or attributes on this type return nil } @@ -1265,9 +1281,17 @@ extension Parser { specifierList = RawTypeSpecifierListSyntax(elements: specifiers, arena: arena) } + let lateSpecifierList: RawTypeSpecifierListSyntax + if lateSpecifiers.isEmpty { + lateSpecifierList = self.emptyCollection(RawTypeSpecifierListSyntax.self) + } else { + lateSpecifierList = RawTypeSpecifierListSyntax(elements: lateSpecifiers, arena: arena) + } + return ( specifierList, - attributes ?? self.emptyCollection(RawAttributeListSyntax.self) + attributes ?? self.emptyCollection(RawAttributeListSyntax.self), + lateSpecifierList ) } diff --git a/Sources/SwiftParser/generated/ExperimentalFeatures.swift b/Sources/SwiftParser/generated/ExperimentalFeatures.swift index 77c5206bb99..c8c8c373856 100644 --- a/Sources/SwiftParser/generated/ExperimentalFeatures.swift +++ b/Sources/SwiftParser/generated/ExperimentalFeatures.swift @@ -43,17 +43,17 @@ extension Parser.ExperimentalFeatures { /// Whether to enable the parsing of coroutine accessors. public static let coroutineAccessors = Self (rawValue: 1 << 5) - /// Whether to enable the parsing of @abi attribute. - public static let abiAttribute = Self (rawValue: 1 << 6) - /// Whether to enable the parsing of keypaths with method members. - public static let keypathWithMethodMembers = Self (rawValue: 1 << 7) + public static let keypathWithMethodMembers = Self (rawValue: 1 << 6) /// Whether to enable the parsing of `_move` and `_borrow` as ownership operators. - public static let oldOwnershipOperatorSpellings = Self (rawValue: 1 << 8) + public static let oldOwnershipOperatorSpellings = Self (rawValue: 1 << 7) /// Whether to enable the parsing of sugar type for InlineArray. - public static let inlineArrayTypeSugar = Self (rawValue: 1 << 9) + public static let inlineArrayTypeSugar = Self (rawValue: 1 << 8) + + /// Whether to enable the parsing of set default actor isolation for a file. + public static let defaultIsolationPerFile = Self (rawValue: 1 << 9) /// Creates a new value representing the experimental feature with the /// given name, or returns nil if the name is not recognized. @@ -71,14 +71,14 @@ extension Parser.ExperimentalFeatures { self = .trailingComma case "CoroutineAccessors": self = .coroutineAccessors - case "ABIAttribute": - self = .abiAttribute case "KeypathWithMethodMembers": self = .keypathWithMethodMembers case "OldOwnershipOperatorSpellings": self = .oldOwnershipOperatorSpellings case "InlineArrayTypeSugar": self = .inlineArrayTypeSugar + case "DefaultIsolationPerFile": + self = .defaultIsolationPerFile default: return nil } diff --git a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift index 9a9d00393e7..52e2023df3e 100644 --- a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift @@ -362,6 +362,8 @@ extension SyntaxKind { return "availability entry" case .specializeTargetFunctionArgument: return "attribute argument" + case .specializedAttributeArgument: + return "argument to '@specialized" case .stringLiteralExpr: return "string literal" case .structDecl: @@ -406,6 +408,8 @@ extension SyntaxKind { return "ternary operator" case .unsafeExpr: return "'unsafe' expression" + case .usingDecl: + return "using" case .valueBindingPattern: return "value binding pattern" case .variableDecl: diff --git a/Sources/SwiftRefactor/CMakeLists.txt b/Sources/SwiftRefactor/CMakeLists.txt index 1864c71f2ab..8494f3b91cc 100644 --- a/Sources/SwiftRefactor/CMakeLists.txt +++ b/Sources/SwiftRefactor/CMakeLists.txt @@ -8,6 +8,7 @@ add_swift_syntax_library(SwiftRefactor AddSeparatorsToIntegerLiteral.swift + CallLikeSyntax.swift CallToTrailingClosures.swift ConvertComputedPropertyToStored.swift ConvertComputedPropertyToZeroParameterFunction.swift diff --git a/Sources/SwiftRefactor/CallLikeSyntax.swift b/Sources/SwiftRefactor/CallLikeSyntax.swift new file mode 100644 index 00000000000..c620a52fe97 --- /dev/null +++ b/Sources/SwiftRefactor/CallLikeSyntax.swift @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#if compiler(>=6) +public import SwiftSyntax +#else +import SwiftSyntax +#endif + +// TODO: We ought to consider exposing this as a public syntax protocol. +@_spi(Testing) public protocol CallLikeSyntax: SyntaxProtocol { + var arguments: LabeledExprListSyntax { get set } + var leftParen: TokenSyntax? { get set } + var rightParen: TokenSyntax? { get set } + var trailingClosure: ClosureExprSyntax? { get set } + var additionalTrailingClosures: MultipleTrailingClosureElementListSyntax { get set } +} +@_spi(Testing) extension FunctionCallExprSyntax: CallLikeSyntax {} +@_spi(Testing) extension MacroExpansionExprSyntax: CallLikeSyntax {} +@_spi(Testing) extension MacroExpansionDeclSyntax: CallLikeSyntax {} + +extension SyntaxProtocol { + @_spi(Testing) public func asProtocol(_: CallLikeSyntax.Protocol) -> (any CallLikeSyntax)? { + Syntax(self).asProtocol(SyntaxProtocol.self) as? CallLikeSyntax + } +} diff --git a/Sources/SwiftRefactor/CallToTrailingClosures.swift b/Sources/SwiftRefactor/CallToTrailingClosures.swift index f2781d4b7ed..858c1185b61 100644 --- a/Sources/SwiftRefactor/CallToTrailingClosures.swift +++ b/Sources/SwiftRefactor/CallToTrailingClosures.swift @@ -50,19 +50,41 @@ public struct CallToTrailingClosures: SyntaxRefactoringProvider { } } + public typealias Input = Syntax + public typealias Output = Syntax + + /// Apply the refactoring to a given syntax node. If either a + /// non-function-like syntax node is passed, or the refactoring fails, + /// `nil` is returned. // TODO: Rather than returning nil, we should consider throwing errors with // appropriate messages instead. + public static func refactor( + syntax: Syntax, + in context: Context = Context() + ) -> Syntax? { + guard let call = syntax.asProtocol(CallLikeSyntax.self) else { return nil } + return Syntax(fromProtocol: _refactor(syntax: call, in: context)) + } + + @available(*, deprecated, message: "Pass a Syntax argument instead of FunctionCallExprSyntax") public static func refactor( syntax call: FunctionCallExprSyntax, in context: Context = Context() ) -> FunctionCallExprSyntax? { + _refactor(syntax: call, in: context) + } + + internal static func _refactor( + syntax call: C, + in context: Context = Context() + ) -> C? { let converted = call.convertToTrailingClosures(from: context.startAtArgument) - return converted?.formatted().as(FunctionCallExprSyntax.self) + return converted?.formatted().as(C.self) } } -extension FunctionCallExprSyntax { - fileprivate func convertToTrailingClosures(from startAtArgument: Int) -> FunctionCallExprSyntax? { +extension CallLikeSyntax { + fileprivate func convertToTrailingClosures(from startAtArgument: Int) -> Self? { guard trailingClosure == nil, additionalTrailingClosures.isEmpty, leftParen != nil, rightParen != nil else { // Already have trailing closures return nil diff --git a/Sources/SwiftRefactor/ExpandEditorPlaceholder.swift b/Sources/SwiftRefactor/ExpandEditorPlaceholder.swift index 7bf87269489..50854f65e37 100644 --- a/Sources/SwiftRefactor/ExpandEditorPlaceholder.swift +++ b/Sources/SwiftRefactor/ExpandEditorPlaceholder.swift @@ -180,7 +180,7 @@ public struct ExpandEditorPlaceholder: EditRefactoringProvider { placeholder.baseName.isEditorPlaceholder, let arg = placeholder.parent?.as(LabeledExprSyntax.self), let argList = arg.parent?.as(LabeledExprListSyntax.self), - let call = argList.parent?.as(FunctionCallExprSyntax.self), + let call = argList.parent?.asProtocol(CallLikeSyntax.self), let expandedClosures = ExpandEditorPlaceholdersToLiteralClosures.expandClosurePlaceholders( in: call, ifIncluded: arg, @@ -266,6 +266,26 @@ public struct ExpandEditorPlaceholdersToLiteralClosures: SyntaxRefactoringProvid } } + public typealias Input = Syntax + public typealias Output = Syntax + + /// Apply the refactoring to a given syntax node. If either a + /// non-function-like syntax node is passed, or the refactoring fails, + /// `nil` is returned. + public static func refactor( + syntax: Syntax, + in context: Context = Context() + ) -> Syntax? { + guard let call = syntax.asProtocol(CallLikeSyntax.self) else { return nil } + let expanded = Self.expandClosurePlaceholders( + in: call, + ifIncluded: nil, + context: context + ) + return Syntax(fromProtocol: expanded) + } + + @available(*, deprecated, message: "Pass a Syntax argument instead of FunctionCallExprSyntax") public static func refactor( syntax call: FunctionCallExprSyntax, in context: Context = Context() @@ -282,11 +302,11 @@ public struct ExpandEditorPlaceholdersToLiteralClosures: SyntaxRefactoringProvid /// closure, then return a replacement of this call with one that uses /// closures based on the function types provided by each editor placeholder. /// Otherwise return nil. - fileprivate static func expandClosurePlaceholders( - in call: FunctionCallExprSyntax, + fileprivate static func expandClosurePlaceholders( + in call: C, ifIncluded arg: LabeledExprSyntax?, context: Context - ) -> FunctionCallExprSyntax? { + ) -> C? { switch context.format { case let .custom(formatter, allowNestedPlaceholders: allowNesting): let expanded = call.expandClosurePlaceholders( @@ -305,11 +325,7 @@ public struct ExpandEditorPlaceholdersToLiteralClosures: SyntaxRefactoringProvid let callToTrailingContext = CallToTrailingClosures.Context( startAtArgument: call.arguments.count - expanded.numClosures ) - guard let trailing = CallToTrailingClosures.refactor(syntax: expanded.expr, in: callToTrailingContext) else { - return nil - } - - return trailing + return CallToTrailingClosures._refactor(syntax: expanded.expr, in: callToTrailingContext) } } } @@ -382,7 +398,7 @@ extension TupleTypeElementSyntax { } } -extension FunctionCallExprSyntax { +extension CallLikeSyntax { /// If the given argument is `nil` or one of the last arguments that are all /// function-typed placeholders and this call doesn't have a trailing /// closure, then return a replacement of this call with one that uses @@ -393,7 +409,7 @@ extension FunctionCallExprSyntax { indentationWidth: Trivia? = nil, customFormat: BasicFormat? = nil, allowNestedPlaceholders: Bool = false - ) -> (expr: FunctionCallExprSyntax, numClosures: Int)? { + ) -> (expr: Self, numClosures: Int)? { var includedArg = false var argsToExpand = 0 for arg in arguments.reversed() { diff --git a/Sources/SwiftSyntax/AbsolutePosition.swift b/Sources/SwiftSyntax/AbsolutePosition.swift index bd2ce4efe9d..dfd49784f7b 100644 --- a/Sources/SwiftSyntax/AbsolutePosition.swift +++ b/Sources/SwiftSyntax/AbsolutePosition.swift @@ -21,11 +21,17 @@ public struct AbsolutePosition: Comparable, Hashable, Sendable { self.utf8Offset = utf8Offset } + public static func < (lhs: AbsolutePosition, rhs: AbsolutePosition) -> Bool { + return lhs.utf8Offset < rhs.utf8Offset + } +} + +extension AbsolutePosition: Strideable { public func advanced(by offset: Int) -> AbsolutePosition { - return AbsolutePosition(utf8Offset: self.utf8Offset + offset) + AbsolutePosition(utf8Offset: self.utf8Offset + offset) } - public static func < (lhs: AbsolutePosition, rhs: AbsolutePosition) -> Bool { - return lhs.utf8Offset < rhs.utf8Offset + public func distance(to other: AbsolutePosition) -> Int { + self.utf8Offset.distance(to: other.utf8Offset) } } diff --git a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md index 4ec126dbe4f..124109abadf 100644 --- a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md +++ b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md @@ -303,6 +303,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code. ### Attributes +- - - - @@ -326,6 +327,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code. - - - +- ### Miscellaneous Syntax diff --git a/Sources/SwiftSyntax/SourceLocation.swift b/Sources/SwiftSyntax/SourceLocation.swift index dcca9d2a74f..4cd64d612b9 100644 --- a/Sources/SwiftSyntax/SourceLocation.swift +++ b/Sources/SwiftSyntax/SourceLocation.swift @@ -701,7 +701,7 @@ fileprivate extension SyntaxText { /// - Returns: The position at the end of the walk. func forEachEndOfLine( position: AbsolutePosition, - body: (AbsolutePosition) -> () + body: (AbsolutePosition) -> Void ) -> AbsolutePosition { guard let startPtr = buffer.baseAddress else { return position @@ -745,7 +745,7 @@ fileprivate extension RawTriviaPiece { /// - Returns: The position at the end of the walk. func forEachEndOfLine( position: AbsolutePosition, - body: (AbsolutePosition) -> () + body: (AbsolutePosition) -> Void ) -> AbsolutePosition { var position = position switch self { @@ -788,7 +788,7 @@ fileprivate extension RawTriviaPieceBuffer { /// - Returns: The position at the end of the walk. func forEachEndOfLine( position: AbsolutePosition, - body: (AbsolutePosition) -> () + body: (AbsolutePosition) -> Void ) -> AbsolutePosition { var position = position for piece in self { @@ -810,8 +810,8 @@ fileprivate extension RawSyntax { /// - Returns: The position at the end of the walk. func forEachEndOfLine( position: AbsolutePosition, - body: (AbsolutePosition) -> (), - handleSourceLocationDirective: (_ position: AbsolutePosition, _ rawSyntax: RawSyntax) -> () + body: (AbsolutePosition) -> Void, + handleSourceLocationDirective: (_ position: AbsolutePosition, _ rawSyntax: RawSyntax) -> Void ) -> AbsolutePosition { var position = position switch self.rawData.payload { diff --git a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift index 802b6ae8003..0bcd20aee62 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -286,8 +286,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "unexpectedBetweenSpecifiersAndAttributes" case \AttributedTypeSyntax.attributes: return "attributes" - case \AttributedTypeSyntax.unexpectedBetweenAttributesAndBaseType: - return "unexpectedBetweenAttributesAndBaseType" + case \AttributedTypeSyntax.unexpectedBetweenAttributesAndLateSpecifiers: + return "unexpectedBetweenAttributesAndLateSpecifiers" + case \AttributedTypeSyntax.lateSpecifiers: + return "lateSpecifiers" + case \AttributedTypeSyntax.unexpectedBetweenLateSpecifiersAndBaseType: + return "unexpectedBetweenLateSpecifiersAndBaseType" case \AttributedTypeSyntax.baseType: return "baseType" case \AttributedTypeSyntax.unexpectedAfterBaseType: @@ -2962,6 +2966,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "trailingComma" case \SpecializeTargetFunctionArgumentSyntax.unexpectedAfterTrailingComma: return "unexpectedAfterTrailingComma" + case \SpecializedAttributeArgumentSyntax.unexpectedBeforeGenericWhereClause: + return "unexpectedBeforeGenericWhereClause" + case \SpecializedAttributeArgumentSyntax.genericWhereClause: + return "genericWhereClause" + case \SpecializedAttributeArgumentSyntax.unexpectedAfterGenericWhereClause: + return "unexpectedAfterGenericWhereClause" case \StringLiteralExprSyntax.unexpectedBeforeOpeningPounds: return "unexpectedBeforeOpeningPounds" case \StringLiteralExprSyntax.openingPounds: @@ -3444,6 +3454,16 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "expression" case \UnsafeExprSyntax.unexpectedAfterExpression: return "unexpectedAfterExpression" + case \UsingDeclSyntax.unexpectedBeforeUsingKeyword: + return "unexpectedBeforeUsingKeyword" + case \UsingDeclSyntax.usingKeyword: + return "usingKeyword" + case \UsingDeclSyntax.unexpectedBetweenUsingKeywordAndSpecifier: + return "unexpectedBetweenUsingKeywordAndSpecifier" + case \UsingDeclSyntax.specifier: + return "specifier" + case \UsingDeclSyntax.unexpectedAfterSpecifier: + return "unexpectedAfterSpecifier" case \ValueBindingPatternSyntax.unexpectedBeforeBindingSpecifier: return "unexpectedBeforeBindingSpecifier" case \ValueBindingPatternSyntax.bindingSpecifier: diff --git a/Sources/SwiftSyntax/generated/Keyword.swift b/Sources/SwiftSyntax/generated/Keyword.swift index 20b36ff1455..61e59e93cbc 100644 --- a/Sources/SwiftSyntax/generated/Keyword.swift +++ b/Sources/SwiftSyntax/generated/Keyword.swift @@ -46,6 +46,7 @@ public enum Keyword: UInt8, Hashable, Sendable { case _PackageDescription case _read case _RefCountedObject + case specialized case _specialize case _spi_available case _Trivial @@ -54,7 +55,6 @@ public enum Keyword: UInt8, Hashable, Sendable { case _underlyingVersion case _UnknownLayout case _version - @_spi(ExperimentalLanguageFeatures) case abi case accesses case actor @@ -215,6 +215,7 @@ public enum Keyword: UInt8, Hashable, Sendable { case unsafe case unsafeAddress case unsafeMutableAddress + case using case `var` case visibility case weak @@ -222,19 +223,10 @@ public enum Keyword: UInt8, Hashable, Sendable { case `while` case willSet case wrt - @_spi(ExperimentalLanguageFeatures) - case x case yield @_spi(RawSyntax) public init?(_ text: SyntaxText) { switch text.count { - case 1: - switch text { - case "x": - self = .x - default: - return nil - } case 2: switch text { case "as": @@ -376,6 +368,8 @@ public enum Keyword: UInt8, Hashable, Sendable { self = .swift case "throw": self = .throw + case "using": + self = .using case "where": self = .where case "while": @@ -602,6 +596,8 @@ public enum Keyword: UInt8, Hashable, Sendable { self = ._implements case "_noMetadata": self = ._noMetadata + case "specialized": + self = .specialized case "_specialize": self = ._specialize case "autoclosure": @@ -790,6 +786,7 @@ public enum Keyword: UInt8, Hashable, Sendable { "_PackageDescription", "_read", "_RefCountedObject", + "specialized", "_specialize", "_spi_available", "_Trivial", @@ -954,6 +951,7 @@ public enum Keyword: UInt8, Hashable, Sendable { "unsafe", "unsafeAddress", "unsafeMutableAddress", + "using", "var", "visibility", "weak", @@ -961,7 +959,6 @@ public enum Keyword: UInt8, Hashable, Sendable { "while", "willSet", "wrt", - "x", "yield", ] diff --git a/Sources/SwiftSyntax/generated/RenamedNodesCompatibility.swift b/Sources/SwiftSyntax/generated/RenamedNodesCompatibility.swift index d9eed528b19..3aa308c9fc1 100644 --- a/Sources/SwiftSyntax/generated/RenamedNodesCompatibility.swift +++ b/Sources/SwiftSyntax/generated/RenamedNodesCompatibility.swift @@ -178,6 +178,9 @@ public typealias SpecializeAttributeSpecListSyntax = SpecializeAttributeArgument @available(*, deprecated, renamed: "GenericSpecializationExprSyntax") public typealias SpecializeExprSyntax = GenericSpecializationExprSyntax +@available(*, deprecated, renamed: "SpecializedAttributeArgumentSyntax") +public typealias SpecializedAttributeSyntax = SpecializedAttributeArgumentSyntax + @available(*, deprecated, renamed: "StringLiteralSegmentListSyntax") public typealias StringLiteralSegmentsSyntax = StringLiteralSegmentListSyntax @@ -493,6 +496,11 @@ extension SyntaxKind { return .genericSpecializationExpr } + @available(*, deprecated, renamed: "SpecializedAttributeArgumentSyntax") + public static var specializedAttribute: Self { + return .specializedAttributeArgument + } + @available(*, deprecated, renamed: "StringLiteralSegmentListSyntax") public static var stringLiteralSegments: Self { return .stringLiteralSegmentList diff --git a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift index 124561440e0..134ae3fcaf8 100644 --- a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift @@ -57,12 +57,10 @@ open class SyntaxAnyVisitor: SyntaxVisitor { visitAnyPost(node._syntaxNode) } - @_spi(ExperimentalLanguageFeatures) override open func visit(_ node: ABIAttributeArgumentsSyntax) -> SyntaxVisitorContinueKind { return visitAny(node._syntaxNode) } - @_spi(ExperimentalLanguageFeatures) override open func visitPost(_ node: ABIAttributeArgumentsSyntax) { visitAnyPost(node._syntaxNode) } @@ -1985,6 +1983,14 @@ open class SyntaxAnyVisitor: SyntaxVisitor { visitAnyPost(node._syntaxNode) } + override open func visit(_ node: SpecializedAttributeArgumentSyntax) -> SyntaxVisitorContinueKind { + return visitAny(node._syntaxNode) + } + + override open func visitPost(_ node: SpecializedAttributeArgumentSyntax) { + visitAnyPost(node._syntaxNode) + } + override open func visit(_ node: StringLiteralExprSyntax) -> SyntaxVisitorContinueKind { return visitAny(node._syntaxNode) } @@ -2291,6 +2297,16 @@ open class SyntaxAnyVisitor: SyntaxVisitor { visitAnyPost(node._syntaxNode) } + @_spi(ExperimentalLanguageFeatures) + override open func visit(_ node: UsingDeclSyntax) -> SyntaxVisitorContinueKind { + return visitAny(node._syntaxNode) + } + + @_spi(ExperimentalLanguageFeatures) + override open func visitPost(_ node: UsingDeclSyntax) { + visitAnyPost(node._syntaxNode) + } + override open func visit(_ node: ValueBindingPatternSyntax) -> SyntaxVisitorContinueKind { return visitAny(node._syntaxNode) } diff --git a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift index 8c1a8444f88..3268316597d 100644 --- a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift +++ b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift @@ -214,7 +214,7 @@ public struct DeclSyntax: DeclSyntaxProtocol, SyntaxHashable { public init?(_ node: __shared some SyntaxProtocol) { switch node.raw.kind { - case .accessorDecl, .actorDecl, .associatedTypeDecl, .classDecl, .deinitializerDecl, .editorPlaceholderDecl, .enumCaseDecl, .enumDecl, .extensionDecl, .functionDecl, .ifConfigDecl, .importDecl, .initializerDecl, .macroDecl, .macroExpansionDecl, .missingDecl, .operatorDecl, .poundSourceLocation, .precedenceGroupDecl, .protocolDecl, .structDecl, .subscriptDecl, .typeAliasDecl, .variableDecl: + case .accessorDecl, .actorDecl, .associatedTypeDecl, .classDecl, .deinitializerDecl, .editorPlaceholderDecl, .enumCaseDecl, .enumDecl, .extensionDecl, .functionDecl, .ifConfigDecl, .importDecl, .initializerDecl, .macroDecl, .macroExpansionDecl, .missingDecl, .operatorDecl, .poundSourceLocation, .precedenceGroupDecl, .protocolDecl, .structDecl, .subscriptDecl, .typeAliasDecl, .usingDecl, .variableDecl: self._syntaxNode = node._syntaxNode default: return nil @@ -262,6 +262,7 @@ public struct DeclSyntax: DeclSyntaxProtocol, SyntaxHashable { .node(StructDeclSyntax.self), .node(SubscriptDeclSyntax.self), .node(TypeAliasDeclSyntax.self), + .node(UsingDeclSyntax.self), .node(VariableDeclSyntax.self) ]) } @@ -1749,6 +1750,7 @@ extension Syntax { .node(SpecializeAttributeArgumentListSyntax.self), .node(SpecializeAvailabilityArgumentSyntax.self), .node(SpecializeTargetFunctionArgumentSyntax.self), + .node(SpecializedAttributeArgumentSyntax.self), .node(StringLiteralExprSyntax.self), .node(StringLiteralSegmentListSyntax.self), .node(StringSegmentSyntax.self), @@ -1787,6 +1789,7 @@ extension Syntax { .node(UnresolvedIsExprSyntax.self), .node(UnresolvedTernaryExprSyntax.self), .node(UnsafeExprSyntax.self), + .node(UsingDeclSyntax.self), .node(ValueBindingPatternSyntax.self), .node(VariableDeclSyntax.self), .node(VersionComponentListSyntax.self), diff --git a/Sources/SwiftSyntax/generated/SyntaxCollections.swift b/Sources/SwiftSyntax/generated/SyntaxCollections.swift index a34717855b7..529785471e9 100644 --- a/Sources/SwiftSyntax/generated/SyntaxCollections.swift +++ b/Sources/SwiftSyntax/generated/SyntaxCollections.swift @@ -1918,6 +1918,7 @@ public struct TupleTypeElementListSyntax: SyntaxCollection, SyntaxHashable { /// ### Contained in /// /// - ``AttributedTypeSyntax``.``AttributedTypeSyntax/specifiers`` +/// - ``AttributedTypeSyntax``.``AttributedTypeSyntax/lateSpecifiers`` public struct TypeSpecifierListSyntax: SyntaxCollection, SyntaxHashable { public enum Element: SyntaxChildChoices, SyntaxHashable { /// A specifier that can be attached to a type to eg. mark a parameter as `inout` or `consuming` diff --git a/Sources/SwiftSyntax/generated/SyntaxEnum.swift b/Sources/SwiftSyntax/generated/SyntaxEnum.swift index 283c1d82d03..b94aae22e71 100644 --- a/Sources/SwiftSyntax/generated/SyntaxEnum.swift +++ b/Sources/SwiftSyntax/generated/SyntaxEnum.swift @@ -16,7 +16,6 @@ /// Enum to exhaustively switch over all different syntax nodes. public enum SyntaxEnum: Sendable { case token(TokenSyntax) - @_spi(ExperimentalLanguageFeatures) case abiAttributeArguments(ABIAttributeArgumentsSyntax) @_spi(Compiler) case accessorBlockFile(AccessorBlockFileSyntax) @@ -266,6 +265,7 @@ public enum SyntaxEnum: Sendable { case specializeAttributeArgumentList(SpecializeAttributeArgumentListSyntax) case specializeAvailabilityArgument(SpecializeAvailabilityArgumentSyntax) case specializeTargetFunctionArgument(SpecializeTargetFunctionArgumentSyntax) + case specializedAttributeArgument(SpecializedAttributeArgumentSyntax) case stringLiteralExpr(StringLiteralExprSyntax) case stringLiteralSegmentList(StringLiteralSegmentListSyntax) case stringSegment(StringSegmentSyntax) @@ -305,6 +305,8 @@ public enum SyntaxEnum: Sendable { case unresolvedIsExpr(UnresolvedIsExprSyntax) case unresolvedTernaryExpr(UnresolvedTernaryExprSyntax) case unsafeExpr(UnsafeExprSyntax) + @_spi(ExperimentalLanguageFeatures) + case usingDecl(UsingDeclSyntax) case valueBindingPattern(ValueBindingPatternSyntax) case variableDecl(VariableDeclSyntax) case versionComponentList(VersionComponentListSyntax) @@ -801,6 +803,8 @@ extension Syntax { return .specializeAvailabilityArgument(SpecializeAvailabilityArgumentSyntax(self)!) case .specializeTargetFunctionArgument: return .specializeTargetFunctionArgument(SpecializeTargetFunctionArgumentSyntax(self)!) + case .specializedAttributeArgument: + return .specializedAttributeArgument(SpecializedAttributeArgumentSyntax(self)!) case .stringLiteralExpr: return .stringLiteralExpr(StringLiteralExprSyntax(self)!) case .stringLiteralSegmentList: @@ -877,6 +881,8 @@ extension Syntax { return .unresolvedTernaryExpr(UnresolvedTernaryExprSyntax(self)!) case .unsafeExpr: return .unsafeExpr(UnsafeExprSyntax(self)!) + case .usingDecl: + return .usingDecl(UsingDeclSyntax(self)!) case .valueBindingPattern: return .valueBindingPattern(ValueBindingPatternSyntax(self)!) case .variableDecl: @@ -930,6 +936,8 @@ public enum DeclSyntaxEnum { case structDecl(StructDeclSyntax) case subscriptDecl(SubscriptDeclSyntax) case typeAliasDecl(TypeAliasDeclSyntax) + @_spi(ExperimentalLanguageFeatures) + case usingDecl(UsingDeclSyntax) case variableDecl(VariableDeclSyntax) } @@ -983,6 +991,8 @@ extension DeclSyntax { return .subscriptDecl(SubscriptDeclSyntax(self)!) case .typeAliasDecl: return .typeAliasDecl(TypeAliasDeclSyntax(self)!) + case .usingDecl: + return .usingDecl(UsingDeclSyntax(self)!) case .variableDecl: return .variableDecl(VariableDeclSyntax(self)!) default: diff --git a/Sources/SwiftSyntax/generated/SyntaxKind.swift b/Sources/SwiftSyntax/generated/SyntaxKind.swift index 62883dd7ac3..dcfaf4e18b0 100644 --- a/Sources/SwiftSyntax/generated/SyntaxKind.swift +++ b/Sources/SwiftSyntax/generated/SyntaxKind.swift @@ -16,7 +16,6 @@ /// Enumerates the known kinds of Syntax represented in the Syntax tree. public enum SyntaxKind: Sendable { case token - @_spi(ExperimentalLanguageFeatures) case abiAttributeArguments @_spi(Compiler) case accessorBlockFile @@ -266,6 +265,7 @@ public enum SyntaxKind: Sendable { case specializeAttributeArgumentList case specializeAvailabilityArgument case specializeTargetFunctionArgument + case specializedAttributeArgument case stringLiteralExpr case stringLiteralSegmentList case stringSegment @@ -305,6 +305,8 @@ public enum SyntaxKind: Sendable { case unresolvedIsExpr case unresolvedTernaryExpr case unsafeExpr + @_spi(ExperimentalLanguageFeatures) + case usingDecl case valueBindingPattern case variableDecl case versionComponentList @@ -926,6 +928,8 @@ public enum SyntaxKind: Sendable { return SpecializeAvailabilityArgumentSyntax.self case .specializeTargetFunctionArgument: return SpecializeTargetFunctionArgumentSyntax.self + case .specializedAttributeArgument: + return SpecializedAttributeArgumentSyntax.self case .stringLiteralExpr: return StringLiteralExprSyntax.self case .stringLiteralSegmentList: @@ -1002,6 +1006,8 @@ public enum SyntaxKind: Sendable { return UnresolvedTernaryExprSyntax.self case .unsafeExpr: return UnsafeExprSyntax.self + case .usingDecl: + return UsingDeclSyntax.self case .valueBindingPattern: return ValueBindingPatternSyntax.self case .variableDecl: diff --git a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift index 77eb14701ba..c82f5b54f20 100644 --- a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift +++ b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift @@ -99,10 +99,9 @@ open class SyntaxRewriter { return token } - /// Visit a `ABIAttributeArgumentsSyntax`. + /// Visit a ``ABIAttributeArgumentsSyntax``. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node - @_spi(ExperimentalLanguageFeatures) open func visit(_ node: ABIAttributeArgumentsSyntax) -> ABIAttributeArgumentsSyntax { return ABIAttributeArgumentsSyntax(unsafeCasting: visitChildren(node._syntaxNode)) } @@ -1777,6 +1776,13 @@ open class SyntaxRewriter { return SpecializeTargetFunctionArgumentSyntax(unsafeCasting: visitChildren(node._syntaxNode)) } + /// Visit a ``SpecializedAttributeArgumentSyntax``. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + open func visit(_ node: SpecializedAttributeArgumentSyntax) -> SpecializedAttributeArgumentSyntax { + return SpecializedAttributeArgumentSyntax(unsafeCasting: visitChildren(node._syntaxNode)) + } + /// Visit a ``StringLiteralExprSyntax``. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node @@ -2044,6 +2050,14 @@ open class SyntaxRewriter { return ExprSyntax(UnsafeExprSyntax(unsafeCasting: visitChildren(node._syntaxNode))) } + /// Visit a `UsingDeclSyntax`. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + @_spi(ExperimentalLanguageFeatures) + open func visit(_ node: UsingDeclSyntax) -> DeclSyntax { + return DeclSyntax(UsingDeclSyntax(unsafeCasting: visitChildren(node._syntaxNode))) + } + /// Visit a ``ValueBindingPatternSyntax``. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node @@ -3358,6 +3372,11 @@ open class SyntaxRewriter { Syntax(visit(SpecializeTargetFunctionArgumentSyntax(unsafeCasting: node))) } + @inline(never) + private func visitSpecializedAttributeArgumentSyntaxImpl(_ node: Syntax) -> Syntax { + Syntax(visit(SpecializedAttributeArgumentSyntax(unsafeCasting: node))) + } + @inline(never) private func visitStringLiteralExprSyntaxImpl(_ node: Syntax) -> Syntax { Syntax(visit(StringLiteralExprSyntax(unsafeCasting: node))) @@ -3548,6 +3567,11 @@ open class SyntaxRewriter { Syntax(visit(UnsafeExprSyntax(unsafeCasting: node))) } + @inline(never) + private func visitUsingDeclSyntaxImpl(_ node: Syntax) -> Syntax { + Syntax(visit(UsingDeclSyntax(unsafeCasting: node))) + } + @inline(never) private func visitValueBindingPatternSyntaxImpl(_ node: Syntax) -> Syntax { Syntax(visit(ValueBindingPatternSyntax(unsafeCasting: node))) @@ -4112,6 +4136,8 @@ open class SyntaxRewriter { return self.visitSpecializeAvailabilityArgumentSyntaxImpl(_:) case .specializeTargetFunctionArgument: return self.visitSpecializeTargetFunctionArgumentSyntaxImpl(_:) + case .specializedAttributeArgument: + return self.visitSpecializedAttributeArgumentSyntaxImpl(_:) case .stringLiteralExpr: return self.visitStringLiteralExprSyntaxImpl(_:) case .stringLiteralSegmentList: @@ -4188,6 +4214,8 @@ open class SyntaxRewriter { return self.visitUnresolvedTernaryExprSyntaxImpl(_:) case .unsafeExpr: return self.visitUnsafeExprSyntaxImpl(_:) + case .usingDecl: + return self.visitUsingDeclSyntaxImpl(_:) case .valueBindingPattern: return self.visitValueBindingPatternSyntaxImpl(_:) case .variableDecl: @@ -4698,6 +4726,8 @@ open class SyntaxRewriter { return visitSpecializeAvailabilityArgumentSyntaxImpl(node) case .specializeTargetFunctionArgument: return visitSpecializeTargetFunctionArgumentSyntaxImpl(node) + case .specializedAttributeArgument: + return visitSpecializedAttributeArgumentSyntaxImpl(node) case .stringLiteralExpr: return visitStringLiteralExprSyntaxImpl(node) case .stringLiteralSegmentList: @@ -4774,6 +4804,8 @@ open class SyntaxRewriter { return visitUnresolvedTernaryExprSyntaxImpl(node) case .unsafeExpr: return visitUnsafeExprSyntaxImpl(node) + case .usingDecl: + return visitUsingDeclSyntaxImpl(node) case .valueBindingPattern: return visitValueBindingPatternSyntaxImpl(node) case .variableDecl: diff --git a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift index 739a203874c..914b87f2692 100644 --- a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift @@ -35,17 +35,15 @@ open class SyntaxVisitor { dispatchVisit(Syntax(node)) } - /// Visiting `ABIAttributeArgumentsSyntax` specifically. + /// Visiting ``ABIAttributeArgumentsSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: how should we continue visiting. - @_spi(ExperimentalLanguageFeatures) open func visit(_ node: ABIAttributeArgumentsSyntax) -> SyntaxVisitorContinueKind { return .visitChildren } - /// The function called after visiting `ABIAttributeArgumentsSyntax` and its descendants. + /// The function called after visiting ``ABIAttributeArgumentsSyntax`` and its descendants. /// - node: the node we just finished visiting. - @_spi(ExperimentalLanguageFeatures) open func visitPost(_ node: ABIAttributeArgumentsSyntax) { } @@ -2915,6 +2913,18 @@ open class SyntaxVisitor { open func visitPost(_ node: SpecializeTargetFunctionArgumentSyntax) { } + /// Visiting ``SpecializedAttributeArgumentSyntax`` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: how should we continue visiting. + open func visit(_ node: SpecializedAttributeArgumentSyntax) -> SyntaxVisitorContinueKind { + return .visitChildren + } + + /// The function called after visiting ``SpecializedAttributeArgumentSyntax`` and its descendants. + /// - node: the node we just finished visiting. + open func visitPost(_ node: SpecializedAttributeArgumentSyntax) { + } + /// Visiting ``StringLiteralExprSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: how should we continue visiting. @@ -3373,6 +3383,20 @@ open class SyntaxVisitor { open func visitPost(_ node: UnsafeExprSyntax) { } + /// Visiting `UsingDeclSyntax` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: how should we continue visiting. + @_spi(ExperimentalLanguageFeatures) + open func visit(_ node: UsingDeclSyntax) -> SyntaxVisitorContinueKind { + return .visitChildren + } + + /// The function called after visiting `UsingDeclSyntax` and its descendants. + /// - node: the node we just finished visiting. + @_spi(ExperimentalLanguageFeatures) + open func visitPost(_ node: UsingDeclSyntax) { + } + /// Visiting ``ValueBindingPatternSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: how should we continue visiting. @@ -5440,6 +5464,14 @@ open class SyntaxVisitor { visitPost(SpecializeTargetFunctionArgumentSyntax(unsafeCasting: node)) } + @inline(never) + private func visitSpecializedAttributeArgumentSyntaxImpl(_ node: Syntax) { + if visit(SpecializedAttributeArgumentSyntax(unsafeCasting: node)) == .visitChildren { + visitChildren(node) + } + visitPost(SpecializedAttributeArgumentSyntax(unsafeCasting: node)) + } + @inline(never) private func visitStringLiteralExprSyntaxImpl(_ node: Syntax) { if visit(StringLiteralExprSyntax(unsafeCasting: node)) == .visitChildren { @@ -5744,6 +5776,14 @@ open class SyntaxVisitor { visitPost(UnsafeExprSyntax(unsafeCasting: node)) } + @inline(never) + private func visitUsingDeclSyntaxImpl(_ node: Syntax) { + if visit(UsingDeclSyntax(unsafeCasting: node)) == .visitChildren { + visitChildren(node) + } + visitPost(UsingDeclSyntax(unsafeCasting: node)) + } + @inline(never) private func visitValueBindingPatternSyntaxImpl(_ node: Syntax) { if visit(ValueBindingPatternSyntax(unsafeCasting: node)) == .visitChildren { @@ -6344,6 +6384,8 @@ open class SyntaxVisitor { return self.visitSpecializeAvailabilityArgumentSyntaxImpl(_:) case .specializeTargetFunctionArgument: return self.visitSpecializeTargetFunctionArgumentSyntaxImpl(_:) + case .specializedAttributeArgument: + return self.visitSpecializedAttributeArgumentSyntaxImpl(_:) case .stringLiteralExpr: return self.visitStringLiteralExprSyntaxImpl(_:) case .stringLiteralSegmentList: @@ -6420,6 +6462,8 @@ open class SyntaxVisitor { return self.visitUnresolvedTernaryExprSyntaxImpl(_:) case .unsafeExpr: return self.visitUnsafeExprSyntaxImpl(_:) + case .usingDecl: + return self.visitUsingDeclSyntaxImpl(_:) case .valueBindingPattern: return self.visitValueBindingPatternSyntaxImpl(_:) case .variableDecl: @@ -6930,6 +6974,8 @@ open class SyntaxVisitor { self.visitSpecializeAvailabilityArgumentSyntaxImpl(node) case .specializeTargetFunctionArgument: self.visitSpecializeTargetFunctionArgumentSyntaxImpl(node) + case .specializedAttributeArgument: + self.visitSpecializedAttributeArgumentSyntaxImpl(node) case .stringLiteralExpr: self.visitStringLiteralExprSyntaxImpl(node) case .stringLiteralSegmentList: @@ -7006,6 +7052,8 @@ open class SyntaxVisitor { self.visitUnresolvedTernaryExprSyntaxImpl(node) case .unsafeExpr: self.visitUnsafeExprSyntaxImpl(node) + case .usingDecl: + self.visitUsingDeclSyntaxImpl(node) case .valueBindingPattern: self.visitValueBindingPatternSyntaxImpl(node) case .variableDecl: diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift index 5c824e33f3c..a04d4c66d1a 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift @@ -13,7 +13,6 @@ // Do not edit directly! // swift-format-ignore-file -@_spi(ExperimentalLanguageFeatures) @_spi(RawSyntax) public struct RawABIAttributeArgumentsSyntax: RawSyntaxNodeProtocol { public enum Provider: RawSyntaxNodeProtocol { @@ -1606,6 +1605,7 @@ public struct RawAttributeSyntax: RawSyntaxNodeProtocol { case argumentList(RawLabeledExprListSyntax) case availability(RawAvailabilityArgumentListSyntax) case specializeArguments(RawSpecializeAttributeArgumentListSyntax) + case specializedArguments(RawSpecializedAttributeArgumentSyntax) case objCName(RawObjCSelectorPieceListSyntax) case implementsArguments(RawImplementsAttributeArgumentsSyntax) case differentiableArguments(RawDifferentiableAttributeArgumentsSyntax) @@ -1615,12 +1615,10 @@ public struct RawAttributeSyntax: RawSyntaxNodeProtocol { case dynamicReplacementArguments(RawDynamicReplacementAttributeArgumentsSyntax) case effectsArguments(RawEffectsAttributeArgumentListSyntax) case documentationArguments(RawDocumentationAttributeArgumentListSyntax) - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) case abiArguments(RawABIAttributeArgumentsSyntax) public static func isKindOf(_ raw: RawSyntax) -> Bool { - RawLabeledExprListSyntax.isKindOf(raw) || RawAvailabilityArgumentListSyntax.isKindOf(raw) || RawSpecializeAttributeArgumentListSyntax.isKindOf(raw) || RawObjCSelectorPieceListSyntax.isKindOf(raw) || RawImplementsAttributeArgumentsSyntax.isKindOf(raw) || RawDifferentiableAttributeArgumentsSyntax.isKindOf(raw) || RawDerivativeAttributeArgumentsSyntax.isKindOf(raw) || RawBackDeployedAttributeArgumentsSyntax.isKindOf(raw) || RawOriginallyDefinedInAttributeArgumentsSyntax.isKindOf(raw) || RawDynamicReplacementAttributeArgumentsSyntax.isKindOf(raw) || RawEffectsAttributeArgumentListSyntax.isKindOf(raw) || RawDocumentationAttributeArgumentListSyntax.isKindOf(raw) || RawABIAttributeArgumentsSyntax.isKindOf(raw) + RawLabeledExprListSyntax.isKindOf(raw) || RawAvailabilityArgumentListSyntax.isKindOf(raw) || RawSpecializeAttributeArgumentListSyntax.isKindOf(raw) || RawSpecializedAttributeArgumentSyntax.isKindOf(raw) || RawObjCSelectorPieceListSyntax.isKindOf(raw) || RawImplementsAttributeArgumentsSyntax.isKindOf(raw) || RawDifferentiableAttributeArgumentsSyntax.isKindOf(raw) || RawDerivativeAttributeArgumentsSyntax.isKindOf(raw) || RawBackDeployedAttributeArgumentsSyntax.isKindOf(raw) || RawOriginallyDefinedInAttributeArgumentsSyntax.isKindOf(raw) || RawDynamicReplacementAttributeArgumentsSyntax.isKindOf(raw) || RawEffectsAttributeArgumentListSyntax.isKindOf(raw) || RawDocumentationAttributeArgumentListSyntax.isKindOf(raw) || RawABIAttributeArgumentsSyntax.isKindOf(raw) } public var raw: RawSyntax { @@ -1631,6 +1629,8 @@ public struct RawAttributeSyntax: RawSyntaxNodeProtocol { return node.raw case .specializeArguments(let node): return node.raw + case .specializedArguments(let node): + return node.raw case .objCName(let node): return node.raw case .implementsArguments(let node): @@ -1661,6 +1661,8 @@ public struct RawAttributeSyntax: RawSyntaxNodeProtocol { self = .availability(node) } else if let node = node.as(RawSpecializeAttributeArgumentListSyntax.self) { self = .specializeArguments(node) + } else if let node = node.as(RawSpecializedAttributeArgumentSyntax.self) { + self = .specializedArguments(node) } else if let node = node.as(RawObjCSelectorPieceListSyntax.self) { self = .objCName(node) } else if let node = node.as(RawImplementsAttributeArgumentsSyntax.self) { @@ -1825,21 +1827,25 @@ public struct RawAttributedTypeSyntax: RawTypeSyntaxNodeProtocol { specifiers: RawTypeSpecifierListSyntax, _ unexpectedBetweenSpecifiersAndAttributes: RawUnexpectedNodesSyntax? = nil, attributes: RawAttributeListSyntax, - _ unexpectedBetweenAttributesAndBaseType: RawUnexpectedNodesSyntax? = nil, + _ unexpectedBetweenAttributesAndLateSpecifiers: RawUnexpectedNodesSyntax? = nil, + lateSpecifiers: RawTypeSpecifierListSyntax, + _ unexpectedBetweenLateSpecifiersAndBaseType: RawUnexpectedNodesSyntax? = nil, baseType: some RawTypeSyntaxNodeProtocol, _ unexpectedAfterBaseType: RawUnexpectedNodesSyntax? = nil, arena: __shared RawSyntaxArena ) { let raw = RawSyntax.makeLayout( - kind: .attributedType, uninitializedCount: 7, arena: arena) { layout in + kind: .attributedType, uninitializedCount: 9, arena: arena) { layout in layout.initialize(repeating: nil) layout[0] = unexpectedBeforeSpecifiers?.raw layout[1] = specifiers.raw layout[2] = unexpectedBetweenSpecifiersAndAttributes?.raw layout[3] = attributes.raw - layout[4] = unexpectedBetweenAttributesAndBaseType?.raw - layout[5] = baseType.raw - layout[6] = unexpectedAfterBaseType?.raw + layout[4] = unexpectedBetweenAttributesAndLateSpecifiers?.raw + layout[5] = lateSpecifiers.raw + layout[6] = unexpectedBetweenLateSpecifiersAndBaseType?.raw + layout[7] = baseType.raw + layout[8] = unexpectedAfterBaseType?.raw } self.init(unchecked: raw) } @@ -1860,16 +1866,24 @@ public struct RawAttributedTypeSyntax: RawTypeSyntaxNodeProtocol { layoutView.children[3].map(RawAttributeListSyntax.init(raw:))! } - public var unexpectedBetweenAttributesAndBaseType: RawUnexpectedNodesSyntax? { + public var unexpectedBetweenAttributesAndLateSpecifiers: RawUnexpectedNodesSyntax? { layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) } + public var lateSpecifiers: RawTypeSpecifierListSyntax { + layoutView.children[5].map(RawTypeSpecifierListSyntax.init(raw:))! + } + + public var unexpectedBetweenLateSpecifiersAndBaseType: RawUnexpectedNodesSyntax? { + layoutView.children[6].map(RawUnexpectedNodesSyntax.init(raw:)) + } + public var baseType: RawTypeSyntax { - layoutView.children[5].map(RawTypeSyntax.init(raw:))! + layoutView.children[7].map(RawTypeSyntax.init(raw:))! } public var unexpectedAfterBaseType: RawUnexpectedNodesSyntax? { - layoutView.children[6].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[8].map(RawUnexpectedNodesSyntax.init(raw:)) } } diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesD.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesD.swift index d9f5b337aea..79480c99c6b 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesD.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesD.swift @@ -499,7 +499,7 @@ public struct RawDeclSyntax: RawDeclSyntaxNodeProtocol { public static func isKindOf(_ raw: RawSyntax) -> Bool { switch raw.kind { - case .accessorDecl, .actorDecl, .associatedTypeDecl, .classDecl, .deinitializerDecl, .editorPlaceholderDecl, .enumCaseDecl, .enumDecl, .extensionDecl, .functionDecl, .ifConfigDecl, .importDecl, .initializerDecl, .macroDecl, .macroExpansionDecl, .missingDecl, .operatorDecl, .poundSourceLocation, .precedenceGroupDecl, .protocolDecl, .structDecl, .subscriptDecl, .typeAliasDecl, .variableDecl: + case .accessorDecl, .actorDecl, .associatedTypeDecl, .classDecl, .deinitializerDecl, .editorPlaceholderDecl, .enumCaseDecl, .enumDecl, .extensionDecl, .functionDecl, .ifConfigDecl, .importDecl, .initializerDecl, .macroDecl, .macroExpansionDecl, .missingDecl, .operatorDecl, .poundSourceLocation, .precedenceGroupDecl, .protocolDecl, .structDecl, .subscriptDecl, .typeAliasDecl, .usingDecl, .variableDecl: return true default: return false diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesQRS.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesQRS.swift index e4313ae32a7..3092d21e457 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesQRS.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesQRS.swift @@ -1190,6 +1190,64 @@ public struct RawSpecializeTargetFunctionArgumentSyntax: RawSyntaxNodeProtocol { } } +@_spi(RawSyntax) +public struct RawSpecializedAttributeArgumentSyntax: RawSyntaxNodeProtocol { + @_spi(RawSyntax) + public var layoutView: RawSyntaxLayoutView { + return raw.layoutView! + } + + public static func isKindOf(_ raw: RawSyntax) -> Bool { + return raw.kind == .specializedAttributeArgument + } + + 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( + _ unexpectedBeforeGenericWhereClause: RawUnexpectedNodesSyntax? = nil, + genericWhereClause: RawGenericWhereClauseSyntax, + _ unexpectedAfterGenericWhereClause: RawUnexpectedNodesSyntax? = nil, + arena: __shared RawSyntaxArena + ) { + let raw = RawSyntax.makeLayout( + kind: .specializedAttributeArgument, uninitializedCount: 3, arena: arena) { layout in + layout.initialize(repeating: nil) + layout[0] = unexpectedBeforeGenericWhereClause?.raw + layout[1] = genericWhereClause.raw + layout[2] = unexpectedAfterGenericWhereClause?.raw + } + self.init(unchecked: raw) + } + + public var unexpectedBeforeGenericWhereClause: RawUnexpectedNodesSyntax? { + layoutView.children[0].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var genericWhereClause: RawGenericWhereClauseSyntax { + layoutView.children[1].map(RawGenericWhereClauseSyntax.init(raw:))! + } + + public var unexpectedAfterGenericWhereClause: RawUnexpectedNodesSyntax? { + layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + } +} + @_spi(RawSyntax) public struct RawStmtSyntax: RawStmtSyntaxNodeProtocol { @_spi(RawSyntax) diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesTUVWXYZ.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesTUVWXYZ.swift index e4b5a2b69a0..704219505b9 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesTUVWXYZ.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesTUVWXYZ.swift @@ -1863,6 +1863,108 @@ public struct RawUnsafeExprSyntax: RawExprSyntaxNodeProtocol { } } +@_spi(ExperimentalLanguageFeatures) +@_spi(RawSyntax) +public struct RawUsingDeclSyntax: RawDeclSyntaxNodeProtocol { + public enum Specifier: RawSyntaxNodeProtocol { + case attribute(RawAttributeSyntax) + /// ### Tokens + /// + /// For syntax trees generated by the parser, this is guaranteed to be ``. + case modifier(RawTokenSyntax) + + public static func isKindOf(_ raw: RawSyntax) -> Bool { + RawAttributeSyntax.isKindOf(raw) || RawTokenSyntax.isKindOf(raw) + } + + public var raw: RawSyntax { + switch self { + case .attribute(let node): + return node.raw + case .modifier(let node): + return node.raw + } + } + + public init?(_ node: __shared some RawSyntaxNodeProtocol) { + if let node = node.as(RawAttributeSyntax.self) { + self = .attribute(node) + } else if let node = node.as(RawTokenSyntax.self) { + self = .modifier(node) + } else { + return nil + } + } + } + + @_spi(RawSyntax) + public var layoutView: RawSyntaxLayoutView { + return raw.layoutView! + } + + public static func isKindOf(_ raw: RawSyntax) -> Bool { + return raw.kind == .usingDecl + } + + 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( + _ unexpectedBeforeUsingKeyword: RawUnexpectedNodesSyntax? = nil, + usingKeyword: RawTokenSyntax, + _ unexpectedBetweenUsingKeywordAndSpecifier: RawUnexpectedNodesSyntax? = nil, + specifier: Specifier, + _ unexpectedAfterSpecifier: RawUnexpectedNodesSyntax? = nil, + arena: __shared RawSyntaxArena + ) { + let raw = RawSyntax.makeLayout( + kind: .usingDecl, uninitializedCount: 5, arena: arena) { layout in + layout.initialize(repeating: nil) + layout[0] = unexpectedBeforeUsingKeyword?.raw + layout[1] = usingKeyword.raw + layout[2] = unexpectedBetweenUsingKeywordAndSpecifier?.raw + layout[3] = specifier.raw + layout[4] = unexpectedAfterSpecifier?.raw + } + self.init(unchecked: raw) + } + + public var unexpectedBeforeUsingKeyword: RawUnexpectedNodesSyntax? { + layoutView.children[0].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var usingKeyword: RawTokenSyntax { + layoutView.children[1].map(RawTokenSyntax.init(raw:))! + } + + public var unexpectedBetweenUsingKeywordAndSpecifier: RawUnexpectedNodesSyntax? { + layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var specifier: RawSyntax { + layoutView.children[3]! + } + + public var unexpectedAfterSpecifier: RawUnexpectedNodesSyntax? { + layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) + } +} + @_spi(RawSyntax) public struct RawValueBindingPatternSyntax: RawPatternSyntaxNodeProtocol { @_spi(RawSyntax) diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index 0ca5359f6e7..4def2848664 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -422,14 +422,16 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 10, verify(layout[10], as: RawUnexpectedNodesSyntax?.self)) } func validateAttributedTypeSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { - assert(layout.count == 7) + assert(layout.count == 9) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 1, verify(layout[1], as: RawTypeSpecifierListSyntax.self)) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 3, verify(layout[3], as: RawAttributeListSyntax.self)) assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 5, verify(layout[5], as: RawTypeSyntax.self)) + assertNoError(kind, 5, verify(layout[5], as: RawTypeSpecifierListSyntax.self)) assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 7, verify(layout[7], as: RawTypeSyntax.self)) + assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self)) } func validateAvailabilityArgumentListSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { for (index, element) in layout.enumerated() { @@ -1748,7 +1750,7 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 3, verify(layout[3], as: RawGenericArgumentSyntax.self)) assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 5, verify(layout[5], as: RawTokenSyntax.self, tokenChoices: [.keyword("x")])) + assertNoError(kind, 5, verify(layout[5], as: RawTokenSyntax.self, tokenChoices: [.keyword("of")])) assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 7, verify(layout[7], as: RawGenericArgumentSyntax.self)) assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self)) @@ -2638,6 +2640,12 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 7, verify(layout[7], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.comma)])) assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self)) } + func validateSpecializedAttributeArgumentSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { + assert(layout.count == 3) + assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 1, verify(layout[1], as: RawGenericWhereClauseSyntax.self)) + assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + } func validateStringLiteralExprSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { assert(layout.count == 11) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) @@ -3015,6 +3023,15 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 3, verify(layout[3], as: RawExprSyntax.self)) assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) } + func validateUsingDeclSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { + assert(layout.count == 5) + assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [.keyword("using")])) + assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + assertAnyHasNoError(kind, 3, [ + verify(layout[3], as: RawSyntax.self)]) + assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) + } func validateValueBindingPatternSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { assert(layout.count == 5) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) @@ -3606,6 +3623,8 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { validateSpecializeAvailabilityArgumentSyntax(kind: kind, layout: layout) case .specializeTargetFunctionArgument: validateSpecializeTargetFunctionArgumentSyntax(kind: kind, layout: layout) + case .specializedAttributeArgument: + validateSpecializedAttributeArgumentSyntax(kind: kind, layout: layout) case .stringLiteralExpr: validateStringLiteralExprSyntax(kind: kind, layout: layout) case .stringLiteralSegmentList: @@ -3682,6 +3701,8 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { validateUnresolvedTernaryExprSyntax(kind: kind, layout: layout) case .unsafeExpr: validateUnsafeExprSyntax(kind: kind, layout: layout) + case .usingDecl: + validateUsingDeclSyntax(kind: kind, layout: layout) case .valueBindingPattern: validateValueBindingPatternSyntax(kind: kind, layout: layout) case .variableDecl: diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift index 1a444b28949..4e07265bc4a 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift @@ -17,8 +17,6 @@ /// The arguments of the '@abi' attribute /// -/// - Note: Requires experimental feature `abiAttribute`. -/// /// ### Children /// /// - `provider`: (``AssociatedTypeDeclSyntax`` | ``DeinitializerDeclSyntax`` | ``EnumCaseDeclSyntax`` | ``FunctionDeclSyntax`` | ``InitializerDeclSyntax`` | ``MissingDeclSyntax`` | ``SubscriptDeclSyntax`` | ``TypeAliasDeclSyntax`` | ``VariableDeclSyntax``) @@ -26,7 +24,6 @@ /// ### Contained in /// /// - ``AttributeSyntax``.``AttributeSyntax/arguments`` -@_spi(ExperimentalLanguageFeatures) public struct ABIAttributeArgumentsSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodeProtocol { public enum Provider: SyntaxChildChoices, SyntaxHashable { case associatedType(AssociatedTypeDeclSyntax) @@ -2600,6 +2597,10 @@ public struct AssignmentExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafExp /// - `inheritanceClause`: ``InheritanceClauseSyntax``? /// - `initializer`: ``TypeInitializerClauseSyntax``? /// - `genericWhereClause`: ``GenericWhereClauseSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct AssociatedTypeDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax @@ -3097,7 +3098,7 @@ public struct AttributeClauseFileSyntax: SyntaxProtocol, SyntaxHashable, _LeafSy /// - `atSign`: `@` /// - `attributeName`: ``TypeSyntax`` /// - `leftParen`: `(`? -/// - `arguments`: (``LabeledExprListSyntax`` | ``AvailabilityArgumentListSyntax`` | ``SpecializeAttributeArgumentListSyntax`` | ``ObjCSelectorPieceListSyntax`` | ``ImplementsAttributeArgumentsSyntax`` | ``DifferentiableAttributeArgumentsSyntax`` | ``DerivativeAttributeArgumentsSyntax`` | ``BackDeployedAttributeArgumentsSyntax`` | ``OriginallyDefinedInAttributeArgumentsSyntax`` | ``DynamicReplacementAttributeArgumentsSyntax`` | ``EffectsAttributeArgumentListSyntax`` | ``DocumentationAttributeArgumentListSyntax`` | `ABIAttributeArgumentsSyntax`)? +/// - `arguments`: (``LabeledExprListSyntax`` | ``AvailabilityArgumentListSyntax`` | ``SpecializeAttributeArgumentListSyntax`` | ``SpecializedAttributeArgumentSyntax`` | ``ObjCSelectorPieceListSyntax`` | ``ImplementsAttributeArgumentsSyntax`` | ``DifferentiableAttributeArgumentsSyntax`` | ``DerivativeAttributeArgumentsSyntax`` | ``BackDeployedAttributeArgumentsSyntax`` | ``OriginallyDefinedInAttributeArgumentsSyntax`` | ``DynamicReplacementAttributeArgumentsSyntax`` | ``EffectsAttributeArgumentListSyntax`` | ``DocumentationAttributeArgumentListSyntax`` | ``ABIAttributeArgumentsSyntax``)? /// - `rightParen`: `)`? /// /// ### Contained in @@ -3109,6 +3110,7 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr case argumentList(LabeledExprListSyntax) case availability(AvailabilityArgumentListSyntax) case specializeArguments(SpecializeAttributeArgumentListSyntax) + case specializedArguments(SpecializedAttributeArgumentSyntax) case objCName(ObjCSelectorPieceListSyntax) case implementsArguments(ImplementsAttributeArgumentsSyntax) case differentiableArguments(DifferentiableAttributeArgumentsSyntax) @@ -3118,8 +3120,6 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr case dynamicReplacementArguments(DynamicReplacementAttributeArgumentsSyntax) case effectsArguments(EffectsAttributeArgumentListSyntax) case documentationArguments(DocumentationAttributeArgumentListSyntax) - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) case abiArguments(ABIAttributeArgumentsSyntax) public var _syntaxNode: Syntax { @@ -3130,6 +3130,8 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr return node._syntaxNode case .specializeArguments(let node): return node._syntaxNode + case .specializedArguments(let node): + return node._syntaxNode case .objCName(let node): return node._syntaxNode case .implementsArguments(let node): @@ -3165,6 +3167,10 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr self = .specializeArguments(node) } + public init(_ node: SpecializedAttributeArgumentSyntax) { + self = .specializedArguments(node) + } + public init(_ node: ObjCSelectorPieceListSyntax) { self = .objCName(node) } @@ -3201,8 +3207,6 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr self = .documentationArguments(node) } - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) public init(_ node: ABIAttributeArgumentsSyntax) { self = .abiArguments(node) } @@ -3214,6 +3218,8 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr self = .availability(node) } else if let node = node.as(SpecializeAttributeArgumentListSyntax.self) { self = .specializeArguments(node) + } else if let node = node.as(SpecializedAttributeArgumentSyntax.self) { + self = .specializedArguments(node) } else if let node = node.as(ObjCSelectorPieceListSyntax.self) { self = .objCName(node) } else if let node = node.as(ImplementsAttributeArgumentsSyntax.self) { @@ -3244,6 +3250,7 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr .node(LabeledExprListSyntax.self), .node(AvailabilityArgumentListSyntax.self), .node(SpecializeAttributeArgumentListSyntax.self), + .node(SpecializedAttributeArgumentSyntax.self), .node(ObjCSelectorPieceListSyntax.self), .node(ImplementsAttributeArgumentsSyntax.self), .node(DifferentiableAttributeArgumentsSyntax.self), @@ -3323,6 +3330,28 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr return self.as(SpecializeAttributeArgumentListSyntax.self)! } + /// Checks if the current syntax node can be cast to ``SpecializedAttributeArgumentSyntax``. + /// + /// - Returns: `true` if the node can be cast, `false` otherwise. + public func `is`(_ syntaxType: SpecializedAttributeArgumentSyntax.Type) -> Bool { + return self.as(syntaxType) != nil + } + + /// Attempts to cast the current syntax node to ``SpecializedAttributeArgumentSyntax``. + /// + /// - Returns: An instance of ``SpecializedAttributeArgumentSyntax``, or `nil` if the cast fails. + public func `as`(_ syntaxType: SpecializedAttributeArgumentSyntax.Type) -> SpecializedAttributeArgumentSyntax? { + return SpecializedAttributeArgumentSyntax.init(self) + } + + /// Force-casts the current syntax node to ``SpecializedAttributeArgumentSyntax``. + /// + /// - Returns: An instance of ``SpecializedAttributeArgumentSyntax``. + /// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast. + public func cast(_ syntaxType: SpecializedAttributeArgumentSyntax.Type) -> SpecializedAttributeArgumentSyntax { + return self.as(SpecializedAttributeArgumentSyntax.self)! + } + /// Checks if the current syntax node can be cast to ``ObjCSelectorPieceListSyntax``. /// /// - Returns: `true` if the node can be cast, `false` otherwise. @@ -3521,30 +3550,24 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr return self.as(DocumentationAttributeArgumentListSyntax.self)! } - /// Checks if the current syntax node can be cast to `ABIAttributeArgumentsSyntax`. + /// Checks if the current syntax node can be cast to ``ABIAttributeArgumentsSyntax``. /// /// - Returns: `true` if the node can be cast, `false` otherwise. - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) public func `is`(_ syntaxType: ABIAttributeArgumentsSyntax.Type) -> Bool { return self.as(syntaxType) != nil } - /// Attempts to cast the current syntax node to `ABIAttributeArgumentsSyntax`. + /// Attempts to cast the current syntax node to ``ABIAttributeArgumentsSyntax``. /// - /// - Returns: An instance of `ABIAttributeArgumentsSyntax`, or `nil` if the cast fails. - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) + /// - Returns: An instance of ``ABIAttributeArgumentsSyntax``, or `nil` if the cast fails. public func `as`(_ syntaxType: ABIAttributeArgumentsSyntax.Type) -> ABIAttributeArgumentsSyntax? { return ABIAttributeArgumentsSyntax.init(self) } - /// Force-casts the current syntax node to `ABIAttributeArgumentsSyntax`. + /// Force-casts the current syntax node to ``ABIAttributeArgumentsSyntax``. /// - /// - Returns: An instance of `ABIAttributeArgumentsSyntax`. + /// - Returns: An instance of ``ABIAttributeArgumentsSyntax``. /// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast. - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) public func cast(_ syntaxType: ABIAttributeArgumentsSyntax.Type) -> ABIAttributeArgumentsSyntax { return self.as(ABIAttributeArgumentsSyntax.self)! } @@ -3766,6 +3789,7 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr /// /// - `specifiers`: ``TypeSpecifierListSyntax`` /// - `attributes`: ``AttributeListSyntax`` +/// - `lateSpecifiers`: ``TypeSpecifierListSyntax`` /// - `baseType`: ``TypeSyntax`` public struct AttributedTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSyntaxNodeProtocol { public let _syntaxNode: Syntax @@ -3786,6 +3810,7 @@ public struct AttributedTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp /// - 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. /// - specifiers: A list of specifiers that can be attached to the type, such as `inout`, `isolated`, or `consuming`. /// - attributes: A list of attributes that can be attached to the type, such as `@escaping`. + /// - lateSpecifiers: A list of specifiers that can be attached to the type after the attributes, such as 'nonisolated'. /// - baseType: The type to with the specifiers and attributes are applied. /// - 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( @@ -3794,7 +3819,9 @@ public struct AttributedTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp specifiers: TypeSpecifierListSyntax = [], _ unexpectedBetweenSpecifiersAndAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], - _ unexpectedBetweenAttributesAndBaseType: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenAttributesAndLateSpecifiers: UnexpectedNodesSyntax? = nil, + lateSpecifiers: TypeSpecifierListSyntax = [], + _ unexpectedBetweenLateSpecifiersAndBaseType: UnexpectedNodesSyntax? = nil, baseType: some TypeSyntaxProtocol, _ unexpectedAfterBaseType: UnexpectedNodesSyntax? = nil, trailingTrivia: Trivia? = nil @@ -3806,7 +3833,9 @@ public struct AttributedTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp specifiers, unexpectedBetweenSpecifiersAndAttributes, attributes, - unexpectedBetweenAttributesAndBaseType, + unexpectedBetweenAttributesAndLateSpecifiers, + lateSpecifiers, + unexpectedBetweenLateSpecifiersAndBaseType, baseType, unexpectedAfterBaseType ))) { (arena, _) in @@ -3815,7 +3844,9 @@ public struct AttributedTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp specifiers.raw, unexpectedBetweenSpecifiersAndAttributes?.raw, attributes.raw, - unexpectedBetweenAttributesAndBaseType?.raw, + unexpectedBetweenAttributesAndLateSpecifiers?.raw, + lateSpecifiers.raw, + unexpectedBetweenLateSpecifiersAndBaseType?.raw, baseType.raw, unexpectedAfterBaseType?.raw ] @@ -3922,7 +3953,7 @@ public struct AttributedTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp .cast(AttributedTypeSyntax.self) } - public var unexpectedBetweenAttributesAndBaseType: UnexpectedNodesSyntax? { + public var unexpectedBetweenAttributesAndLateSpecifiers: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) } @@ -3931,17 +3962,17 @@ public struct AttributedTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp } } - /// The type to with the specifiers and attributes are applied. - public var baseType: TypeSyntax { + /// A list of specifiers that can be attached to the type after the attributes, such as 'nonisolated'. + public var lateSpecifiers: TypeSpecifierListSyntax { get { - return Syntax(self).child(at: 5)!.cast(TypeSyntax.self) + return Syntax(self).child(at: 5)!.cast(TypeSpecifierListSyntax.self) } set(value) { self = Syntax(self).replacingChild(at: 5, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(AttributedTypeSyntax.self) } } - public var unexpectedAfterBaseType: UnexpectedNodesSyntax? { + public var unexpectedBetweenLateSpecifiersAndBaseType: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 6)?.cast(UnexpectedNodesSyntax.self) } @@ -3950,12 +3981,33 @@ public struct AttributedTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTyp } } + /// The type to with the specifiers and attributes are applied. + public var baseType: TypeSyntax { + get { + return Syntax(self).child(at: 7)!.cast(TypeSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 7, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(AttributedTypeSyntax.self) + } + } + + public var unexpectedAfterBaseType: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 8)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 8, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(AttributedTypeSyntax.self) + } + } + public static let structure: SyntaxNodeStructure = .layout([ \Self.unexpectedBeforeSpecifiers, \Self.specifiers, \Self.unexpectedBetweenSpecifiersAndAttributes, \Self.attributes, - \Self.unexpectedBetweenAttributesAndBaseType, + \Self.unexpectedBetweenAttributesAndLateSpecifiers, + \Self.lateSpecifiers, + \Self.unexpectedBetweenLateSpecifiersAndBaseType, \Self.baseType, \Self.unexpectedAfterBaseType ]) diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift index 6c8b49198a3..4891b0cdf97 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift @@ -893,6 +893,10 @@ public struct DeferStmtSyntax: StmtSyntaxProtocol, SyntaxHashable, _LeafStmtSynt /// - `deinitKeyword`: `deinit` /// - `effectSpecifiers`: ``DeinitializerEffectSpecifiersSyntax``? /// - `body`: ``CodeBlockSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct DeinitializerDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift index 2c9f89946cf..41c56cd8b1d 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift @@ -312,6 +312,10 @@ public struct EditorPlaceholderExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _ /// - `modifiers`: ``DeclModifierListSyntax`` /// - `caseKeyword`: `case` /// - `elements`: ``EnumCaseElementListSyntax`` +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct EnumCaseDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax @@ -3312,6 +3316,10 @@ public struct FunctionCallExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafE /// - `signature`: ``FunctionSignatureSyntax`` /// - `genericWhereClause`: ``GenericWhereClauseSyntax``? /// - `body`: ``CodeBlockSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct FunctionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift index d28ff8b926b..b6eec06d4b0 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift @@ -1261,6 +1261,7 @@ public struct GenericSpecializationExprSyntax: ExprSyntaxProtocol, SyntaxHashabl /// - ``MacroDeclSyntax``.``MacroDeclSyntax/genericWhereClause`` /// - ``ProtocolDeclSyntax``.``ProtocolDeclSyntax/genericWhereClause`` /// - ``SpecializeAttributeArgumentListSyntax`` +/// - ``SpecializedAttributeArgumentSyntax``.``SpecializedAttributeArgumentSyntax/genericWhereClause`` /// - ``StructDeclSyntax``.``StructDeclSyntax/genericWhereClause`` /// - ``SubscriptDeclSyntax``.``SubscriptDeclSyntax/genericWhereClause`` /// - ``TypeAliasDeclSyntax``.``TypeAliasDeclSyntax/genericWhereClause`` @@ -4022,6 +4023,10 @@ public struct InitializerClauseSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynt /// - `signature`: ``FunctionSignatureSyntax`` /// - `genericWhereClause`: ``GenericWhereClauseSyntax``? /// - `body`: ``CodeBlockSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct InitializerDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax @@ -4368,7 +4373,7 @@ public struct InitializerDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDe // MARK: - InlineArrayTypeSyntax -/// An inline array type `[3 x Int]`, sugar for `InlineArray<3, Int>`. +/// An inline array type `[3 of Int]`, sugar for `InlineArray<3, Int>`. /// /// - Note: Requires experimental feature `inlineArrayTypeSugar`. /// @@ -4376,7 +4381,7 @@ public struct InitializerDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDe /// /// - `leftSquare`: `[` /// - `count`: ``GenericArgumentSyntax`` -/// - `separator`: `x` +/// - `separator`: `of` /// - `element`: ``GenericArgumentSyntax`` /// - `rightSquare`: `]` @_spi(ExperimentalLanguageFeatures) @@ -4407,7 +4412,7 @@ public struct InlineArrayTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTy _ unexpectedBetweenLeftSquareAndCount: UnexpectedNodesSyntax? = nil, count: GenericArgumentSyntax, _ unexpectedBetweenCountAndSeparator: UnexpectedNodesSyntax? = nil, - separator: TokenSyntax = .keyword(.x), + separator: TokenSyntax = .keyword(.of), _ unexpectedBetweenSeparatorAndElement: UnexpectedNodesSyntax? = nil, element: GenericArgumentSyntax, _ unexpectedBetweenElementAndRightSquare: UnexpectedNodesSyntax? = nil, @@ -4486,7 +4491,7 @@ public struct InlineArrayTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTy /// The `count` argument for the inline array type. /// - /// - Note: In semantically valid Swift code, this is always an integer or a wildcard type, e.g `_` in `[_ x Int]`. + /// - Note: In semantically valid Swift code, this is always an integer or a wildcard type, e.g `_` in `[_ of Int]`. public var count: GenericArgumentSyntax { get { return Syntax(self).child(at: 3)!.cast(GenericArgumentSyntax.self) @@ -4507,7 +4512,7 @@ public struct InlineArrayTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTy /// ### Tokens /// - /// For syntax trees generated by the parser, this is guaranteed to be `x`. + /// For syntax trees generated by the parser, this is guaranteed to be `of`. public var separator: TokenSyntax { get { return Syntax(self).child(at: 5)!.cast(TokenSyntax.self) diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift index fe4e496d5ab..902e11c9a85 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift @@ -4536,6 +4536,10 @@ public struct MetatypeTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeS /// - `attributes`: ``AttributeListSyntax`` /// - `modifiers`: ``DeclModifierListSyntax`` /// - `placeholder`: `` +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct MissingDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift index 2431b585fc8..e8af78d650f 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift @@ -2062,6 +2062,87 @@ public struct SpecializeTargetFunctionArgumentSyntax: SyntaxProtocol, SyntaxHash ]) } +// MARK: - SpecializedAttributeArgumentSyntax + +/// The generic where clause for the `@specialized` attribute +/// +/// ### Children +/// +/// - `genericWhereClause`: ``GenericWhereClauseSyntax`` +/// +/// ### Contained in +/// +/// - ``AttributeSyntax``.``AttributeSyntax/arguments`` +public struct SpecializedAttributeArgumentSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodeProtocol { + public let _syntaxNode: Syntax + + public init?(_ node: __shared some SyntaxProtocol) { + guard node.raw.kind == .specializedAttributeArgument else { + return nil + } + self._syntaxNode = node._syntaxNode + } + + @_transparent + init(unsafeCasting node: Syntax) { + self._syntaxNode = node + } + + /// - 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. + /// - 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, + _ unexpectedBeforeGenericWhereClause: UnexpectedNodesSyntax? = nil, + genericWhereClause: GenericWhereClauseSyntax, + _ unexpectedAfterGenericWhereClause: 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((RawSyntaxArena(), (unexpectedBeforeGenericWhereClause, genericWhereClause, unexpectedAfterGenericWhereClause))) { (arena, _) in + let layout: [RawSyntax?] = [unexpectedBeforeGenericWhereClause?.raw, genericWhereClause.raw, unexpectedAfterGenericWhereClause?.raw] + let raw = RawSyntax.makeLayout( + kind: SyntaxKind.specializedAttributeArgument, + from: layout, + arena: arena, + leadingTrivia: leadingTrivia, + trailingTrivia: trailingTrivia + ) + return Syntax.forRoot(raw, rawNodeArena: arena).cast(Self.self) + } + } + + public var unexpectedBeforeGenericWhereClause: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 0)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 0, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(SpecializedAttributeArgumentSyntax.self) + } + } + + public var genericWhereClause: GenericWhereClauseSyntax { + get { + return Syntax(self).child(at: 1)!.cast(GenericWhereClauseSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 1, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(SpecializedAttributeArgumentSyntax.self) + } + } + + public var unexpectedAfterGenericWhereClause: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 2, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(SpecializedAttributeArgumentSyntax.self) + } + } + + public static let structure: SyntaxNodeStructure = .layout([\Self.unexpectedBeforeGenericWhereClause, \Self.genericWhereClause, \Self.unexpectedAfterGenericWhereClause]) +} + // MARK: - StringLiteralExprSyntax /// A string literal. @@ -3108,6 +3189,10 @@ public struct SubscriptCallExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Leaf /// - `returnClause`: ``ReturnClauseSyntax`` /// - `genericWhereClause`: ``GenericWhereClauseSyntax``? /// - `accessorBlock`: ``AccessorBlockSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct SubscriptDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift index 88aa709709f..bf5973151ba 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift @@ -1851,6 +1851,10 @@ public struct TupleTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSynt /// - `genericParameterClause`: ``GenericParameterClauseSyntax``? /// - `initializer`: ``TypeInitializerClauseSyntax`` /// - `genericWhereClause`: ``GenericWhereClauseSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct TypeAliasDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax @@ -3082,6 +3086,222 @@ public struct UnsafeExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafExprSyn ]) } +// MARK: - UsingDeclSyntax + +/// A `using` declaration, currently used to control actor isolation within the current file. +/// +/// An example of a `using` declaration is +/// +/// ```swift +/// using @MainActor +/// ``` +/// +/// - Note: Requires experimental feature `defaultIsolationPerFile`. +/// +/// ### Children +/// +/// - `usingKeyword`: `using` +/// - `specifier`: (``AttributeSyntax`` | ``) +@_spi(ExperimentalLanguageFeatures) +public struct UsingDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { + public enum Specifier: SyntaxChildChoices, SyntaxHashable { + case attribute(AttributeSyntax) + /// ### Tokens + /// + /// For syntax trees generated by the parser, this is guaranteed to be ``. + case modifier(TokenSyntax) + + public var _syntaxNode: Syntax { + switch self { + case .attribute(let node): + return node._syntaxNode + case .modifier(let node): + return node._syntaxNode + } + } + + public init(_ node: AttributeSyntax) { + self = .attribute(node) + } + + public init(_ node: TokenSyntax) { + self = .modifier(node) + } + + public init?(_ node: __shared some SyntaxProtocol) { + if let node = node.as(AttributeSyntax.self) { + self = .attribute(node) + } else if let node = node.as(TokenSyntax.self) { + self = .modifier(node) + } else { + return nil + } + } + + public static var structure: SyntaxNodeStructure { + return .choices([.node(AttributeSyntax.self), .node(TokenSyntax.self)]) + } + + /// Checks if the current syntax node can be cast to ``AttributeSyntax``. + /// + /// - Returns: `true` if the node can be cast, `false` otherwise. + public func `is`(_ syntaxType: AttributeSyntax.Type) -> Bool { + return self.as(syntaxType) != nil + } + + /// Attempts to cast the current syntax node to ``AttributeSyntax``. + /// + /// - Returns: An instance of ``AttributeSyntax``, or `nil` if the cast fails. + public func `as`(_ syntaxType: AttributeSyntax.Type) -> AttributeSyntax? { + return AttributeSyntax.init(self) + } + + /// Force-casts the current syntax node to ``AttributeSyntax``. + /// + /// - Returns: An instance of ``AttributeSyntax``. + /// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast. + public func cast(_ syntaxType: AttributeSyntax.Type) -> AttributeSyntax { + return self.as(AttributeSyntax.self)! + } + + /// Checks if the current syntax node can be cast to ``TokenSyntax``. + /// + /// - Returns: `true` if the node can be cast, `false` otherwise. + public func `is`(_ syntaxType: TokenSyntax.Type) -> Bool { + return self.as(syntaxType) != nil + } + + /// Attempts to cast the current syntax node to ``TokenSyntax``. + /// + /// - Returns: An instance of ``TokenSyntax``, or `nil` if the cast fails. + public func `as`(_ syntaxType: TokenSyntax.Type) -> TokenSyntax? { + return TokenSyntax.init(self) + } + + /// Force-casts the current syntax node to ``TokenSyntax``. + /// + /// - Returns: An instance of ``TokenSyntax``. + /// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast. + public func cast(_ syntaxType: TokenSyntax.Type) -> TokenSyntax { + return self.as(TokenSyntax.self)! + } + } + + public let _syntaxNode: Syntax + + public init?(_ node: __shared some SyntaxProtocol) { + guard node.raw.kind == .usingDecl else { + return nil + } + self._syntaxNode = node._syntaxNode + } + + @_transparent + init(unsafeCasting node: Syntax) { + self._syntaxNode = node + } + + /// - 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. + /// - usingKeyword: The `using` keyword for this declaration. + /// - specifier: The specifier that could be either an attribute or a modifier. + /// - 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, + _ unexpectedBeforeUsingKeyword: UnexpectedNodesSyntax? = nil, + usingKeyword: TokenSyntax = .keyword(.using), + _ unexpectedBetweenUsingKeywordAndSpecifier: UnexpectedNodesSyntax? = nil, + specifier: Specifier, + _ unexpectedAfterSpecifier: 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((RawSyntaxArena(), ( + unexpectedBeforeUsingKeyword, + usingKeyword, + unexpectedBetweenUsingKeywordAndSpecifier, + specifier, + unexpectedAfterSpecifier + ))) { (arena, _) in + let layout: [RawSyntax?] = [ + unexpectedBeforeUsingKeyword?.raw, + usingKeyword.raw, + unexpectedBetweenUsingKeywordAndSpecifier?.raw, + specifier.raw, + unexpectedAfterSpecifier?.raw + ] + let raw = RawSyntax.makeLayout( + kind: SyntaxKind.usingDecl, + from: layout, + arena: arena, + leadingTrivia: leadingTrivia, + trailingTrivia: trailingTrivia + ) + return Syntax.forRoot(raw, rawNodeArena: arena).cast(Self.self) + } + } + + public var unexpectedBeforeUsingKeyword: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 0)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 0, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(UsingDeclSyntax.self) + } + } + + /// The `using` keyword for this declaration. + /// + /// ### Tokens + /// + /// For syntax trees generated by the parser, this is guaranteed to be `using`. + public var usingKeyword: TokenSyntax { + get { + return Syntax(self).child(at: 1)!.cast(TokenSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 1, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(UsingDeclSyntax.self) + } + } + + public var unexpectedBetweenUsingKeywordAndSpecifier: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 2, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(UsingDeclSyntax.self) + } + } + + /// The specifier that could be either an attribute or a modifier. + public var specifier: Specifier { + get { + return Syntax(self).child(at: 3)!.cast(Specifier.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 3, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(UsingDeclSyntax.self) + } + } + + public var unexpectedAfterSpecifier: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 4, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(UsingDeclSyntax.self) + } + } + + public static let structure: SyntaxNodeStructure = .layout([ + \Self.unexpectedBeforeUsingKeyword, + \Self.usingKeyword, + \Self.unexpectedBetweenUsingKeywordAndSpecifier, + \Self.specifier, + \Self.unexpectedAfterSpecifier + ]) +} + // MARK: - ValueBindingPatternSyntax /// ### Children @@ -3219,6 +3439,10 @@ public struct ValueBindingPatternSyntax: PatternSyntaxProtocol, SyntaxHashable, /// - `modifiers`: ``DeclModifierListSyntax`` /// - `bindingSpecifier`: (`let` | `var` | `inout` | `_mutating` | `_borrowing` | `_consuming`) /// - `bindings`: ``PatternBindingListSyntax`` +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct VariableDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Sources/SwiftSyntaxMacros/MacroProtocols/Macro.swift b/Sources/SwiftSyntaxMacros/MacroProtocols/Macro.swift index 6203a6f9127..3045b364475 100644 --- a/Sources/SwiftSyntaxMacros/MacroProtocols/Macro.swift +++ b/Sources/SwiftSyntaxMacros/MacroProtocols/Macro.swift @@ -10,9 +10,18 @@ // //===----------------------------------------------------------------------===// +#if compiler(>=6.2) +/// Describes a macro. +public protocol Macro: SendableMetatype { + /// How the resulting expansion should be formatted, `.auto` by default. + /// Use `.disabled` for the expansion to be used as is. + static var formatMode: FormatMode { get } +} +#else /// Describes a macro. public protocol Macro { /// How the resulting expansion should be formatted, `.auto` by default. /// Use `.disabled` for the expansion to be used as is. static var formatMode: FormatMode { get } } +#endif diff --git a/Tests/SwiftIDEUtilsTest/FixItApplierTests.swift b/Tests/SwiftIDEUtilsTest/FixItApplierTests.swift new file mode 100644 index 00000000000..d45be14f3c5 --- /dev/null +++ b/Tests/SwiftIDEUtilsTest/FixItApplierTests.swift @@ -0,0 +1,418 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +@_spi(FixItApplier) import SwiftIDEUtils +import SwiftSyntax +import XCTest + +private extension SourceEdit { + init(range: Range, replacement: String) { + self.init( + range: AbsolutePosition(utf8Offset: range.lowerBound)..) { + if subrange.isEmpty { return } + var lower = subrange.lowerBound + var upper = subrange.upperBound + while lower < upper { + formIndex(before: &upper) + swapAt(lower, upper) + formIndex(after: &lower) + } + } +} + +private extension MutableCollection where Self: BidirectionalCollection, Element: Comparable { + /// Permutes this collection's elements through all the lexical orderings. + /// + /// Call `nextPermutation()` repeatedly starting with the collection in sorted + /// order. When the full cycle of all permutations has been completed, the + /// collection will be back in sorted order and this method will return + /// `false`. + /// + /// - Returns: A Boolean value indicating whether the collection still has + /// remaining permutations. When this method returns `false`, the collection + /// is in ascending order according to `areInIncreasingOrder`. + /// + /// - Complexity: O(*n*), where *n* is the length of the collection. + mutating func nextPermutation(upperBound: Index? = nil) -> Bool { + // Ensure we have > 1 element in the collection. + guard !isEmpty else { return false } + var i = index(before: endIndex) + if i == startIndex { return false } + + let upperBound = upperBound ?? endIndex + + while true { + let ip1 = i + formIndex(before: &i) + + // Find the last ascending pair (ie. ..., a, b, ... where a < b) + if self[i] < self[ip1] { + // Find the last element greater than self[i] + // swift-format-ignore: NeverForceUnwrap + // This is _always_ at most `ip1` due to if statement above + let j = lastIndex(where: { self[i] < $0 })! + + // At this point we have something like this: + // 0, 1, 4, 3, 2 + // ^ ^ + // i j + swapAt(i, j) + self.reverse(subrange: ip1.. == <#type#>) + func foo() { + } + """ + ) } func testMissingGenericTypeToAttribute() { @@ -87,6 +111,12 @@ final class AttributeTests: ParserTestCase { func foo(_ t: T) {} """ ) + assertParse( + """ + @specialized(where T : Int) + func foo(_ t: T) {} + """ + ) } func testMissingClosingParenToAttribute() { @@ -960,23 +990,20 @@ final class AttributeTests: ParserTestCase { parameterClause: FunctionParameterClauseSyntax {}, returnClause: ReturnClauseSyntax(type: TypeSyntax("Int")) ) - ) {}, - experimentalFeatures: [.abiAttribute] + ) {} ) assertParse( """ @abi(associatedtype AssocTy) associatedtype AssocTy - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(deinit) deinit {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -984,50 +1011,43 @@ final class AttributeTests: ParserTestCase { @abi(case someCase) case someCase } - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(func fn()) func fn() - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(init()) init() {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(subscript(i: Int) -> Element) subscript(i: Int) -> Element {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(typealias Typealias = @escaping () -> Void) typealias Typealias = () -> Void - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(let c1, c2) let c1, c2 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(var v1, v2) var v1, v2 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( @@ -1042,8 +1062,7 @@ final class AttributeTests: ParserTestCase { ), diagnostics: [ DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file") - ], - experimentalFeatures: [.abiAttribute] + ] ) assertParse( @@ -1067,8 +1086,7 @@ final class AttributeTests: ParserTestCase { ), diagnostics: [ DiagnosticSpec(locationMarker: "1️⃣", message: "import is not permitted as ABI-providing declaration") - ], - experimentalFeatures: [.abiAttribute] + ] ) // @@ -1079,15 +1097,13 @@ final class AttributeTests: ParserTestCase { """ @abi(associatedtype AssocTy = T) associatedtype AssocTy - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(deinit {}) deinit {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -1095,50 +1111,43 @@ final class AttributeTests: ParserTestCase { @abi(case someCase = 42) case someCase } - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(func fn() {}) func fn() - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(init() {}) init() {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(subscript(i: Int) -> Element { get {} set {} }) subscript(i: Int) -> Element {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(let c1 = 1, c2 = 2) let c1, c2 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(var v1 = 1, v2 = 2) var v1, v2 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(var v3 { get {} set {} }) var v3 - """, - experimentalFeatures: [.abiAttribute] + """ ) // @@ -1160,8 +1169,7 @@ final class AttributeTests: ParserTestCase { fixedSource: """ @abi(var <#pattern#>) var v1 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -1184,8 +1192,7 @@ final class AttributeTests: ParserTestCase { fixedSource: """ @abi(var v2) var v2 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -1203,8 +1210,7 @@ final class AttributeTests: ParserTestCase { fixedSource: """ @abi(<#declaration#>) func fn2() {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -1221,8 +1227,7 @@ final class AttributeTests: ParserTestCase { fixedSource: """ @abi(<#declaration#>) func fn3() {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -1244,8 +1249,7 @@ final class AttributeTests: ParserTestCase { fixedSource: """ @abi(<#declaration#>) func fn4_abi()) func fn4() {} - """, - experimentalFeatures: [.abiAttribute] + """ ) // `#if` is banned inside an `@abi` attribute. @@ -1278,51 +1282,7 @@ final class AttributeTests: ParserTestCase { func _fn() throws(E) ) func fn() throws(E) {} - """, - experimentalFeatures: [.abiAttribute] - ) - } - - func testABIAttributeWithoutFeature() throws { - assertParse( - """ - @abi(1️⃣func fn() -> Int2️⃣) - func fn1() -> Int { } - """, - substructure: FunctionDeclSyntax( - attributes: [ - .attribute( - AttributeSyntax( - attributeName: TypeSyntax("abi"), - leftParen: .leftParenToken(), - [Syntax(try FunctionDeclSyntax("func fn() -> Int"))], - arguments: .argumentList([]), - rightParen: .rightParenToken() - ) - ) - ], - name: "fn1", - signature: FunctionSignatureSyntax( - parameterClause: FunctionParameterClauseSyntax {}, - returnClause: ReturnClauseSyntax(type: TypeSyntax("Int")) - ) - ) {}, - diagnostics: [ - DiagnosticSpec( - locationMarker: "1️⃣", - message: "unexpected code 'func fn() -> Int' in attribute" - ), - DiagnosticSpec( - locationMarker: "2️⃣", - message: "expected argument for '@abi' attribute", - fixIts: ["insert attribute argument"] - ), - ], - fixedSource: """ - @abi(func fn() -> Int) - func fn1() -> Int { } - """, - experimentalFeatures: [] + """ ) } diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index 7ec097ec5bd..6a7bac74f68 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -12,7 +12,7 @@ import SwiftBasicFormat @_spi(Testing) @_spi(RawSyntax) @_spi(ExperimentalLanguageFeatures) import SwiftParser -@_spi(RawSyntax) import SwiftSyntax +@_spi(RawSyntax) @_spi(ExperimentalLanguageFeatures) import SwiftSyntax import SwiftSyntaxBuilder import XCTest @@ -770,6 +770,15 @@ final class DeclarationTests: ParserTestCase { } """ ) + assertParse( + """ + @specialized(where Array == Int) + @specialized(where T.Element == Int) + public func funcWithComplexSpecializeRequirements(t: T) -> Int { + return 55555 + } + """ + ) } func testParseRetroactiveExtension() { @@ -807,6 +816,17 @@ final class DeclarationTests: ParserTestCase { """ ) + assertParse( + """ + extension Int: @preconcurrency nonisolated Q {} + """ + ) + + assertParse( + """ + extension Int: @unsafe nonisolated Q {} + """ + ) } func testParseDynamicReplacement() { @@ -3529,4 +3549,162 @@ final class DeclarationTests: ParserTestCase { ] ) } + + func testTrailingCommas() { + assertParse( + """ + protocol Baaz< + Foo, + Bar, + > { + associatedtype Foo + associatedtype Bar + } + """ + ) + + assertParse( + """ + struct Foo< + T1, + T2, + T3, + >: Baaz< + T1, + T2, + > {} + """ + ) + } +} + +final class UsingDeclarationTests: ParserTestCase { + override var experimentalFeatures: Parser.ExperimentalFeatures { + [.defaultIsolationPerFile] + } + + func testUsing() { + assertParse( + "using @MainActor", + substructure: UsingDeclSyntax( + usingKeyword: .keyword(.using), + specifier: .attribute( + AttributeSyntax( + attributeName: IdentifierTypeSyntax( + name: .identifier("MainActor") + ) + ) + ) + ) + ) + assertParse( + "using nonisolated", + substructure: UsingDeclSyntax( + usingKeyword: .keyword(.using), + specifier: .modifier(.identifier("nonisolated")) + ) + ) + + assertParse( + "using @Test", + substructure: UsingDeclSyntax( + usingKeyword: .keyword(.using), + specifier: .attribute( + AttributeSyntax( + attributeName: IdentifierTypeSyntax( + name: .identifier("Test") + ) + ) + ) + ) + ) + + assertParse( + "using test", + substructure: UsingDeclSyntax( + usingKeyword: .keyword(.using), + specifier: .modifier(.identifier("test")) + ) + ) + + assertParse( + """ + nonisolated + using + """, + substructure: CodeBlockSyntax( + DeclReferenceExprSyntax(baseName: .identifier("using")) + ) + ) + + assertParse( + """ + @MainActor + using + """, + substructure: CodeBlockSyntax( + DeclReferenceExprSyntax(baseName: .identifier("using")) + ) + ) + + assertParse( + """ + using + @MainActor 1️⃣ + """, + diagnostics: [ + DiagnosticSpec( + message: "expected declaration after attribute", + fixIts: ["insert declaration"] + ) + ], + fixedSource: + """ + using + @MainActor <#declaration#> + """ + ) + + assertParse( + """ + using + nonisolated + """, + substructure: CodeBlockSyntax( + DeclReferenceExprSyntax(baseName: .identifier("using")) + ) + ) + + assertParse( + """ + func + using (x: Int) {} + """ + ) + + assertParse( + """ + func + using + (x: Int) {} + """ + ) + + assertParse( + """ + let + using = 42 + """ + ) + + assertParse("let (x: Int, using: String) = (x: 42, using: \"\")") + + assertParse( + """ + do { + using @MainActor + } + """ + ) + } } diff --git a/Tests/SwiftParserTest/ExpressionTests.swift b/Tests/SwiftParserTest/ExpressionTests.swift index e63d753d2da..e47abffd938 100644 --- a/Tests/SwiftParserTest/ExpressionTests.swift +++ b/Tests/SwiftParserTest/ExpressionTests.swift @@ -1882,6 +1882,62 @@ final class ExpressionTests: ParserTestCase { ) } + func testInvalidMultiLineClosingDelimiter() { + assertParse( + #""" + "a"1️⃣""2️⃣ a3️⃣ a4️⃣ℹ️"""5️⃣ + """#, + diagnostics: [ + DiagnosticSpec( + locationMarker: "1️⃣", + message: "consecutive statements on a line must be separated by newline or ';'", + fixIts: [ + "insert newline", "insert ';'", + ] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "consecutive statements on a line must be separated by newline or ';'", + fixIts: [ + "insert newline", "insert ';'", + ] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "consecutive statements on a line must be separated by newline or ';'", + fixIts: [ + "insert newline", "insert ';'", + ] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "consecutive statements on a line must be separated by newline or ';'", + fixIts: [ + "insert newline", "insert ';'", + ] + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: #"expected '"""' to end string literal"#, + notes: [ + NoteSpec(message: #"to match this opening '"""'"#) + ], + fixIts: [ + #"insert '"""'"# + ] + ), + ], + fixedSource: #""" + "a" + "" + a + a + """ + """ + """# + ) + } + func testEmptyLineInMultilineStringLiteral() { assertParse( #""" @@ -2125,6 +2181,46 @@ final class ExpressionTests: ParserTestCase { """ ) } + + func testTrailingCommasInTypeExpressions() { + assertParse( + """ + let _ = Foo2.self + """ + ) + + assertParse( + """ + let _ = Foo2() + """ + ) + + assertParse( + """ + let _ = ((Int, Bool, String,) -> Void).self + """ + ) + } + + func testSecondaryArgumentLabelDollarIdentifierInClosure() { + assertParse( + """ + ℹ️{ a1️⃣: (a $ + """, + diagnostics: [ + DiagnosticSpec( + message: "expected '}' to end closure", + notes: [NoteSpec(message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), + DiagnosticSpec(message: "extraneous code ': (a $' at top level"), + ], + fixedSource: """ + { a + }: (a $ + """ + ) + } } final class MemberExprTests: ParserTestCase { diff --git a/Tests/SwiftParserTest/ExpressionTypeTests.swift b/Tests/SwiftParserTest/ExpressionTypeTests.swift index 5def6ec1241..f9f6587dbe4 100644 --- a/Tests/SwiftParserTest/ExpressionTypeTests.swift +++ b/Tests/SwiftParserTest/ExpressionTypeTests.swift @@ -111,26 +111,26 @@ final class ExpressionTypeTests: ParserTestCase { // Make sure we can handle cases where the type is spelled first in // an InlineArray sugar type. let cases: [UInt: String] = [ - #line: "[3 x Int]", - #line: "[[3 x Int]]", - #line: "[[Int x 3]]", - #line: "[_ x Int]", - #line: "[Int x Int]", - #line: "[@escaping () -> Int x Int]", - #line: "[Int.Type x Int]", - #line: "[sending P & Q x Int]", - #line: "[(some P & Q) -> Int x Int]", - #line: "[~P x Int]", - #line: "[(Int, String) x Int]", - #line: "[G x Int]", - #line: "[[3 x Int] x Int]", - #line: "[[Int] x Int]", - #line: "[_ x Int]", - #line: "[_? x Int]", - #line: "[_?x Int]", - #line: "[_! x Int]", - #line: "[_!x Int]", - #line: "[Int?x Int]", + #line: "[3 of Int]", + #line: "[[3 of Int]]", + #line: "[[Int of 3]]", + #line: "[_ of Int]", + #line: "[Int of Int]", + #line: "[@escaping () -> Int of Int]", + #line: "[Int.Type of Int]", + #line: "[sending P & Q of Int]", + #line: "[(some P & Q) -> Int of Int]", + #line: "[~P of Int]", + #line: "[(Int, String) of Int]", + #line: "[G of Int]", + #line: "[[3 of Int] of Int]", + #line: "[[Int] of Int]", + #line: "[_ of Int]", + #line: "[_? of Int]", + #line: "[_?of Int]", + #line: "[_! of Int]", + #line: "[_!of Int]", + #line: "[Int?of Int]", ] for (line, type) in cases { assertParse( diff --git a/Tests/SwiftParserTest/TypeTests.swift b/Tests/SwiftParserTest/TypeTests.swift index 6e49d5fa75d..4ab3316b6b7 100644 --- a/Tests/SwiftParserTest/TypeTests.swift +++ b/Tests/SwiftParserTest/TypeTests.swift @@ -734,6 +734,44 @@ final class TypeTests: ParserTestCase { fixedSource: "func foo(test: nonisolated(nonsendinghello) () async -> Void)" ) } + + func testTrailingCommas() { + assertParse( + """ + let foo: ( + bar: String, + quux: String, + ) + """ + ) + + assertParse( + """ + let closure: ( + String, + String, + ) -> ( + bar: String, + quux: String, + ) + """ + ) + + assertParse( + """ + struct Foo {} + + typealias Bar< + T1, + T2, + > = Foo< + T1, + T2, + Bool, + > + """ + ) + } } final class InlineArrayTypeTests: ParserTestCase { @@ -743,18 +781,18 @@ final class InlineArrayTypeTests: ParserTestCase { func testBasic() { assertParse( - "[3 x Int]", + "[3 of Int]", substructure: InlineArrayTypeSyntax( count: .init(argument: .expr("3")), - separator: .keyword(.x), + separator: .keyword(.of), element: .init(argument: .type(TypeSyntax("Int"))) ) ) assertParse( - "[Int x _]", + "[Int of _]", substructure: InlineArrayTypeSyntax( count: .init(argument: .type(TypeSyntax("Int"))), - separator: .keyword(.x), + separator: .keyword(.of), element: .init(argument: .type(TypeSyntax("_"))) ) ) @@ -766,7 +804,7 @@ final class InlineArrayTypeTests: ParserTestCase { """ S<[ 3 - 1️⃣x + 1️⃣of Int ]>() """, @@ -777,7 +815,7 @@ final class InlineArrayTypeTests: ParserTestCase { assertParse( """ S<[3 - 1️⃣x + 1️⃣of Int ]>() """, @@ -788,23 +826,23 @@ final class InlineArrayTypeTests: ParserTestCase { assertParse( """ S<[3 - 1️⃣x Int]>() + 1️⃣of Int]>() """, diagnostics: [ - DiagnosticSpec(message: "unexpected code 'x Int' in array") + DiagnosticSpec(message: "unexpected code 'of Int' in array") ] ) // These are okay. assertParse( """ - S<[3 x + S<[3 of Int]>() """ ) assertParse( """ S<[ - 3 x Int + 3 of Int ]>() """ ) @@ -812,17 +850,17 @@ final class InlineArrayTypeTests: ParserTestCase { func testDiagnostics() { assertParse( - "2️⃣[3 x1️⃣", + "2️⃣[3 of1️⃣", diagnostics: [ DiagnosticSpec( message: "expected element type and ']' to end inline array type", fixIts: ["insert element type and ']'"] ) ], - fixedSource: "[3 x <#type#>]" + fixedSource: "[3 of <#type#>]" ) assertParse( - "ℹ️[3 x Int1️⃣", + "ℹ️[3 of Int1️⃣", diagnostics: [ DiagnosticSpec( message: "expected ']' to end inline array type", @@ -830,12 +868,12 @@ final class InlineArrayTypeTests: ParserTestCase { fixIts: ["insert ']'"] ) ], - fixedSource: "[3 x Int]" + fixedSource: "[3 of Int]" ) } func testEllipsis() { - // Make sure this isn't parsed as ' x ' - assertParse("[x...x]") + // Make sure this isn't parsed as ' of ' + assertParse("[x...of]") } } diff --git a/Tests/SwiftParserTest/translated/StringLiteralEofTests.swift b/Tests/SwiftParserTest/translated/StringLiteralEofTests.swift index 00dc1127bb8..ae17fe465fd 100644 --- a/Tests/SwiftParserTest/translated/StringLiteralEofTests.swift +++ b/Tests/SwiftParserTest/translated/StringLiteralEofTests.swift @@ -243,4 +243,37 @@ final class StringLiteralEofTests: ParserTestCase { """## ) } + + func testSimpleMultilineStringLiteralWith() { + assertParse( + #""" + #sourceLocation1️⃣(file: 2️⃣"""3️⃣\(4️⃣"5️⃣ + """#, + diagnostics: [ + DiagnosticSpec(locationMarker: "3️⃣", message: "argument cannot be an interpolated string literal"), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"""' to end simple string literal"#, + notes: [NoteSpec(locationMarker: "2️⃣", message: #"to match this opening '"""'"#)], + fixIts: [#"insert '"""'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "expected ', line:' and line number in '#sourceLocation' arguments", + fixIts: ["insert ', line:' and line number"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "expected ')' in '#sourceLocation' directive", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec(locationMarker: "4️⃣", message: "extra tokens following the #sourceLocation directive"), + ], + fixedSource: #""" + #sourceLocation(file: """\( + """, line: <#integer literal#>)" + """# + ) + } } diff --git a/Tests/SwiftRefactorTest/ExpandEditorPlaceholderTests.swift b/Tests/SwiftRefactorTest/ExpandEditorPlaceholderTests.swift index 859963a737c..97d5d1660b2 100644 --- a/Tests/SwiftRefactorTest/ExpandEditorPlaceholderTests.swift +++ b/Tests/SwiftRefactorTest/ExpandEditorPlaceholderTests.swift @@ -451,6 +451,58 @@ final class ExpandEditorPlaceholderTests: XCTestCase { format: .testCustom() ) } + + func testMacroTrailingClosureExpansion1() throws { + try assertRefactorPlaceholderToken( + "#foo(\(closurePlaceholder), \(intPlaceholder))", + expected: """ + { + \(voidPlaceholder) + } + """ + ) + } + + func testMacroTrailingClosureExpansion2() throws { + let call = "#foo(fn: \(closureWithArgPlaceholder))" + let expanded = """ + #foo { someInt in + \(stringPlaceholder) + } + """ + + try assertRefactorPlaceholderCall(call, expected: expanded) + try assertExpandEditorPlaceholdersToClosures(call, expected: expanded) + } + + func testMacroTrailingClosureExpansion3() throws { + let call = "#foo(fn1: \(closurePlaceholder), fn2: \(closureWithArgPlaceholder))" + let expanded = """ + #foo { + \(voidPlaceholder) + } fn2: { someInt in + \(stringPlaceholder) + } + """ + + try assertRefactorPlaceholderCall(call, expected: expanded) + try assertExpandEditorPlaceholdersToClosures(call, expected: expanded) + } + + func testMacroTrailingClosureExpansion4() throws { + try assertExpandEditorPlaceholdersToClosures( + decl: """ + #foo(fn1: \(closurePlaceholder), fn2: \(closurePlaceholder)) + """, + expected: """ + #foo { + \(voidPlaceholder) + } fn2: { + \(voidPlaceholder) + } + """ + ) + } } fileprivate func assertRefactorPlaceholder( @@ -489,7 +541,7 @@ fileprivate func assertRefactorPlaceholderCall( line: UInt = #line ) throws { var parser = Parser(expr) - let call = try XCTUnwrap(ExprSyntax.parse(from: &parser).as(FunctionCallExprSyntax.self), file: file, line: line) + let call = try XCTUnwrap(ExprSyntax.parse(from: &parser).asProtocol(CallLikeSyntax.self), file: file, line: line) let arg = call.arguments[call.arguments.index(at: placeholder)] let token: TokenSyntax = try XCTUnwrap(arg.expression.as(DeclReferenceExprSyntax.self), file: file, line: line) .baseName @@ -513,7 +565,7 @@ fileprivate func assertRefactorPlaceholderToken( line: UInt = #line ) throws { var parser = Parser(expr) - let call = try XCTUnwrap(ExprSyntax.parse(from: &parser).as(FunctionCallExprSyntax.self), file: file, line: line) + let call = try XCTUnwrap(ExprSyntax.parse(from: &parser).asProtocol(CallLikeSyntax.self), file: file, line: line) let arg = call.arguments[call.arguments.index(at: placeholder)] let token: TokenSyntax = try XCTUnwrap(arg.expression.as(DeclReferenceExprSyntax.self), file: file, line: line) .baseName @@ -529,15 +581,12 @@ fileprivate func assertRefactorPlaceholderToken( } fileprivate func assertExpandEditorPlaceholdersToClosures( - _ expr: String, + _ call: some CallLikeSyntax, expected: String, format: ExpandEditorPlaceholdersToLiteralClosures.Context.Format = .trailing(indentationWidth: nil), file: StaticString = #filePath, line: UInt = #line ) throws { - var parser = Parser(expr) - let call = try XCTUnwrap(ExprSyntax.parse(from: &parser).as(FunctionCallExprSyntax.self), file: file, line: line) - try assertRefactor( call, context: ExpandEditorPlaceholdersToLiteralClosures.Context(format: format), @@ -548,6 +597,42 @@ fileprivate func assertExpandEditorPlaceholdersToClosures( ) } +fileprivate func assertExpandEditorPlaceholdersToClosures( + _ expr: String, + expected: String, + format: ExpandEditorPlaceholdersToLiteralClosures.Context.Format = .trailing(indentationWidth: nil), + file: StaticString = #filePath, + line: UInt = #line +) throws { + var parser = Parser(expr) + let call = try XCTUnwrap(ExprSyntax.parse(from: &parser).asProtocol(CallLikeSyntax.self), file: file, line: line) + try assertExpandEditorPlaceholdersToClosures( + call, + expected: expected, + format: format, + file: file, + line: line + ) +} + +fileprivate func assertExpandEditorPlaceholdersToClosures( + decl: String, + expected: String, + format: ExpandEditorPlaceholdersToLiteralClosures.Context.Format = .trailing(indentationWidth: nil), + file: StaticString = #filePath, + line: UInt = #line +) throws { + var parser = Parser(decl) + let call = try XCTUnwrap(DeclSyntax.parse(from: &parser).asProtocol(CallLikeSyntax.self), file: file, line: line) + try assertExpandEditorPlaceholdersToClosures( + call, + expected: expected, + format: format, + file: file, + line: line + ) +} + fileprivate extension ExpandEditorPlaceholdersToLiteralClosures.Context.Format { static func testCustom(indentationWidth: Trivia? = nil) -> Self { .custom(CustomClosureFormat(indentationWidth: indentationWidth), allowNestedPlaceholders: true)