From 848e5fed804299dac55e37a4283f04f87e83bb29 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Fri, 28 Mar 2025 14:50:36 -0700 Subject: [PATCH 01/13] Fix build warning `name` should have been in a string interpolation here. This makes swift-syntax build without warnings --- Sources/SwiftIfConfig/BuildConfiguration.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SwiftIfConfig/BuildConfiguration.swift b/Sources/SwiftIfConfig/BuildConfiguration.swift index 1621db389f1..407aa1a13d6 100644 --- a/Sources/SwiftIfConfig/BuildConfiguration.swift +++ b/Sources/SwiftIfConfig/BuildConfiguration.swift @@ -43,7 +43,7 @@ enum BuildConfigurationError: Error, CustomStringConvertible { var description: String { switch self { case .experimentalFeature(let name): - return "'name' is an experimental feature" + return "'\(name)' is an experimental feature" } } } From c8f189e510e7990f002975a7e58aca5441a599a4 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Tue, 1 Apr 2025 10:09:51 -0700 Subject: [PATCH 02/13] [bazel] Add new C files --- BUILD.bazel | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.bazel b/BUILD.bazel index 1360cff9043..288ea92e065 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -376,6 +376,7 @@ cc_library( cc_library( name = "_SwiftSyntaxCShims", + srcs = glob(["Sources/_SwiftSyntaxCShims/*.c"]), hdrs = glob(["Sources/_SwiftSyntaxCShims/include/*.h"]), includes = ["Sources/_SwiftSyntaxCShims/include"], tags = ["swift_module=_SwiftSyntaxCShims"], From 52c4bc2fa925fea2e5c51249ebe9a9934cb91c22 Mon Sep 17 00:00:00 2001 From: Stuart Montgomery Date: Wed, 10 Jul 2024 12:45:38 -0500 Subject: [PATCH 03/13] Include try and await expressions which are parents of a freestanding expression macro in lexicalContext Resolves rdar://109470248 --- .../SwiftSyntaxMacros/Syntax+LexicalContext.swift | 14 ++++++++++++++ .../LexicalContextTests.swift | 8 +++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift b/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift index 5f17e391db4..96110ce5803 100644 --- a/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift +++ b/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift @@ -67,6 +67,20 @@ extension SyntaxProtocol { case let freestandingMacro as FreestandingMacroExpansionSyntax: return Syntax(freestandingMacro.detached) as Syntax + // Try and await are preserved: A freestanding expression macro preceded + // by try or await may need to know whether those keywords are present so it + // can propagate them to any expressions in its expansion which were passed + // as arguments to the macro. The expression of the try or await is replaced + // with a trivial placeholder, though. + case var tryExpr as TryExprSyntax: + tryExpr = tryExpr.detached + tryExpr.expression = ExprSyntax(TypeExprSyntax(type: IdentifierTypeSyntax(name: .wildcardToken()))) + return Syntax(tryExpr) + case var awaitExpr as AwaitExprSyntax: + awaitExpr = awaitExpr.detached + awaitExpr.expression = ExprSyntax(TypeExprSyntax(type: IdentifierTypeSyntax(name: .wildcardToken()))) + return Syntax(awaitExpr) + default: return nil } diff --git a/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift b/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift index 533a2a4d19f..6b426aa7431 100644 --- a/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift +++ b/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift @@ -531,7 +531,7 @@ final class LexicalContextTests: XCTestCase { struct S { let arg: C var contextDescription: String { - #lexicalContextDescription + try await #lexicalContextDescription } } return S(arg: c) @@ -542,7 +542,9 @@ final class LexicalContextTests: XCTestCase { struct S { let arg: C var contextDescription: String { - """ + try await """ + await _ + try _ contextDescription: String struct S {} { c in @@ -551,7 +553,7 @@ final class LexicalContextTests: XCTestCase { struct S { let arg: C var contextDescription: String { - #lexicalContextDescription + try await #lexicalContextDescription } } return S(arg: c) From 2b9a763eab621d8874122f670e0fd2367754053a Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Tue, 1 Apr 2025 21:02:09 +0100 Subject: [PATCH 04/13] Handle `try` and `await` in unfolded sequences We can say that any `try`/`await` element also covers all elements to the right of it in an unfolded sequence. Cases where this isn't true will be rejected by the compiler, e.g: ``` 0 * try foo() + bar() _ = try foo() ~~~ bar() // Assuming `~~~` has lower precedence than `=` ``` rdar://109470248 --- .../OperatorTable+Folding.swift | 2 + .../Syntax+LexicalContext.swift | 33 ++++ .../LexicalContextTests.swift | 161 ++++++++++++++++++ 3 files changed, 196 insertions(+) diff --git a/Sources/SwiftOperators/OperatorTable+Folding.swift b/Sources/SwiftOperators/OperatorTable+Folding.swift index 06371c9f50a..c1c4f7f6025 100644 --- a/Sources/SwiftOperators/OperatorTable+Folding.swift +++ b/Sources/SwiftOperators/OperatorTable+Folding.swift @@ -155,6 +155,8 @@ extension OperatorTable { ) ) } + // NOTE: If you add a new try/await/unsafe-like hoisting case here, make + // sure to also update `allMacroLexicalContexts` to handle it. // The form of the binary operation depends on the operator itself, // which will be one of the unresolved infix operators. diff --git a/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift b/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift index 96110ce5803..6de517bee35 100644 --- a/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift +++ b/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift @@ -106,6 +106,39 @@ extension SyntaxProtocol { if let parentContext = parentNode.asMacroLexicalContext() { parentContexts.append(parentContext) } + if let sequence = parentNode.as(SequenceExprSyntax.self) { + var sequenceExprContexts: [Syntax] = [] + for elt in sequence.elements { + if elt.range.contains(self.position) { + // `sequenceExprContexts` is built from the top-down, but we + // build the rest of the contexts bottom-up. Reverse for + // consistency. + parentContexts += sequenceExprContexts.reversed() + break + } + var elt = elt + while true { + if let tryElt = elt.as(TryExprSyntax.self) { + sequenceExprContexts.append(tryElt.asMacroLexicalContext()!) + elt = tryElt.expression + continue + } + if let awaitElt = elt.as(AwaitExprSyntax.self) { + sequenceExprContexts.append(awaitElt.asMacroLexicalContext()!) + elt = awaitElt.expression + continue + } + if let unsafeElt = elt.as(UnsafeExprSyntax.self) { + // No scope for this currently, but we need to look through it + // since it's similar to 'try' in that it's hoisted above a + // binary operator when appearing on the LHS. + elt = unsafeElt.expression + continue + } + break + } + } + } currentNode = parentNode } diff --git a/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift b/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift index 6b426aa7431..2e1b5c8399c 100644 --- a/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift +++ b/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift @@ -567,4 +567,165 @@ final class LexicalContextTests: XCTestCase { macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] ) } + + func testTryAwaitInSequenceLexicalContext() { + // Valid cases. + assertMacroExpansion( + "try await #lexicalContextDescription + #lexicalContextDescription", + expandedSource: #""" + try await """ + await _ + try _ + """ + """ + await _ + try _ + """ + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + assertMacroExpansion( + "try await 0 + 1 + foo(#lexicalContextDescription) + 2", + expandedSource: #""" + try await 0 + 1 + foo(""" + await _ + try _ + """) + 2 + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + assertMacroExpansion( + "x = try await 0 + 1 + foo(#lexicalContextDescription) + 2", + expandedSource: #""" + x = try await 0 + 1 + foo(""" + await _ + try _ + """) + 2 + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + // `try await` in the 'then' branch doesn't cover condition or else. + assertMacroExpansion( + "#lexicalContextDescription ? try await #lexicalContextDescription : #lexicalContextDescription", + expandedSource: #""" + """ + """ ? try await """ + await _ + try _ + """ : """ + """ + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + // Same for else. + assertMacroExpansion( + "#lexicalContextDescription ? #lexicalContextDescription : try await #lexicalContextDescription", + expandedSource: #""" + """ + """ ? """ + """ : try await """ + await _ + try _ + """ + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + // 'try await' in the condition here covers the entire expression + assertMacroExpansion( + "try await #lexicalContextDescription ? #lexicalContextDescription : #lexicalContextDescription ~~ #lexicalContextDescription", + expandedSource: #""" + try await """ + await _ + try _ + """ ? """ + await _ + try _ + """ : """ + await _ + try _ + """ ~~ """ + await _ + try _ + """ + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + assertMacroExpansion( + "x = unsafe try try! await 0 + #lexicalContextDescription", + expandedSource: #""" + x = unsafe try try! await 0 + """ + await _ + try! _ + try _ + """ + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + + // Invalid cases + assertMacroExpansion( + "0 + try await #lexicalContextDescription", + expandedSource: #""" + 0 + try await """ + await _ + try _ + """ + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + // The 'try await' may not actually cover 'lexicalContextDescription' here, + // but this will be rejected by the compiler. + assertMacroExpansion( + "0 + try await 1 ^ #lexicalContextDescription", + expandedSource: #""" + 0 + try await 1 ^ """ + await _ + try _ + """ + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + // Invalid if '^' has a lower precedence than '='. + assertMacroExpansion( + "x = try await 0 ^ #lexicalContextDescription", + expandedSource: #""" + x = try await 0 ^ """ + await _ + try _ + """ + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + // Unassignable + assertMacroExpansion( + "#lexicalContextDescription = try await 0 + 1", + expandedSource: #""" + """ + """ = try await 0 + 1 + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + assertMacroExpansion( + "try await #lexicalContextDescription = 0 + #lexicalContextDescription", + expandedSource: #""" + try await """ + await _ + try _ + """ = 0 + """ + await _ + try _ + """ + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + assertMacroExpansion( + "try await foo() ? 0 : 1 = #lexicalContextDescription", + expandedSource: #""" + try await foo() ? 0 : 1 = """ + await _ + try _ + """ + """#, + macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] + ) + } } From 2c16aebd00ebe17b1f99b0cb6655b914249fed2f Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Thu, 3 Apr 2025 20:39:03 +0100 Subject: [PATCH 05/13] Add `unsafe` as a lexical context too Match the behavior of `try` and `await`. --- .../Syntax+LexicalContext.swift | 24 ++++-- .../LexicalContextTests.swift | 82 +++++++++++-------- 2 files changed, 66 insertions(+), 40 deletions(-) diff --git a/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift b/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift index 6de517bee35..f9132040dff 100644 --- a/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift +++ b/Sources/SwiftSyntaxMacros/Syntax+LexicalContext.swift @@ -67,11 +67,11 @@ extension SyntaxProtocol { case let freestandingMacro as FreestandingMacroExpansionSyntax: return Syntax(freestandingMacro.detached) as Syntax - // Try and await are preserved: A freestanding expression macro preceded - // by try or await may need to know whether those keywords are present so it - // can propagate them to any expressions in its expansion which were passed - // as arguments to the macro. The expression of the try or await is replaced - // with a trivial placeholder, though. + // `try`, `await`, and `unsafe` are preserved: A freestanding expression + // macro may need to know whether those keywords are present so it can + // propagate them to any expressions in its expansion which were passed as + // arguments to the macro. The sub-expression is replaced with a trivial + // placeholder, though. case var tryExpr as TryExprSyntax: tryExpr = tryExpr.detached tryExpr.expression = ExprSyntax(TypeExprSyntax(type: IdentifierTypeSyntax(name: .wildcardToken()))) @@ -80,6 +80,10 @@ extension SyntaxProtocol { awaitExpr = awaitExpr.detached awaitExpr.expression = ExprSyntax(TypeExprSyntax(type: IdentifierTypeSyntax(name: .wildcardToken()))) return Syntax(awaitExpr) + case var unsafeExpr as UnsafeExprSyntax: + unsafeExpr = unsafeExpr.detached + unsafeExpr.expression = ExprSyntax(TypeExprSyntax(type: IdentifierTypeSyntax(name: .wildcardToken()))) + return Syntax(unsafeExpr) default: return nil @@ -106,6 +110,12 @@ extension SyntaxProtocol { if let parentContext = parentNode.asMacroLexicalContext() { parentContexts.append(parentContext) } + // Unfolded sequence expressions require special handling - effect marker + // nodes like `try`, `await`, and `unsafe` are treated as lexical contexts + // for all the nodes on their right. Cases where they don't end up + // covering nodes to their right in the folded tree are invalid and will + // be diagnosed by the compiler. This matches the compiler's ASTScope + // handling logic. if let sequence = parentNode.as(SequenceExprSyntax.self) { var sequenceExprContexts: [Syntax] = [] for elt in sequence.elements { @@ -129,9 +139,7 @@ extension SyntaxProtocol { continue } if let unsafeElt = elt.as(UnsafeExprSyntax.self) { - // No scope for this currently, but we need to look through it - // since it's similar to 'try' in that it's hoisted above a - // binary operator when appearing on the LHS. + sequenceExprContexts.append(unsafeElt.asMacroLexicalContext()!) elt = unsafeElt.expression continue } diff --git a/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift b/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift index 2e1b5c8399c..e0cbe3ef9e2 100644 --- a/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift +++ b/Tests/SwiftSyntaxMacroExpansionTest/LexicalContextTests.swift @@ -531,7 +531,7 @@ final class LexicalContextTests: XCTestCase { struct S { let arg: C var contextDescription: String { - try await #lexicalContextDescription + unsafe try await #lexicalContextDescription } } return S(arg: c) @@ -542,9 +542,10 @@ final class LexicalContextTests: XCTestCase { struct S { let arg: C var contextDescription: String { - try await """ + unsafe try await """ await _ try _ + unsafe _ contextDescription: String struct S {} { c in @@ -553,7 +554,7 @@ final class LexicalContextTests: XCTestCase { struct S { let arg: C var contextDescription: String { - try await #lexicalContextDescription + unsafe try await #lexicalContextDescription } } return S(arg: c) @@ -568,49 +569,54 @@ final class LexicalContextTests: XCTestCase { ) } - func testTryAwaitInSequenceLexicalContext() { + func testEffectMarkersInSequenceLexicalContext() { // Valid cases. assertMacroExpansion( - "try await #lexicalContextDescription + #lexicalContextDescription", + "unsafe try await #lexicalContextDescription + #lexicalContextDescription", expandedSource: #""" - try await """ + unsafe try await """ await _ try _ + unsafe _ """ + """ await _ try _ + unsafe _ """ """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] ) assertMacroExpansion( - "try await 0 + 1 + foo(#lexicalContextDescription) + 2", + "try unsafe await 0 + 1 + foo(#lexicalContextDescription) + 2", expandedSource: #""" - try await 0 + 1 + foo(""" + try unsafe await 0 + 1 + foo(""" await _ + unsafe _ try _ """) + 2 """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] ) assertMacroExpansion( - "x = try await 0 + 1 + foo(#lexicalContextDescription) + 2", + "x = try await unsafe 0 + 1 + foo(#lexicalContextDescription) + 2", expandedSource: #""" - x = try await 0 + 1 + foo(""" + x = try await unsafe 0 + 1 + foo(""" + unsafe _ await _ try _ """) + 2 """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] ) - // `try await` in the 'then' branch doesn't cover condition or else. + // `unsafe try await` in the 'then' branch doesn't cover condition or else. assertMacroExpansion( - "#lexicalContextDescription ? try await #lexicalContextDescription : #lexicalContextDescription", + "#lexicalContextDescription ? unsafe try await #lexicalContextDescription : #lexicalContextDescription", expandedSource: #""" """ - """ ? try await """ + """ ? unsafe try await """ await _ try _ + unsafe _ """ : """ """ """#, @@ -618,33 +624,38 @@ final class LexicalContextTests: XCTestCase { ) // Same for else. assertMacroExpansion( - "#lexicalContextDescription ? #lexicalContextDescription : try await #lexicalContextDescription", + "#lexicalContextDescription ? #lexicalContextDescription : unsafe try await #lexicalContextDescription", expandedSource: #""" """ """ ? """ - """ : try await """ + """ : unsafe try await """ await _ try _ + unsafe _ """ """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] ) - // 'try await' in the condition here covers the entire expression + // 'unsafe try await' in the condition here covers the entire expression assertMacroExpansion( - "try await #lexicalContextDescription ? #lexicalContextDescription : #lexicalContextDescription ~~ #lexicalContextDescription", + "unsafe try await #lexicalContextDescription ? #lexicalContextDescription : #lexicalContextDescription ~~ #lexicalContextDescription", expandedSource: #""" - try await """ + unsafe try await """ await _ try _ + unsafe _ """ ? """ await _ try _ + unsafe _ """ : """ await _ try _ + unsafe _ """ ~~ """ await _ try _ + unsafe _ """ """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] @@ -656,6 +667,7 @@ final class LexicalContextTests: XCTestCase { await _ try! _ try _ + unsafe _ """ """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] @@ -663,66 +675,72 @@ final class LexicalContextTests: XCTestCase { // Invalid cases assertMacroExpansion( - "0 + try await #lexicalContextDescription", + "0 + unsafe try await #lexicalContextDescription", expandedSource: #""" - 0 + try await """ + 0 + unsafe try await """ await _ try _ + unsafe _ """ """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] ) - // The 'try await' may not actually cover 'lexicalContextDescription' here, - // but this will be rejected by the compiler. + // The `unsafe try await` may not actually cover `lexicalContextDescription` + // here, but this will be rejected by the compiler. assertMacroExpansion( - "0 + try await 1 ^ #lexicalContextDescription", + "0 + unsafe try await 1 ^ #lexicalContextDescription", expandedSource: #""" - 0 + try await 1 ^ """ + 0 + unsafe try await 1 ^ """ await _ try _ + unsafe _ """ """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] ) // Invalid if '^' has a lower precedence than '='. assertMacroExpansion( - "x = try await 0 ^ #lexicalContextDescription", + "x = unsafe try await 0 ^ #lexicalContextDescription", expandedSource: #""" - x = try await 0 ^ """ + x = unsafe try await 0 ^ """ await _ try _ + unsafe _ """ """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] ) // Unassignable assertMacroExpansion( - "#lexicalContextDescription = try await 0 + 1", + "#lexicalContextDescription = unsafe try await 0 + 1", expandedSource: #""" """ - """ = try await 0 + 1 + """ = unsafe try await 0 + 1 """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] ) assertMacroExpansion( - "try await #lexicalContextDescription = 0 + #lexicalContextDescription", + "unsafe try await #lexicalContextDescription = 0 + #lexicalContextDescription", expandedSource: #""" - try await """ + unsafe try await """ await _ try _ + unsafe _ """ = 0 + """ await _ try _ + unsafe _ """ """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] ) assertMacroExpansion( - "try await foo() ? 0 : 1 = #lexicalContextDescription", + "unsafe try await foo() ? 0 : 1 = #lexicalContextDescription", expandedSource: #""" - try await foo() ? 0 : 1 = """ + unsafe try await foo() ? 0 : 1 = """ await _ try _ + unsafe _ """ """#, macros: ["lexicalContextDescription": LexicalContextDescriptionMacro.self] From 660b9a1fa789440aa1cb94caa0e58e3416d80fcb Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Thu, 3 Apr 2025 16:28:47 +0100 Subject: [PATCH 06/13] [Windows] Remove extra newlines from diagnostic output. We are outputting lots of extra newlines on Windows, which makes it hard to read the diagnostics. rdar://148520063 --- .../DiagnosticsFormatter.swift | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Sources/SwiftDiagnostics/DiagnosticsFormatter.swift b/Sources/SwiftDiagnostics/DiagnosticsFormatter.swift index 28f4d18bf4e..9717ecb4ac7 100644 --- a/Sources/SwiftDiagnostics/DiagnosticsFormatter.swift +++ b/Sources/SwiftDiagnostics/DiagnosticsFormatter.swift @@ -293,10 +293,13 @@ public struct DiagnosticsFormatter { ) ) - // If the line did not end with \n (e.g. the last line), append it manually - if annotatedSource.last != "\n" { - annotatedSource.append("\n") + // Remove any trailing newline and replace it; this may seem + // counterintuitive, but if we're running within CMake and we let a + // '\r\n' through, CMake will turn that into *two* newlines. + if let last = annotatedSource.last, last.isNewline { + annotatedSource.removeLast() } + annotatedSource.append("\n") let columnsWithDiagnostics = Set( annotatedLine.diagnostics.map { @@ -331,8 +334,13 @@ public struct DiagnosticsFormatter { } // Add suffix text. - annotatedSource.append(annotatedLine.suffixText) - if annotatedSource.last != "\n" { + if !annotatedLine.suffixText.isEmpty { + annotatedSource.append(annotatedLine.suffixText) + + // See above for an explanation of why we do this + if let last = annotatedSource.last, last.isNewline { + annotatedSource.removeLast() + } annotatedSource.append("\n") } } From 820501e3cf5894ad1deb8de95649b938a8bbe9f4 Mon Sep 17 00:00:00 2001 From: Brandon Williams <135203+mbrandonw@users.noreply.github.com> Date: Fri, 4 Apr 2025 13:23:21 -0700 Subject: [PATCH 07/13] Add dependencies to SwiftSyntax60[12] (#3034) Adds missing dependencies to the version marker modules from SwiftSyntax so that they can be found from a `canImport`. --- BUILD.bazel | 9 +++++++++ Package.swift | 4 +++- Sources/VersionMarkerModules/CMakeLists.txt | 4 ++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/BUILD.bazel b/BUILD.bazel index 1360cff9043..0ac2123ce63 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -219,6 +219,8 @@ swift_syntax_library( ":SwiftSyntax509", ":SwiftSyntax510", ":SwiftSyntax600", + ":SwiftSyntax601", + ":SwiftSyntax602", ":_SwiftSyntaxCShims", ], ) @@ -251,6 +253,13 @@ swift_syntax_library( ], ) +swift_syntax_library( + name = "SwiftSyntax602", + srcs = glob(["Sources/VersionMarkerModules/SwiftSyntax602/**/*.swift"]), + deps = [ + ], +) + swift_syntax_library( name = "SwiftSyntaxBuilder", deps = [ diff --git a/Package.swift b/Package.swift index 43df607866b..5c20ee04b86 100644 --- a/Package.swift +++ b/Package.swift @@ -210,7 +210,9 @@ let package = Package( .target( name: "SwiftSyntax", - dependencies: ["_SwiftSyntaxCShims", "SwiftSyntax509", "SwiftSyntax510", "SwiftSyntax600"], + dependencies: [ + "_SwiftSyntaxCShims", "SwiftSyntax509", "SwiftSyntax510", "SwiftSyntax600", "SwiftSyntax601", "SwiftSyntax602", + ], exclude: ["CMakeLists.txt"], swiftSettings: swiftSyntaxSwiftSettings ), diff --git a/Sources/VersionMarkerModules/CMakeLists.txt b/Sources/VersionMarkerModules/CMakeLists.txt index 52457d79b36..467d4aa2202 100644 --- a/Sources/VersionMarkerModules/CMakeLists.txt +++ b/Sources/VersionMarkerModules/CMakeLists.txt @@ -14,3 +14,7 @@ add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax510 STATIC SwiftSyntax509/Empty.swift) add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax600 STATIC SwiftSyntax509/Empty.swift) +add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax601 STATIC + SwiftSyntax509/Empty.swift) +add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax602 STATIC + SwiftSyntax509/Empty.swift) \ No newline at end of file From 2fcf9c4481a0362dd948eb42d7c78ba3b1066cfd Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Mon, 7 Apr 2025 09:54:13 -0700 Subject: [PATCH 08/13] =?UTF-8?q?Don=E2=80=99t=20exclude=205.8=20in=20PR?= =?UTF-8?q?=20testing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swift 5.8 was removed from the underlying workflow in https://github.com/swiftlang/github-workflows/pull/107 --- .github/workflows/pull_request.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 01cce58414d..19031c98946 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -8,8 +8,6 @@ jobs: tests: name: Test uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main - with: - linux_exclude_swift_versions: "[{\"swift_version\": \"5.8\"}]" soundness: name: Soundness uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main From 491c5c9837a32e2aff973b7fe8196d2023e70354 Mon Sep 17 00:00:00 2001 From: TTOzzi Date: Tue, 8 Apr 2025 04:02:50 +0900 Subject: [PATCH 09/13] Add concurrency control to cancel in-progress PR workflows (#3042) --- .github/workflows/pull_request.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 01cce58414d..62d15071b42 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -4,6 +4,10 @@ on: pull_request: types: [opened, reopened, synchronize] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: tests: name: Test From 163756675ef150e9c3a54646b95349b942e24e25 Mon Sep 17 00:00:00 2001 From: ttozzi Date: Sat, 5 Apr 2025 20:04:40 +0900 Subject: [PATCH 10/13] Removes duplicate trivia from UnsafeExprSyntax --- Sources/SwiftOperators/OperatorTable+Folding.swift | 4 +--- Tests/SwiftOperatorsTest/OperatorTableTests.swift | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Sources/SwiftOperators/OperatorTable+Folding.swift b/Sources/SwiftOperators/OperatorTable+Folding.swift index c1c4f7f6025..3c2c63d3e97 100644 --- a/Sources/SwiftOperators/OperatorTable+Folding.swift +++ b/Sources/SwiftOperators/OperatorTable+Folding.swift @@ -141,7 +141,6 @@ extension OperatorTable { if let unsafeExpr = lhs.as(UnsafeExprSyntax.self) { return ExprSyntax( UnsafeExprSyntax( - leadingTrivia: unsafeExpr.leadingTrivia, unsafeExpr.unexpectedBeforeUnsafeKeyword, unsafeKeyword: unsafeExpr.unsafeKeyword, unsafeExpr.unexpectedBetweenUnsafeKeywordAndExpression, @@ -150,8 +149,7 @@ extension OperatorTable { op: op, rhs: rhs ), - unsafeExpr.unexpectedAfterExpression, - trailingTrivia: unsafeExpr.trailingTrivia + unsafeExpr.unexpectedAfterExpression ) ) } diff --git a/Tests/SwiftOperatorsTest/OperatorTableTests.swift b/Tests/SwiftOperatorsTest/OperatorTableTests.swift index e4c81c4605b..47e5bd2ad2f 100644 --- a/Tests/SwiftOperatorsTest/OperatorTableTests.swift +++ b/Tests/SwiftOperatorsTest/OperatorTableTests.swift @@ -435,4 +435,10 @@ class OperatorPrecedenceTests: XCTestCase { } } + + func testTriviaAroundUnsafeExpr() throws { + let original = ExprSyntax("/*leading*/ unsafe a /*trailing*/ + b") + let folded = try OperatorTable.standardOperators.foldAll(original) + XCTAssertEqual(original.description, folded.description) + } } From ea776865d8b1862cfdd6b2e7aca6a27640a0f5c5 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Wed, 9 Apr 2025 15:13:28 -0700 Subject: [PATCH 11/13] Change default release version to 603.0.0 --- .github/workflows/publish_release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_release.yml b/.github/workflows/publish_release.yml index 969181fc799..44f68cce276 100644 --- a/.github/workflows/publish_release.yml +++ b/.github/workflows/publish_release.yml @@ -11,7 +11,7 @@ on: required: true swift_syntax_version: type: string - default: 601.0.0 + default: 603.0.0 description: "swift-syntax version" # The version of swift-syntax to tag. If this is a prerelease, `-prerelease-` is added to this version. required: true From 0ef1dc377a0060c919c3362f59c3ea772c3695f4 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Wed, 9 Apr 2025 15:27:23 -0700 Subject: [PATCH 12/13] Add SwiftSyntax603 version marker module --- BUILD.bazel | 8 ++++++++ Package.swift | 6 ++++++ Sources/VersionMarkerModules/CMakeLists.txt | 10 ++++++---- .../SwiftSyntax603/Empty.swift | 15 +++++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 Sources/VersionMarkerModules/SwiftSyntax603/Empty.swift diff --git a/BUILD.bazel b/BUILD.bazel index 5a710ddeeb4..86301f4eec6 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -221,6 +221,7 @@ swift_syntax_library( ":SwiftSyntax600", ":SwiftSyntax601", ":SwiftSyntax602", + ":SwiftSyntax603", ":_SwiftSyntaxCShims", ], ) @@ -260,6 +261,13 @@ swift_syntax_library( ], ) +swift_syntax_library( + name = "SwiftSyntax603", + srcs = glob(["Sources/VersionMarkerModules/SwiftSyntax603/**/*.swift"]), + deps = [ + ], +) + swift_syntax_library( name = "SwiftSyntaxBuilder", deps = [ diff --git a/Package.swift b/Package.swift index 5c20ee04b86..844bfacc40a 100644 --- a/Package.swift +++ b/Package.swift @@ -212,6 +212,7 @@ let package = Package( name: "SwiftSyntax", dependencies: [ "_SwiftSyntaxCShims", "SwiftSyntax509", "SwiftSyntax510", "SwiftSyntax600", "SwiftSyntax601", "SwiftSyntax602", + "SwiftSyntax603", ], exclude: ["CMakeLists.txt"], swiftSettings: swiftSyntaxSwiftSettings @@ -250,6 +251,11 @@ let package = Package( path: "Sources/VersionMarkerModules/SwiftSyntax602" ), + .target( + name: "SwiftSyntax603", + path: "Sources/VersionMarkerModules/SwiftSyntax603" + ), + // MARK: SwiftSyntaxBuilder .target( diff --git a/Sources/VersionMarkerModules/CMakeLists.txt b/Sources/VersionMarkerModules/CMakeLists.txt index 467d4aa2202..609f1d308d4 100644 --- a/Sources/VersionMarkerModules/CMakeLists.txt +++ b/Sources/VersionMarkerModules/CMakeLists.txt @@ -11,10 +11,12 @@ add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax509 STATIC SwiftSyntax509/Empty.swift) add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax510 STATIC - SwiftSyntax509/Empty.swift) + SwiftSyntax510/Empty.swift) add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax600 STATIC - SwiftSyntax509/Empty.swift) + SwiftSyntax600/Empty.swift) add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax601 STATIC - SwiftSyntax509/Empty.swift) + SwiftSyntax601/Empty.swift) add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax602 STATIC - SwiftSyntax509/Empty.swift) \ No newline at end of file + SwiftSyntax602/Empty.swift) +add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax603 STATIC + SwiftSyntax603/Empty.swift) diff --git a/Sources/VersionMarkerModules/SwiftSyntax603/Empty.swift b/Sources/VersionMarkerModules/SwiftSyntax603/Empty.swift new file mode 100644 index 00000000000..cc2ffc3c32a --- /dev/null +++ b/Sources/VersionMarkerModules/SwiftSyntax603/Empty.swift @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 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 +// +//===----------------------------------------------------------------------===// + +// The SwiftSyntax603 module is intentionally empty. +// It serves as an indicator which version of swift-syntax a package is building against. +// See the 'Macro Versioning.md' document for more details. From b9df7d0264b023ebf02eeeac8839e46c9e63d485 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 10 Apr 2025 08:51:12 -0700 Subject: [PATCH 13/13] Revert "Add SwiftSyntax603 version marker module" This reverts commit 0ef1dc377a0060c919c3362f59c3ea772c3695f4. --- BUILD.bazel | 8 -------- Package.swift | 6 ------ Sources/VersionMarkerModules/CMakeLists.txt | 10 ++++------ .../SwiftSyntax603/Empty.swift | 15 --------------- 4 files changed, 4 insertions(+), 35 deletions(-) delete mode 100644 Sources/VersionMarkerModules/SwiftSyntax603/Empty.swift diff --git a/BUILD.bazel b/BUILD.bazel index 86301f4eec6..5a710ddeeb4 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -221,7 +221,6 @@ swift_syntax_library( ":SwiftSyntax600", ":SwiftSyntax601", ":SwiftSyntax602", - ":SwiftSyntax603", ":_SwiftSyntaxCShims", ], ) @@ -261,13 +260,6 @@ swift_syntax_library( ], ) -swift_syntax_library( - name = "SwiftSyntax603", - srcs = glob(["Sources/VersionMarkerModules/SwiftSyntax603/**/*.swift"]), - deps = [ - ], -) - swift_syntax_library( name = "SwiftSyntaxBuilder", deps = [ diff --git a/Package.swift b/Package.swift index 844bfacc40a..5c20ee04b86 100644 --- a/Package.swift +++ b/Package.swift @@ -212,7 +212,6 @@ let package = Package( name: "SwiftSyntax", dependencies: [ "_SwiftSyntaxCShims", "SwiftSyntax509", "SwiftSyntax510", "SwiftSyntax600", "SwiftSyntax601", "SwiftSyntax602", - "SwiftSyntax603", ], exclude: ["CMakeLists.txt"], swiftSettings: swiftSyntaxSwiftSettings @@ -251,11 +250,6 @@ let package = Package( path: "Sources/VersionMarkerModules/SwiftSyntax602" ), - .target( - name: "SwiftSyntax603", - path: "Sources/VersionMarkerModules/SwiftSyntax603" - ), - // MARK: SwiftSyntaxBuilder .target( diff --git a/Sources/VersionMarkerModules/CMakeLists.txt b/Sources/VersionMarkerModules/CMakeLists.txt index 609f1d308d4..467d4aa2202 100644 --- a/Sources/VersionMarkerModules/CMakeLists.txt +++ b/Sources/VersionMarkerModules/CMakeLists.txt @@ -11,12 +11,10 @@ add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax509 STATIC SwiftSyntax509/Empty.swift) add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax510 STATIC - SwiftSyntax510/Empty.swift) + SwiftSyntax509/Empty.swift) add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax600 STATIC - SwiftSyntax600/Empty.swift) + SwiftSyntax509/Empty.swift) add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax601 STATIC - SwiftSyntax601/Empty.swift) + SwiftSyntax509/Empty.swift) add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax602 STATIC - SwiftSyntax602/Empty.swift) -add_library(${SWIFTSYNTAX_TARGET_NAMESPACE}SwiftSyntax603 STATIC - SwiftSyntax603/Empty.swift) + SwiftSyntax509/Empty.swift) \ No newline at end of file diff --git a/Sources/VersionMarkerModules/SwiftSyntax603/Empty.swift b/Sources/VersionMarkerModules/SwiftSyntax603/Empty.swift deleted file mode 100644 index cc2ffc3c32a..00000000000 --- a/Sources/VersionMarkerModules/SwiftSyntax603/Empty.swift +++ /dev/null @@ -1,15 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 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 -// -//===----------------------------------------------------------------------===// - -// The SwiftSyntax603 module is intentionally empty. -// It serves as an indicator which version of swift-syntax a package is building against. -// See the 'Macro Versioning.md' document for more details.