diff --git a/Package.resolved b/Package.resolved index c80de824..bffd0b13 100644 --- a/Package.resolved +++ b/Package.resolved @@ -23,9 +23,9 @@ "package": "XcodeEdit", "repositoryURL": "https://github.com/tomlokhorst/XcodeEdit", "state": { - "branch": null, - "revision": "3262eff18497ae856eb4fb4b7506cd5c15d28dd4", - "version": "1.1.0" + "branch": "release/2.0", + "revision": "2a6ab33948312a4342269099b548fb19af4ad16d", + "version": null } } ] diff --git a/Package.swift b/Package.swift index c691f13b..0f7a5ddc 100644 --- a/Package.swift +++ b/Package.swift @@ -5,7 +5,7 @@ let package = Package( name: "rswift", dependencies: [ .package(url: "https://github.com/kylef/Commander.git", .upToNextMinor(from: "0.6.0")), - .package(url: "https://github.com/tomlokhorst/XcodeEdit", from: "1.0.0") + .package(url: "https://github.com/tomlokhorst/XcodeEdit", .branch("release/2.0")) ], targets: [ .target( diff --git a/ResourceApp/ResourceApp.xcodeproj/project.pbxproj b/ResourceApp/ResourceApp.xcodeproj/project.pbxproj index 7300ee84..f0a51f41 100644 --- a/ResourceApp/ResourceApp.xcodeproj/project.pbxproj +++ b/ResourceApp/ResourceApp.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + DEADBEEFDEADBEEFDEADBEEF /* Dummy build file that is'nt used */ = {isa = PBXBuildFile; fileRef = C0FEFEC0FEFEC0FEFEC0FEFE /* Localizable.strings */; }; 5D1AFAB11C858637003FE7AB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5D1AFAAF1C858637003FE7AB /* Localizable.strings */; }; 5D9E41341C96918E002172D3 /* StringsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D9E41331C96918E002172D3 /* StringsTests.swift */; }; 8A0FBCE6E8FF0950B8821B0B /* Pods_Shared_ResourceApp_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF513940333862726B930435 /* Pods_Shared_ResourceApp_tvOS.framework */; }; diff --git a/ResourceApp/ResourceAppTests/ResourceAppTests.swift b/ResourceApp/ResourceAppTests/ResourceAppTests.swift index 15be65ea..91eca5c2 100644 --- a/ResourceApp/ResourceAppTests/ResourceAppTests.swift +++ b/ResourceApp/ResourceAppTests/ResourceAppTests.swift @@ -12,45 +12,51 @@ import XCTest class ResourceAppTests: XCTestCase { - let expectedWarnings = [ - "warning: [R.swift] Skipping color 'Red' in 'Display P3.clr' because it is colorspace 'Display P3 colorspace', R.swift currently only supports colorspace RGB", - "warning: [R.swift] Skipping color 'Green' in 'Display P3.clr' because it is colorspace 'Display P3 colorspace', R.swift currently only supports colorspace RGB", + let expectedWarnings = """ + warning: [R.swift] project.pbxproj is internally inconsistent. - "warning: [R.swift] Skipping 2 images because symbol 'second' would be generated for all of these images: Second, second", - "warning: [R.swift] Skipping 2 xibs because symbol 'duplicate' would be generated for all of these files: Duplicate, duplicate", - "warning: [R.swift] Skipping 2 storyboards because symbol 'duplicate' would be generated for all of these files: Duplicate, duplicate", - "warning: [R.swift] Skipping 2 reuseIdentifiers because symbol 'duplicateCellView' would be generated for all of these reuseIdentifiers: DuplicateCellView, duplicateCellView", - "warning: [R.swift] Skipping 2 segues for 'SecondViewController' because symbol 'toFirst' would be generated for all of these segues: ToFirst, toFirst", - "warning: [R.swift] Skipping 2 images because symbol 'theAppIcon' would be generated for all of these images: The App Icon, TheAppIcon", - "warning: [R.swift] Skipping 2 images because symbol 'second' would be generated for all of these images: Second, second", - "warning: [R.swift] Skipping 2 resource files because symbol 'duplicateJson' would be generated for all of these files: Duplicate.json, duplicateJson", - "warning: [R.swift] Destination view controller with id Zbd-89-K73 for segue toUnknown in FirstViewController not found in storyboard References. Is this storyboard corrupt?", - "warning: [R.swift] Skipping 2 view controllers because symbol 'validationClash' would be generated for all of these view controller identifiers: Validation clash, ValidationClash", - "warning: [R.swift] Skipping 1 reuseIdentifier because no swift identifier can be generated for reuseIdentifier: ' '", - "warning: [R.swift] Skipping 2 colors in palette 'My R.swift colors' because symbol 'black' would be generated for all of these colors: Black, Black?", - "warning: [R.swift] Skipping 2 colors because symbol 'myRed' would be generated for all of these colors: My Red, My Red", + - PBXBuildFile (DEADBEEFDEADBEEFDEADBEEF) references missing fileRef C0FEFEC0FEFEC0FEFEC0FEFE + - PBXBuildFile (DEADBEEFDEADBEEFDEADBEEF) is not used - "warning: [R.swift] Skipping 2 strings files because symbol 'duplicate' would be generated for all of these files: Duplicate, Duplicate#", - "warning: [R.swift] Skipping 1 strings file because no swift identifier can be generated for file: '@@'", - "warning: [R.swift] Skipping 1 string in 'Generic' because no swift identifier can be generated for key: '#'", - "warning: [R.swift] Strings file 'Localizable' (en) is missing translations for keys: 'japanese only'", - "warning: [R.swift] Strings file 'Localizable' (es) is missing translations for keys: 'japanese only'", - "warning: [R.swift] Strings file 'Settings' (nl) is missing translations for keys: 'Not translated', 'incorrect in dutch'", - "warning: [R.swift] Skipping string FormatSpecifiers2 in 'Settings' (nl), not all format specifiers are consecutive", - "warning: [R.swift] Skipping string FormatSpecifiers6 in 'Settings' (Base), not all format specifiers are consecutive", - "warning: [R.swift] Skipping string FormatSpecifiers6 in 'Settings' (nl), not all format specifiers are consecutive", - "warning: [R.swift] Skipping string for key FormatSpecifiers5 (Settings), format specifiers don't match for all locales: Base, nl", - "warning: [R.swift] Skipping string for key mismatch (Settings), format specifiers don't match for all locales: Base, nl", + Perhaps a merge conflict? - "warning: [R.swift] Missing reference 'missing' in 'fault delta' 'Generic.stringsdict'", - "warning: [R.swift] Can't unify 'first' in 'fault beta' 'Generic.stringsdict'", - "warning: [R.swift] Can't unify 'first' in 'fault gamma' 'Generic.stringsdict'", - "warning: [R.swift] Missing reference 'missing' in 'fault alpha' 'Generic.stringsdict'", - "warning: [R.swift] Missing reference 'first_one' in 'fault epsilon' 'Generic.stringsdict'", - "warning: [R.swift] Missing reference 'first' in 'incorrect in dutch' 'Settings.stringsdict' (nl)", - "warning: [R.swift] Skipping asset subfolder because symbol 'conflicting' would conflict with image: conflicting", - "warning: [R.swift] Skipping 2 images because symbol 'second' would be generated for all of these images: Second, Second" - ] + warning: [R.swift] Skipping color 'Red' in 'Display P3.clr' because it is colorspace 'Display P3 colorspace', R.swift currently only supports colorspace RGB + warning: [R.swift] Skipping color 'Green' in 'Display P3.clr' because it is colorspace 'Display P3 colorspace', R.swift currently only supports colorspace RGB + warning: [R.swift] Missing reference 'missing' in 'fault delta' 'Generic.stringsdict' + warning: [R.swift] Can't unify 'first' in 'fault beta' 'Generic.stringsdict' + warning: [R.swift] Can't unify 'first' in 'fault gamma' 'Generic.stringsdict' + warning: [R.swift] Missing reference 'missing' in 'fault alpha' 'Generic.stringsdict' + warning: [R.swift] Missing reference 'first_one' in 'fault epsilon' 'Generic.stringsdict' + warning: [R.swift] Missing reference 'first' in 'incorrect in dutch' 'Settings.stringsdict' (nl) + warning: [R.swift] Skipping 2 colors in palette 'My R.swift colors' because symbol 'black' would be generated for all of these colors: Black, Black? + warning: [R.swift] Skipping 2 images because symbol 'second' would be generated for all of these images: Second, second + warning: [R.swift] Skipping 2 images because symbol 'theAppIcon' would be generated for all of these images: The App Icon, TheAppIcon + warning: [R.swift] Skipping asset subfolder because symbol 'conflicting' would conflict with image: conflicting + warning: [R.swift] Skipping 2 images because symbol 'second' would be generated for all of these images: Second, Second + warning: [R.swift] Skipping 2 colors because symbol 'myRed' would be generated for all of these colors: My Red, My Red + warning: [R.swift] Destination view controller with id Zbd-89-K73 for segue toUnknown in FirstViewController not found in storyboard References. Is this storyboard corrupt? + warning: [R.swift] Skipping 2 segues for 'SecondViewController' because symbol 'toFirst' would be generated for all of these segues: ToFirst, toFirst + warning: [R.swift] Skipping 2 storyboards because symbol 'duplicate' would be generated for all of these files: Duplicate, duplicate + warning: [R.swift] Skipping 2 view controllers because symbol 'validationClash' would be generated for all of these view controller identifiers: Validation clash, ValidationClash + warning: [R.swift] Skipping 2 xibs because symbol 'duplicate' would be generated for all of these files: Duplicate, duplicate + warning: [R.swift] Skipping 2 reuseIdentifiers because symbol 'duplicateCellView' would be generated for all of these reuseIdentifiers: DuplicateCellView, duplicateCellView + warning: [R.swift] Skipping 1 reuseIdentifier because no swift identifier can be generated for reuseIdentifier: ' ' + warning: [R.swift] Skipping 2 resource files because symbol 'duplicateJson' would be generated for all of these files: Duplicate.json, duplicateJson + warning: [R.swift] Skipping 2 strings files because symbol 'duplicate' would be generated for all of these files: Duplicate, Duplicate# + warning: [R.swift] Skipping 1 strings file because no swift identifier can be generated for file: '@@' + warning: [R.swift] Strings file 'Localizable' (es) is missing translations for keys: 'japanese only' + warning: [R.swift] Strings file 'Localizable' (en) is missing translations for keys: 'japanese only' + warning: [R.swift] Strings file 'Settings' (nl) is missing translations for keys: 'Not translated', 'incorrect in dutch' + warning: [R.swift] Skipping string FormatSpecifiers2 in 'Settings' (nl), not all format specifiers are consecutive + warning: [R.swift] Skipping string FormatSpecifiers6 in 'Settings' (Base), not all format specifiers are consecutive + warning: [R.swift] Skipping string FormatSpecifiers6 in 'Settings' (nl), not all format specifiers are consecutive + warning: [R.swift] Skipping string for key FormatSpecifiers5 (Settings), format specifiers don't match for all locales: Base, nl + warning: [R.swift] Skipping string for key mismatch (Settings), format specifiers don't match for all locales: Base, nl + warning: [R.swift] Skipping 1 string in 'Generic' because no swift identifier can be generated for key: '#' + warning: [R.swift] Skipping 2 colors in palette 'My R.swift colors' because symbol 'black' would be generated for all of these colors: Black, Black? + """ + .trimmingCharacters(in: .whitespacesAndNewlines) + .components(separatedBy: "\n") func testWarningsAreLogged() { guard let logURL = Bundle(for: ResourceAppTests.self).url(forResource: "rswift", withExtension: "log") else { @@ -60,7 +66,9 @@ class ResourceAppTests: XCTestCase { do { let logContent = try String(contentsOf: logURL) - let logLines = logContent.components(separatedBy: "\n").filter { !$0.isEmpty } + let logLines = logContent + .trimmingCharacters(in: .whitespacesAndNewlines) + .components(separatedBy: "\n") for warning in expectedWarnings { XCTAssertTrue(logLines.contains(warning), "Warning is not logged: '\(warning)'") diff --git a/Sources/RswiftCore/ResourceTypes/Xcodeproj.swift b/Sources/RswiftCore/ResourceTypes/Xcodeproj.swift index 8e3fb519..31b5c1e0 100644 --- a/Sources/RswiftCore/ResourceTypes/Xcodeproj.swift +++ b/Sources/RswiftCore/ResourceTypes/Xcodeproj.swift @@ -17,9 +17,20 @@ struct Xcodeproj: WhiteListedExtensionsResourceType { init(url: URL) throws { try Xcodeproj.throwIfUnsupportedExtension(url.pathExtension) + let projectFile: XCProjectFile // Parse project file - guard let projectFile = try? XCProjectFile(xcodeprojURL: url) else { + do { + do { + projectFile = try XCProjectFile(xcodeprojURL: url) + } + catch let error as ProjectFileError { + warn(error.description) + + projectFile = try XCProjectFile(xcodeprojURL: url, ignoreReferenceErrors: true) + } + } + catch { throw ResourceParsingError.parsingFailed("Project file at '\(url)' could not be parsed, is this a valid Xcode project file ending in *.xcodeproj?") } @@ -28,25 +39,25 @@ struct Xcodeproj: WhiteListedExtensionsResourceType { func resourcePathsForTarget(_ targetName: String) throws -> [Path] { // Look for target in project file - let allTargets = projectFile.project.targets + let allTargets = projectFile.project.targets.flatMap { $0.value } guard let target = allTargets.filter({ $0.name == targetName }).first else { - let availableTargets = allTargets.map { $0.name }.joined(separator: ", ") + let availableTargets = allTargets.flatMap { $0.name }.joined(separator: ", ") throw ResourceParsingError.parsingFailed("Target '\(targetName)' not found in project file, available targets are: \(availableTargets)") } let resourcesFileRefs = target.buildPhases - .flatMap { $0 as? PBXResourcesBuildPhase } + .flatMap { $0.value as? PBXResourcesBuildPhase } .flatMap { $0.files } - .map { $0.fileRef } + .flatMap { $0.value?.fileRef } let fileRefPaths = resourcesFileRefs - .flatMap { $0 as? PBXFileReference } - .map { $0.fullPath } + .flatMap { $0.value as? PBXFileReference } + .flatMap { $0.fullPath } let variantGroupPaths = resourcesFileRefs - .flatMap { $0 as? PBXVariantGroup } + .flatMap { $0.value as? PBXVariantGroup } .flatMap { $0.fileRefs } - .map { $0.fullPath } + .flatMap { $0.value?.fullPath } return fileRefPaths + variantGroupPaths }