diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a4f0bf4c8..0fd2db638 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: inputs: version: - description: 'The version to release' + description: "The version to release" type: string permissions: @@ -19,7 +19,7 @@ permissions: jobs: release: name: Release - runs-on: 'ubuntu-latest' + runs-on: "ubuntu-latest" timeout-minutes: 15 if: "!startsWith(github.event.head_commit.message, '[Release]')" steps: @@ -62,7 +62,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | echo "RELEASE_NOTES<> "$GITHUB_OUTPUT" - git cliff 8.22.0.. --unreleased >> "$GITHUB_OUTPUT" + git cliff 8.22.0.. --bump --unreleased >> "$GITHUB_OUTPUT" echo "EOF" >> "$GITHUB_OUTPUT" - name: Update CHANGELOG.md if: env.should-release == 'true' @@ -74,7 +74,7 @@ jobs: uses: stefanzweifel/git-auto-commit-action@v5 if: env.should-release == 'true' with: - commit_options: '--allow-empty' + commit_options: "--allow-empty" tagging_message: ${{ steps.next-version.outputs.NEXT_VERSION }} skip_dirty_check: true commit_message: "[Release] XcodeProj ${{ steps.next-version.outputs.NEXT_VERSION }}" diff --git a/.github/workflows/xcodeproj.yml b/.github/workflows/xcodeproj.yml index 904880cdb..abe2b1317 100644 --- a/.github/workflows/xcodeproj.yml +++ b/.github/workflows/xcodeproj.yml @@ -20,6 +20,8 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v3 + - name: Select Xcode 16 + run: sudo xcode-select -switch /Applications/Xcode_16.app/Contents/Developer - uses: jdx/mise-action@v2 - name: Build run: mise run build @@ -36,6 +38,8 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v3 + - name: Select Xcode 16 + run: sudo xcode-select -switch /Applications/Xcode_16.app/Contents/Developer - uses: jdx/mise-action@v2 - name: Run tests run: mise run test @@ -54,5 +58,7 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v3 + - name: Select Xcode 16 + run: sudo xcode-select -switch /Applications/Xcode_16.app/Contents/Developer - uses: jdx/mise-action@v2 - run: mise run lint diff --git a/Fixtures/SynchronizedRootGroups/SynchronizedRootGroups.xcodeproj/project.pbxproj b/Fixtures/SynchronizedRootGroups/SynchronizedRootGroups.xcodeproj/project.pbxproj index 5db92414b..c6a599659 100644 --- a/Fixtures/SynchronizedRootGroups/SynchronizedRootGroups.xcodeproj/project.pbxproj +++ b/Fixtures/SynchronizedRootGroups/SynchronizedRootGroups.xcodeproj/project.pbxproj @@ -21,7 +21,18 @@ /* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ - 6CF05B9D2C53F64800EF267F /* SynchronizedRootGroups */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (6CF05BA32C53F97F00EF267F /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = SynchronizedRootGroups; sourceTree = ""; }; + 6CF05B9D2C53F64800EF267F /* SynchronizedRootGroups */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 6CF05BA32C53F97F00EF267F /* PBXFileSystemSynchronizedBuildFileExceptionSet */, + ); + explicitFileTypes = { + }; + explicitFolders = ( + ); + path = SynchronizedRootGroups; + sourceTree = ""; + }; /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ diff --git a/Fixtures/Xcode16/README.md b/Fixtures/Xcode16/README.md new file mode 100644 index 000000000..e1673acd1 --- /dev/null +++ b/Fixtures/Xcode16/README.md @@ -0,0 +1,3 @@ +# Xcode 16 project + +Xcode 16 introduced some changes in Xcode projects, like [this one](https://github.com/tuist/XcodeProj/issues/861), so this fixture tries to capture those changes to run tests against them. diff --git a/Fixtures/Xcode16/Test.xcodeproj/project.pbxproj b/Fixtures/Xcode16/Test.xcodeproj/project.pbxproj new file mode 100644 index 000000000..38d0a9761 --- /dev/null +++ b/Fixtures/Xcode16/Test.xcodeproj/project.pbxproj @@ -0,0 +1,340 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXFileReference section */ + A4C5307E2CAAC8EA00EDC73B /* Test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Test.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + A4C530802CAAC8EA00EDC73B /* Test */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = Test; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + A4C5307B2CAAC8EA00EDC73B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A4C530752CAAC8EA00EDC73B = { + isa = PBXGroup; + children = ( + A4C530802CAAC8EA00EDC73B /* Test */, + A4C5307F2CAAC8EA00EDC73B /* Products */, + ); + sourceTree = ""; + }; + A4C5307F2CAAC8EA00EDC73B /* Products */ = { + isa = PBXGroup; + children = ( + A4C5307E2CAAC8EA00EDC73B /* Test.app */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A4C5307D2CAAC8EA00EDC73B /* Test */ = { + isa = PBXNativeTarget; + buildConfigurationList = A4C5308D2CAAC8EC00EDC73B /* Build configuration list for PBXNativeTarget "Test" */; + buildPhases = ( + A4C5307A2CAAC8EA00EDC73B /* Sources */, + A4C5307B2CAAC8EA00EDC73B /* Frameworks */, + A4C5307C2CAAC8EA00EDC73B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + A4C530802CAAC8EA00EDC73B /* Test */, + ); + name = Test; + packageProductDependencies = ( + ); + productName = Test; + productReference = A4C5307E2CAAC8EA00EDC73B /* Test.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A4C530762CAAC8EA00EDC73B /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1610; + LastUpgradeCheck = 1610; + TargetAttributes = { + A4C5307D2CAAC8EA00EDC73B = { + CreatedOnToolsVersion = 16.1; + }; + }; + }; + buildConfigurationList = A4C530792CAAC8EA00EDC73B /* Build configuration list for PBXProject "Test" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A4C530752CAAC8EA00EDC73B; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = A4C5307F2CAAC8EA00EDC73B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A4C5307D2CAAC8EA00EDC73B /* Test */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A4C5307C2CAAC8EA00EDC73B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A4C5307A2CAAC8EA00EDC73B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + A4C5308B2CAAC8EC00EDC73B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + A4C5308C2CAAC8EC00EDC73B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SWIFT_COMPILATION_MODE = wholemodule; + }; + name = Release; + }; + A4C5308E2CAAC8EC00EDC73B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Test/Test.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Test/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 18.1; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.Test; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + XROS_DEPLOYMENT_TARGET = 2.1; + }; + name = Debug; + }; + A4C5308F2CAAC8EC00EDC73B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Test/Test.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Test/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 18.1; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.Test; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + XROS_DEPLOYMENT_TARGET = 2.1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A4C530792CAAC8EA00EDC73B /* Build configuration list for PBXProject "Test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A4C5308B2CAAC8EC00EDC73B /* Debug */, + A4C5308C2CAAC8EC00EDC73B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A4C5308D2CAAC8EC00EDC73B /* Build configuration list for PBXNativeTarget "Test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A4C5308E2CAAC8EC00EDC73B /* Debug */, + A4C5308F2CAAC8EC00EDC73B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A4C530762CAAC8EA00EDC73B /* Project object */; +} diff --git a/Fixtures/Xcode16/Test/Assets.xcassets/AccentColor.colorset/Contents.json b/Fixtures/Xcode16/Test/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 000000000..eb8789700 --- /dev/null +++ b/Fixtures/Xcode16/Test/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fixtures/Xcode16/Test/Assets.xcassets/AppIcon.appiconset/Contents.json b/Fixtures/Xcode16/Test/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..ffdfe150b --- /dev/null +++ b/Fixtures/Xcode16/Test/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,85 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fixtures/Xcode16/Test/Assets.xcassets/Contents.json b/Fixtures/Xcode16/Test/Assets.xcassets/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Fixtures/Xcode16/Test/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fixtures/Xcode16/Test/ContentView.swift b/Fixtures/Xcode16/Test/ContentView.swift new file mode 100644 index 000000000..32435833a --- /dev/null +++ b/Fixtures/Xcode16/Test/ContentView.swift @@ -0,0 +1,24 @@ +// +// ContentView.swift +// Test +// +// Created by F1248 on 30.09.24. +// + +import SwiftUI + +struct ContentView: View { + var body: some View { + VStack { + Image(systemName: "globe") + .imageScale(.large) + .foregroundStyle(.tint) + Text("Hello, world!") + } + .padding() + } +} + +#Preview { + ContentView() +} diff --git a/Fixtures/Xcode16/Test/Preview Content/Preview Assets.xcassets/Contents.json b/Fixtures/Xcode16/Test/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Fixtures/Xcode16/Test/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fixtures/Xcode16/Test/Test.entitlements b/Fixtures/Xcode16/Test/Test.entitlements new file mode 100644 index 000000000..f2ef3ae02 --- /dev/null +++ b/Fixtures/Xcode16/Test/Test.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + diff --git a/Fixtures/Xcode16/Test/TestApp.swift b/Fixtures/Xcode16/Test/TestApp.swift new file mode 100644 index 000000000..bb7480e72 --- /dev/null +++ b/Fixtures/Xcode16/Test/TestApp.swift @@ -0,0 +1,17 @@ +// +// TestApp.swift +// Test +// +// Created by F1248 on 30.09.24. +// + +import SwiftUI + +@main +struct TestApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/Fixtures/Xcode16/copy.xcodeproj/project.pbxproj b/Fixtures/Xcode16/copy.xcodeproj/project.pbxproj new file mode 100644 index 000000000..4a66fedfd --- /dev/null +++ b/Fixtures/Xcode16/copy.xcodeproj/project.pbxproj @@ -0,0 +1,335 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXFileReference section */ + A4C5307E2CAAC8EA00EDC73B /* Test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Test.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + A4C530802CAAC8EA00EDC73B /* Test */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Test; sourceTree = ""; }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + A4C5307B2CAAC8EA00EDC73B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A4C530752CAAC8EA00EDC73B = { + isa = PBXGroup; + children = ( + A4C530802CAAC8EA00EDC73B /* Test */, + A4C5307F2CAAC8EA00EDC73B /* Products */, + ); + sourceTree = ""; + }; + A4C5307F2CAAC8EA00EDC73B /* Products */ = { + isa = PBXGroup; + children = ( + A4C5307E2CAAC8EA00EDC73B /* Test.app */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A4C5307D2CAAC8EA00EDC73B /* Test */ = { + isa = PBXNativeTarget; + buildConfigurationList = A4C5308D2CAAC8EC00EDC73B /* Build configuration list for PBXNativeTarget "Test" */; + buildPhases = ( + A4C5307A2CAAC8EA00EDC73B /* Sources */, + A4C5307B2CAAC8EA00EDC73B /* Frameworks */, + A4C5307C2CAAC8EA00EDC73B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + A4C530802CAAC8EA00EDC73B /* Test */, + ); + name = Test; + packageProductDependencies = ( + ); + productName = Test; + productReference = A4C5307E2CAAC8EA00EDC73B /* Test.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A4C530762CAAC8EA00EDC73B /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1610; + LastUpgradeCheck = 1610; + TargetAttributes = { + A4C5307D2CAAC8EA00EDC73B = { + CreatedOnToolsVersion = 16.1; + }; + }; + }; + buildConfigurationList = A4C530792CAAC8EA00EDC73B /* Build configuration list for PBXProject "copy" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A4C530752CAAC8EA00EDC73B; + preferredProjectObjectVersion = 77; + productRefGroup = A4C5307F2CAAC8EA00EDC73B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A4C5307D2CAAC8EA00EDC73B /* Test */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A4C5307C2CAAC8EA00EDC73B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A4C5307A2CAAC8EA00EDC73B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + A4C5308B2CAAC8EC00EDC73B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + A4C5308C2CAAC8EC00EDC73B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SWIFT_COMPILATION_MODE = wholemodule; + }; + name = Release; + }; + A4C5308E2CAAC8EC00EDC73B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Test/Test.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Test/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 18.1; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.Test; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + XROS_DEPLOYMENT_TARGET = 2.1; + }; + name = Debug; + }; + A4C5308F2CAAC8EC00EDC73B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Test/Test.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Test/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 18.1; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.Test; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + XROS_DEPLOYMENT_TARGET = 2.1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A4C530792CAAC8EA00EDC73B /* Build configuration list for PBXProject "copy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A4C5308B2CAAC8EC00EDC73B /* Debug */, + A4C5308C2CAAC8EC00EDC73B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A4C5308D2CAAC8EC00EDC73B /* Build configuration list for PBXNativeTarget "Test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A4C5308E2CAAC8EC00EDC73B /* Debug */, + A4C5308F2CAAC8EC00EDC73B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A4C530762CAAC8EA00EDC73B /* Project object */; +} diff --git a/Sources/XcodeProj/Objects/Files/PBXFileSystemSynchronizedRootGroup.swift b/Sources/XcodeProj/Objects/Files/PBXFileSystemSynchronizedRootGroup.swift index 5df7fe342..882d27db5 100644 --- a/Sources/XcodeProj/Objects/Files/PBXFileSystemSynchronizedRootGroup.swift +++ b/Sources/XcodeProj/Objects/Files/PBXFileSystemSynchronizedRootGroup.swift @@ -5,7 +5,7 @@ public class PBXFileSystemSynchronizedRootGroup: PBXFileElement { /// It maps relative paths inside the synchronized root group to a particular file type. /// If a path doesn't have a particular file type specified, Xcode defaults to the default file type /// based on the extension of the file. - public var explicitFileTypes: [String: String] + public var explicitFileTypes: [String: String]? /// Returns the references of the exceptions. var exceptionsReferences: [PBXObjectReference]? @@ -22,7 +22,7 @@ public class PBXFileSystemSynchronizedRootGroup: PBXFileElement { } /// A list of relative paths to children folder whose configuration is overriden. - public var explicitFolders: [String] + public var explicitFolders: [String]? /// Initializes the file element with its properties. /// @@ -74,16 +74,16 @@ public class PBXFileSystemSynchronizedRootGroup: PBXFileElement { let objects = decoder.context.objects let objectReferenceRepository = decoder.context.objectReferenceRepository let container = try decoder.container(keyedBy: CodingKeys.self) - explicitFileTypes = try (container.decodeIfPresent(.explicitFileTypes)) ?? [:] + explicitFileTypes = try container.decodeIfPresent(.explicitFileTypes) let exceptionsReferences: [String] = try (container.decodeIfPresent(.exceptions)) ?? [] self.exceptionsReferences = exceptionsReferences.map { objectReferenceRepository.getOrCreate(reference: $0, objects: objects) } - explicitFolders = try (container.decodeIfPresent(.explicitFolders)) ?? [] + explicitFolders = try container.decodeIfPresent(.explicitFolders) try super.init(from: decoder) } // MARK: - PlistSerializable - override var multiline: Bool { false } + override var multiline: Bool { true } override func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try super.plistKeyAndValue(proj: proj, reference: reference).value.dictionary ?? [:] @@ -93,10 +93,14 @@ public class PBXFileSystemSynchronizedRootGroup: PBXFileElement { .string(CommentedString(exceptionReference.value, comment: "PBXFileSystemSynchronizedBuildFileExceptionSet")) }) } - dictionary["explicitFileTypes"] = .dictionary(Dictionary(uniqueKeysWithValues: explicitFileTypes.map { relativePath, fileType in - (CommentedString(relativePath), .string(CommentedString(fileType))) - })) - dictionary["explicitFolders"] = .array(explicitFolders.map { .string(CommentedString($0)) }) + if let explicitFileTypes { + dictionary["explicitFileTypes"] = .dictionary(Dictionary(uniqueKeysWithValues: explicitFileTypes.map { relativePath, fileType in + (CommentedString(relativePath), .string(CommentedString(fileType))) + })) + } + if let explicitFolders { + dictionary["explicitFolders"] = .array(explicitFolders.map { .string(CommentedString($0)) }) + } return (key: CommentedString(reference, comment: name ?? path), value: .dictionary(dictionary)) diff --git a/Sources/XcodeProj/Objects/Project/PBXProject.swift b/Sources/XcodeProj/Objects/Project/PBXProject.swift index 14e896995..50dd148d0 100644 --- a/Sources/XcodeProj/Objects/Project/PBXProject.swift +++ b/Sources/XcodeProj/Objects/Project/PBXProject.swift @@ -26,6 +26,9 @@ public final class PBXProject: PBXObject { /// An int representation of the PreferredProjectObjectVersion. public var preferredProjectObjectVersion: Int? + /// An int representation of the minimizedProjectReferenceProxies attribute + public var minimizedProjectReferenceProxies: Int? + /// The region of development. public var developmentRegion: String? @@ -290,6 +293,7 @@ public final class PBXProject: PBXObject { /// - buildConfigurationList: project build configuration list. /// - compatibilityVersion: project compatibility version. /// - preferredProjectObjectVersion: preferred project object version + /// - minimizedProjectReferenceProxies: minimized project reference proxies /// - mainGroup: project main group. /// - developmentRegion: project has development region. /// - hasScannedForEncodings: project has scanned for encodings. @@ -306,6 +310,7 @@ public final class PBXProject: PBXObject { buildConfigurationList: XCConfigurationList, compatibilityVersion: String?, preferredProjectObjectVersion: Int?, + minimizedProjectReferenceProxies: Int?, mainGroup: PBXGroup, developmentRegion: String? = nil, hasScannedForEncodings: Int = 0, @@ -322,6 +327,7 @@ public final class PBXProject: PBXObject { buildConfigurationListReference = buildConfigurationList.reference self.compatibilityVersion = compatibilityVersion self.preferredProjectObjectVersion = preferredProjectObjectVersion + self.minimizedProjectReferenceProxies = minimizedProjectReferenceProxies mainGroupReference = mainGroup.reference self.developmentRegion = developmentRegion self.hasScannedForEncodings = hasScannedForEncodings @@ -345,6 +351,7 @@ public final class PBXProject: PBXObject { case buildConfigurationList case compatibilityVersion case preferredProjectObjectVersion + case minimizedProjectReferenceProxies case developmentRegion case hasScannedForEncodings case knownRegions @@ -367,7 +374,20 @@ public final class PBXProject: PBXObject { let buildConfigurationListReference: String = try container.decode(.buildConfigurationList) self.buildConfigurationListReference = referenceRepository.getOrCreate(reference: buildConfigurationListReference, objects: objects) compatibilityVersion = try container.decodeIfPresent(.compatibilityVersion) - preferredProjectObjectVersion = try container.decodeIfPresent(.preferredProjectObjectVersion) + preferredProjectObjectVersion = if let stringValue = try container.decodeIfPresent(String.self, forKey: .preferredProjectObjectVersion) { + Int(stringValue) + } else if let intValue = try container.decodeIfPresent(Int.self, forKey: .preferredProjectObjectVersion) { + intValue + } else { + nil + } + minimizedProjectReferenceProxies = if let stringValue = try container.decodeIfPresent(String.self, forKey: .minimizedProjectReferenceProxies) { + Int(stringValue) + } else if let intValue = try container.decodeIfPresent(Int.self, forKey: .minimizedProjectReferenceProxies) { + intValue + } else { + nil + } developmentRegion = try container.decodeIfPresent(.developmentRegion) let hasScannedForEncodingsString: String? = try container.decodeIfPresent(.hasScannedForEncodings) hasScannedForEncodings = hasScannedForEncodingsString.flatMap { Int($0) } ?? 0 @@ -507,6 +527,9 @@ extension PBXProject: PlistSerializable { if let preferredProjectObjectVersion { dictionary["preferredProjectObjectVersion"] = .string(CommentedString(preferredProjectObjectVersion.description)) } + if let minimizedProjectReferenceProxies { + dictionary["minimizedProjectReferenceProxies"] = .string(CommentedString(minimizedProjectReferenceProxies.description)) + } if let productsGroupReference { let productRefGroupObject: PBXGroup? = productsGroupReference.getObject() dictionary["productRefGroup"] = .string(CommentedString(productsGroupReference.value, diff --git a/Tests/XcodeProjTests/Objects/Files/PBXContainerItemProxyTests.swift b/Tests/XcodeProjTests/Objects/Files/PBXContainerItemProxyTests.swift index f0c7fa4bd..e5f660a78 100644 --- a/Tests/XcodeProjTests/Objects/Files/PBXContainerItemProxyTests.swift +++ b/Tests/XcodeProjTests/Objects/Files/PBXContainerItemProxyTests.swift @@ -20,7 +20,7 @@ final class PBXContainerItemProxyTests: XCTestCase { func test_maintains_remoteID() { let target = PBXNativeTarget(name: "") - let project = PBXProject(name: "", buildConfigurationList: XCConfigurationList(), compatibilityVersion: "", preferredProjectObjectVersion: nil, mainGroup: PBXGroup()) + let project = PBXProject(name: "", buildConfigurationList: XCConfigurationList(), compatibilityVersion: "", preferredProjectObjectVersion: nil, minimizedProjectReferenceProxies: nil, mainGroup: PBXGroup()) let containerProxy = PBXContainerItemProxy(containerPortal: .project(project), remoteGlobalID: .object(target)) XCTAssertEqual(target.uuid, containerProxy.remoteGlobalID?.uuid) diff --git a/Tests/XcodeProjTests/Objects/Files/PBXFileElementTests.swift b/Tests/XcodeProjTests/Objects/Files/PBXFileElementTests.swift index 3a0859f27..b7b5acd81 100644 --- a/Tests/XcodeProjTests/Objects/Files/PBXFileElementTests.swift +++ b/Tests/XcodeProjTests/Objects/Files/PBXFileElementTests.swift @@ -55,6 +55,7 @@ final class PBXFileElementTests: XCTestCase { buildConfigurationList: XCConfigurationList(), compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup) let objects = PBXObjects(objects: [project, mainGroup, fileref, group]) @@ -111,6 +112,7 @@ final class PBXFileElementTests: XCTestCase { buildConfigurationList: XCConfigurationList(), compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: rootGroup) let objects = PBXObjects(objects: [fileref, nestedGroup, rootGroup, project]) diff --git a/Tests/XcodeProjTests/Objects/Files/PBXGroupTests.swift b/Tests/XcodeProjTests/Objects/Files/PBXGroupTests.swift index 41080cf09..fae0e530d 100644 --- a/Tests/XcodeProjTests/Objects/Files/PBXGroupTests.swift +++ b/Tests/XcodeProjTests/Objects/Files/PBXGroupTests.swift @@ -19,6 +19,7 @@ final class PBXGroupTests: XCTestCase { buildConfigurationList: XCConfigurationList(), compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: group) project.add(object: pbxProject) @@ -141,6 +142,7 @@ final class PBXGroupTests: XCTestCase { buildConfigurationList: XCConfigurationList(), compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: group) project.add(object: pbxProject) @@ -166,6 +168,7 @@ final class PBXGroupTests: XCTestCase { buildConfigurationList: XCConfigurationList(), compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: group) project.add(object: pbxProject) @@ -190,6 +193,7 @@ final class PBXGroupTests: XCTestCase { buildConfigurationList: XCConfigurationList(), compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: group) project.add(object: pbxProject) diff --git a/Tests/XcodeProjTests/Objects/Project/PBXProjEncoderTests.swift b/Tests/XcodeProjTests/Objects/Project/PBXProjEncoderTests.swift index 9ff5e3cbc..482bf8cce 100644 --- a/Tests/XcodeProjTests/Objects/Project/PBXProjEncoderTests.swift +++ b/Tests/XcodeProjTests/Objects/Project/PBXProjEncoderTests.swift @@ -294,7 +294,18 @@ class PBXProjEncoderTests: XCTestCase { let lines = lines(fromFile: encodeProject(settings: settings)) let beginGroup = lines.findLine("/* Begin PBXFileSystemSynchronizedRootGroup section */") - var line = lines.validate(line: "6CF05B9D2C53F64800EF267F /* SynchronizedRootGroups */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (6CF05BA32C53F97F00EF267F /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = SynchronizedRootGroups; sourceTree = \"\"; };", after: beginGroup) + var line = lines.validate(line: "6CF05B9D2C53F64800EF267F /* SynchronizedRootGroups */ = {", after: beginGroup) + line = lines.validate(line: "isa = PBXFileSystemSynchronizedRootGroup;", after: line) + line = lines.validate(line: "exceptions = (", after: line) + line = lines.validate(line: "6CF05BA32C53F97F00EF267F /* PBXFileSystemSynchronizedBuildFileExceptionSet */,", after: line) + line = lines.validate(line: ");", after: line) + line = lines.validate(line: "explicitFileTypes = {", after: line) + line = lines.validate(line: "};", after: line) + line = lines.validate(line: "explicitFolders = (", after: line) + line = lines.validate(line: ");", after: line) + line = lines.validate(line: "path = SynchronizedRootGroups;", after: line) + line = lines.validate(line: "sourceTree = \"\";", after: line) + line = lines.validate(line: "};", after: line) line = lines.validate(line: "/* End PBXFileSystemSynchronizedRootGroup section */", after: line) } diff --git a/Tests/XcodeProjTests/Objects/Project/PBXProject+Fixtures.swift b/Tests/XcodeProjTests/Objects/Project/PBXProject+Fixtures.swift index d59c3e9c8..dd51d4143 100644 --- a/Tests/XcodeProjTests/Objects/Project/PBXProject+Fixtures.swift +++ b/Tests/XcodeProjTests/Objects/Project/PBXProject+Fixtures.swift @@ -11,6 +11,7 @@ extension PBXProject { buildConfigurationList: buildConfigurationList, compatibilityVersion: compatibilityVersion, preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup) } } diff --git a/Tests/XcodeProjTests/Objects/Project/PBXProjectTests.swift b/Tests/XcodeProjTests/Objects/Project/PBXProjectTests.swift index 8353a8a80..dc79c4698 100644 --- a/Tests/XcodeProjTests/Objects/Project/PBXProjectTests.swift +++ b/Tests/XcodeProjTests/Objects/Project/PBXProjectTests.swift @@ -13,6 +13,7 @@ final class PBXProjectTests: XCTestCase { buildConfigurationList: XCConfigurationList(), compatibilityVersion: "", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: PBXGroup(), attributes: ["LastUpgradeCheck": "0940"], targetAttributes: [target: ["TestTargetID": "123"]]) @@ -56,6 +57,7 @@ final class PBXProjectTests: XCTestCase { buildConfigurationList: configurationList, compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup, targets: [target]) @@ -92,6 +94,7 @@ final class PBXProjectTests: XCTestCase { buildConfigurationList: configurationList, compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup, targets: [target]) @@ -129,6 +132,7 @@ final class PBXProjectTests: XCTestCase { buildConfigurationList: configurationList, compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup, targets: [target]) @@ -170,6 +174,7 @@ final class PBXProjectTests: XCTestCase { buildConfigurationList: configurationList, compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup, targets: [target]) @@ -224,6 +229,7 @@ final class PBXProjectTests: XCTestCase { buildConfigurationList: configurationList, compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup, targets: [target, secondTarget]) @@ -299,6 +305,7 @@ final class PBXProjectTests: XCTestCase { buildConfigurationList: configurationList, compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup, targets: [target, secondTarget]) diff --git a/Tests/XcodeProjTests/Objects/Targets/PBXAggregateTargetTests.swift b/Tests/XcodeProjTests/Objects/Targets/PBXAggregateTargetTests.swift index 3083d623e..09947e76c 100644 --- a/Tests/XcodeProjTests/Objects/Targets/PBXAggregateTargetTests.swift +++ b/Tests/XcodeProjTests/Objects/Targets/PBXAggregateTargetTests.swift @@ -40,6 +40,7 @@ final class PBXAggregateTargetTests: XCTestCase { buildConfigurationList: configurationList, compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup) objects.add(object: project) diff --git a/Tests/XcodeProjTests/Objects/Targets/PBXNativeTargetTests.swift b/Tests/XcodeProjTests/Objects/Targets/PBXNativeTargetTests.swift index 3a08b7aa9..11aa27581 100644 --- a/Tests/XcodeProjTests/Objects/Targets/PBXNativeTargetTests.swift +++ b/Tests/XcodeProjTests/Objects/Targets/PBXNativeTargetTests.swift @@ -41,6 +41,7 @@ final class PBXNativeTargetTests: XCTestCase { buildConfigurationList: configurationList, compatibilityVersion: "0", preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup) objects.add(object: project) diff --git a/Tests/XcodeProjTests/Project/XcodeProjIntegrationTests.swift b/Tests/XcodeProjTests/Project/XcodeProjIntegrationTests.swift index 8bcb72580..374515c8b 100644 --- a/Tests/XcodeProjTests/Project/XcodeProjIntegrationTests.swift +++ b/Tests/XcodeProjTests/Project/XcodeProjIntegrationTests.swift @@ -4,6 +4,11 @@ import XCTest @testable import XcodeProj final class XcodeProjIntegrationTests: XCTestCase { + func test_write_xcode16Project() throws { + try testReadWriteProducesNoDiff(from: xcode16ProjectPath, + initModel: XcodeProj.init(path:)) + } + func test_read_iosXcodeProj() throws { let subject = try XcodeProj(path: iosProjectPath) assert(project: subject) @@ -96,6 +101,10 @@ final class XcodeProjIntegrationTests: XCTestCase { fixturesPath() + "iOS/Project.xcodeproj" } + private var xcode16ProjectPath: Path { + fixturesPath() + "Xcode16/Test.xcodeproj" + } + private var synchronizedRootGroupsFixturePath: Path { fixturesPath() + "SynchronizedRootGroups/SynchronizedRootGroups.xcodeproj" } diff --git a/Tests/XcodeProjTests/Utils/ReferenceGeneratorTests.swift b/Tests/XcodeProjTests/Utils/ReferenceGeneratorTests.swift index e9d15059c..6df8959c3 100644 --- a/Tests/XcodeProjTests/Utils/ReferenceGeneratorTests.swift +++ b/Tests/XcodeProjTests/Utils/ReferenceGeneratorTests.swift @@ -95,6 +95,7 @@ private extension PBXProj { buildConfigurationList: XCConfigurationList.fixture(), compatibilityVersion: Xcode.Default.compatibilityVersion, preferredProjectObjectVersion: nil, + minimizedProjectReferenceProxies: nil, mainGroup: mainGroup) add(object: mainGroup)