From 5d6681dd8e43e93d69982a00b86c1622689c5a65 Mon Sep 17 00:00:00 2001 From: mlch911 Date: Mon, 1 Dec 2025 11:21:17 +0800 Subject: [PATCH 1/4] Downgrade supporting for Xcode 15 --- Demo/Demo.xcodeproj/project.pbxproj | 185 ++++- Package.swift | 149 ++-- Package@swift-5.9.swift | 124 +++ .../QuickLayout/QuickLayout/QuickLayout.swift | 2 + .../4-ListExample/BarsModels.swift | 4 + .../QuickLayoutBridge/QuickLayout.swift | 2 +- .../QuickLayoutMacroDeclaration.swift | 2 + .../BodyAppearanceCoordinator.swift | 8 +- .../QuickLayoutCore/Element+UIKit.swift | 7 +- .../QuickLayoutMacro/QuickLayout.swift | 43 + .../QuickLayoutTests.swift | 770 ++++++++++-------- 11 files changed, 876 insertions(+), 420 deletions(-) create mode 100644 Package@swift-5.9.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index bf1e641..7604e20 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -3,28 +3,53 @@ archiveVersion = 1; classes = { }; - objectVersion = 77; + objectVersion = 63; objects = { /* Begin PBXBuildFile section */ + 0E18AC1B2EC0EA5E00BC420B /* HelloWorldView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC1C2EC0EA5E00BC420B /* HelloWorldView.swift */; }; + 0E18AC1D2EC0EA5E00BC420B /* StateManagementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC1E2EC0EA5E00BC420B /* StateManagementView.swift */; }; + 0E18AC1F2EC0EA5E00BC420B /* UpdatingWithAnimationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC202EC0EA5E00BC420B /* UpdatingWithAnimationView.swift */; }; + 0E18AC212EC0EA5E00BC420B /* BarsCardViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC222EC0EA5E00BC420B /* BarsCardViewCell.swift */; }; + 0E18AC232EC0EA5E00BC420B /* BarsListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC242EC0EA5E00BC420B /* BarsListViewController.swift */; }; + 0E18AC252EC0EA5E00BC420B /* BarsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC262EC0EA5E00BC420B /* BarsModels.swift */; }; + 0E18AC272EC0EA5E00BC420B /* AlignmentGuidesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC282EC0EA5E00BC420B /* AlignmentGuidesView.swift */; }; + 0E18AC292EC0EA5E00BC420B /* CustomAlignmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC2A2EC0EA5E00BC420B /* CustomAlignmentView.swift */; }; + 0E18AC2B2EC0EA5E00BC420B /* EmojiAlignmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC2C2EC0EA5E00BC420B /* EmojiAlignmentView.swift */; }; + 0E18AC2D2EC0EA5E00BC420B /* FirstLabelAlignmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC2E2EC0EA5E00BC420B /* FirstLabelAlignmentView.swift */; }; + 0E18AC2F2EC0EA5E00BC420B /* FruitSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC302EC0EA5E00BC420B /* FruitSelectorView.swift */; }; + 0E18AC312EC0EA5E00BC420B /* AdvanceSizingContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC322EC0EA5E00BC420B /* AdvanceSizingContainerView.swift */; }; + 0E18AC332EC0EA5E00BC420B /* AdvanceSizingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC342EC0EA5E00BC420B /* AdvanceSizingView.swift */; }; + 0E18AC352EC0EA5E00BC420B /* LazyInstantiationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC362EC0EA5E00BC420B /* LazyInstantiationView.swift */; }; + 0E18AC372EC0EA5E00BC420B /* MobileConfigMigrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC382EC0EA5E00BC420B /* MobileConfigMigrationView.swift */; }; + 0E18AC392EC0EA5E00BC420B /* GridLayoutExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC3A2EC0EA5E00BC420B /* GridLayoutExampleView.swift */; }; + 0E18AC3B2EC0EA5E00BC420B /* QuickLayoutShowcaseApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E18AC3C2EC0EA5E00BC420B /* QuickLayoutShowcaseApp.swift */; }; 0E56B79C2EBCE521004F79FC /* QuickLayoutShowcaseAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E56B79B2EBCE521004F79FC /* QuickLayoutShowcaseAssets.xcassets */; }; 0E6E97342EB93FDF0030E0DA /* QuickLayout in Frameworks */ = {isa = PBXBuildFile; productRef = 0E6E97332EB93FDF0030E0DA /* QuickLayout */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 0E18AC1C2EC0EA5E00BC420B /* HelloWorldView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelloWorldView.swift; sourceTree = ""; }; + 0E18AC1E2EC0EA5E00BC420B /* StateManagementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateManagementView.swift; sourceTree = ""; }; + 0E18AC202EC0EA5E00BC420B /* UpdatingWithAnimationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdatingWithAnimationView.swift; sourceTree = ""; }; + 0E18AC222EC0EA5E00BC420B /* BarsCardViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarsCardViewCell.swift; sourceTree = ""; }; + 0E18AC242EC0EA5E00BC420B /* BarsListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarsListViewController.swift; sourceTree = ""; }; + 0E18AC262EC0EA5E00BC420B /* BarsModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarsModels.swift; sourceTree = ""; }; + 0E18AC282EC0EA5E00BC420B /* AlignmentGuidesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlignmentGuidesView.swift; sourceTree = ""; }; + 0E18AC2A2EC0EA5E00BC420B /* CustomAlignmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAlignmentView.swift; sourceTree = ""; }; + 0E18AC2C2EC0EA5E00BC420B /* EmojiAlignmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiAlignmentView.swift; sourceTree = ""; }; + 0E18AC2E2EC0EA5E00BC420B /* FirstLabelAlignmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstLabelAlignmentView.swift; sourceTree = ""; }; + 0E18AC302EC0EA5E00BC420B /* FruitSelectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FruitSelectorView.swift; sourceTree = ""; }; + 0E18AC322EC0EA5E00BC420B /* AdvanceSizingContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvanceSizingContainerView.swift; sourceTree = ""; }; + 0E18AC342EC0EA5E00BC420B /* AdvanceSizingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvanceSizingView.swift; sourceTree = ""; }; + 0E18AC362EC0EA5E00BC420B /* LazyInstantiationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyInstantiationView.swift; sourceTree = ""; }; + 0E18AC382EC0EA5E00BC420B /* MobileConfigMigrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MobileConfigMigrationView.swift; sourceTree = ""; }; + 0E18AC3A2EC0EA5E00BC420B /* GridLayoutExampleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridLayoutExampleView.swift; sourceTree = ""; }; + 0E18AC3C2EC0EA5E00BC420B /* QuickLayoutShowcaseApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickLayoutShowcaseApp.swift; sourceTree = ""; }; 0E56B79B2EBCE521004F79FC /* QuickLayoutShowcaseAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = QuickLayoutShowcaseAssets.xcassets; path = ../Sources/QuickLayout/QuickLayoutShowcaseAssets.xcassets; sourceTree = SOURCE_ROOT; }; 0E6E96F72EB93F9C0030E0DA /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ -/* Begin PBXFileSystemSynchronizedRootGroup section */ - 0E18AC1A2EC0EA5E00BC420B /* __showcase__ */ = { - isa = PBXFileSystemSynchronizedRootGroup; - name = __showcase__; - path = ../Sources/QuickLayout/QuickLayout/__showcase__; - sourceTree = SOURCE_ROOT; - }; -/* End PBXFileSystemSynchronizedRootGroup section */ - /* Begin PBXFrameworksBuildPhase section */ 0E6E96F42EB93F9C0030E0DA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; @@ -37,6 +62,103 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0E18AC1A2EC0EA5E00BC420B /* __showcase__ */ = { + isa = PBXGroup; + children = ( + 0E18AC3C2EC0EA5E00BC420B /* QuickLayoutShowcaseApp.swift */, + 0E18AC1B2EC0EA5E00BC420C /* 1-HelloWorld */, + 0E18AC1D2EC0EA5E00BC420C /* 2-StateManagementView */, + 0E18AC1F2EC0EA5E00BC420C /* 3-Animations */, + 0E18AC212EC0EA5E00BC420C /* 4-ListExample */, + 0E18AC272EC0EA5E00BC420C /* 5-Alignment */, + 0E18AC312EC0EA5E00BC420C /* 6-AdvanceSizing */, + 0E18AC352EC0EA5E00BC420C /* 7-LazyView */, + 0E18AC372EC0EA5E00BC420C /* 8-MobileConfigMigrationView */, + 0E18AC392EC0EA5E00BC420C /* 9-LayoutContainers */, + ); + name = __showcase__; + path = ../Sources/QuickLayout/QuickLayout/__showcase__; + sourceTree = SOURCE_ROOT; + }; + 0E18AC1B2EC0EA5E00BC420C /* 1-HelloWorld */ = { + isa = PBXGroup; + children = ( + 0E18AC1C2EC0EA5E00BC420B /* HelloWorldView.swift */, + ); + path = "1-HelloWorld"; + sourceTree = ""; + }; + 0E18AC1D2EC0EA5E00BC420C /* 2-StateManagementView */ = { + isa = PBXGroup; + children = ( + 0E18AC1E2EC0EA5E00BC420B /* StateManagementView.swift */, + ); + path = "2-StateManagementView"; + sourceTree = ""; + }; + 0E18AC1F2EC0EA5E00BC420C /* 3-Animations */ = { + isa = PBXGroup; + children = ( + 0E18AC202EC0EA5E00BC420B /* UpdatingWithAnimationView.swift */, + ); + path = "3-Animations"; + sourceTree = ""; + }; + 0E18AC212EC0EA5E00BC420C /* 4-ListExample */ = { + isa = PBXGroup; + children = ( + 0E18AC222EC0EA5E00BC420B /* BarsCardViewCell.swift */, + 0E18AC242EC0EA5E00BC420B /* BarsListViewController.swift */, + 0E18AC262EC0EA5E00BC420B /* BarsModels.swift */, + ); + path = "4-ListExample"; + sourceTree = ""; + }; + 0E18AC272EC0EA5E00BC420C /* 5-Alignment */ = { + isa = PBXGroup; + children = ( + 0E18AC282EC0EA5E00BC420B /* AlignmentGuidesView.swift */, + 0E18AC2A2EC0EA5E00BC420B /* CustomAlignmentView.swift */, + 0E18AC2C2EC0EA5E00BC420B /* EmojiAlignmentView.swift */, + 0E18AC2E2EC0EA5E00BC420B /* FirstLabelAlignmentView.swift */, + 0E18AC302EC0EA5E00BC420B /* FruitSelectorView.swift */, + ); + path = "5-Alignment"; + sourceTree = ""; + }; + 0E18AC312EC0EA5E00BC420C /* 6-AdvanceSizing */ = { + isa = PBXGroup; + children = ( + 0E18AC322EC0EA5E00BC420B /* AdvanceSizingContainerView.swift */, + 0E18AC342EC0EA5E00BC420B /* AdvanceSizingView.swift */, + ); + path = "6-AdvanceSizing"; + sourceTree = ""; + }; + 0E18AC352EC0EA5E00BC420C /* 7-LazyView */ = { + isa = PBXGroup; + children = ( + 0E18AC362EC0EA5E00BC420B /* LazyInstantiationView.swift */, + ); + path = "7-LazyView"; + sourceTree = ""; + }; + 0E18AC372EC0EA5E00BC420C /* 8-MobileConfigMigrationView */ = { + isa = PBXGroup; + children = ( + 0E18AC382EC0EA5E00BC420B /* MobileConfigMigrationView.swift */, + ); + path = "8-MobileConfigMigrationView"; + sourceTree = ""; + }; + 0E18AC392EC0EA5E00BC420C /* 9-LayoutContainers */ = { + isa = PBXGroup; + children = ( + 0E18AC3A2EC0EA5E00BC420B /* GridLayoutExampleView.swift */, + ); + path = "9-LayoutContainers"; + sourceTree = ""; + }; 0E6E96EE2EB93F9C0030E0DA = { isa = PBXGroup; children = ( @@ -77,9 +199,6 @@ ); dependencies = ( ); - fileSystemSynchronizedGroups = ( - 0E18AC1A2EC0EA5E00BC420B /* __showcase__ */, - ); name = Demo; packageProductDependencies = ( 0E6E97332EB93FDF0030E0DA /* QuickLayout */, @@ -95,15 +214,16 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 2600; - LastUpgradeCheck = 2600; + LastSwiftUpdateCheck = 1540; + LastUpgradeCheck = 1540; TargetAttributes = { 0E6E96F62EB93F9C0030E0DA = { - CreatedOnToolsVersion = 26.0; + CreatedOnToolsVersion = 15.4; }; }; }; buildConfigurationList = 0E6E96F22EB93F9C0030E0DA /* Build configuration list for PBXProject "Demo" */; + compatibilityVersion = "Xcode 15.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -115,7 +235,6 @@ packageReferences = ( 0E6E97312EB93FCE0030E0DA /* XCLocalSwiftPackageReference "../" */, ); - preferredProjectObjectVersion = 77; productRefGroup = 0E6E96F82EB93F9C0030E0DA /* Products */; projectDirPath = ""; projectRoot = ""; @@ -141,6 +260,23 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0E18AC1B2EC0EA5E00BC420B /* HelloWorldView.swift in Sources */, + 0E18AC1D2EC0EA5E00BC420B /* StateManagementView.swift in Sources */, + 0E18AC1F2EC0EA5E00BC420B /* UpdatingWithAnimationView.swift in Sources */, + 0E18AC212EC0EA5E00BC420B /* BarsCardViewCell.swift in Sources */, + 0E18AC232EC0EA5E00BC420B /* BarsListViewController.swift in Sources */, + 0E18AC252EC0EA5E00BC420B /* BarsModels.swift in Sources */, + 0E18AC272EC0EA5E00BC420B /* AlignmentGuidesView.swift in Sources */, + 0E18AC292EC0EA5E00BC420B /* CustomAlignmentView.swift in Sources */, + 0E18AC2B2EC0EA5E00BC420B /* EmojiAlignmentView.swift in Sources */, + 0E18AC2D2EC0EA5E00BC420B /* FirstLabelAlignmentView.swift in Sources */, + 0E18AC2F2EC0EA5E00BC420B /* FruitSelectorView.swift in Sources */, + 0E18AC312EC0EA5E00BC420B /* AdvanceSizingContainerView.swift in Sources */, + 0E18AC332EC0EA5E00BC420B /* AdvanceSizingView.swift in Sources */, + 0E18AC352EC0EA5E00BC420B /* LazyInstantiationView.swift in Sources */, + 0E18AC372EC0EA5E00BC420B /* MobileConfigMigrationView.swift in Sources */, + 0E18AC392EC0EA5E00BC420B /* GridLayoutExampleView.swift in Sources */, + 0E18AC3B2EC0EA5E00BC420B /* QuickLayoutShowcaseApp.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -199,7 +335,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -256,7 +392,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; @@ -273,13 +409,16 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 98R958M4DW; ENABLE_PREVIEWS = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -288,10 +427,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.meta.SampleApp; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; - SWIFT_APPROACHABLE_CONCURRENCY = YES; - SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -304,6 +440,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 98R958M4DW; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -311,6 +448,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -319,10 +457,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.meta.SampleApp; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; - SWIFT_APPROACHABLE_CONCURRENCY = YES; - SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/Package.swift b/Package.swift index e308ca1..b35c388 100644 --- a/Package.swift +++ b/Package.swift @@ -10,72 +10,115 @@ import CompilerPluginSupport import PackageDescription -let package = Package( - name: "QuickLayout", - platforms: [ - .iOS(.v15), - .macOS(.v10_15), - ], - products: [ +#if os(iOS) || !os(macOS) +var QuickLayoutDependencies: [Target.Dependency] = [ + "QuickLayoutMacro", + "QuickLayoutBridge", +] +#else +var QuickLayoutDependencies: [Target.Dependency] = [ + "QuickLayoutMacro", +] +#endif + +var targets: [Target] = [ + .target( + name: "QuickLayout", + dependencies: QuickLayoutDependencies, + path: "Sources/QuickLayout/QuickLayout", + exclude: [ + "__showcase__/" + ] + ), + .macro( + name: "QuickLayoutMacro", + dependencies: [ + .swiftSyntaxMacros, + .swiftCompilerPlugin, + ], + path: "Sources/QuickLayout/QuickLayoutMacro" + ), + .target( + name: "FastResultBuilder", + path: "Sources/FastResultBuilder/FastResultBuilder", + exclude: [ + "__tests__/" + ] + ), + .testTarget( + name: "QuickLayoutMacroTests", + dependencies: [ + "QuickLayoutMacro", + .swiftSyntaxMacrosTestSupport, + .macroTesting, + ], + path: "Sources/QuickLayout/QuickLayoutMacroTests" + ), +] + +var products: [Product] = [ .library( name: "QuickLayout", targets: ["QuickLayout"] ), - .library( - name: "QuickLayoutCore", - targets: ["QuickLayoutCore"] - ), .library( name: "FastResultBuilder", targets: ["FastResultBuilder"] ), +] + +// iOS-only targets +#if os(iOS) || !os(macOS) +targets += [ + .target( + name: "QuickLayoutCore", + path: "Sources/QuickLayout/QuickLayoutCore" + ), + .target( + name: "QuickLayoutBridge", + dependencies: ["FastResultBuilder", "QuickLayoutCore"], + path: "Sources/QuickLayout/QuickLayoutBridge", + exclude: [ + "__server_snapshot_tests__", + "__tests__", + ] + ), +] + +products += [ + .library( + name: "QuickLayoutCore", + targets: ["QuickLayoutCore"] + ), .library( name: "QuickLayoutBridge", targets: ["QuickLayoutBridge"] ), +] +#endif + +let package = Package( + name: "QuickLayout", + platforms: [ + .iOS(.v15), + .macOS(.v10_15), ], + products: products, dependencies: [ - .package(url: "https://github.com/apple/swift-syntax.git", from: "600.0.0") - ], - targets: [ - .target( - name: "QuickLayout", - dependencies: [ - "QuickLayoutMacro", - "QuickLayoutBridge", - ], - path: "Sources/QuickLayout/QuickLayout", - exclude: [ - "__showcase__/" - ] - ), - .macro( - name: "QuickLayoutMacro", - dependencies: [ - .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), - .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), - ], - path: "Sources/QuickLayout/QuickLayoutMacro", - ), - .target( - name: "QuickLayoutCore", - path: "Sources/QuickLayout/QuickLayoutCore", - ), - .target( - name: "FastResultBuilder", - path: "Sources/FastResultBuilder/FastResultBuilder", - exclude: [ - "__tests__/" - ] - ), - .target( - name: "QuickLayoutBridge", - dependencies: ["FastResultBuilder", "QuickLayoutCore"], - path: "Sources/QuickLayout/QuickLayoutBridge", - exclude: [ - "__server_snapshot_tests__", - "__tests__", - ] - ), + .package(url: "https://github.com/apple/swift-syntax.git", from: "602.0.0"), + .package(url: "https://github.com/pointfreeco/swift-macro-testing.git", from: "0.6.4"), ], + targets: targets ) + +extension Target.Dependency { + // swift-syntax + static let swiftSyntax = Self.product(name: "SwiftSyntax", package: "swift-syntax") + static let swiftSyntaxMacros = Self.product(name: "SwiftSyntaxMacros", package: "swift-syntax") + static let swiftCompilerPlugin = Self.product(name: "SwiftCompilerPlugin", package: "swift-syntax") + static let swiftSyntaxBuilder = Self.product(name: "SwiftSyntaxBuilder", package: "swift-syntax") + static let swiftParserDiagnostics = Self.product(name: "SwiftParserDiagnostics", package: "swift-syntax") + static let swiftSyntaxMacrosTestSupport = Self.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax") + // swift-macro-testing + static let macroTesting = Self.product(name: "MacroTesting", package: "swift-macro-testing") +} diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift new file mode 100644 index 0000000..b2e9ac9 --- /dev/null +++ b/Package@swift-5.9.swift @@ -0,0 +1,124 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompilerPluginSupport +import PackageDescription + +#if os(iOS) || !os(macOS) +var QuickLayoutDependencies: [Target.Dependency] = [ + "QuickLayoutMacro", + "QuickLayoutBridge", +] +#else +var QuickLayoutDependencies: [Target.Dependency] = [ + "QuickLayoutMacro", +] +#endif + +var targets: [Target] = [ + .target( + name: "QuickLayout", + dependencies: QuickLayoutDependencies, + path: "Sources/QuickLayout/QuickLayout", + exclude: [ + "__showcase__/" + ] + ), + .macro( + name: "QuickLayoutMacro", + dependencies: [ + .swiftSyntaxMacros, + .swiftCompilerPlugin, + ], + path: "Sources/QuickLayout/QuickLayoutMacro" + ), + .target( + name: "FastResultBuilder", + path: "Sources/FastResultBuilder/FastResultBuilder", + exclude: [ + "__tests__/" + ] + ), + .testTarget( + name: "QuickLayoutMacroTests", + dependencies: [ + "QuickLayoutMacro", + .swiftSyntaxMacrosTestSupport, + .macroTesting, + ], + path: "Sources/QuickLayout/QuickLayoutMacroTests" + ), +] + +var products: [Product] = [ + .library( + name: "QuickLayout", + targets: ["QuickLayout"] + ), + .library( + name: "FastResultBuilder", + targets: ["FastResultBuilder"] + ), +] + +// iOS-only targets +#if os(iOS) || !os(macOS) +targets += [ + .target( + name: "QuickLayoutCore", + path: "Sources/QuickLayout/QuickLayoutCore" + ), + .target( + name: "QuickLayoutBridge", + dependencies: ["FastResultBuilder", "QuickLayoutCore"], + path: "Sources/QuickLayout/QuickLayoutBridge", + exclude: [ + "__server_snapshot_tests__", + "__tests__", + ] + ), +] + +products += [ + .library( + name: "QuickLayoutCore", + targets: ["QuickLayoutCore"] + ), + .library( + name: "QuickLayoutBridge", + targets: ["QuickLayoutBridge"] + ), +] +#endif + +let package = Package( + name: "QuickLayout", + platforms: [ + .iOS(.v15), + .macOS(.v10_15), + ], + products: products, + dependencies: [ + .package(url: "https://github.com/apple/swift-syntax.git", from: "602.0.0"), + .package(url: "https://github.com/pointfreeco/swift-macro-testing.git", from: "0.6.4"), + ], + targets: targets +) + +extension Target.Dependency { + // swift-syntax + static let swiftSyntax = Self.product(name: "SwiftSyntax", package: "swift-syntax") + static let swiftSyntaxMacros = Self.product(name: "SwiftSyntaxMacros", package: "swift-syntax") + static let swiftCompilerPlugin = Self.product(name: "SwiftCompilerPlugin", package: "swift-syntax") + static let swiftSyntaxBuilder = Self.product(name: "SwiftSyntaxBuilder", package: "swift-syntax") + static let swiftParserDiagnostics = Self.product(name: "SwiftParserDiagnostics", package: "swift-syntax") + static let swiftSyntaxMacrosTestSupport = Self.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax") + // swift-macro-testing + static let macroTesting = Self.product(name: "MacroTesting", package: "swift-macro-testing") +} diff --git a/Sources/QuickLayout/QuickLayout/QuickLayout.swift b/Sources/QuickLayout/QuickLayout/QuickLayout.swift index c9d63d9..cf4e5cf 100644 --- a/Sources/QuickLayout/QuickLayout/QuickLayout.swift +++ b/Sources/QuickLayout/QuickLayout/QuickLayout.swift @@ -5,4 +5,6 @@ * LICENSE file in the root directory of this source tree. */ +#if canImport(QuickLayoutBridge) @_exported import QuickLayoutBridge +#endif diff --git a/Sources/QuickLayout/QuickLayout/__showcase__/4-ListExample/BarsModels.swift b/Sources/QuickLayout/QuickLayout/__showcase__/4-ListExample/BarsModels.swift index 515f8f4..fd3a965 100644 --- a/Sources/QuickLayout/QuickLayout/__showcase__/4-ListExample/BarsModels.swift +++ b/Sources/QuickLayout/QuickLayout/__showcase__/4-ListExample/BarsModels.swift @@ -14,7 +14,11 @@ struct BarModel { let description: String let shareURL: URL } +#if compiler(>=6.1) nonisolated extension BarModel: Hashable {} +#else +extension BarModel: Hashable {} +#endif // swiftlint:disable force_unwrapping actor BarsStore { diff --git a/Sources/QuickLayout/QuickLayoutBridge/QuickLayout.swift b/Sources/QuickLayout/QuickLayoutBridge/QuickLayout.swift index f8e6c4c..28e7f3a 100644 --- a/Sources/QuickLayout/QuickLayoutBridge/QuickLayout.swift +++ b/Sources/QuickLayout/QuickLayoutBridge/QuickLayout.swift @@ -76,7 +76,7 @@ public func Grid( alignment: Alignment = .center, horizontalSpacing: CGFloat = 0, verticalSpacing: CGFloat = 0, - @FastArrayBuilder rows: () -> [GridRowElement] = { [] }, + @FastArrayBuilder rows: () -> [GridRowElement] = { [] } ) -> Element & Layout { GridElement(rows: rows(), alignment: alignment, horizontalSpacing: horizontalSpacing, verticalSpacing: verticalSpacing) } diff --git a/Sources/QuickLayout/QuickLayoutBridge/QuickLayoutMacroDeclaration.swift b/Sources/QuickLayout/QuickLayoutBridge/QuickLayoutMacroDeclaration.swift index 8a5c6e3..08225b0 100644 --- a/Sources/QuickLayout/QuickLayoutBridge/QuickLayoutMacroDeclaration.swift +++ b/Sources/QuickLayout/QuickLayoutBridge/QuickLayoutMacroDeclaration.swift @@ -17,8 +17,10 @@ @attached(extension, conformances: HasBody) public macro QuickLayout() = #externalMacro(module: "QuickLayoutMacro", type: "QuickLayout") +#if compiler(>=6) /** This macro is an implementation detail of @QuickLayout. It is not intended to be used directly. */ @attached(body) public macro _QuickLayoutInjection(_ value: String) = #externalMacro(module: "QuickLayoutMacro", type: "QuickLayoutInjection") +#endif diff --git a/Sources/QuickLayout/QuickLayoutBridge/ViewImplementation/BodyAppearanceCoordinator.swift b/Sources/QuickLayout/QuickLayoutBridge/ViewImplementation/BodyAppearanceCoordinator.swift index 983674f..f67291f 100644 --- a/Sources/QuickLayout/QuickLayoutBridge/ViewImplementation/BodyAppearanceCoordinator.swift +++ b/Sources/QuickLayout/QuickLayoutBridge/ViewImplementation/BodyAppearanceCoordinator.swift @@ -12,7 +12,7 @@ private let disappearanceAnimationKey = "BodyAppearanceCoordinator-disappearance private let disappearanceAnimationIDKey = "BodyAppearanceCoordinator-disappearance-id" @MainActor -final class BodyAppearanceCoordinator: NSObject, @preconcurrency CAAnimationDelegate { +final class BodyAppearanceCoordinator: NSObject { private var disappearanceAnimationID: Int = 0 private var appearingViews: Set = [] private var activeViews: Set = [] @@ -123,3 +123,9 @@ fileprivate extension UIView { animationKeys.forEach { layer.removeAnimation(forKey: $0) } } } + +#if compiler(>=6) +extension BodyAppearanceCoordinator: @preconcurrency CAAnimationDelegate {} +#else +extension BodyAppearanceCoordinator: CAAnimationDelegate {} +#endif diff --git a/Sources/QuickLayout/QuickLayoutCore/Element+UIKit.swift b/Sources/QuickLayout/QuickLayoutCore/Element+UIKit.swift index 0659b56..bbfd171 100644 --- a/Sources/QuickLayout/QuickLayoutCore/Element+UIKit.swift +++ b/Sources/QuickLayout/QuickLayoutCore/Element+UIKit.swift @@ -22,8 +22,13 @@ private func sanitizeSize(_ size: CGSize) -> CGSize { } // patternlint-disable-next-line retroactive-conformance-systemlib -extension UIView: @preconcurrency LeafElement { +#if compiler(>=6) +extension UIView: @preconcurrency LeafElement {} +#else +extension UIView: LeafElement {} +#endif +extension UIView { public func quick_layoutThatFits(_ proposedSize: CGSize) -> LayoutNode { assert(Thread.isMainThread, "UIViews can be laid out only on the main thread.") diff --git a/Sources/QuickLayout/QuickLayoutMacro/QuickLayout.swift b/Sources/QuickLayout/QuickLayoutMacro/QuickLayout.swift index 4eb4897..9b2cade 100644 --- a/Sources/QuickLayout/QuickLayoutMacro/QuickLayout.swift +++ b/Sources/QuickLayout/QuickLayoutMacro/QuickLayout.swift @@ -7,6 +7,26 @@ import SwiftSyntax import SwiftSyntaxMacros +import SwiftDiagnostics + +enum QuickLayoutDiagnostic: DiagnosticMessage { + case missingRequiredImplementation(functionName: String, requiredCall: String) + + var message: String { + switch self { + case .missingRequiredImplementation(let functionName, let requiredCall): + return "Method '\(functionName)' is missing required implementation call. Below Swift 6.0, you must manually add the following call:\n\(requiredCall)" + } + } + + var diagnosticID: MessageID { + MessageID(domain: "QuickLayout", id: "missingRequiredImplementation") + } + + var severity: DiagnosticSeverity { + .error + } +} public struct QuickLayout: ExtensionMacro, MemberMacro, MemberAttributeMacro { // MARK: - ExtensionMacro @@ -63,7 +83,30 @@ public struct QuickLayout: ExtensionMacro, MemberMacro, MemberAttributeMacro { case .deferToProvidedDefinition: continue case .injectIntoProvidedDefinition(let impl): +#if compiler(>=6) return ["@_QuickLayoutInjection(\"\(raw: impl(memberFunction))\")"] +#else + // 在 Swift 6.0 以下,检查方法体中是否已包含必要的实现调用 + let requiredCall = impl(memberFunction) + let functionBody = memberFunction.body?.statements.description ?? "" + + // 检查方法体中是否包含必要的调用 + if functionBody.contains(requiredCall) { + // 已经包含必要的实现,跳过 + continue + } else { + // 缺少必要的实现,抛出诊断错误 + let diagnostic = Diagnostic( + node: memberFunction, + message: QuickLayoutDiagnostic.missingRequiredImplementation( + functionName: memberFunction.name.text, + requiredCall: requiredCall + ) + ) + context.diagnose(diagnostic) + continue + } +#endif } } } else if let memberVariable = member.variable { diff --git a/Sources/QuickLayout/QuickLayoutMacroTests/QuickLayoutTests.swift b/Sources/QuickLayout/QuickLayoutMacroTests/QuickLayoutTests.swift index d090901..5005b1b 100644 --- a/Sources/QuickLayout/QuickLayoutMacroTests/QuickLayoutTests.swift +++ b/Sources/QuickLayout/QuickLayoutMacroTests/QuickLayoutTests.swift @@ -5,21 +5,30 @@ * LICENSE file in the root directory of this source tree. */ -import QuickLayoutMacro import SwiftSyntaxMacros import SwiftSyntaxMacrosTestSupport import XCTest +import MacroTesting +#if canImport(QuickLayoutMacro) +@testable import QuickLayoutMacro // patternlint-disable meta-subclass-view -let testMacros: [String: Macro.Type] = [ - "QuickLayout": QuickLayout.self, - "_QuickLayoutInjection": QuickLayoutInjection.self, -] - class QuickLayoutTests: XCTestCase { + override func invokeTest() { + withMacroTesting( + record: .failed, + macros: [ + "QuickLayout": QuickLayout.self, + "_QuickLayoutInjection": QuickLayoutInjection.self, + ] + ) { + super.invokeTest() + } + } + func testBasicMacroExpansion() throws { - assertMacroExpansion( + assertMacro { #""" @QuickLayout class TestView: UIView { @@ -27,44 +36,42 @@ class QuickLayoutTests: XCTestCase { EmptyLayout() } } - """#, - expandedSource: - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """#, - macros: testMacros, - indentationWidth: .spaces(2) - ) + """# + } expansion: { + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """# + } } func testApplicableMethodsDeferToProvidedImplementation() throws { - assertMacroExpansion( + assertMacro { #""" @QuickLayout class TestView: UIView { @@ -80,44 +87,139 @@ class QuickLayoutTests: XCTestCase { return uniqueFlexibilityValue } } - """#, - expandedSource: - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - public func sizeThatFits(_ size: CGSize) -> CGSize { - return uniqueSizeValue - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return uniqueFlexibilityValue - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - } - - extension TestView: HasBody { - } - """#, - macros: testMacros, - indentationWidth: .spaces(2) - ) + """# + } expansion: { + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + public func sizeThatFits(_ size: CGSize) -> CGSize { + return uniqueSizeValue + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return uniqueFlexibilityValue + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + } + + extension TestView: HasBody { + } + """# + } } func testApplicableMethodsInjectQuickLayoutBridgeementation() throws { - assertMacroExpansion( +#if compiler(>=6) + assertMacro { + #""" + @QuickLayout + class TestView: UIView { + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + someUniqueWillMoveToWindowLogic() + } + + public override func layoutSubviews() { + super.layoutSubviews() + someUniqueLayoutSubviewsLogic() + } + } + """# + } expansion: { + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + someUniqueWillMoveToWindowLogic() + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + someUniqueLayoutSubviewsLogic() + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """# + } +#else + assertMacro { + #""" + @QuickLayout + class TestView: UIView { + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + someUniqueWillMoveToWindowLogic() + } + + public override func layoutSubviews() { + super.layoutSubviews() + someUniqueLayoutSubviewsLogic() + } + } + """# + } diagnostics: { + """ + @QuickLayout + class TestView: UIView { + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + ╰─ 🛑 方法 'willMove' 缺少必要的实现调用。在 Swift 6.0 以下,你必须手动添加以下调用: + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + super.willMove(toWindow: newWindow) + someUniqueWillMoveToWindowLogic() + } + + public override func layoutSubviews() { + ╰─ 🛑 方法 'layoutSubviews' 缺少必要的实现调用。在 Swift 6.0 以下,你必须手动添加以下调用: + _QuickLayoutViewImplementation.layoutSubviews(self) + super.layoutSubviews() + someUniqueLayoutSubviewsLogic() + } + } + """ + } + assertMacro { #""" @QuickLayout class TestView: UIView { @@ -127,54 +229,55 @@ class QuickLayoutTests: XCTestCase { public override func willMove(toWindow newWindow: UIWindow?) { super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) someUniqueWillMoveToWindowLogic() } public override func layoutSubviews() { super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) someUniqueLayoutSubviewsLogic() } } - """#, - expandedSource: - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - someUniqueWillMoveToWindowLogic() - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - someUniqueLayoutSubviewsLogic() - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """#, - macros: testMacros, - indentationWidth: .spaces(2) - ) + """# + } expansion: { + """ + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + someUniqueWillMoveToWindowLogic() + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + someUniqueLayoutSubviewsLogic() + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """ + } +#endif } func testTypeScopedFunctionsDoNotConflict() throws { - assertMacroExpansion( + assertMacro { #""" @QuickLayout class TestView: UIView { @@ -186,48 +289,46 @@ class QuickLayoutTests: XCTestCase { return uniqueSizeValue } } - """#, - expandedSource: - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - static func sizeThatFits(_ size: CGSize) -> CGSize { - return uniqueSizeValue - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """#, - macros: testMacros, - indentationWidth: .spaces(2) - ) + """# + } expansion: { + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + static func sizeThatFits(_ size: CGSize) -> CGSize { + return uniqueSizeValue + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """# + } } func testOverloadedFunctionsDoNotConflict() throws { - assertMacroExpansion( + assertMacro { #""" @QuickLayout class TestView: UIView { @@ -239,48 +340,46 @@ class QuickLayoutTests: XCTestCase { return uniqueSizeValue } } - """#, - expandedSource: - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - func sizeThatFits(_ size: CGSize) -> NotACGSize { - return uniqueSizeValue - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """#, - macros: testMacros, - indentationWidth: .spaces(2) - ) + """# + } expansion: { + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + func sizeThatFits(_ size: CGSize) -> NotACGSize { + return uniqueSizeValue + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """# + } } func testParameterMismatchedFunctionsDoNotConflict() throws { - assertMacroExpansion( + assertMacro { #""" @QuickLayout class TestView: UIView { @@ -292,48 +391,46 @@ class QuickLayoutTests: XCTestCase { return uniqueSizeValue } } - """#, - expandedSource: - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - func sizeThatFits(_ notASize: NotACGSize) -> CGSize { - return uniqueSizeValue - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """#, - macros: testMacros, - indentationWidth: .spaces(2) - ) + """# + } expansion: { + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + func sizeThatFits(_ notASize: NotACGSize) -> CGSize { + return uniqueSizeValue + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """# + } } func testLayoutBuilderAttributeNotAddedIfPresent() throws { - assertMacroExpansion( + assertMacro { #""" @QuickLayout class TestView: UIView { @@ -342,44 +439,42 @@ class QuickLayoutTests: XCTestCase { EmptyLayout() } } - """#, - expandedSource: - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """#, - macros: testMacros, - indentationWidth: .spaces(2) - ) + """# + } expansion: { + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """# + } } func testLayoutBuilderAttributeOnlyAddedToBody() throws { - assertMacroExpansion( + assertMacro { #""" @QuickLayout class TestView: UIView { @@ -391,48 +486,46 @@ class QuickLayoutTests: XCTestCase { EmptyLayout() } } - """#, - expandedSource: - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - var notBody: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """#, - macros: testMacros, - indentationWidth: .spaces(2) - ) + """# + } expansion: { + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + var notBody: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """# + } } func testLayoutBuilderAttributeAppliesToAnyLayout() throws { - assertMacroExpansion( + assertMacro { #""" @QuickLayout class TestView: UIView { @@ -440,39 +533,38 @@ class QuickLayoutTests: XCTestCase { EmptyLayout() } } - """#, - expandedSource: - #""" - class TestView: UIView { - @LayoutBuilder - var body: any Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """#, - macros: testMacros, - indentationWidth: .spaces(2) - ) + """# + } expansion: { + #""" + class TestView: UIView { + @LayoutBuilder + var body: any Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """# + } } } +#endif From d0d5bbe63ca1581bac8f55bc1ca850b97a3a3938 Mon Sep 17 00:00:00 2001 From: mlch911 Date: Mon, 1 Dec 2025 14:51:13 +0800 Subject: [PATCH 2/4] remove DEVELOPMENT_TEAM and EXCLUDED_ARCHS --- Demo/Demo.xcodeproj/project.pbxproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 7604e20..6b50c1b 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -409,9 +409,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 98R958M4DW; ENABLE_PREVIEWS = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; @@ -440,7 +438,6 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 98R958M4DW; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; From cdc75e40007005622e34ed318d497d4be38cf717 Mon Sep 17 00:00:00 2001 From: mlch911 Date: Mon, 1 Dec 2025 16:00:47 +0800 Subject: [PATCH 3/4] fix --- Package.swift | 148 +++++++++++++++++----------------------- Package@swift-5.9.swift | 124 --------------------------------- 2 files changed, 61 insertions(+), 211 deletions(-) delete mode 100644 Package@swift-5.9.swift diff --git a/Package.swift b/Package.swift index b35c388..79dedb9 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.0 +// swift-tools-version: 5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. /* * Copyright (c) Meta Platforms, Inc. and affiliates. @@ -10,53 +10,13 @@ import CompilerPluginSupport import PackageDescription -#if os(iOS) || !os(macOS) -var QuickLayoutDependencies: [Target.Dependency] = [ - "QuickLayoutMacro", - "QuickLayoutBridge", -] -#else -var QuickLayoutDependencies: [Target.Dependency] = [ - "QuickLayoutMacro", -] -#endif - -var targets: [Target] = [ - .target( - name: "QuickLayout", - dependencies: QuickLayoutDependencies, - path: "Sources/QuickLayout/QuickLayout", - exclude: [ - "__showcase__/" - ] - ), - .macro( - name: "QuickLayoutMacro", - dependencies: [ - .swiftSyntaxMacros, - .swiftCompilerPlugin, - ], - path: "Sources/QuickLayout/QuickLayoutMacro" - ), - .target( - name: "FastResultBuilder", - path: "Sources/FastResultBuilder/FastResultBuilder", - exclude: [ - "__tests__/" - ] - ), - .testTarget( - name: "QuickLayoutMacroTests", - dependencies: [ - "QuickLayoutMacro", - .swiftSyntaxMacrosTestSupport, - .macroTesting, - ], - path: "Sources/QuickLayout/QuickLayoutMacroTests" - ), -] - -var products: [Product] = [ +let package = Package( + name: "QuickLayout", + platforms: [ + .iOS(.v15), + .macOS(.v10_15), + ], + products: [ .library( name: "QuickLayout", targets: ["QuickLayout"] @@ -65,50 +25,64 @@ var products: [Product] = [ name: "FastResultBuilder", targets: ["FastResultBuilder"] ), -] - -// iOS-only targets -#if os(iOS) || !os(macOS) -targets += [ - .target( - name: "QuickLayoutCore", - path: "Sources/QuickLayout/QuickLayoutCore" - ), - .target( - name: "QuickLayoutBridge", - dependencies: ["FastResultBuilder", "QuickLayoutCore"], - path: "Sources/QuickLayout/QuickLayoutBridge", - exclude: [ - "__server_snapshot_tests__", - "__tests__", - ] - ), -] - -products += [ - .library( - name: "QuickLayoutCore", - targets: ["QuickLayoutCore"] - ), - .library( - name: "QuickLayoutBridge", - targets: ["QuickLayoutBridge"] - ), -] -#endif - -let package = Package( - name: "QuickLayout", - platforms: [ - .iOS(.v15), - .macOS(.v10_15), ], - products: products, dependencies: [ .package(url: "https://github.com/apple/swift-syntax.git", from: "602.0.0"), .package(url: "https://github.com/pointfreeco/swift-macro-testing.git", from: "0.6.4"), ], - targets: targets + targets: [ + .target( + name: "QuickLayout", + dependencies: [ + "QuickLayoutMacro", + .target(name: "QuickLayoutBridge", condition: .when(platforms: [.iOS])), + ], + path: "Sources/QuickLayout/QuickLayout", + exclude: [ + "__showcase__/" + ] + ), + .macro( + name: "QuickLayoutMacro", + dependencies: [ + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), + ], + path: "Sources/QuickLayout/QuickLayoutMacro" + ), + .target( + name: "QuickLayoutCore", + path: "Sources/QuickLayout/QuickLayoutCore" + ), + .target( + name: "FastResultBuilder", + path: "Sources/FastResultBuilder/FastResultBuilder", + exclude: [ + "__tests__/" + ] + ), + .target( + name: "QuickLayoutBridge", + dependencies: [ + "FastResultBuilder", + .target(name: "QuickLayoutCore", condition: .when(platforms: [.iOS])), + ], + path: "Sources/QuickLayout/QuickLayoutBridge", + exclude: [ + "__server_snapshot_tests__", + "__tests__", + ] + ), + .testTarget( + name: "QuickLayoutMacroTests", + dependencies: [ + "QuickLayoutMacro", + .swiftSyntaxMacrosTestSupport, + .macroTesting, + ], + path: "Sources/QuickLayout/QuickLayoutMacroTests" + ) + ] ) extension Target.Dependency { diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift deleted file mode 100644 index b2e9ac9..0000000 --- a/Package@swift-5.9.swift +++ /dev/null @@ -1,124 +0,0 @@ -// swift-tools-version: 5.9 -// The swift-tools-version declares the minimum version of Swift required to build this package. -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import CompilerPluginSupport -import PackageDescription - -#if os(iOS) || !os(macOS) -var QuickLayoutDependencies: [Target.Dependency] = [ - "QuickLayoutMacro", - "QuickLayoutBridge", -] -#else -var QuickLayoutDependencies: [Target.Dependency] = [ - "QuickLayoutMacro", -] -#endif - -var targets: [Target] = [ - .target( - name: "QuickLayout", - dependencies: QuickLayoutDependencies, - path: "Sources/QuickLayout/QuickLayout", - exclude: [ - "__showcase__/" - ] - ), - .macro( - name: "QuickLayoutMacro", - dependencies: [ - .swiftSyntaxMacros, - .swiftCompilerPlugin, - ], - path: "Sources/QuickLayout/QuickLayoutMacro" - ), - .target( - name: "FastResultBuilder", - path: "Sources/FastResultBuilder/FastResultBuilder", - exclude: [ - "__tests__/" - ] - ), - .testTarget( - name: "QuickLayoutMacroTests", - dependencies: [ - "QuickLayoutMacro", - .swiftSyntaxMacrosTestSupport, - .macroTesting, - ], - path: "Sources/QuickLayout/QuickLayoutMacroTests" - ), -] - -var products: [Product] = [ - .library( - name: "QuickLayout", - targets: ["QuickLayout"] - ), - .library( - name: "FastResultBuilder", - targets: ["FastResultBuilder"] - ), -] - -// iOS-only targets -#if os(iOS) || !os(macOS) -targets += [ - .target( - name: "QuickLayoutCore", - path: "Sources/QuickLayout/QuickLayoutCore" - ), - .target( - name: "QuickLayoutBridge", - dependencies: ["FastResultBuilder", "QuickLayoutCore"], - path: "Sources/QuickLayout/QuickLayoutBridge", - exclude: [ - "__server_snapshot_tests__", - "__tests__", - ] - ), -] - -products += [ - .library( - name: "QuickLayoutCore", - targets: ["QuickLayoutCore"] - ), - .library( - name: "QuickLayoutBridge", - targets: ["QuickLayoutBridge"] - ), -] -#endif - -let package = Package( - name: "QuickLayout", - platforms: [ - .iOS(.v15), - .macOS(.v10_15), - ], - products: products, - dependencies: [ - .package(url: "https://github.com/apple/swift-syntax.git", from: "602.0.0"), - .package(url: "https://github.com/pointfreeco/swift-macro-testing.git", from: "0.6.4"), - ], - targets: targets -) - -extension Target.Dependency { - // swift-syntax - static let swiftSyntax = Self.product(name: "SwiftSyntax", package: "swift-syntax") - static let swiftSyntaxMacros = Self.product(name: "SwiftSyntaxMacros", package: "swift-syntax") - static let swiftCompilerPlugin = Self.product(name: "SwiftCompilerPlugin", package: "swift-syntax") - static let swiftSyntaxBuilder = Self.product(name: "SwiftSyntaxBuilder", package: "swift-syntax") - static let swiftParserDiagnostics = Self.product(name: "SwiftParserDiagnostics", package: "swift-syntax") - static let swiftSyntaxMacrosTestSupport = Self.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax") - // swift-macro-testing - static let macroTesting = Self.product(name: "MacroTesting", package: "swift-macro-testing") -} From 14384ef3cc30ccce8bedba04380d184490332aa3 Mon Sep 17 00:00:00 2001 From: mlch911 Date: Tue, 2 Dec 2025 12:31:11 +0800 Subject: [PATCH 4/4] remove MacroTesting --- Package.swift | 3 - .../QuickLayoutMacro/QuickLayout.swift | 3 +- .../QuickLayoutTests.swift | 795 +++++++++--------- 3 files changed, 391 insertions(+), 410 deletions(-) diff --git a/Package.swift b/Package.swift index 79dedb9..3120d93 100644 --- a/Package.swift +++ b/Package.swift @@ -78,7 +78,6 @@ let package = Package( dependencies: [ "QuickLayoutMacro", .swiftSyntaxMacrosTestSupport, - .macroTesting, ], path: "Sources/QuickLayout/QuickLayoutMacroTests" ) @@ -93,6 +92,4 @@ extension Target.Dependency { static let swiftSyntaxBuilder = Self.product(name: "SwiftSyntaxBuilder", package: "swift-syntax") static let swiftParserDiagnostics = Self.product(name: "SwiftParserDiagnostics", package: "swift-syntax") static let swiftSyntaxMacrosTestSupport = Self.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax") - // swift-macro-testing - static let macroTesting = Self.product(name: "MacroTesting", package: "swift-macro-testing") } diff --git a/Sources/QuickLayout/QuickLayoutMacro/QuickLayout.swift b/Sources/QuickLayout/QuickLayoutMacro/QuickLayout.swift index 9b2cade..78b1287 100644 --- a/Sources/QuickLayout/QuickLayoutMacro/QuickLayout.swift +++ b/Sources/QuickLayout/QuickLayoutMacro/QuickLayout.swift @@ -8,6 +8,7 @@ import SwiftSyntax import SwiftSyntaxMacros import SwiftDiagnostics +import Foundation enum QuickLayoutDiagnostic: DiagnosticMessage { case missingRequiredImplementation(functionName: String, requiredCall: String) @@ -91,7 +92,7 @@ public struct QuickLayout: ExtensionMacro, MemberMacro, MemberAttributeMacro { let functionBody = memberFunction.body?.statements.description ?? "" // 检查方法体中是否包含必要的调用 - if functionBody.contains(requiredCall) { + if (functionBody as NSString).contains(requiredCall) { // 已经包含必要的实现,跳过 continue } else { diff --git a/Sources/QuickLayout/QuickLayoutMacroTests/QuickLayoutTests.swift b/Sources/QuickLayout/QuickLayoutMacroTests/QuickLayoutTests.swift index 5005b1b..3ca63bd 100644 --- a/Sources/QuickLayout/QuickLayoutMacroTests/QuickLayoutTests.swift +++ b/Sources/QuickLayout/QuickLayoutMacroTests/QuickLayoutTests.swift @@ -8,27 +8,19 @@ import SwiftSyntaxMacros import SwiftSyntaxMacrosTestSupport import XCTest -import MacroTesting #if canImport(QuickLayoutMacro) @testable import QuickLayoutMacro // patternlint-disable meta-subclass-view -class QuickLayoutTests: XCTestCase { - override func invokeTest() { - withMacroTesting( - record: .failed, - macros: [ - "QuickLayout": QuickLayout.self, - "_QuickLayoutInjection": QuickLayoutInjection.self, - ] - ) { - super.invokeTest() - } - } +let testMacros: [String: Macro.Type] = [ + "QuickLayout": QuickLayout.self, + "_QuickLayoutInjection": QuickLayoutInjection.self, +] +class QuickLayoutTests: XCTestCase { func testBasicMacroExpansion() throws { - assertMacro { + assertMacroExpansion( #""" @QuickLayout class TestView: UIView { @@ -36,42 +28,44 @@ class QuickLayoutTests: XCTestCase { EmptyLayout() } } - """# - } expansion: { - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """# - } + """#, + expandedSource: + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """#, + macros: testMacros, + indentationWidth: .spaces(2) + ) } func testApplicableMethodsDeferToProvidedImplementation() throws { - assertMacro { + assertMacroExpansion( #""" @QuickLayout class TestView: UIView { @@ -87,43 +81,45 @@ class QuickLayoutTests: XCTestCase { return uniqueFlexibilityValue } } - """# - } expansion: { - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - public func sizeThatFits(_ size: CGSize) -> CGSize { - return uniqueSizeValue - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return uniqueFlexibilityValue - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - } - - extension TestView: HasBody { - } - """# - } + """#, + expandedSource: + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + public func sizeThatFits(_ size: CGSize) -> CGSize { + return uniqueSizeValue + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return uniqueFlexibilityValue + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + } + + extension TestView: HasBody { + } + """#, + macros: testMacros, + indentationWidth: .spaces(2) + ) } func testApplicableMethodsInjectQuickLayoutBridgeementation() throws { #if compiler(>=6) - assertMacro { + assertMacroExpansion( #""" @QuickLayout class TestView: UIView { @@ -141,42 +137,44 @@ class QuickLayoutTests: XCTestCase { someUniqueLayoutSubviewsLogic() } } - """# - } expansion: { - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - someUniqueWillMoveToWindowLogic() - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - someUniqueLayoutSubviewsLogic() - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """# - } + """#, + expandedSource: + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + someUniqueWillMoveToWindowLogic() + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + someUniqueLayoutSubviewsLogic() + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """#, + macros: testMacros, + indentationWidth: .spaces(2) + ) #else - assertMacro { + assertMacroExpansion( #""" @QuickLayout class TestView: UIView { @@ -194,90 +192,63 @@ class QuickLayoutTests: XCTestCase { someUniqueLayoutSubviewsLogic() } } - """# - } diagnostics: { - """ - @QuickLayout - class TestView: UIView { - var body: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - ╰─ 🛑 方法 'willMove' 缺少必要的实现调用。在 Swift 6.0 以下,你必须手动添加以下调用: - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - super.willMove(toWindow: newWindow) - someUniqueWillMoveToWindowLogic() - } - - public override func layoutSubviews() { - ╰─ 🛑 方法 'layoutSubviews' 缺少必要的实现调用。在 Swift 6.0 以下,你必须手动添加以下调用: - _QuickLayoutViewImplementation.layoutSubviews(self) - super.layoutSubviews() - someUniqueLayoutSubviewsLogic() - } - } - """ - } - assertMacro { - #""" - @QuickLayout - class TestView: UIView { - var body: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) + """#, + expandedSource: + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + someUniqueWillMoveToWindowLogic() + } + + public override func layoutSubviews() { + super.layoutSubviews() + someUniqueLayoutSubviewsLogic() + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """#, + diagnostics: [ + .init( + message: """ + Method 'willMove' is missing required implementation call. Below Swift 6.0, you must manually add the following call: _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - someUniqueWillMoveToWindowLogic() - } - - public override func layoutSubviews() { - super.layoutSubviews() + """, + line: 7, + column: 3 + ), + .init( + message: """ + Method 'layoutSubviews' is missing required implementation call. Below Swift 6.0, you must manually add the following call: _QuickLayoutViewImplementation.layoutSubviews(self) - someUniqueLayoutSubviewsLogic() - } - } - """# - } expansion: { - """ - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - someUniqueWillMoveToWindowLogic() - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - someUniqueLayoutSubviewsLogic() - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """ - } + """, + line: 12, + column: 3 + ), + ], + macros: testMacros, + indentationWidth: .spaces(2) + ) #endif } func testTypeScopedFunctionsDoNotConflict() throws { - assertMacro { + assertMacroExpansion( #""" @QuickLayout class TestView: UIView { @@ -289,46 +260,48 @@ class QuickLayoutTests: XCTestCase { return uniqueSizeValue } } - """# - } expansion: { - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - static func sizeThatFits(_ size: CGSize) -> CGSize { - return uniqueSizeValue - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """# - } + """#, + expandedSource: + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + static func sizeThatFits(_ size: CGSize) -> CGSize { + return uniqueSizeValue + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """#, + macros: testMacros, + indentationWidth: .spaces(2) + ) } func testOverloadedFunctionsDoNotConflict() throws { - assertMacro { + assertMacroExpansion( #""" @QuickLayout class TestView: UIView { @@ -340,46 +313,48 @@ class QuickLayoutTests: XCTestCase { return uniqueSizeValue } } - """# - } expansion: { - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - func sizeThatFits(_ size: CGSize) -> NotACGSize { - return uniqueSizeValue - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """# - } + """#, + expandedSource: + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + func sizeThatFits(_ size: CGSize) -> NotACGSize { + return uniqueSizeValue + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """#, + macros: testMacros, + indentationWidth: .spaces(2) + ) } func testParameterMismatchedFunctionsDoNotConflict() throws { - assertMacro { + assertMacroExpansion( #""" @QuickLayout class TestView: UIView { @@ -391,46 +366,48 @@ class QuickLayoutTests: XCTestCase { return uniqueSizeValue } } - """# - } expansion: { - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - func sizeThatFits(_ notASize: NotACGSize) -> CGSize { - return uniqueSizeValue - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """# - } + """#, + expandedSource: + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + func sizeThatFits(_ notASize: NotACGSize) -> CGSize { + return uniqueSizeValue + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """#, + macros: testMacros, + indentationWidth: .spaces(2) + ) } func testLayoutBuilderAttributeNotAddedIfPresent() throws { - assertMacro { + assertMacroExpansion( #""" @QuickLayout class TestView: UIView { @@ -439,42 +416,44 @@ class QuickLayoutTests: XCTestCase { EmptyLayout() } } - """# - } expansion: { - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """# - } + """#, + expandedSource: + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """#, + macros: testMacros, + indentationWidth: .spaces(2) + ) } func testLayoutBuilderAttributeOnlyAddedToBody() throws { - assertMacro { + assertMacroExpansion( #""" @QuickLayout class TestView: UIView { @@ -486,46 +465,48 @@ class QuickLayoutTests: XCTestCase { EmptyLayout() } } - """# - } expansion: { - #""" - class TestView: UIView { - @LayoutBuilder - var body: Layout { - EmptyLayout() - } - - var notBody: Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """# - } + """#, + expandedSource: + #""" + class TestView: UIView { + @LayoutBuilder + var body: Layout { + EmptyLayout() + } + + var notBody: Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """#, + macros: testMacros, + indentationWidth: .spaces(2) + ) } func testLayoutBuilderAttributeAppliesToAnyLayout() throws { - assertMacro { + assertMacroExpansion( #""" @QuickLayout class TestView: UIView { @@ -533,38 +514,40 @@ class QuickLayoutTests: XCTestCase { EmptyLayout() } } - """# - } expansion: { - #""" - class TestView: UIView { - @LayoutBuilder - var body: any Layout { - EmptyLayout() - } - - public override func willMove(toWindow newWindow: UIWindow?) { - super.willMove(toWindow: newWindow) - _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) - } - - public override func layoutSubviews() { - super.layoutSubviews() - _QuickLayoutViewImplementation.layoutSubviews(self) - } - - public override func sizeThatFits(_ size: CGSize) -> CGSize { - return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) - } - - public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { - return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) - } - } - - extension TestView: HasBody { - } - """# - } + """#, + expandedSource: + #""" + class TestView: UIView { + @LayoutBuilder + var body: any Layout { + EmptyLayout() + } + + public override func willMove(toWindow newWindow: UIWindow?) { + super.willMove(toWindow: newWindow) + _QuickLayoutViewImplementation.willMove(self, toWindow: newWindow) + } + + public override func layoutSubviews() { + super.layoutSubviews() + _QuickLayoutViewImplementation.layoutSubviews(self) + } + + public override func sizeThatFits(_ size: CGSize) -> CGSize { + return _QuickLayoutViewImplementation.sizeThatFits(self, size: size) ?? super.sizeThatFits(size) + } + + public override func quick_flexibility(for axis: QuickLayoutCore.Axis) -> Flexibility { + return _QuickLayoutViewImplementation.quick_flexibility(self, for: axis) ?? super.quick_flexibility(for: axis) + } + } + + extension TestView: HasBody { + } + """#, + macros: testMacros, + indentationWidth: .spaces(2) + ) } } #endif