From de15b2a19f6b57c1d3c73b93c7b389c3e8c6fc02 Mon Sep 17 00:00:00 2001 From: Kuniwak Date: Fri, 1 Feb 2019 02:06:06 +0900 Subject: [PATCH] Ready to be 4.0.0 (#42) * Support Swift 5 (#41) * Update .gitignore * Update CocoaPods * Migrate to Swift5 * Update README.md * Make CircleCI happy by migrating to Swift 4.2.1 * Try to fix the error from "pod spec lint" Related: https://github.com/CocoaPods/fourflusher/pull/15 * Fix swift_version (#40) * Ready to be v4.0.0 --- .circleci/config.yml | 3 +- .gitignore | 205 +++++++++++++++++------- .swift-version | 2 +- Gemfile | 2 +- Gemfile.lock | 81 +++++----- MirrorDiffKit.podspec | 2 +- MirrorDiffKit.xcodeproj/project.pbxproj | 17 +- Package.swift | 23 ++- README.md | 4 +- Sources/DiffableSet.swift | 2 +- Sources/Dwifft.swift | 6 +- Sources/Transformer.swift | 192 +++++++++++----------- bin/update-gitignore | 19 +++ 13 files changed, 351 insertions(+), 207 deletions(-) create mode 100755 bin/update-gitignore diff --git a/.circleci/config.yml b/.circleci/config.yml index 5094669..0172727 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,8 @@ version: 2 jobs: build: docker: - - image: library/swift:4.1 + # TODO: Use library/swift:5.0 if available + - image: library/swift:4.2.1 steps: - checkout - run: diff --git a/.gitignore b/.gitignore index abe2ce6..b6b1d62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ + MirrorDiffKit.framework.zip # Created by https://www.gitignore.io/api/swift +# Edit at https://www.gitignore.io/?templates=swift ### Swift ### # Xcode @@ -42,11 +44,26 @@ playground.xcworkspace # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. # Packages/ # Package.pins +# Package.resolved .build/ -# CocoaPods - Refactored to standalone file +# 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/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts -# Carthage - Refactored to standalone file +Carthage/Build # fastlane # @@ -57,24 +74,120 @@ playground.xcworkspace fastlane/report.xml fastlane/Preview.html -fastlane/screenshots +fastlane/screenshots/**/*.png fastlane/test_output +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ # End of https://www.gitignore.io/api/swift +# Created by https://www.gitignore.io/api/carthage +# Edit at https://www.gitignore.io/?templates=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 +# Edit at https://www.gitignore.io/?templates=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 + +# Created by https://www.gitignore.io/api/ruby +# Edit at https://www.gitignore.io/?templates=ruby + +### Ruby ### +*.gem +*.rbc +/.config +/coverage/ +/InstalledFiles +/pkg/ +/spec/reports/ +/spec/examples.txt +/test/tmp/ +/test/version_tmp/ +/tmp/ + +# Used by dotenv library to load environment variables. +# .env + +## Specific to RubyMotion: +.dat* +.repl_history +build/ +*.bridgesupport +build-iPhoneOS/ +build-iPhoneSimulator/ + +## Specific to RubyMotion (use of 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 +# +# vendor/Pods/ + +## Documentation cache and generated files: +/.yardoc/ +/_yardoc/ +/doc/ +/rdoc/ + +## Environment normalization: +/.bundle/ +/vendor/bundle +/lib/bundler/man/ + +# for a library or gem, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# Gemfile.lock +# .ruby-version +# .ruby-gemset + +# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: +.rvmrc + +# End of https://www.gitignore.io/api/ruby + # Created by https://www.gitignore.io/api/xcode +# Edit at https://www.gitignore.io/?templates=xcode ### Xcode ### # Xcode # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore -## Build generated +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) build/ DerivedData/ - -## Various settings +*.moved-aside *.pbxuser !default.pbxuser *.mode1v3 @@ -83,12 +196,6 @@ DerivedData/ !default.mode2v3 *.perspectivev3 !default.perspectivev3 -xcuserdata/ - -## Other -*.moved-aside -*.xccheckout -*.xcscmblueprint ### Xcode Patch ### *.xcodeproj/* @@ -96,47 +203,59 @@ xcuserdata/ !*.xcodeproj/xcshareddata/ !*.xcworkspace/contents.xcworkspacedata /*.gcno - +**/xcshareddata/WorkspaceSettings.xcsettings # End of https://www.gitignore.io/api/xcode # Created by https://www.gitignore.io/api/appcode +# Edit at https://www.gitignore.io/?templates=appcode ### AppCode ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# 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: +# User-specific stuff .idea/**/workspace.xml .idea/**/tasks.xml -.idea/dictionaries +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml -# Sensitive or high-churn files: +# 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 +.idea/**/dbnavigator.xml -# Gradle: +# Gradle .idea/**/gradle.xml .idea/**/libraries +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + # CMake -cmake-build-debug/ +cmake-build-*/ -# Mongo Explorer plugin: +# Mongo Explorer plugin .idea/**/mongoSettings.xml -## File-based project format: +# File-based project format *.iws -## Plugin-specific files: - # IntelliJ -/out/ +out/ # mpeltonen/sbt-idea plugin .idea_modules/ @@ -147,15 +266,18 @@ 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 +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + ### AppCode Patch ### # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 @@ -167,31 +289,4 @@ fabric.properties # 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/.swift-version b/.swift-version index 7d5c902..bf77d54 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.1 +4.2 diff --git a/Gemfile b/Gemfile index 2579fbe..442015e 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ # frozen_string_literal: true source "https://rubygems.org" -gem "cocoapods", "~> 1.2.0" +gem "cocoapods", "~> 1.6.0.rc.2" diff --git a/Gemfile.lock b/Gemfile.lock index adc38c6..c84b879 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,73 +1,76 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (2.3.5) - activesupport (4.2.8) + CFPropertyList (3.0.0) + activesupport (4.2.11) i18n (~> 0.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - claide (1.0.1) - cocoapods (1.2.0) + atomos (0.1.3) + claide (1.0.2) + cocoapods (1.6.0.rc.2) activesupport (>= 4.0.2, < 5) - claide (>= 1.0.1, < 2.0) - cocoapods-core (= 1.2.0) - cocoapods-deintegrate (>= 1.0.1, < 2.0) - cocoapods-downloader (>= 1.1.3, < 2.0) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.6.0.rc.2) + cocoapods-deintegrate (>= 1.0.2, < 2.0) + cocoapods-downloader (>= 1.2.2, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) cocoapods-search (>= 1.0.0, < 2.0) cocoapods-stats (>= 1.0.0, < 2.0) - cocoapods-trunk (>= 1.1.2, < 2.0) + cocoapods-trunk (>= 1.3.1, < 2.0) cocoapods-try (>= 1.1.0, < 2.0) - colored (~> 1.2) + colored2 (~> 3.1) escape (~> 0.0.4) - fourflusher (~> 2.0.1) + fourflusher (>= 2.2.0, < 3.0) gh_inspector (~> 1.0) - molinillo (~> 0.5.5) + molinillo (~> 0.6.6) nap (~> 1.0) - ruby-macho (~> 0.2.5) - xcodeproj (>= 1.4.1, < 2.0) - cocoapods-core (1.2.0) - activesupport (>= 4.0.2, < 5) + ruby-macho (~> 1.3, >= 1.3.1) + xcodeproj (>= 1.8.0, < 2.0) + cocoapods-core (1.6.0.rc.2) + activesupport (>= 4.0.2, < 6) fuzzy_match (~> 2.0.4) nap (~> 1.0) - cocoapods-deintegrate (1.0.1) - cocoapods-downloader (1.1.3) + cocoapods-deintegrate (1.0.2) + cocoapods-downloader (1.2.2) cocoapods-plugins (1.0.0) nap cocoapods-search (1.0.0) - cocoapods-stats (1.0.0) - cocoapods-trunk (1.1.2) + cocoapods-stats (1.1.0) + cocoapods-trunk (1.3.1) nap (>= 0.8, < 2.0) - netrc (= 0.7.8) + netrc (~> 0.11) cocoapods-try (1.1.0) - colored (1.2) + colored2 (3.1.2) + concurrent-ruby (1.1.4) escape (0.0.4) - fourflusher (2.0.1) + fourflusher (2.2.0) fuzzy_match (2.0.4) - gh_inspector (1.0.3) - i18n (0.8.1) - minitest (5.10.1) - molinillo (0.5.7) - nanaimo (0.2.3) + gh_inspector (1.1.3) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + minitest (5.11.3) + molinillo (0.6.6) + nanaimo (0.2.6) nap (1.1.0) - netrc (0.7.8) - ruby-macho (0.2.6) + netrc (0.11.0) + ruby-macho (1.3.1) thread_safe (0.3.6) - tzinfo (1.2.2) + tzinfo (1.2.5) thread_safe (~> 0.1) - xcodeproj (1.4.2) - CFPropertyList (~> 2.3.3) - activesupport (>= 3) - claide (>= 1.0.1, < 2.0) - colored (~> 1.2) - nanaimo (~> 0.2.3) + xcodeproj (1.8.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.6) PLATFORMS ruby DEPENDENCIES - cocoapods (~> 1.2.0) + cocoapods (~> 1.6.0.rc.2) BUNDLED WITH - 1.14.4 + 1.16.1 diff --git a/MirrorDiffKit.podspec b/MirrorDiffKit.podspec index ab9fe7c..a8a6af0 100644 --- a/MirrorDiffKit.podspec +++ b/MirrorDiffKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "MirrorDiffKit" - s.version = "3.1.0" + s.version = "4.0.0" s.summary = "Structual diff between any struct/class for efficient testing" s.description = <<-DESC Structual diff between any struct/class for efficient testing. diff --git a/MirrorDiffKit.xcodeproj/project.pbxproj b/MirrorDiffKit.xcodeproj/project.pbxproj index 35bf747..6ba5a3d 100644 --- a/MirrorDiffKit.xcodeproj/project.pbxproj +++ b/MirrorDiffKit.xcodeproj/project.pbxproj @@ -637,11 +637,11 @@ }; 52D6DA0E1BF000BD002C0205 = { CreatedOnToolsVersion = 7.1; - LastSwiftMigration = 1000; + LastSwiftMigration = 1020; }; DD7502791C68FCFC006590AF = { CreatedOnToolsVersion = 7.2.1; - LastSwiftMigration = 1000; + LastSwiftMigration = 1020; }; DD75028C1C690C7A006590AF = { CreatedOnToolsVersion = 7.2.1; @@ -655,6 +655,7 @@ hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 52D6D9721BEFF229002C0205; productRefGroup = 52D6D97D1BEFF229002C0205 /* Products */; @@ -1022,7 +1023,7 @@ SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -1074,7 +1075,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -1274,7 +1275,7 @@ PRODUCT_NAME = MirrorDiffKit; SDKROOT = macosx; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -1298,7 +1299,7 @@ SDKROOT = macosx; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -1313,7 +1314,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.MirrorDiffKit.MirrorDiffKit-macOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -1329,7 +1330,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Package.swift b/Package.swift index f6752c1..a40a24a 100644 --- a/Package.swift +++ b/Package.swift @@ -1,5 +1,26 @@ +// swift-tools-version:4.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + import PackageDescription let package = Package( - name: "MirrorDiffKit" + name: "MirrorDiffKit", + products: [ + .library( + name: "MirrorDiffKit", + targets: ["MirrorDiffKit"] + ) + ], + targets: [ + .target( + name: "MirrorDiffKit", + path: "Sources" + ), + .testTarget( + name: "MirrorDiffKitTests", + dependencies: [ + "MirrorDiffKit" + ] + ) + ] ) diff --git a/README.md b/README.md index 696cd7a..7d56071 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.2 compatible](https://img.shields.io/badge/Swift%20version-4.2-green.svg) +![Swift 5.0 compatible](https://img.shields.io/badge/Swift%20version-5.0-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) @@ -83,7 +83,7 @@ Add the following line to your `Package.swift`: ``` -.Package(url: "https://github.com/Kuniwak/MirrorDiffKit.git") +.package(url: "https://github.com/Kuniwak/MirrorDiffKit.git") ``` diff --git a/Sources/DiffableSet.swift b/Sources/DiffableSet.swift index 61264ac..a0d40a1 100644 --- a/Sources/DiffableSet.swift +++ b/Sources/DiffableSet.swift @@ -22,7 +22,7 @@ struct DiffableSet { var inserted = b.nonHashables deleted.enumerated().forEach { (indexOfDeleted, l) in - if let indexOfInserted = inserted.index(of: l) { + if let indexOfInserted = inserted.firstIndex(of: l) { inserted.remove(at: indexOfInserted) deleted.remove(at: indexOfDeleted) notChanged.append(l) diff --git a/Sources/Dwifft.swift b/Sources/Dwifft.swift index 49f93b6..1abe0f0 100644 --- a/Sources/Dwifft.swift +++ b/Sources/Dwifft.swift @@ -72,7 +72,7 @@ public enum DiffStep : CustomDebugStringConvertible { public extension Array where Element: Equatable { /// Returns the sequence of ArrayDiffResults required to transform one array into another. - public func diff(_ other: [Element]) -> Diff { + func diff(_ other: [Element]) -> Diff { let table = MemoizedSequenceComparison.buildTable(self, other, self.count, other.count) return Array.diffFromIndices(table, self, other, self.count, other.count) } @@ -96,7 +96,7 @@ public extension Array where Element: Equatable { /// Applies a generated diff to an array. The following should always be true: /// Given x: [T], y: [T], x.apply(x.diff(y)) == y - public func apply(_ diff: Diff) -> Array { + func apply(_ diff: Diff) -> Array { var copy = self for result in diff.deletions { copy.remove(at: result.idx) @@ -112,7 +112,7 @@ public extension Array where Element: Equatable { public extension Array where Element: Equatable { /// Returns the longest common subsequence between two arrays. - public func LCS(_ other: [Element]) -> [Element] { + func LCS(_ other: [Element]) -> [Element] { let table = MemoizedSequenceComparison.buildTable(self, other, self.count, other.count) return Array.lcsFromIndices(table, self, other, self.count, other.count) } diff --git a/Sources/Transformer.swift b/Sources/Transformer.swift index 907a22a..7b72764 100644 --- a/Sources/Transformer.swift +++ b/Sources/Transformer.swift @@ -49,108 +49,112 @@ private func transformFromNonOptionalAny(_ x: Any) -> Diffable { func transformMirror(of x: Any) -> Diffable { do { let mirror = Mirror(reflecting: x) - - switch mirror.displayStyle { - - case .some(.optional): - // XXX: Handle `nil` in a variable typed Any here. - // - // (lldb) po let $var: Any? = nil - // (lldb) po let $container: Any = $var - // (lldb) po $container == nil - // false <- FUUUUUUUUUUUUU - // - // (lldb) po Mirror(reflecting: $container) - // Mirror for Optional - // - // Therefore we can handle it by only using Mirrors. - if let firstChild = mirror.children.first { - return transform(fromAny: firstChild.value) - } - else { - return .none + + if let displayStyle = mirror.displayStyle { + switch displayStyle { + + case .optional: + // XXX: Handle `nil` in a variable typed Any here. + // + // (lldb) po let $var: Any? = nil + // (lldb) po let $container: Any = $var + // (lldb) po $container == nil + // false <- FUUUUUUUUUUUUU + // + // (lldb) po Mirror(reflecting: $container) + // Mirror for Optional + // + // Therefore we can handle it by only using Mirrors. + if let firstChild = mirror.children.first { + return transform(fromAny: firstChild.value) + } + else { + return .none + } + + case .tuple: + let entries = transformFromTupleMirror(of: mirror) + // NOTE: .subjectType should not to be used. Because .subjectType can be different from + // the original type if x is a CustomReflectable. + let trulyType = type(of: x) + return .tuple(type: trulyType, entries: entries) + + case .set: + let elements = transformFromNonLabeledMirror(of: mirror) + // NOTE: .subjectType should not to be used. Because .subjectType can be different from + // the original type if x is a CustomReflectable. + let trulyType = type(of: x) + return .set(type: trulyType, elements: elements) + + case .collection: + let elements = transformFromNonLabeledMirror(of: mirror) + // NOTE: .subjectType should not to be used. Because .subjectType can be different from + // the original type if x is a CustomReflectable. + let trulyType = type(of: x) + return .collection(type: trulyType, elements: elements) + + case .dictionary: + let entries = try transformFromDictionaryEntryMirror(of: mirror) + // NOTE: .subjectType should not to be used. Because .subjectType can be different from + // the original type if x is a CustomReflectable. + let trulyType = type(of: x) + return .dictionary(type: trulyType, entries: entries) + + case .enum: + let associated = transformFromEnumMirror(of: mirror) + // NOTE: .subjectType should not to be used. Because .subjectType can be different from + // the original type if x is a CustomReflectable. + let trulyType = type(of: x) + + return .anyEnum( + type: trulyType, + caseName: try .from(mirror: mirror, original: x), + associated: associated + ) + + case .struct: + let entries = try transformFromLabeledMirror(of: mirror) + // NOTE: .subjectType should not to be used. Because .subjectType can be different from + // the original type if x is a CustomReflectable. + let trulyType = type(of: x) + return .anyStruct(type: trulyType, entries: entries) + + case .class: + let entries = try transformFromLabeledMirror(of: mirror) + // NOTE: .subjectType should not to be used. Because .subjectType can be different from + // the original type if x is a CustomReflectable. + let trulyType = type(of: x) + return .anyClass(type: trulyType, entries: entries) + + @unknown default: + return .unrecognizable(debugInfo: "reason=UNKNOWN_DISPLAY_STYLE, displayStyle=`\(displayStyle)`, description=`\(x)`") } + } + + // NOTE: The types can have nil .displayType are only MetaTypes and OpaqueImpls and some CustomReflectables. + // https://github.com/apple/swift/blob/3ec7fc169d21f805366c19c0f8e1d437646c6149/stdlib/public/runtime/ReflectionMirror.mm#L512 + // https://github.com/apple/swift/blob/c35d508600516b892732e2fd3f0f0a17ca4562ba/stdlib/public/core/ReflectionMirror.swift#L154 - case .some(.tuple): - let entries = transformFromTupleMirror(of: mirror) - // NOTE: .subjectType should not to be used. Because .subjectType can be different from - // the original type if x is a CustomReflectable. - let trulyType = type(of: x) - return .tuple(type: trulyType, entries: entries) - - case .some(.set): - let elements = transformFromNonLabeledMirror(of: mirror) - // NOTE: .subjectType should not to be used. Because .subjectType can be different from - // the original type if x is a CustomReflectable. - let trulyType = type(of: x) - return .set(type: trulyType, elements: elements) - - case .some(.collection): - let elements = transformFromNonLabeledMirror(of: mirror) - // NOTE: .subjectType should not to be used. Because .subjectType can be different from - // the original type if x is a CustomReflectable. - let trulyType = type(of: x) - return .collection(type: trulyType, elements: elements) - - case .some(.dictionary): - let entries = try transformFromDictionaryEntryMirror(of: mirror) - // NOTE: .subjectType should not to be used. Because .subjectType can be different from - // the original type if x is a CustomReflectable. - let trulyType = type(of: x) - return .dictionary(type: trulyType, entries: entries) - - case .some(.enum): - let associated = transformFromEnumMirror(of: mirror) - // NOTE: .subjectType should not to be used. Because .subjectType can be different from - // the original type if x is a CustomReflectable. - let trulyType = type(of: x) - - return .anyEnum( - type: trulyType, - caseName: try .from(mirror: mirror, original: x), - associated: associated - ) - - case .some(.struct): - let entries = try transformFromLabeledMirror(of: mirror) - // NOTE: .subjectType should not to be used. Because .subjectType can be different from - // the original type if x is a CustomReflectable. - let trulyType = type(of: x) - return .anyStruct(type: trulyType, entries: entries) - - case .some(.class): - let entries = try transformFromLabeledMirror(of: mirror) - // NOTE: .subjectType should not to be used. Because .subjectType can be different from - // the original type if x is a CustomReflectable. - let trulyType = type(of: x) - return .anyClass(type: trulyType, entries: entries) - - case .none: - // NOTE: The types can have nil .displayType are only MetaTypes and OpaqueImpls and some CustomReflectables. - // https://github.com/apple/swift/blob/3ec7fc169d21f805366c19c0f8e1d437646c6149/stdlib/public/runtime/ReflectionMirror.mm#L512 - // https://github.com/apple/swift/blob/c35d508600516b892732e2fd3f0f0a17ca4562ba/stdlib/public/core/ReflectionMirror.swift#L154 - - if let y = x as? Any.Type { - return .type(y) - } + if let y = x as? Any.Type { + return .type(y) + } - // NOTE: .subjectType should not to be used. Because .subjectType can be different from - // the original type if x is a CustomReflectable. - let trulyType = type(of: x) - let entries = try transformFromLabeledMirror(of: mirror) + // NOTE: .subjectType should not to be used. Because .subjectType can be different from + // the original type if x is a CustomReflectable. + let trulyType = type(of: x) + let entries = try transformFromLabeledMirror(of: mirror) - if let y = x as? CustomReflectable { - guard !entries.isEmpty else { - return .minorCustomReflectable(type: trulyType, content: .empty(description: "\(y)")) - } - return .minorCustomReflectable(type: trulyType, content: .notEmpty(entries: entries)) + if let y = x as? CustomReflectable { + guard !entries.isEmpty else { + return .minorCustomReflectable(type: trulyType, content: .empty(description: "\(y)")) } - - return .unrecognizable(debugInfo: "type=`\(trulyType)`, description=`\(x)`") + return .minorCustomReflectable(type: trulyType, content: .notEmpty(entries: entries)) } + + return .unrecognizable(debugInfo: "reason=UNKNOWN_TYPE, type=`\(trulyType)`, description=`\(x)`") } catch { - return .unrecognizable(debugInfo: "error=`\(error)`, value=`\(x)`") + return .unrecognizable(debugInfo: "reason=TRANSFORM_ERROR, error=`\(error)`, value=`\(x)`") } } diff --git a/bin/update-gitignore b/bin/update-gitignore new file mode 100755 index 0000000..cc2c7b4 --- /dev/null +++ b/bin/update-gitignore @@ -0,0 +1,19 @@ +#!/bin/bash -eu +set -o pipefail + +BASE_DIR="$(cd "$(dirname "$0")/.."; pwd)" +GITIGNORE_FILE="${BASE_DIR}/.gitignore" + + +(cd "$BASE_DIR" + echo > "$GITIGNORE_FILE" + + echo "MirrorDiffKit.framework.zip" >> "$GITIGNORE_FILE" + + git ignore swift >> "$GITIGNORE_FILE" + git ignore carthage >> "$GITIGNORE_FILE" + git ignore cocoapods >> "$GITIGNORE_FILE" + git ignore ruby >> "$GITIGNORE_FILE" + git ignore xcode >> "$GITIGNORE_FILE" + git ignore appcode >> "$GITIGNORE_FILE" +)