Search code examples
swiftregexswift-package-manager

Does the Swift Package Manager support regex literals?


I am using the Swift Package Manager, with Swift 5.7.1. I would like to compile code with a regex literal. For example, main.swift could be as follows:

let message = "Hello, world"
print(message.replacing(/[aeiou]/, with: "[vowel]"))

I am not at present interested in the output, but with the compilation.

If I create a project in XCode, it works just fine. However, if I try it in the Swift Package Manager (using swift build) it obviously does not recognize that /[aeiou]/ is a regex literal. Instead, I get messages like '/' is not a prefix unary operator.

Is there any way to get this to work with the Swift Package Manager, or is it simply not yet supported?


Solution

  • Swift 5.7's regex literals can work when using the Swift Package Manager, but they must be explicitly enabled in your Package.swift. By default, the new syntax is disabled since it's a source-breaking language change (due to the existing use of "/" in comment syntax and operators the / operator).

    Here's an illustrative Package.swift that sets "-enable-bare-slash-regex" for all the package targets. I've also included a couple of additional settings that you may want if you're working towards fully adopting Swift 5.7:

    // swift-tools-version: 5.7
    
    import PackageDescription
    
    let package = Package(
      name: "your-package-name",
      platforms: [...],
      dependencies: [...],
      targets: [
        .target(
          name: "FooBar",
          dependencies: []
        ),
        .testTarget(
          name: "FooBarTests",
          dependencies: [
            "FooBar",
          ]
        ),
      ]
    )
    
    for target in package.targets {
      target.swiftSettings = target.swiftSettings ?? []
      target.swiftSettings?.append(
        .unsafeFlags([
          "-Xfrontend", "-warn-concurrency",
          "-Xfrontend", "-enable-actor-data-race-checks",
          "-enable-bare-slash-regex",
        ])
      )
    }
    

    In a future Swift version and once there’s been time for existing code to transition to Swift 5.7, regex literals will likely be enabled by default.


    Swift 5.8 Update

    The Swift 5.8 release supports the piecemeal adoption of upcoming language improvements. The enableUpcomingFeature helps avoid the situation where "use of unsafe flags make the products containing this target ineligible for use by other packages".

    let swiftSettings: [SwiftSetting] = [
        // -enable-bare-slash-regex becomes
        .enableUpcomingFeature("BareSlashRegexLiterals"), 
        // -warn-concurrency becomes
        .enableUpcomingFeature("StrictConcurrency"), 
        .unsafeFlags(["-enable-actor-data-race-checks"], 
            .when(configuration: .debug)),
    ]
    
    for target in package.targets {
        target.swiftSettings = target.swiftSettings ?? []
        target.swiftSettings?.append(contentsOf: swiftSettings)
    }