Repository: apple/swift-syntax
Pull request #2685 (2024-06-14 17:43:50)

[Windows] Avoid linking with swiftWinSDK.dll
Avoid `import WinSDK` in swift sources or `#include` in headers. This is to avoid linking with Swift overlay library (swiftWinSDK.dll) so swift-frontend with plugins won't depend on it.

rintaro: @swift-ci Please test
rintaro: @swift-ci Please test
rintaro: @swift-ci Please test Windows
rintaro: @swift-ci Please test
rintaro: @swift-ci Please test

Patch:
diff --git a/.spi.yml b/.spi.yml
index 5b8d7351..3bcefa3f 100644
--- a/.spi.yml
+++ b/.spi.yml
@@ -13,6 +13,7 @@ builder:
       - SwiftCompilerPluginMessageHandling
       - SwiftDiagnostics
       - SwiftIDEUtils
+      - SwiftLibraryPluginProvider
       - SwiftOperators
       - SwiftParser
       - SwiftParserDiagnostics
diff --git a/Package.swift b/Package.swift
index dde4f667..a579ed66 100644
--- a/Package.swift
+++ b/Package.swift
@@ -18,6 +18,7 @@ let package = Package(
     .library(name: "SwiftCompilerPluginMessageHandling", targets: ["SwiftCompilerPluginMessageHandling"]),
     .library(name: "SwiftDiagnostics", targets: ["SwiftDiagnostics"]),
     .library(name: "SwiftIDEUtils", targets: ["SwiftIDEUtils"]),
+    .library(name: "SwiftLibraryPluginProvider", targets: ["SwiftLibraryPluginProvider"]),
     .library(name: "SwiftOperators", targets: ["SwiftOperators"]),
     .library(name: "SwiftParser", targets: ["SwiftParser"]),
     .library(name: "SwiftParserDiagnostics", targets: ["SwiftParserDiagnostics"]),
@@ -143,7 +144,12 @@ let package = Package(
 
     .target(
       name: "SwiftLibraryPluginProvider",
-      dependencies: ["SwiftSyntaxMacros", "SwiftCompilerPluginMessageHandling"],
+      dependencies: ["SwiftSyntaxMacros", "SwiftCompilerPluginMessageHandling", "_SwiftLibraryPluginProviderCShims"],
+      exclude: ["CMakeLists.txt"]
+    ),
+
+    .target(
+      name: "_SwiftLibraryPluginProviderCShims",
       exclude: ["CMakeLists.txt"]
     ),
 
diff --git a/Sources/CMakeLists.txt b/Sources/CMakeLists.txt
index d9fe5e6c..f9e6c3ed 100644
--- a/Sources/CMakeLists.txt
+++ b/Sources/CMakeLists.txt
@@ -6,6 +6,7 @@
 # See http://swift.org/LICENSE.txt for license information
 # See http://swift.org/CONTRIBUTORS.txt for Swift project authors
 
+add_subdirectory(_SwiftLibraryPluginProviderCShims)
 add_subdirectory(_SwiftSyntaxCShims)
 add_subdirectory(SwiftBasicFormat)
 add_subdirectory(SwiftSyntax)
diff --git a/Sources/SwiftIDEUtils/DeclNameLocation.swift b/Sources/SwiftIDEUtils/DeclNameLocation.swift
index b7c5c886..d6b35271 100644
--- a/Sources/SwiftIDEUtils/DeclNameLocation.swift
+++ b/Sources/SwiftIDEUtils/DeclNameLocation.swift
@@ -102,12 +102,6 @@ public struct DeclNameLocation: Equatable {
     /// The parameter of a function declaration, like `func foo(a b: Int)`
     case parameters([Argument])
 
-    /// An enum case declaration like `case myCase(label: String)`.
-    ///
-    /// For enum case parameters the argument label is removed when set to empty instead of being changed to eg.
-    /// `myCase(_ label: String)`
-    case enumCaseParameters([Argument])
-
     /// Same as `param` but the parameters can't be collapsed if they are the same. This is the case for subscript
     /// declarations.
     ///
@@ -129,8 +123,6 @@ public struct DeclNameLocation: Equatable {
         )
       case .parameters(let parameters):
         return .parameters(parameters.map { $0.advanced(by: utf8Offset) })
-      case .enumCaseParameters(let parameters):
-        return .enumCaseParameters(parameters.map { $0.advanced(by: utf8Offset) })
       case .noncollapsibleParameters(let parameters):
         return .noncollapsibleParameters(parameters.map { $0.advanced(by: utf8Offset) })
       case .selector(let arguments):
diff --git a/Sources/SwiftIDEUtils/NameMatcher.swift b/Sources/SwiftIDEUtils/NameMatcher.swift
index c868831b..d1991b27 100644
--- a/Sources/SwiftIDEUtils/NameMatcher.swift
+++ b/Sources/SwiftIDEUtils/NameMatcher.swift
@@ -298,7 +298,7 @@ public class NameMatcher: SyntaxAnyVisitor {
           return .unlabeled(argument: Syntax(argument.secondName) ?? Syntax(argument.colon) ?? Syntax(argument.type))
         }
       }
-      addResolvedLocIfRequested(baseName: node.name, argumentLabels: .enumCaseParameters(argumentLabels))
+      addResolvedLocIfRequested(baseName: node.name, argumentLabels: .parameters(argumentLabels))
     }
     return .visitChildren
   }
diff --git a/Sources/SwiftLibraryPluginProvider/CMakeLists.txt b/Sources/SwiftLibraryPluginProvider/CMakeLists.txt
index 4ae5d9d4..fc3d24c0 100644
--- a/Sources/SwiftLibraryPluginProvider/CMakeLists.txt
+++ b/Sources/SwiftLibraryPluginProvider/CMakeLists.txt
@@ -9,7 +9,9 @@
 add_swift_syntax_library(SwiftLibraryPluginProvider
   LibraryPluginProvider.swift
 )
-
+target_link_libraries(SwiftLibraryPluginProvider PRIVATE
+  _SwiftLibraryPluginProviderCShims
+)
 target_link_swift_syntax_libraries(SwiftLibraryPluginProvider PUBLIC
   SwiftSyntaxMacros
   SwiftCompilerPluginMessageHandling
diff --git a/Sources/SwiftLibraryPluginProvider/LibraryPluginProvider.swift b/Sources/SwiftLibraryPluginProvider/LibraryPluginProvider.swift
index c88f0179..eb06cca2 100644
--- a/Sources/SwiftLibraryPluginProvider/LibraryPluginProvider.swift
+++ b/Sources/SwiftLibraryPluginProvider/LibraryPluginProvider.swift
@@ -13,6 +13,7 @@
 #if swift(>=6.0)
 public import SwiftSyntaxMacros
 @_spi(PluginMessage) public import SwiftCompilerPluginMessageHandling
+private import _SwiftLibraryPluginProviderCShims
 // NOTE: Do not use '_SwiftSyntaxCShims' for 'dlopen' and 'LoadLibraryW' (Windows)
 // because we don't want other modules depend on 'WinSDK'.
 #if canImport(Darwin)
@@ -21,20 +22,17 @@ private import Darwin
 private import Glibc
 #elseif canImport(Musl)
 private import Musl
-#elseif canImport(WinSDK)
-private import WinSDK
 #endif
 #else
 import SwiftSyntaxMacros
 @_spi(PluginMessage) import SwiftCompilerPluginMessageHandling
+@_implementationOnly import _SwiftLibraryPluginProviderCShims
 #if canImport(Darwin)
 @_implementationOnly import Darwin
 #elseif canImport(Glibc)
 @_implementationOnly import Glibc
 #elseif canImport(Musl)
 @_implementationOnly import Musl
-#elseif canImport(WinSDK)
-@_implementationOnly import WinSDK
 #endif
 #endif
 
@@ -130,9 +128,9 @@ private func _loadLibrary(_ path: String) throws -> UnsafeMutableRawPointer {
   let end = utf16Path.initialize(fromContentsOf: path.utf16)
   utf16Path.initializeElement(at: end, to: 0)
 
-  guard let dlHandle = LoadLibraryW(utf16Path.baseAddress) else {
+  guard let dlHandle = swiftlibrarypluginprovider_LoadLibraryW(utf16Path.baseAddress) else {
     // FIXME: Format the error code to string.
-    throw LibraryPluginError(message: "loader error: \(GetLastError())")
+    throw LibraryPluginError(message: "loader error: \(swiftlibrarypluginprovider_GetLastError())")
   }
   return UnsafeMutableRawPointer(dlHandle)
 }
diff --git a/Sources/SwiftSyntax/SourceLocation.swift b/Sources/SwiftSyntax/SourceLocation.swift
index 4a95ca77..5efa83d7 100644
--- a/Sources/SwiftSyntax/SourceLocation.swift
+++ b/Sources/SwiftSyntax/SourceLocation.swift
@@ -141,7 +141,7 @@ fileprivate struct SourceLocationDirectiveArguments {
 /// Converts ``AbsolutePosition``s of syntax nodes to ``SourceLocation``s, and
 /// vice-versa. The ``AbsolutePosition``s must be originating from nodes that are
 /// part of the same tree that was used to initialize this class.
-public final class SourceLocationConverter: Sendable {
+public final class SourceLocationConverter {
   private let fileName: String
   /// The source of the file, modeled as data so it can contain invalid UTF-8.
   private let source: [UInt8]
@@ -157,7 +157,7 @@ public final class SourceLocationConverter: Sendable {
   ///   `#sourceLocation(...)` directive within the current file.
   /// - `arguments` are the `file` and `line` arguments of the directive or `nil`
   ///   if spelled as `#sourceLocation()` to reset the source location directive.
-  private let sourceLocationDirectives: [(sourceLine: Int, arguments: SourceLocationDirectiveArguments?)]
+  private var sourceLocationDirectives: [(sourceLine: Int, arguments: SourceLocationDirectiveArguments?)] = []
 
   /// Create a new ``SourceLocationConverter`` to convert between ``AbsolutePosition``
   /// and ``SourceLocation`` in a syntax tree.
@@ -212,7 +212,6 @@ public final class SourceLocationConverter: Sendable {
       return computeLines(SyntaxText(buffer: syntaxArenaBuf))
     }
     precondition(source.utf8.count == endOfFile.utf8Offset)
-    self.sourceLocationDirectives = []
   }
 
   /// Execute the body with an array that contains each source line.
diff --git a/Sources/_SwiftLibraryPluginProviderCShims/CMakeLists.txt b/Sources/_SwiftLibraryPluginProviderCShims/CMakeLists.txt
new file mode 100644
index 00000000..6efd0094
--- /dev/null
+++ b/Sources/_SwiftLibraryPluginProviderCShims/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_library(_SwiftLibraryPluginProviderCShims STATIC
+  LoadLibrary.c
+)
+target_include_directories(_SwiftLibraryPluginProviderCShims PUBLIC "include")
+set_property(GLOBAL APPEND PROPERTY SWIFT_EXPORTS _SwiftLibraryPluginProviderCShims)
+install(TARGETS _SwiftLibraryPluginProviderCShims EXPORT SwiftSyntaxTargets)
diff --git a/Sources/_SwiftLibraryPluginProviderCShims/LoadLibrary.c b/Sources/_SwiftLibraryPluginProviderCShims/LoadLibrary.c
new file mode 100644
index 00000000..05dfdfe5
--- /dev/null
+++ b/Sources/_SwiftLibraryPluginProviderCShims/LoadLibrary.c
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoadLibrary.h"
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <libloaderapi.h>
+#include <errhandlingapi.h>
+
+void *swiftlibrarypluginprovider_LoadLibraryW(uint16_t *lpLibFileName) {
+  return LoadLibraryW(lpLibFileName);
+}
+
+unsigned long swiftlibrarypluginprovider_GetLastError() {
+  return GetLastError();
+}
+
+#endif /* _WIN32 */
diff --git a/Sources/_SwiftLibraryPluginProviderCShims/include/LoadLibrary.h b/Sources/_SwiftLibraryPluginProviderCShims/include/LoadLibrary.h
new file mode 100644
index 00000000..dbc2e961
--- /dev/null
+++ b/Sources/_SwiftLibraryPluginProviderCShims/include/LoadLibrary.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_LIBRARY_PLUGIN_PROVIDER_LOAD_LIBRARY_H
+#define SWIFT_LIBRARY_PLUGIN_PROVIDER_LOAD_LIBRARY_H
+
+#ifdef _WIN32
+
+#include <stdint.h>
+
+void *swiftlibrarypluginprovider_LoadLibraryW(uint16_t *lpLibFileName);
+unsigned long swiftlibrarypluginprovider_GetLastError();
+
+#endif /* _WIN32 */
+
+#endif /* SWIFT_LIBRARY_PLUGIN_PROVIDER_LOAD_LIBRARY_H */
diff --git a/Sources/_SwiftLibraryPluginProviderCShims/include/module.modulemap b/Sources/_SwiftLibraryPluginProviderCShims/include/module.modulemap
new file mode 100644
index 00000000..feb00a74
--- /dev/null
+++ b/Sources/_SwiftLibraryPluginProviderCShims/include/module.modulemap
@@ -0,0 +1,4 @@
+module _SwiftLibraryPluginProviderCShims {
+  header "LoadLibrary.h"
+  export *
+}


Test patch:
diff --git a/Tests/SwiftIDEUtilsTest/NameMatcherTests.swift b/Tests/SwiftIDEUtilsTest/NameMatcherTests.swift
index 8383c1a2..b2139978 100644
--- a/Tests/SwiftIDEUtilsTest/NameMatcherTests.swift
+++ b/Tests/SwiftIDEUtilsTest/NameMatcherTests.swift
@@ -51,7 +51,6 @@ private func assertNameMatcherResult(
     case .noArguments: argumentLabels = []
     case .call(let labels, _): argumentLabels = labels
     case .parameters(let labels): argumentLabels = labels
-    case .enumCaseParameters(let labels): argumentLabels = labels
     case .noncollapsibleParameters(let labels): argumentLabels = labels
     case .selector(let labels): argumentLabels = labels
     }
@@ -76,7 +75,6 @@ private struct DeclNameLocationSpec {
     case noArguments
     case call
     case parameters
-    case enumCaseParameters
     case noncollapsibleParameters
     case selector
 
@@ -85,7 +83,6 @@ private struct DeclNameLocationSpec {
       case .noArguments: self = .noArguments
       case .call: self = .call
       case .parameters: self = .parameters
-      case .enumCaseParameters: self = .enumCaseParameters
       case .noncollapsibleParameters: self = .noncollapsibleParameters
       case .selector: self = .selector
       }
@@ -329,56 +326,4 @@ class NameMatcherTests: XCTestCase {
       ]
     )
   }
-
-  func testEnumCaseParameterWithLabels() {
-    assertNameMatcherResult(
-      """
-      enum MyEnum {
-        case 1️⃣myCase(label: String)
-      }
-      """,
-      expected: [
-        DeclNameLocationSpec(baseName: "myCase", argumentLabels: ["label"], type: .enumCaseParameters)
-      ]
-    )
-  }
-
-  func testEnumCaseParameterWithoutLabels() {
-    assertNameMatcherResult(
-      """
-      enum MyEnum {
-        case 1️⃣myCase(String)
-      }
-      """,
-      expected: [
-        DeclNameLocationSpec(baseName: "myCase", argumentLabels: [""], type: .enumCaseParameters)
-      ]
-    )
-  }
-
-  func testEnumCaseParameterWithoutAssociatedValues() {
-    assertNameMatcherResult(
-      """
-      enum MyEnum {
-        case 1️⃣myCase
-      }
-      """,
-      expected: [
-        DeclNameLocationSpec(baseName: "myCase", argumentLabels: [], type: .noArguments)
-      ]
-    )
-  }
-
-  func testEnumCaseParameterWithoutWildcardAsExternalLabel() {
-    assertNameMatcherResult(
-      """
-      enum MyEnum {
-        case 1️⃣myCase(_ label: String)
-      }
-      """,
-      expected: [
-        DeclNameLocationSpec(baseName: "myCase", argumentLabels: ["_ label"], type: .enumCaseParameters)
-      ]
-    )
-  }
 }