Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Sources/FoundationInternationalization/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

add_library(FoundationInternationalization
BinaryFloatingPoint.swift
CurrentBundle.swift
Date+ICU.swift
Duration+Utils.swift
RangeExpression.swift
Expand Down
22 changes: 22 additions & 0 deletions Sources/FoundationInternationalization/CurrentBundle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===----------------------------------------------------------------------===//
//
// 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 FOUNDATION_FRAMEWORK
/// Returns the bundle most likely to contain resources for the calling code.
///
/// Code in an app, app extension, framework, etc. will return the bundle associated with that target.
/// Code in a Swift Package target will return the resource bundle associated with that target.
@available(macOS 10.0, iOS 2.0, tvOS 9.0, watchOS 2.0, *)
@freestanding(expression)
public macro bundle() -> Bundle = #externalMacro(module: "FoundationMacros", type: "BundleMacro")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Tantalum73 @jmschonfeld should this go somewhere other than FoundationInternationalization given that bundles are not just for internationalization? For example someone could easily use this to lookup an asset or some other resource.

Copy link
Contributor

@jmschonfeld jmschonfeld Apr 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, Bundle does not exist in FoundationInternationalization and this is just a FOUNDATION_FRAMEWORK piece that will be picked up by the Foundation.framework build. For this to be fully usable on non-Darwin, this macro would currently need to be declared in the Foundation module in the swift-corelibs-foundation repo as well / separately (which we can do next). Eventually, if we sink Bundle down to swift-foundation this would remove the FOUNDATION_FRAMEWORK ifdef and would go alongside wherever Bundle is defined, but given that Bundle does not currently exist in swift-foundation I'm ok leaving this here for now as just a piece for the Foundation.framework build to pickup and moving it whenever we decide where Bundle will go later

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the same question as @matthewseaman when I read this. IMO Bundle will very likely be in FoundationEssentials if/when we move it, so we'll likely move this there, though like Jeremy said it doesn't really matter now for swift-foundation when building as a package

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Removed the declaration and now only the implementation in FoundationMacros remains.

#endif

30 changes: 30 additions & 0 deletions Sources/FoundationMacros/BundleMacro.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

import SwiftSyntax
import SwiftSyntaxMacros

public struct BundleMacro: SwiftSyntaxMacros.ExpressionMacro, Sendable {
public static func expansion(of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext) throws -> ExprSyntax {
"""
{
#if SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE
return Bundle.module
#elseif SWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE
#error("No resource bundle is available for this module. If resources are included elsewhere, specify the bundle manually.")
#else
return Bundle(_dsoHandle: #dsohandle) ?? .main
#endif
}()
"""
}
}
1 change: 1 addition & 0 deletions Sources/FoundationMacros/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ target_compile_options(FoundationMacros PRIVATE -parse-as-library)

target_sources(FoundationMacros PRIVATE
FoundationMacros.swift
BundleMacro.swift
PredicateMacro.swift)

target_compile_options(FoundationMacros PRIVATE
Expand Down
6 changes: 5 additions & 1 deletion Sources/FoundationMacros/FoundationMacros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import SwiftCompilerPlugin

@main
struct FoundationMacros: CompilerPlugin {
var providingMacros: [Macro.Type] = [PredicateMacro.self, ExpressionMacro.self]
var providingMacros: [Macro.Type] = [
PredicateMacro.self,
ExpressionMacro.self,
BundleMacro.self
]
}

#endif
57 changes: 57 additions & 0 deletions Tests/FoundationMacrosTests/BundleMacroTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022-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
//
//===----------------------------------------------------------------------===//

import XCTest
import FoundationMacros

final class BundleMacroTests: XCTestCase {

func testSimple() {
AssertMacroExpansion(
macros: ["bundle": BundleMacro.self],
"""
#bundle
""",
"""
{
#if SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE
return Bundle.module
#elseif SWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE
#error("No resource bundle is available for this module. If resources are included elsewhere, specify the bundle manually.")
#else
return Bundle(_dsoHandle: #dsohandle) ?? .main
#endif
}()
"""
)
}

func testUsingParenthesis() {
AssertMacroExpansion(
macros: ["bundle": BundleMacro.self],
"""
#bundle()
""",
"""
{
#if SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE
return Bundle.module
#elseif SWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE
#error("No resource bundle is available for this module. If resources are included elsewhere, specify the bundle manually.")
#else
return Bundle(_dsoHandle: #dsohandle) ?? .main
#endif
}()
"""
)
}
}