From f35ddd5c5105469aee89e8c7af8c1c7c2b316abe Mon Sep 17 00:00:00 2001 From: Kuniwak Date: Sun, 10 Jun 2018 12:40:36 +0900 Subject: [PATCH] Support Swift 4.2 (#38) * Refresh gitignore * Migrate to Swift 4.2 * Support the new associated value representation of Swift 4.2 * Ignore artifacts that created by Carthage * Fix a problem about compatibility for Swift 4.1 --- .gitignore | 157 ++++++++++++++++-- Configs/Frameworks/MirrorDiffKit.plist | 28 ++++ Configs/Tests/MirrorDiffKitTests.plist | 24 +++ MirrorDiffKit.xcodeproj/project.pbxproj | 22 ++- .../xcschemes/MirrorDiffKit-iOS.xcscheme | 8 +- .../xcschemes/MirrorDiffKit-macOS.xcscheme | 8 +- .../xcschemes/MirrorDiffKit-tvOS.xcscheme | 8 +- .../xcschemes/MirrorDiffKit-watchOS.xcscheme | 8 +- README.md | 2 +- Sources/TupleRepresentationDetector.swift | 47 ++++-- .../MirrorDiffKit.diffTests.swift | 16 +- .../MirrorDiffKitTests/TransformerTests.swift | 10 +- 12 files changed, 275 insertions(+), 63 deletions(-) create mode 100644 Configs/Frameworks/MirrorDiffKit.plist create mode 100644 Configs/Tests/MirrorDiffKitTests.plist diff --git a/.gitignore b/.gitignore index c9d2305..abe2ce6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ +MirrorDiffKit.framework.zip + +# Created by https://www.gitignore.io/api/swift + +### Swift ### # Xcode # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore @@ -35,24 +40,13 @@ playground.xcworkspace # Swift Package Manager # # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. -Packages/ +# Packages/ # Package.pins .build/ -# CocoaPods -# -# We recommend against adding the Pods directory to your .gitignore. However -# you should judge for yourself, the pros and cons are mentioned at: -# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control -# -# Pods/ - -# Carthage -# -# Add this line if you want to avoid checking in source code from Carthage dependencies. -# Carthage/Checkouts +# CocoaPods - Refactored to standalone file -Carthage/Build +# Carthage - Refactored to standalone file # fastlane # @@ -66,3 +60,138 @@ fastlane/Preview.html fastlane/screenshots fastlane/test_output + +# End of https://www.gitignore.io/api/swift + +# Created by https://www.gitignore.io/api/xcode + +### Xcode ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +### Xcode Patch ### +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno + + +# End of https://www.gitignore.io/api/xcode + +# Created by https://www.gitignore.io/api/appcode + +### AppCode ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Ruby plugin and RubyMine +/.rakeTasks + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### AppCode Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + + +# End of https://www.gitignore.io/api/appcode + +# Created by https://www.gitignore.io/api/carthage + +### Carthage ### +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + + +# End of https://www.gitignore.io/api/carthage + +# Created by https://www.gitignore.io/api/cocoapods + +### CocoaPods ### +## CocoaPods GitIgnore Template + +# CocoaPods - Only use to conserve bandwidth / Save time on Pushing +# - Also handy if you have a large number of dependant pods +# - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE +Pods/ + + +# End of https://www.gitignore.io/api/cocoapods diff --git a/Configs/Frameworks/MirrorDiffKit.plist b/Configs/Frameworks/MirrorDiffKit.plist new file mode 100644 index 0000000..37e1691 --- /dev/null +++ b/Configs/Frameworks/MirrorDiffKit.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2017 Kuniwak. All rights reserved. + NSPrincipalClass + + + diff --git a/Configs/Tests/MirrorDiffKitTests.plist b/Configs/Tests/MirrorDiffKitTests.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/Configs/Tests/MirrorDiffKitTests.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/MirrorDiffKit.xcodeproj/project.pbxproj b/MirrorDiffKit.xcodeproj/project.pbxproj index a64611d..35bf747 100644 --- a/MirrorDiffKit.xcodeproj/project.pbxproj +++ b/MirrorDiffKit.xcodeproj/project.pbxproj @@ -616,7 +616,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0900; + LastUpgradeCheck = 1000; ORGANIZATIONNAME = MirrorDiffKit; TargetAttributes = { 52D6D97B1BEFF229002C0205 = { @@ -637,11 +637,11 @@ }; 52D6DA0E1BF000BD002C0205 = { CreatedOnToolsVersion = 7.1; - LastSwiftMigration = 0800; + LastSwiftMigration = 1000; }; DD7502791C68FCFC006590AF = { CreatedOnToolsVersion = 7.2.1; - LastSwiftMigration = 0800; + LastSwiftMigration = 1000; }; DD75028C1C690C7A006590AF = { CreatedOnToolsVersion = 7.2.1; @@ -981,12 +981,14 @@ 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_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_RANGE_LOOP_ANALYSIS = YES; @@ -1020,7 +1022,7 @@ SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -1039,12 +1041,14 @@ 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_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_RANGE_LOOP_ANALYSIS = YES; @@ -1070,7 +1074,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -1270,7 +1274,7 @@ PRODUCT_NAME = MirrorDiffKit; SDKROOT = macosx; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1294,7 +1298,7 @@ SDKROOT = macosx; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; }; @@ -1309,7 +1313,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.MirrorDiffKit.MirrorDiffKit-macOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1325,7 +1329,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; }; diff --git a/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-iOS.xcscheme b/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-iOS.xcscheme index 7125e77..96b6c85 100644 --- a/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-iOS.xcscheme +++ b/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-iOS.xcscheme @@ -1,6 +1,6 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -57,7 +56,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-macOS.xcscheme b/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-macOS.xcscheme index ac7871f..0be2dad 100644 --- a/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-macOS.xcscheme +++ b/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-macOS.xcscheme @@ -1,6 +1,6 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -57,7 +56,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-tvOS.xcscheme b/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-tvOS.xcscheme index 68b40be..3dcf2f7 100644 --- a/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-tvOS.xcscheme +++ b/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-tvOS.xcscheme @@ -1,6 +1,6 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -57,7 +56,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-watchOS.xcscheme b/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-watchOS.xcscheme index 049ff40..bcfccda 100644 --- a/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-watchOS.xcscheme +++ b/MirrorDiffKit.xcodeproj/xcshareddata/xcschemes/MirrorDiffKit-watchOS.xcscheme @@ -1,6 +1,6 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -38,7 +37,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/README.md b/README.md index 725e3c6..696cd7a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![MirrorDiffKit](https://raw.githubusercontent.com/Kuniwak/MirrorDiffKit/master/Documentation/Images/logo.png) ============= -![Swift 4.1 compatible](https://img.shields.io/badge/Swift%20version-4.1-green.svg) +![Swift 4.2 compatible](https://img.shields.io/badge/Swift%20version-4.2-green.svg) ![CocoaPods](https://img.shields.io/cocoapods/v/MirrorDiffKit.svg) ![Carthage](https://img.shields.io/badge/Carthage-compatible-green.svg) ![Swift Package Manager](https://img.shields.io/badge/SPM-compatible-green.svg) diff --git a/Sources/TupleRepresentationDetector.swift b/Sources/TupleRepresentationDetector.swift index 65e35d8..3ebb601 100644 --- a/Sources/TupleRepresentationDetector.swift +++ b/Sources/TupleRepresentationDetector.swift @@ -1,18 +1,36 @@ /// Since Swift 3.1, enums become labeled tuple such as (key: K, value: V). /// But before Swift 3.1, enums become not labeled tuple such as (K, V). -enum TupleRepresentation { - /// For example, (key: K, value: V) becomes ["key": K, "value" V]. - /// This is Swift 3.1+. - case labeled +public enum TupleRepresentation { + /// For example, (key: K, value: V) becomes ["key": K, "value" V] and + /// an assocated tuple of .something(associated: K) becomes ["associated": K]. + /// This is Swift >= 4.2. + case fullyLabeled + + /// For example, an associated tuple of .something(associated: K) becomes K. + /// This is Swift 3.1..<4.2. + case labeledWithoutSingleAssociatedType /// For example, (key: K, value: V) becomes [".0": K, ".1" V]. - /// This is Swift 3.0.2-. + /// This is Swift < 3.0.2. case notLabeled - var isLabeled: Bool { + public var isFullyLabeled: Bool { + switch self { + case .fullyLabeled: + return true + case .labeledWithoutSingleAssociatedType: + return false + case .notLabeled: + return false + } + } + + public var isAlmostLabeled: Bool { switch self { - case .labeled: + case .fullyLabeled: + return true + case .labeledWithoutSingleAssociatedType: return true case .notLabeled: return false @@ -20,7 +38,7 @@ enum TupleRepresentation { } - static let current = TupleRepresentation.detect() + public static let current = TupleRepresentation.detect() private static func detect() -> TupleRepresentation { @@ -30,7 +48,11 @@ enum TupleRepresentation { // NOTE: This is Swift 3.1+. if label == "label1" { - return .labeled + let anotherMirror = Mirror(reflecting: SampleEnum.caseAssociatedSingleType(label: "value")) + + return type(of: anotherMirror.children.first!.value) != String.self + ? .fullyLabeled // NOTE: This is Swift 4.2+ + : .labeledWithoutSingleAssociatedType } // NOTE: This is Swift 3.0.2-. @@ -40,4 +62,9 @@ enum TupleRepresentation { fatalError("Cannot detect enum representation: " + String(describing: label)) } -} \ No newline at end of file + + + fileprivate enum SampleEnum { + case caseAssociatedSingleType(label: String) + } +} diff --git a/Tests/MirrorDiffKitTests/MirrorDiffKit.diffTests.swift b/Tests/MirrorDiffKitTests/MirrorDiffKit.diffTests.swift index d868d69..06f13af 100644 --- a/Tests/MirrorDiffKitTests/MirrorDiffKit.diffTests.swift +++ b/Tests/MirrorDiffKitTests/MirrorDiffKit.diffTests.swift @@ -85,11 +85,17 @@ class MirrorDiffKitDiffTests: XCTestCase { #line: TestCase( diffBetween: EnumStub.AssociatedBySameKeys.one(key: "value"), and: EnumStub.AssociatedBySameKeys.one(key: "value"), - is: [ - "", - " AssociatedBySameKeys.one(\"value\")", // NOTE: Label has gone away X-( - "", - ].joined(separator: "\n") + is: TupleRepresentation.current.isFullyLabeled + ? [ + "", + " AssociatedBySameKeys.one(key: \"value\")", + "", + ].joined(separator: "\n") + : [ + "", + " AssociatedBySameKeys.one(\"value\")", // NOTE: Label has gone away on Swift 4.1 or lower X-( + "", + ].joined(separator: "\n") ), #line: TestCase( diffBetween: EnumStub.AssociatedByNotSameKeys.two(key1b: "value1b", key2b: "value2b"), diff --git a/Tests/MirrorDiffKitTests/TransformerTests.swift b/Tests/MirrorDiffKitTests/TransformerTests.swift index bd1c484..26d46d8 100644 --- a/Tests/MirrorDiffKitTests/TransformerTests.swift +++ b/Tests/MirrorDiffKitTests/TransformerTests.swift @@ -149,7 +149,7 @@ class TransformerTests: XCTestCase { ), #line: TestCase( input: (label1: 10, label2: 20), - target: TupleRepresentation.current.isLabeled + target: TupleRepresentation.current.isAlmostLabeled ? .tuple(type: (label1: Int, label2: Int).self, entries: [ .labeled(label: "label1", value: .number(type: Int.self, value: "10")), .labeled(label: "label2", value: .number(type: Int.self, value: "20")), @@ -356,8 +356,10 @@ class TransformerTests: XCTestCase { type: EnumStub.AssociatedBySameKeys.self, caseName: EnumCaseName("one"), associated: [ - // NOTE: Label has gone away X-( - .notLabeled(index: 0, value: .string(type: String.self, content: "value")), + TupleRepresentation.current.isFullyLabeled + ? .labeled(label: "key", value: .string(type: String.self, content: "value")) + // NOTE: Label has gone away on Swift 4.1 or lower X-( + : .notLabeled(index: 0, value: .string(type: String.self, content: "value")), ] ), expected: true @@ -367,7 +369,7 @@ class TransformerTests: XCTestCase { target: .anyEnum( type: EnumStub.AssociatedByNotSameKeys.self, caseName: EnumCaseName("two"), - associated: TupleRepresentation.current.isLabeled + associated: TupleRepresentation.current.isAlmostLabeled ? [ .labeled(label: "key1b", value: .string(type: String.self, content: "value1b")), .labeled(label: "key2b", value: .string(type: String.self, content: "value2b")),