From ba63cd6b8435e5e0066049eed603386d1a76b368 Mon Sep 17 00:00:00 2001 From: Ruslan Alikhamov Date: Thu, 7 Sep 2023 15:27:22 -0400 Subject: [PATCH] Linux Support (#1188) * work in progress * More conditional checks, less errors * Further steps onto successful compilation * Enabled try-catch back for macOS * reverted redundant change * Replaced getVaList with recommended withVaList * Update FileParser + AttributesModifierSpec.swift fixed wrong find-replace * added missing import of CDispatch * enabled fatalError instead of NSException * enabled value(forKey:) for TypesCollection type * removed commented import * enabled sha256 for macOS * Enabled sha256 hashing for Linux * disabled JavaScriptTemplate tests under Linux * added check for vendor for tests * disabled value(forKeyPath:) calls under Linux * reverted redundant gem * Fixed issue with `swift test` not finding .ejs bundle * removed commented code * switched to `swift test` * enabled GH actions * Temporary check for installed Xcodes - Update swift.yml * Temporary checking Xcode versions - Update swift.yml * Temporary setting Xcode version - Update swift.yml * Temporary remove custom Ruby installation - Update swift.yml * Removed spaces from filenames * removed + from filenames * Added -enable-testing for all test targets * Try Xcode 15 beta * trying to generate LinuxMain * refactoring * running a test for test of a test * set SPM version to 5.8 * added tests to LinuxMain.swift * removed redundantly disabled code * fixed wrong ifdef * Moved diffable implementation to definitions * fixed failing UTs * replaced os(macOS) with canImport(ObjectiveC) * replaced more os(macOS) with canImport(ObjectiveC) * enabled filtering for sorted arrays on linux * eliminating API unsupported by swift-corelibs-foundation * enabled SourceryRuntime to compile under Linux * isEqual overrides only for Darwin platforms * Fixed all SourceryRuntime compilation errors; more green tests * Disabled enum test case * moved isEqual to definitions * fatalError when DynamicMemberLookup fails * disabled failing test * disabled crashing test in DryOutputSpec * Fixed more unit tests * Fixed typo * Added best effort sorting filter * added missing dynamic member lookups * Added missing dynamic member lookup * fixed compilation error * Take into account 1-off linebreak issue between Linux and macOS * Removed diffable from content generation due to new structure * added missing dynamic member lookups * Added missing dynamic member lookup * moving hashing into class definitions * Moved description and hash into class definitions * Added DynamicMemberLookup definition for SourceryRuntime * Added comment why import Stencil is needed * Added missing dynamic member lookup * Removed redundant imports * Fixed failing tests * Adjusted test expectation for Linux * Fixed SourcerySpec template combining test * Temporary commit for CI verification * Adjusted SwiftTemplateSpecs tests for Linux * reverted redundant change * enable more linux tests for CI verification * Adjusted CodableContextTests for Linux * Added more tests that are green * enabled all tests except 3 * Remove verbosity from CI build * Removed redundant steps from CI * Reverted redundant change * Testing job cancellation * Added new dynamic member lookup to generated sources [no ci] * Added different TypesCollection definition for Linux * Make TypesCollection conform to DynamicMemberLookup only on Linux * Moved TypesCollection to separate generated source file * Moved Type to separate file for Linux * Split GitHub actions * removed common GH action * added separate file for Variable on linux * removed DynamicMemberLookup conformance on macOS * removed @objc conditions on Linux * Temporary commit to fix build error * moved NSException workaround to separate file * Fixed compiler warning * moved Types to a separate file * moved generated Types to a separate file * split Enum.swift into separate files * removed redundant imports * added missing import * Removed redundant import * Split Method into separate files * Added DynamicMemberLookup to Method on Linux [no ci] * removed redundant override * added badges for GH Actions * Fixed failing test on macOS * Split Tuple into separate files for Linux * Split EnumCase into separate file for DynamicMemberLookup on Linux * Enabled GeneratorSpec tests * Added missing lookup member * Fixed SourcerySpecTests * enabled SourcerySpec tests * Added missing lookup member * call runCLI on Linux * Disabled codegen for Sourcery * Added missing member lookup * Added missing members lookup * renamed Linux to include experimental * Added missing member lookups * Added missing import * Adjusted padding [no ci] * Added missing member lookups * Adjusted padding [no ci] * Disabled Codable tests on Linux * enabled all tests classes under Linux * Added AssociatedValue for Linux * Added missing member lookups * Changed resource copy path in TemplatesTests for Linux * Updated CHANGELOG * Added LINUX.md * Added references to README and LINUX * Updated content.generated files * Fixed a typo [no ci] * Changed wording related to @objc attribute * Use currentTimestamp() instead of Date().timeIntervalSince1970 * Returned guard statements; removed default values from EJSTemplate --- .github/workflows/{swift.yml => Ubuntu.yml} | 28 +- .github/workflows/macOS.yml | 34 + .sourcery.yml | 12 +- .vscode/launch.json | 28 + .vscode/settings.json | 1 + CHANGELOG.md | 1 + Gemfile.lock | 3 + LINUX.md | 56 + LinuxMain.swift | 82 + Package.resolved | 18 - Package.swift | 158 +- README.md | 6 + Rakefile | 6 +- Sourcery/Configuration.swift | 6 +- .../JavaScript/JavaScriptTemplate.swift | 2 + Sourcery/Sourcery.swift | 65 +- Sourcery/Templates/Coding.stencil | 7 +- Sourcery/Utils/FolderWatcher.swift | 32 + SourceryExecutable/main.swift | 153 +- .../Sources/Parsing/Utils/Time.swift | 2 +- SourceryJS/Sources/EJSTemplate.swift | 38 +- SourceryRuntime/Sources/AST/Actor.swift | 37 +- .../Sources/AST/AssociatedType.swift | 46 +- .../Sources/AST/AssociatedValue.swift | 127 + .../Sources/AST/AssociatedValue_Linux.swift | 148 + SourceryRuntime/Sources/AST/Attribute.swift | 55 +- SourceryRuntime/Sources/AST/Class.swift | 37 +- .../Sources/AST/ClosureParameter.swift | 143 + SourceryRuntime/Sources/AST/Enum.swift | 178 +- SourceryRuntime/Sources/AST/EnumCase.swift | 143 + .../Sources/AST/EnumCase_Linux.swift | 163 + SourceryRuntime/Sources/AST/Enum_Linux.swift | 167 + .../Sources/AST/GenericRequirement.swift | 75 +- SourceryRuntime/Sources/AST/Import.swift | 38 +- SourceryRuntime/Sources/AST/Method.swift | 355 +- .../Sources/AST/MethodParameter.swift | 180 + .../Sources/AST/MethodParameter_Linux.swift | 199 + .../Sources/AST/Method_Linux.swift | 424 + SourceryRuntime/Sources/AST/Modifier.swift | 38 +- .../Sources/AST/NSException_Linux.swift | 17 + SourceryRuntime/Sources/AST/Protocol.swift | 57 +- .../Sources/AST/ProtocolComposition.swift | 46 +- SourceryRuntime/Sources/AST/Struct.swift | 35 +- SourceryRuntime/Sources/AST/Subscript.swift | 127 +- SourceryRuntime/Sources/AST/Type.swift | 255 +- .../Sources/AST/TypeName/Array.swift | 56 +- .../Sources/AST/TypeName/Closure.swift | 82 +- .../Sources/AST/TypeName/Dictionary.swift | 66 +- .../Sources/AST/TypeName/Generic.swift | 87 +- .../Sources/AST/TypeName/Tuple.swift | 98 +- .../Sources/AST/TypeName/Tuple_Linux.swift | 201 + .../Sources/AST/TypeName/TypeName.swift | 81 +- .../Sources/AST/TypeName/TypeName_Linux.swift | 319 + SourceryRuntime/Sources/AST/Type_Linux.swift | 747 ++ SourceryRuntime/Sources/AST/Typealias.swift | 73 +- SourceryRuntime/Sources/AST/Variable.swift | 151 +- .../Sources/AST/Variable_Linux.swift | 330 + SourceryRuntime/Sources/BytesRange.swift | 39 +- .../Sources/Composer/Composer.swift | 2 +- SourceryRuntime/Sources/Diffable.swift | 18 +- .../Sources/FileParserResult.swift | 117 +- .../Generated/Description.generated.swift | 375 - .../Generated/Diffable.generated.swift | 465 -- .../Generated/Equality.generated.swift | 780 -- .../Generated/JSExport.generated.swift | 3 +- SourceryRuntime/Sources/Log.swift | 4 +- SourceryRuntime/Sources/TemplateContext.swift | 269 +- SourceryRuntime/Sources/Types.swift | 181 + SourceryRuntime/Sources/TypesCollection.swift | 84 + .../Sources/TypesCollection_Linux.swift | 87 + SourceryRuntime/Sources/Types_Linux.swift | 209 + SourceryStencil/Sources/StencilTemplate.swift | 44 +- .../SourceryRuntime.content.generated.swift | 4897 ++++++----- ...rceryRuntime_Linux.content.generated.swift | 7298 +++++++++++++++++ SourcerySwift/Sources/SwiftTemplate.swift | 13 +- .../Generating/JavaScriptTemplateSpecs.swift | 12 +- .../Generating/StencilTemplateSpec.swift | 32 + .../Generating/SwiftTemplateSpecs.swift | 23 +- SourceryTests/GeneratorSpec.swift | 7 +- SourceryTests/Models/EnumSpec.swift | 3 + .../Models/TypedSpec.generated.swift | 16 +- SourceryTests/Output/DryOutputSpec.swift | 451 +- SourceryTests/Parsing/ComposerSpec.swift | 1 + ...ft => FileParser_AssociatedTypeSpec.swift} | 2 + ...> FileParser_AttributesModifierSpec.swift} | 0 ...pec.swift => FileParser_MethodsSpec.swift} | 0 ...t => FileParser_ProtocolComposition.swift} | 0 ....swift => FileParser_SubscriptsSpec.swift} | 0 ...ec.swift => FileParser_TypeNameSpec.swift} | 0 ...ec.swift => FileParser_VariableSpec.swift} | 0 ...tionParser_ForceParseInlineCodeSpec.swift} | 0 SourceryTests/SourcerySpec.swift | 28 +- .../Basic+Other+SourceryTemplates_Linux.swift | 32 + SourceryUtils/Sources/Sha.swift | 9 + SourceryUtils/Sources/Version.swift | 6 +- .../CodableContextTests.swift | 35 +- Templates/Tests/Context/AutoCodable.swift | 3 + Templates/Tests/Context_Linux/AutoCases.swift | 27 + .../Tests/Context_Linux/AutoEquatable.swift | 186 + .../Tests/Context_Linux/AutoHashable.swift | 228 + .../Tests/Context_Linux/AutoLenses.swift | 36 + .../Tests/Context_Linux/AutoMockable.swift | 184 + Templates/Tests/Context_Linux/LinuxMain.swift | 37 + .../Generated/AutoCodable.generated.swift | 5 +- Templates/Tests/TemplatesTests.swift | 25 +- 105 files changed, 17451 insertions(+), 4941 deletions(-) rename .github/workflows/{swift.yml => Ubuntu.yml} (70%) create mode 100644 .github/workflows/macOS.yml create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 LINUX.md create mode 100644 LinuxMain.swift create mode 100644 SourceryRuntime/Sources/AST/AssociatedValue.swift create mode 100644 SourceryRuntime/Sources/AST/AssociatedValue_Linux.swift create mode 100644 SourceryRuntime/Sources/AST/ClosureParameter.swift create mode 100644 SourceryRuntime/Sources/AST/EnumCase.swift create mode 100644 SourceryRuntime/Sources/AST/EnumCase_Linux.swift create mode 100644 SourceryRuntime/Sources/AST/Enum_Linux.swift create mode 100644 SourceryRuntime/Sources/AST/MethodParameter.swift create mode 100644 SourceryRuntime/Sources/AST/MethodParameter_Linux.swift create mode 100644 SourceryRuntime/Sources/AST/Method_Linux.swift create mode 100644 SourceryRuntime/Sources/AST/NSException_Linux.swift create mode 100644 SourceryRuntime/Sources/AST/TypeName/Tuple_Linux.swift create mode 100644 SourceryRuntime/Sources/AST/TypeName/TypeName_Linux.swift create mode 100644 SourceryRuntime/Sources/AST/Type_Linux.swift create mode 100644 SourceryRuntime/Sources/AST/Variable_Linux.swift delete mode 100644 SourceryRuntime/Sources/Generated/Description.generated.swift delete mode 100644 SourceryRuntime/Sources/Generated/Diffable.generated.swift delete mode 100644 SourceryRuntime/Sources/Generated/Equality.generated.swift create mode 100644 SourceryRuntime/Sources/Types.swift create mode 100644 SourceryRuntime/Sources/TypesCollection.swift create mode 100644 SourceryRuntime/Sources/TypesCollection_Linux.swift create mode 100644 SourceryRuntime/Sources/Types_Linux.swift create mode 100644 SourcerySwift/Sources/SourceryRuntime_Linux.content.generated.swift rename SourceryTests/Parsing/{FileParser + AssociatedTypeSpec.swift => FileParser_AssociatedTypeSpec.swift} (99%) rename SourceryTests/Parsing/{FileParser + AttributesModifierSpec.swift => FileParser_AttributesModifierSpec.swift} (100%) rename SourceryTests/Parsing/{FileParser + MethodsSpec.swift => FileParser_MethodsSpec.swift} (100%) rename SourceryTests/Parsing/{FileParser + ProtocolComposition.swift => FileParser_ProtocolComposition.swift} (100%) rename SourceryTests/Parsing/{FileParser + SubscriptsSpec.swift => FileParser_SubscriptsSpec.swift} (100%) rename SourceryTests/Parsing/{FileParser + TypeNameSpec.swift => FileParser_TypeNameSpec.swift} (100%) rename SourceryTests/Parsing/{FileParser + VariableSpec.swift => FileParser_VariableSpec.swift} (100%) rename SourceryTests/Parsing/Helpers/{TemplatesAnnotationParser+ForceParseInlineCodeSpec.swift => TemplatesAnnotationParser_ForceParseInlineCodeSpec.swift} (100%) create mode 100644 SourceryTests/Stub/Result/Basic+Other+SourceryTemplates_Linux.swift create mode 100644 Templates/Tests/Context_Linux/AutoCases.swift create mode 100644 Templates/Tests/Context_Linux/AutoEquatable.swift create mode 100644 Templates/Tests/Context_Linux/AutoHashable.swift create mode 100644 Templates/Tests/Context_Linux/AutoLenses.swift create mode 100644 Templates/Tests/Context_Linux/AutoMockable.swift create mode 100644 Templates/Tests/Context_Linux/LinuxMain.swift diff --git a/.github/workflows/swift.yml b/.github/workflows/Ubuntu.yml similarity index 70% rename from .github/workflows/swift.yml rename to .github/workflows/Ubuntu.yml index aa6015ca9..834c9f774 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/Ubuntu.yml @@ -1,7 +1,7 @@ # This workflow will build a Swift project # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift -name: Swift +name: Ubuntu (Experimental) on: push: @@ -9,9 +9,12 @@ on: pull_request: branches: [ "master" ] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} + jobs: linux_build: - if: ${{ false }} runs-on: ubuntu-latest steps: - name: Setup Swift @@ -36,23 +39,6 @@ jobs: - name: Bundle Install run: bundle install - name: Swift Build - run: swift build -v + run: swift build - name: Run tests - run: swift test -v - macos_build: - if: ${{ false }} - runs-on: macos-latest - steps: - - uses: actions/checkout@v3 - - name: Setup Ruby - uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1 - with: - ruby-version: '3.1' - - name: Bundle Install - run: bundle install - - name: Swift Build - run: swift build -v - - name: Run tests - run: swift test -v - - + run: swift test diff --git a/.github/workflows/macOS.yml b/.github/workflows/macOS.yml new file mode 100644 index 000000000..719c66a4e --- /dev/null +++ b/.github/workflows/macOS.yml @@ -0,0 +1,34 @@ +# This workflow will build a Swift project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift + +name: macOS + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} + +jobs: + macos_build: + runs-on: macos-13 + steps: + - name: Set Xcode 14.3.1 + run: sudo xcode-select -s /Applications/Xcode_14.3.1.app/Contents/Developer + #- name: Set Xcode 15.0 Beta + # run: sudo xcode-select -s /Applications/Xcode_15.0.app/Contents/Developer + - name: Print Current Xcode + run: xcode-select -p + - uses: actions/checkout@v3 + - name: Bundle Install + run: bundle install + - name: Swift Build + run: swift build + - name: Run tests + run: swift test + + diff --git a/.sourcery.yml b/.sourcery.yml index da44f058c..a56028d31 100644 --- a/.sourcery.yml +++ b/.sourcery.yml @@ -1,6 +1,6 @@ -sources: - - SourceryRuntime/Sources -templates: - - Sourcery/Templates -output: - SourceryRuntime/Sources/Generated +#sources: +# - SourceryRuntime/Sources +#templates: +# - Sourcery/Templates +#output: +# SourceryRuntime/Sources/Generated diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..8ffd9662f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,28 @@ +{ + "configurations": [ + { + "type": "lldb", + "request": "launch", + "sourceLanguages": [ + "swift" + ], + "name": "Debug sourcery", + "program": "${workspaceFolder:Sourcery}/.build/debug/sourcery", + "args": [], + "cwd": "${workspaceFolder:Sourcery}", + "preLaunchTask": "swift: Build Debug sourcery" + }, + { + "type": "lldb", + "request": "launch", + "sourceLanguages": [ + "swift" + ], + "name": "Release sourcery", + "program": "${workspaceFolder:Sourcery}/.build/release/sourcery", + "args": [], + "cwd": "${workspaceFolder:Sourcery}", + "preLaunchTask": "swift: Build Release sourcery" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7668e59fd..ad6abfdc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Add support to any keyword for function parameter type to AutoMockable.stencil ([#1169](https://github.com/krzysztofzablocki/Sourcery/pull/1169)) - Add support to any keyword for function return type to AutoMockable.stencil([#1186](https://github.com/krzysztofzablocki/Sourcery/pull/1186)) - Add support for protocol compositions in EJS templates. ([#1192](https://github.com/krzysztofzablocki/Sourcery/pull/1192)) +- Linux Support (experimental) ([#1188](https://github.com/krzysztofzablocki/Sourcery/pull/1188)) ## 2.0.3 ## Internal Changes diff --git a/Gemfile.lock b/Gemfile.lock index 1c15debb3..ed425af8d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -135,6 +135,8 @@ GEM nap (1.1.0) netrc (0.11.0) no_proxy_fix (0.1.2) + nokogiri (1.13.3-aarch64-linux) + racc (~> 1.4) nokogiri (1.13.3-arm64-darwin) racc (~> 1.4) octokit (4.22.0) @@ -183,6 +185,7 @@ GEM rouge (~> 2.0.7) PLATFORMS + aarch64-linux arm64-darwin-21 arm64-darwin-23 diff --git a/LINUX.md b/LINUX.md new file mode 100644 index 000000000..af044175b --- /dev/null +++ b/LINUX.md @@ -0,0 +1,56 @@ +## Linux Support + +Currently (as per 2.1.0 release), Linux Support is **experimental**. This means the following: + +1. Running `sourcery` in the root folder of Sourcery project was generating `Equatable.generated.swift` and other autogenerated files with extensions of classes used by `SourceryRuntime`, but they were moved to class definitions due to the abscense of `@objc` attribute on non-Darwin platforms. Thus, `.sourcery.yaml` file was disabled for the moment, until #1198 is resolved. +2. Some unit tests were disabled with `#if canImport(ObjectiveC)`, that is some due to Swift compiler crashes, some due to abscence of `JavaScriptCore`. +3. `FileWatcher` needs to be re-implemented (see [this comment](https://github.com/krzysztofzablocki/Sourcery/pull/1188#issue-1828038476) for a possible fix) + + +All issues related to Linux will be mentioned in #1198 + +## Using Sourcery under Linux + +Simply add package dependency of Sourcery as described in the [README](README.md). + +## Contributing +### Installation of Linux Environment + +I have installed ubuntu VM through [tart](https://github.com/cirruslabs/tart/issues/62#issuecomment-1225956540) and updated to 22.04 according to [this guide](https://www.linuxtechi.com/upgrade-ubuntu-20-04-to-ubuntu-22-04/). + +I had to run the following commands prior to being able to run `bundle install` in Sourcery: + +1. `sudo apt install libffi-dev` +2. `sudo apt install build-essential` +3. `sudo apt install libsqlite3-dev` +4. `sudo apt-get install libncurses5-dev` + +Then, `swiftly` needs to be installed to easily manage Swift installation under Linux. How to install Swiftly is described [in this README](https://github.com/swift-server/swiftly). + +### Running Tests Under Linux + +To run tests, you can use either Visual Studio Code distribution, or simply `swift test` in Sourcery root directory. + +#### Visual Studio Code + +To install VS Code, you can follow [the official guide](https://code.visualstudio.com/docs/setup/linux), which mentions the following commands: + +```bash +sudo apt-get install wget gpg +wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg +sudo install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg +sudo sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list' +rm -f packages.microsoft.gpg + +# Then update the package cache and install the package using: + +sudo apt install apt-transport-https +sudo apt update +sudo apt install code # or code-insiders +``` + +### Test Discovery Under Linux + +Due to a missing feature in Swift Package Manager, tests under Linux are not discovered if the root class, from which tests are inherited, is located "in another Package/Module". Details regarding this [can be found here](https://github.com/apple/swift-package-manager/issues/5573). + +And so, if a new `Spec` needs to be added, that Spec file needs to be put into `LinuxMain.swift` similarly to what is there already, mentioning the new class name accordingly. diff --git a/LinuxMain.swift b/LinuxMain.swift new file mode 100644 index 000000000..6893d7a73 --- /dev/null +++ b/LinuxMain.swift @@ -0,0 +1,82 @@ +import XCTest +import Quick + +@testable import SourceryLibTests +@testable import TemplatesTests +@testable import CodableContextTests + +@main struct Main { + static func main() { + Quick.QCKMain([ + ActorSpec.self, + AnnotationsParserSpec.self, + ClassSpec.self, + ConfigurationSpec.self, + DiffableSpec.self, + DryOutputSpec.self, + EnumSpec.self, + FileParserAssociatedTypeSpec.self, + FileParserAttributesSpec.self, + FileParserMethodsSpec.self, + FileParserProtocolCompositionSpec.self, + FileParserSpec.self, + FileParserSubscriptsSpec.self, + FileParserVariableSpec.self, + GeneratorSpec.self, + MethodSpec.self, + ParserComposerSpec.self, + ProtocolSpec.self, + SourcerySpecTests.self, + StencilTemplateSpec.self, + StringViewSpec.self, + StructSpec.self, + SwiftTemplateTests.self, + TemplateAnnotationsParserSpec.self, + TemplatesAnnotationParserPassInlineCodeSpec.self, + TypeNameSpec.self, + TypeSpec.self, + TypealiasSpec.self, + TypedSpec.self, + VariableSpec.self, + VerifierSpec.self, + CodableContextTests.self, + TemplatesTests.self + ], + configurations: [], + testCases: [ + testCase(ActorSpec.allTests), + testCase(AnnotationsParserSpec.allTests), + testCase(ClassSpec.allTests), + testCase(ConfigurationSpec.allTests), + testCase(DiffableSpec.allTests), + testCase(DryOutputSpec.allTests), + testCase(EnumSpec.allTests), + testCase(FileParserAssociatedTypeSpec.allTests), + testCase(FileParserAttributesSpec.allTests), + testCase(FileParserMethodsSpec.allTests), + testCase(FileParserProtocolCompositionSpec.allTests), + testCase(FileParserSpec.allTests), + testCase(FileParserSubscriptsSpec.allTests), + testCase(FileParserVariableSpec.allTests), + testCase(GeneratorSpec.allTests), + testCase(MethodSpec.allTests), + testCase(ParserComposerSpec.allTests), + testCase(ProtocolSpec.allTests), + testCase(SourcerySpecTests.allTests), + testCase(StencilTemplateSpec.allTests), + testCase(StringViewSpec.allTests), + testCase(StructSpec.allTests), + testCase(SwiftTemplateTests.allTests), + testCase(TemplateAnnotationsParserSpec.allTests), + testCase(TemplatesAnnotationParserPassInlineCodeSpec.allTests), + testCase(TypeNameSpec.allTests), + testCase(TypeSpec.allTests), + testCase(TypealiasSpec.allTests), + testCase(TypedSpec.allTests), + testCase(VariableSpec.allTests), + testCase(VerifierSpec.allTests), + testCase(CodableContextTests.allTests), + testCase(TemplatesTests.allTests) + ]) + } +} \ No newline at end of file diff --git a/Package.resolved b/Package.resolved index 37ac61114..435d37010 100644 --- a/Package.resolved +++ b/Package.resolved @@ -18,24 +18,6 @@ "version" : "0.9.1" } }, - { - "identity" : "cwlcatchexception", - "kind" : "remoteSourceControl", - "location" : "https://github.com/mattgallagher/CwlCatchException.git", - "state" : { - "revision" : "f809deb30dc5c9d9b78c872e553261a61177721a", - "version" : "2.0.0" - } - }, - { - "identity" : "cwlpreconditiontesting", - "kind" : "remoteSourceControl", - "location" : "https://github.com/mattgallagher/CwlPreconditionTesting.git", - "state" : { - "revision" : "02b7a39a99c4da27abe03cab2053a9034379639f", - "version" : "2.0.0" - } - }, { "identity" : "komondor", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index b21c2955e..4acfa8d3b 100644 --- a/Package.swift +++ b/Package.swift @@ -1,50 +1,9 @@ -// swift-tools-version:5.6 +// swift-tools-version:5.8 import PackageDescription import Foundation -let package = Package( - name: "Sourcery", - platforms: [ - .macOS(.v12), - ], - products: [ - // SPM won't generate .swiftmodule for a target directly used by a product, - // hence it can't be imported by tests. Executable target can't be imported too. - .executable(name: "sourcery", targets: ["SourceryExecutable"]), - .library(name: "SourceryRuntime", targets: ["SourceryRuntime"]), - .library(name: "SourceryStencil", targets: ["SourceryStencil"]), - .library(name: "SourceryJS", targets: ["SourceryJS"]), - .library(name: "SourcerySwift", targets: ["SourcerySwift"]), - .library(name: "SourceryFramework", targets: ["SourceryFramework"]), - .library(name: "SourceryLib", targets: ["SourceryLib"]), - .plugin(name: "SourceryCommandPlugin", targets: ["SourceryCommandPlugin"]) - ], - dependencies: [ - .package(url: "https://github.com/jpsim/Yams.git", from: "5.0.3"), - .package(url: "https://github.com/kylef/Commander.git", exact: "0.9.1"), - // PathKit needs to be exact to avoid a SwiftPM bug where dependency resolution takes a very long time. - .package(url: "https://github.com/kylef/PathKit.git", exact: "1.0.1"), - .package(url: "https://github.com/SwiftGen/StencilSwiftKit.git", exact: "2.10.1"), - .package(url: "https://github.com/tuist/XcodeProj.git", exact: "8.3.1"), - .package(url: "https://github.com/apple/swift-syntax.git", from: "508.0.0"), - .package(url: "https://github.com/Quick/Quick.git", from: "3.0.0"), - .package(url: "https://github.com/Quick/Nimble.git", from: "9.0.0"), - .package(url: "https://github.com/apple/swift-package-manager", revision: "fa3db13e0bd00e33c187c63c80673b3ac7c82f55"), - ], - targets: [ - .executableTarget( - name: "SourceryExecutable", - dependencies: ["SourceryLib"], - path: "SourceryExecutable", - exclude: [ - "Info.plist" - ] - ), - .target( - // Xcode doesn't like when a target has the same name as a product but in different case. - name: "SourceryLib", - dependencies: [ +var sourceryLibDependencies: [Target.Dependency] = [ "SourceryFramework", "SourceryRuntime", "SourceryStencil", @@ -56,27 +15,48 @@ let package = Package( "StencilSwiftKit", .product(name: "SwiftSyntax", package: "swift-syntax"), "XcodeProj", - "TryCatch", .product(name: "SwiftPM-auto", package: "swift-package-manager"), - ], - path: "Sourcery", + ] +#if canImport(ObjectiveC) +sourceryLibDependencies.append("TryCatch") +let templatesTestsResourcesCopy: [Resource] = [ + .copy("Templates"), + .copy("Tests/Context"), + .copy("Tests/Expected") +] +#else +sourceryLibDependencies.append(.product(name: "Crypto", package: "swift-crypto")) +let templatesTestsResourcesCopy: [Resource] = [ + .copy("Templates"), + .copy("Tests/Context_Linux"), + .copy("Tests/Expected") +] +#endif + +var targets: [Target] = [ + .executableTarget( + name: "SourceryExecutable", + dependencies: ["SourceryLib"], + path: "SourceryExecutable", exclude: [ - "Templates", + "Info.plist" ] ), .target( - name: "SourceryRuntime", - path: "SourceryRuntime", + // Xcode doesn't like when a target has the same name as a product but in different case. + name: "SourceryLib", + dependencies: sourceryLibDependencies, + path: "Sourcery", exclude: [ - "Supporting Files/Info.plist" + "Templates", ] ), .target( - name: "SourceryUtils", + name: "SourceryRuntime", dependencies: [ - "PathKit" + "StencilSwiftKit" ], - path: "SourceryUtils", + path: "SourceryRuntime", exclude: [ "Supporting Files/Info.plist" ] @@ -157,7 +137,6 @@ let package = Package( "Generated/AutoCodable.generated.swift" ] ), - .target(name: "TryCatch", path: "TryCatch", exclude: ["Info.plist"]), .testTarget( name: "SourceryLibTests", dependencies: [ @@ -178,7 +157,8 @@ let package = Package( .copy("Stub/Result"), .copy("Stub/Templates"), .copy("Stub/Source") - ] + ], + swiftSettings: [.unsafeFlags(["-enable-testing"])] ), .testTarget( name: "CodableContextTests", @@ -190,7 +170,8 @@ let package = Package( path: "Templates/CodableContextTests", exclude: [ "Info.plist" - ] + ], + swiftSettings: [.unsafeFlags(["-enable-testing"])] ), .testTarget( name: "TemplatesTests", @@ -211,11 +192,8 @@ let package = Package( // since there is no way to run script before compilation begins. "Tests/TemplatesTests.swift" ], - resources: [ - .copy("Templates"), - .copy("Tests/Context"), - .copy("Tests/Expected") - ] + resources: templatesTestsResourcesCopy, + swiftSettings: [.unsafeFlags(["-enable-testing"])] ), .plugin( name: "SourceryCommandPlugin", @@ -231,4 +209,62 @@ let package = Package( dependencies: ["SourceryExecutable"] ) ] + +#if canImport(ObjectiveC) +let sourceryUtilsDependencies: [Target.Dependency] = ["PathKit"] +targets.append(.target(name: "TryCatch", path: "TryCatch", exclude: ["Info.plist"])) +#else +let sourceryUtilsDependencies: [Target.Dependency] = [ + "PathKit", + .product(name: "Crypto", package: "swift-crypto") +] +#endif +targets.append( + .target( + name: "SourceryUtils", + dependencies: sourceryUtilsDependencies, + path: "SourceryUtils", + exclude: [ + "Supporting Files/Info.plist" + ] + ) +) + +var dependencies: [Package.Dependency] = [ + .package(url: "https://github.com/jpsim/Yams.git", from: "5.0.3"), + .package(url: "https://github.com/kylef/Commander.git", exact: "0.9.1"), + // PathKit needs to be exact to avoid a SwiftPM bug where dependency resolution takes a very long time. + .package(url: "https://github.com/kylef/PathKit.git", exact: "1.0.1"), + .package(url: "https://github.com/art-divin/StencilSwiftKit.git", branch: "stable"), + .package(url: "https://github.com/art-divin/Stencil.git", branch: "master"), + .package(url: "https://github.com/tuist/XcodeProj.git", exact: "8.3.1"), + .package(url: "https://github.com/apple/swift-syntax.git", from: "508.0.0"), + .package(url: "https://github.com/Quick/Quick.git", from: "3.0.0"), + .package(url: "https://github.com/Quick/Nimble.git", from: "9.0.0"), + .package(url: "https://github.com/apple/swift-package-manager", revision: "fa3db13e0bd00e33c187c63c80673b3ac7c82f55"), +] + +#if !canImport(ObjectiveC) +dependencies.append(.package(url: "https://github.com/apple/swift-crypto", from: "2.2.3")) +#endif + +let package = Package( + name: "Sourcery", + platforms: [ + .macOS(.v12), + ], + products: [ + // SPM won't generate .swiftmodule for a target directly used by a product, + // hence it can't be imported by tests. Executable target can't be imported too. + .executable(name: "sourcery", targets: ["SourceryExecutable"]), + .library(name: "SourceryRuntime", targets: ["SourceryRuntime"]), + .library(name: "SourceryStencil", targets: ["SourceryStencil"]), + .library(name: "SourceryJS", targets: ["SourceryJS"]), + .library(name: "SourcerySwift", targets: ["SourcerySwift"]), + .library(name: "SourceryFramework", targets: ["SourceryFramework"]), + .library(name: "SourceryLib", targets: ["SourceryLib"]), + .plugin(name: "SourceryCommandPlugin", targets: ["SourceryCommandPlugin"]) + ], + dependencies: dependencies, + targets: targets ) diff --git a/README.md b/README.md index e04ba5c37..e96b98d38 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ [![CircleCI](https://circleci.com/gh/krzysztofzablocki/Sourcery.svg?style=shield)](https://circleci.com/gh/krzysztofzablocki/Sourcery) +[![macOS](https://github.com/krzysztofzablocki/Sourcery/actions/workflows/macOS.yml/badge.svg)](https://github.com/krzysztofzablocki/Sourcery/actions/workflows/macOS.yml) +[![Ubuntu (Experimental)](https://github.com/krzysztofzablocki/Sourcery/actions/workflows/Ubuntu.yml/badge.svg)](https://github.com/krzysztofzablocki/Sourcery/actions/workflows/Ubuntu.yml) [![docs](https://krzysztofzablocki.github.io/Sourcery/badge.svg)](https://krzysztofzablocki.github.io/Sourcery/index.html) [![Version](https://img.shields.io/cocoapods/v/Sourcery.svg?style=flat)](http://cocoapods.org/pods/Sourcery) @@ -141,6 +143,10 @@ Add the dependency to `.pre-commit-config.yaml`. Full documentation for the latest release is available [here](http://merowing.info/Sourcery/). +## Linux Support + +Linux support is [described on this page](LINUX.md). + ## Usage ### Running the executable diff --git a/Rakefile b/Rakefile index 73c88a65d..92f4b8c4b 100644 --- a/Rakefile +++ b/Rakefile @@ -6,6 +6,7 @@ require 'yaml' require 'json' require 'net/http' require 'uri' +require 'rbconfig' BUILD_DIR = 'build/' CLI_DIR = 'cli/' @@ -42,10 +43,7 @@ end desc "Run the Unit Tests on all projects" task :tests do print_info "Running Unit Tests" - # we can't use SPM directly because it doesn't link rpath and thus often uses wrong dylib - # sh %Q(swift test) - xcpretty %Q(xcodebuild -scheme sourcery -destination platform=macOS,arch=x86_64) - xcpretty %Q(xcodebuild -scheme Sourcery-Package -destination platform=macOS,arch=x86_64 test) + sh %Q(swift test) end desc "Delete the build/ directory" diff --git a/Sourcery/Configuration.swift b/Sourcery/Configuration.swift index efbe10106..8fa5ebf8b 100644 --- a/Sourcery/Configuration.swift +++ b/Sourcery/Configuration.swift @@ -3,11 +3,11 @@ import XcodeProj import PathKit import Yams import SourceryRuntime -import QuartzCore import Basics import TSCBasic import Workspace import PackageModel +import SourceryFramework public struct Project { public let file: XcodeProj @@ -424,9 +424,9 @@ public enum Configurations { throw Configuration.Error.invalidFormat(message: "Expected dictionary.") } - let start = CFAbsoluteTimeGetCurrent() + let start = currentTimestamp() defer { - Log.benchmark("Resolving configurations took \(CFAbsoluteTimeGetCurrent() - start)") + Log.benchmark("Resolving configurations took \(currentTimestamp() - start)") } if let configurations = dict["configurations"] as? [[String: Any]] { diff --git a/Sourcery/Generating/Templates/JavaScript/JavaScriptTemplate.swift b/Sourcery/Generating/Templates/JavaScript/JavaScriptTemplate.swift index db45f1d7a..f89b90823 100644 --- a/Sourcery/Generating/Templates/JavaScript/JavaScriptTemplate.swift +++ b/Sourcery/Generating/Templates/JavaScript/JavaScriptTemplate.swift @@ -1,6 +1,7 @@ import SourceryFramework import SourceryJS import SourceryRuntime +#if canImport(ObjectiveC) import JavaScriptCore class JavaScriptTemplate: EJSTemplate, Template { @@ -52,3 +53,4 @@ private extension JSContext { } } +#endif diff --git a/Sourcery/Sourcery.swift b/Sourcery/Sourcery.swift index 1632ae640..984f158e5 100644 --- a/Sourcery/Sourcery.swift +++ b/Sourcery/Sourcery.swift @@ -11,7 +11,9 @@ import SourceryRuntime import SourceryJS import SourcerySwift import SourceryStencil +#if canImport(ObjectiveC) import TryCatch +#endif import XcodeProj public class Sourcery { @@ -134,7 +136,7 @@ public class Sourcery { } Log.info("Starting watching sources.") - +#if canImport(ObjectiveC) let sourceWatchers = topPaths(from: watchPaths.allPaths).map({ watchPath in return FolderWatcher.Local(path: watchPath.string) { events in let eventPaths: [Path] = events @@ -187,6 +189,9 @@ public class Sourcery { }) return Array([sourceWatchers, templateWatchers].joined()) +#else + return [] +#endif } private func topPaths(from paths: [Path]) -> [Path] { @@ -235,18 +240,25 @@ public class Sourcery { } } - fileprivate func templates(from: Paths) throws -> [Template] { + private func templatePaths(from: Paths) -> [Path] { + return from.allPaths.filter { $0.isTemplateFile } + } + +} + +#if canImport(ObjectiveC) +private extension Sourcery { + func templates(from: Paths) throws -> [Template] { return try templatePaths(from: from).compactMap { if $0.extension == "sourcerytemplate" { let template = try JSONDecoder().decode(SourceryTemplate.self, from: $0.read()) switch template.instance.kind { case .ejs: - guard EJSTemplate.ejsPath != nil else { + guard let ejsPath = EJSTemplate.ejsPath else { Log.warning("Skipping template \($0). JavaScript templates require EJS path to be set manually when using Sourcery built with Swift Package Manager. Use `--ejsPath` command line argument to set it.") return nil } - return try JavaScriptTemplate(path: $0, templateString: template.instance.content) - + return try JavaScriptTemplate(path: $0, templateString: template.instance.content, ejsPath: ejsPath) case .stencil: return try StencilTemplate(path: $0, templateString: template.instance.content) } @@ -254,22 +266,34 @@ public class Sourcery { let cachePath = cachesDir(sourcePath: $0) return try SwiftTemplate(path: $0, cachePath: cachePath, version: type(of: self).version, buildPath: buildPath) } else if $0.extension == "ejs" { - guard EJSTemplate.ejsPath != nil else { + guard let ejsPath = EJSTemplate.ejsPath else { Log.warning("Skipping template \($0). JavaScript templates require EJS path to be set manually when using Sourcery built with Swift Package Manager. Use `--ejsPath` command line argument to set it.") return nil } - return try JavaScriptTemplate(path: $0) + return try JavaScriptTemplate(path: $0, ejsPath: ejsPath) } else { return try StencilTemplate(path: $0) } } } - - private func templatePaths(from: Paths) -> [Path] { - return from.allPaths.filter { $0.isTemplateFile } +} +#else +private extension Sourcery { + func templates(from: Paths) throws -> [Template] { + return try templatePaths(from: from).compactMap { + if $0.extension == "sourcerytemplate" { + let template = try JSONDecoder().decode(SourceryTemplate.self, from: $0.read()) + return try StencilTemplate(path: $0, templateString: template.instance.content) + } else if $0.extension == "swifttemplate" { + let cachePath = cachesDir(sourcePath: $0) + return try SwiftTemplate(path: $0, cachePath: cachePath, version: type(of: self).version, buildPath: buildPath) + } else { + return try StencilTemplate(path: $0) + } + } } - } +#endif // MARK: - Parsing @@ -431,8 +455,9 @@ extension Sourcery { private func load(artifacts: String, modifiedDate: Date, path: Path) -> FileParserResult? { var unarchivedResult: FileParserResult? - SwiftTryCatch.try({ +#if canImport(ObjectiveC) + SwiftTryCatch.try({ // this deprecation can't be removed atm, new API is 10x slower if let unarchived = NSKeyedUnarchiver.unarchiveObject(withFile: artifacts) as? FileParserResult { if unarchived.sourceryVersion == Sourcery.version, unarchived.modifiedDate == modifiedDate { @@ -442,6 +467,14 @@ extension Sourcery { }, catch: { _ in Log.warning("Failed to unarchive cache for \(path.string) due to error, re-parsing file") }, finallyBlock: {}) +#else + // this deprecation can't be removed atm, new API is 10x slower + if let unarchived = NSKeyedUnarchiver.unarchiveObject(withFile: artifacts) as? FileParserResult { + if unarchived.sourceryVersion == Sourcery.version, unarchived.modifiedDate == modifiedDate { + unarchivedResult = unarchived + } + } +#endif return unarchivedResult } @@ -627,6 +660,7 @@ extension Sourcery { } var result: String = "" +#if canImport(ObjectiveC) SwiftTryCatch.try({ do { result = try Generator.generate(parsingResult.parserResult, types: parsingResult.types, functions: parsingResult.functions, template: template, arguments: self.arguments) @@ -636,6 +670,13 @@ extension Sourcery { }, catch: { error in result = error?.description ?? "" }, finallyBlock: {}) +#else + do { + result = try Generator.generate(parsingResult.parserResult, types: parsingResult.types, functions: parsingResult.functions, template: template, arguments: self.arguments) + } catch { + Log.error(error) + } +#endif return try processRanges(in: parsingResult, result: result, outputPath: outputPath, forceParse: forceParse, baseIndentation: baseIndentation) } diff --git a/Sourcery/Templates/Coding.stencil b/Sourcery/Templates/Coding.stencil index 2d738a52f..73a8763a5 100644 --- a/Sourcery/Templates/Coding.stencil +++ b/Sourcery/Templates/Coding.stencil @@ -45,7 +45,12 @@ extension NSCoder { /// :nodoc: required {{ type.accessLevel }} init?(coder aDecoder: NSCoder) { - {% for variable in type.storedVariables|!annotated:"skipCoding" %}{% if variable.typeName.name == "Bool" or variable.typeName.name == "Int" %}self.{{variable.name}} = aDecoder.decode(forKey: "{{variable.name}}"){% elif variable.typeName.name == "Int32" or variable.typeName.name == "Int64" %}self.{{variable.name}} = aDecoder.decode{{variable.typeName.name}}(forKey: "{{variable.name}}"){% else %}{% if not variable.typeName.isOptional %}guard let {{variable.name}}: {{ variable.typeName.unwrappedTypeName }} = aDecoder.decode(forKey: "{{variable.name}}") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["{{ variable.name }}"])); fatalError() }; self.{{variable.name}} = {{variable.name}}{% else %}self.{{variable.name}} = aDecoder.{% if variable.typeName.unwrappedTypeName == "Any" %}decodeObject{% else %}decode{% endif %}(forKey: "{{variable.name}}"){% endif %}{% endif %} + {% for variable in type.storedVariables|!annotated:"skipCoding" %}{% if variable.typeName.name == "Bool" or variable.typeName.name == "Int" %}self.{{variable.name}} = aDecoder.decode(forKey: "{{variable.name}}"){% elif variable.typeName.name == "Int32" or variable.typeName.name == "Int64" %}self.{{variable.name}} = aDecoder.decode{{variable.typeName.name}}(forKey: "{{variable.name}}"){% else %}{% if not variable.typeName.isOptional %}guard let {{variable.name}}: {{ variable.typeName.unwrappedTypeName }} = aDecoder.decode(forKey: "{{variable.name}}") else { + withVaList(["{{ variable.name }}"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.{{variable.name}} = {{variable.name}}{% else %}self.{{variable.name}} = aDecoder.{% if variable.typeName.unwrappedTypeName == "Any" %}decodeObject{% else %}decode{% endif %}(forKey: "{{variable.name}}"){% endif %}{% endif %} {% endfor %}{% if type.supertype.implements.AutoCoding %}super.init(coder: aDecoder){% endif %} } diff --git a/Sourcery/Utils/FolderWatcher.swift b/Sourcery/Utils/FolderWatcher.swift index 9ae6d7ff7..68998cef3 100644 --- a/Sourcery/Utils/FolderWatcher.swift +++ b/Sourcery/Utils/FolderWatcher.swift @@ -8,6 +8,7 @@ import Foundation +#if canImport(ObjectiveC) public enum FolderWatcher { struct Event { @@ -106,3 +107,34 @@ public enum FolderWatcher { } } } +#else +public enum FolderWatcher { + + struct Event { + let path: String + let flags: Flag + + struct Flag: OptionSet { + let rawValue: UInt + + static let isFile = Flag(rawValue: 1) + } + } + public class Local { + private let path: String + + private let closure: (_ events: [Event]) -> Void + + /// Creates folder watcher. + /// + /// - Parameters: + /// - path: Path to observe + /// - latency: Latency to use + /// - closure: Callback closure + init(path: String, latency: TimeInterval = 1/60, closure: @escaping (_ events: [Event]) -> Void) { + self.path = path + self.closure = closure + } + } +} +#endif diff --git a/SourceryExecutable/main.swift b/SourceryExecutable/main.swift index aaba82499..616370458 100644 --- a/SourceryExecutable/main.swift +++ b/SourceryExecutable/main.swift @@ -87,6 +87,7 @@ private func exit(_ code: ExitCode) -> Never { exit(code.rawValue) } +#if canImport(ObjectiveC) func runCLI() { command( Flag("watch", flag: "w", description: "Watch template for changes and regenerate as needed."), @@ -190,7 +191,7 @@ func runCLI() { } } - let start = CFAbsoluteTimeGetCurrent() + let start = currentTimestamp() let keepAlive = try configurations.flatMap { configuration -> [FolderWatcher.Local] in configuration.validate() @@ -222,7 +223,7 @@ func runCLI() { } if keepAlive.isEmpty { - Log.info("Processing time \(CFAbsoluteTimeGetCurrent() - start) seconds") + Log.info("Processing time \(currentTimestamp() - start) seconds") } else { RunLoop.current.run() _ = keepAlive @@ -243,7 +244,6 @@ func runCLI() { }.run(Sourcery.version) } -#if os(macOS) import AppKit if !inUnitTests { @@ -271,4 +271,151 @@ if !inUnitTests { app.run() } } +#else +func runCLI() { + command( + Flag("disableCache", description: "Stops using cache."), + Flag("verbose", flag: "v", description: "Turn on verbose logging, this causes to log everything we can."), + Flag("logAST", description: "Log AST messages"), + Flag("logBenchmarks", description: "Log time benchmark info"), + Flag("parseDocumentation", description: "Include documentation comments for all declarations."), + Flag("quiet", flag: "q", description: "Turn off any logging, only emmit errors."), + Flag("prune", flag: "p", description: "Remove empty generated files"), + Flag("serialParse", description: "Parses the specified sources in serial, rather than in parallel (the default), which can address stability issues in SwiftSyntax."), + VariadicOption("sources", description: "Path to a source swift files. File or Directory."), + VariadicOption("exclude-sources", description: "Path to a source swift files to exclude. File or Directory."), + VariadicOption("templates", description: "Path to templates. File or Directory."), + VariadicOption("exclude-templates", description: "Path to templates to exclude. File or Directory."), + Option("output", default: "", description: "Path to output. File or Directory. Default is current path."), + Flag("dry", default: false, description: "Dry run, without file system modifications, will output result and errors in JSON format. Not working with --watch."), + VariadicOption("config", default: ["."], description: "Path to config file. File or Directory. Default is current path."), + VariadicOption("force-parse", description: "File extensions that Sourcery will be forced to parse, even if they were generated by Sourcery."), + Option("base-indentation", default: 0, description: "Base indendation to add to sourcery:auto fragments."), + VariadicOption("args", description: + """ + Additional arguments to pass to templates. Each argument can have an explicit value or will have \ + an implicit `true` value. Arguments should be comma-separated without spaces (e.g. --args arg1=value,arg2) \ + or should be passed one by one (e.g. --args arg1=value --args arg2). Arguments are accessible in templates \ + via `argument.`. To pass in string you should use escaped quotes (\\"). + """), + Option("cacheBasePath", default: "", description: "Base path to Sourcery's cache directory"), + Option("buildPath", default: "", description: "Sets a custom build path") + ) { disableCache, verboseLogging, logAST, logBenchmark, parseDocumentation, quiet, prune, serialParse, sources, excludeSources, templates, excludeTemplates, output, isDryRun, configPaths, forceParse, baseIndentation, args, cacheBasePath, buildPath in + do { + Log.stackMessages = isDryRun + switch (quiet, verboseLogging) { + case (true, _): + Log.level = .errors + case (false, let isVerbose): + Log.level = isVerbose ? .verbose : .info + } + Log.logBenchmarks = (verboseLogging || logBenchmark) && !quiet + Log.logAST = (verboseLogging || logAST) && !quiet + + let configurations = configPaths.flatMap { configPath -> [Configuration] in + let yamlPath: Path = configPath.isDirectory ? configPath + ".sourcery.yml" : configPath + + if !yamlPath.exists { + Log.info("No config file provided or it does not exist. Using command line arguments.") + let args = args.joined(separator: ",") + let arguments = AnnotationsParser.parse(line: args) + return [ + Configuration( + sources: Paths(include: sources, exclude: excludeSources) , + templates: Paths(include: templates, exclude: excludeTemplates), + output: output.string.isEmpty ? "." : output, + cacheBasePath: cacheBasePath.string.isEmpty ? Path.defaultBaseCachePath : cacheBasePath, + forceParse: forceParse, + parseDocumentation: parseDocumentation, + baseIndentation: baseIndentation, + args: arguments + ) + ] + } else { + _ = Validators.isFileOrDirectory(path: configPath) + _ = Validators.isReadable(path: yamlPath) + + do { + let relativePath: Path = configPath.isDirectory ? configPath : configPath.parent() + + // Check if the user is passing parameters + // that are ignored cause read from the yaml file + let hasAnyYamlDuplicatedParameter = ( + !sources.isEmpty || + !excludeSources.isEmpty || + !templates.isEmpty || + !excludeTemplates.isEmpty || + !forceParse.isEmpty || + output != "" || + !args.isEmpty + ) + + if hasAnyYamlDuplicatedParameter { + Log.info("Using configuration file at '\(yamlPath)'. WARNING: Ignoring the parameters passed in the command line.") + } else { + Log.info("Using configuration file at '\(yamlPath)'") + } + + return try Configurations.make( + path: yamlPath, + relativePath: relativePath, + env: ProcessInfo.processInfo.environment + ) + } catch { + Log.error("while reading .yml '\(yamlPath)'. '\(error)'") + exit(.invalidConfig) + } + } + } + + let start = currentTimestamp() + + let keepAlive = try configurations.flatMap { configuration -> [FolderWatcher.Local] in + configuration.validate() + + let shouldUseCacheBasePathArg = configuration.cacheBasePath == Path.defaultBaseCachePath && !cacheBasePath.string.isEmpty + + let sourcery = Sourcery(verbose: verboseLogging, + watcherEnabled: false, + cacheDisabled: disableCache, + cacheBasePath: shouldUseCacheBasePathArg ? cacheBasePath : configuration.cacheBasePath, + buildPath: buildPath.string.isEmpty ? nil : buildPath, + prune: prune, + serialParse: serialParse, + arguments: configuration.args) + + return try sourcery.processFiles( + configuration.source, + usingTemplates: configuration.templates, + output: configuration.output, + isDryRun: isDryRun, + forceParse: configuration.forceParse, + parseDocumentation: configuration.parseDocumentation, + baseIndentation: configuration.baseIndentation + ) ?? [] + } + + if keepAlive.isEmpty { + Log.info("Processing time \(currentTimestamp() - start) seconds") + } else { + RunLoop.current.run() + _ = keepAlive + } + } catch { + if isDryRun { + let encoder = JSONEncoder() + encoder.outputFormatting = .prettyPrinted + let data = try? encoder.encode(DryOutputFailure(error: "\(error)", + log: Log.messagesStack)) + data.flatMap { Log.output(String(data: $0, encoding: .utf8) ?? "") } + } else { + Log.error("\(error)") + } + + exit(.other) + } + }.run(Sourcery.version) +} + +runCLI() #endif diff --git a/SourceryFramework/Sources/Parsing/Utils/Time.swift b/SourceryFramework/Sources/Parsing/Utils/Time.swift index b1c34208b..5f66da5d3 100644 --- a/SourceryFramework/Sources/Parsing/Utils/Time.swift +++ b/SourceryFramework/Sources/Parsing/Utils/Time.swift @@ -9,5 +9,5 @@ import Foundation /// Returns current timestamp interval public func currentTimestamp() -> TimeInterval { - return CFAbsoluteTimeGetCurrent() + return Date().timeIntervalSince1970 } diff --git a/SourceryJS/Sources/EJSTemplate.swift b/SourceryJS/Sources/EJSTemplate.swift index 5340ce83a..082615dd7 100644 --- a/SourceryJS/Sources/EJSTemplate.swift +++ b/SourceryJS/Sources/EJSTemplate.swift @@ -1,7 +1,25 @@ +#if canImport(ObjectiveC) import JavaScriptCore import PathKit -private extension Foundation.Bundle { +// (c) https://forums.swift.org/t/swift-5-3-spm-resources-in-tests-uses-wrong-bundle-path/37051/46 +private extension Bundle { + static let mypackageResources: Bundle = { + #if DEBUG + if let moduleName = Bundle(for: BundleFinder.self).bundleIdentifier, + let testBundlePath = ProcessInfo.processInfo.environment["XCTestBundlePath"] { + if let resourceBundle = Bundle(path: testBundlePath + "/\(moduleName)_\(moduleName).bundle") { + return resourceBundle + } + } + #endif + return Bundle.module + }() + + private final class BundleFinder {} +} + +public extension Foundation.Bundle { /// Returns the resource bundle associated with the current Swift module. static var jsModule: Bundle = { let bundleName = "Sourcery_SourceryJS" @@ -23,8 +41,7 @@ private extension Foundation.Bundle { return bundle } } - - return Bundle(for: EJSTemplate.self) + return Bundle.mypackageResources }() } @@ -44,7 +61,13 @@ open class EJSTemplate { #else static let bundle = Bundle(for: EJSTemplate.self) #endif - public static var ejsPath: Path! = bundle.path(forResource: "ejs", ofType: "js").map({ Path($0) }) + public static var ejsPath: Path? = { + let bundle = EJSTemplate.bundle + guard let path = bundle.path(forResource: "ejs", ofType: "js") else { + return nil + } + return Path(path) + }() public let sourcePath: Path public let templateString: String @@ -66,17 +89,17 @@ open class EJSTemplate { } } - public convenience init(path: Path, ejsPath: Path = EJSTemplate.ejsPath) throws { + public convenience init(path: Path, ejsPath: Path) throws { try self.init(path: path, templateString: try path.read(), ejsPath: ejsPath) } - public init(path: Path, templateString: String, ejsPath: Path = EJSTemplate.ejsPath) throws { + public init(path: Path, templateString: String, ejsPath: Path) throws { self.templateString = templateString sourcePath = path self.ejs = try ejsPath.read(.utf8) } - public init(templateString: String, ejsPath: Path = EJSTemplate.ejsPath) throws { + public init(templateString: String, ejsPath: Path) throws { self.templateString = templateString sourcePath = "" self.ejs = try ejsPath.read(.utf8) @@ -120,3 +143,4 @@ open class EJSTemplate { } } +#endif diff --git a/SourceryRuntime/Sources/AST/Actor.swift b/SourceryRuntime/Sources/AST/Actor.swift index c85621b77..10d28c6e2 100644 --- a/SourceryRuntime/Sources/AST/Actor.swift +++ b/SourceryRuntime/Sources/AST/Actor.swift @@ -2,7 +2,10 @@ import Foundation // sourcery: skipDescription /// Descibes Swift actor -@objc(SwiftActor) @objcMembers public final class Actor: Type { +#if canImport(ObjectiveC) +@objc(SwiftActor) @objcMembers +#endif +public final class Actor: Type { /// Returns "actor" public override var kind: String { return "actor" } @@ -46,6 +49,37 @@ import Foundation ) } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \(String(describing: self.kind)), " + string += "isFinal = \(String(describing: self.isFinal))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Actor else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Actor else { return false } + return super.isEqual(rhs) + } + // sourcery:inline:Actor.AutoCoding /// :nodoc: @@ -58,4 +92,5 @@ import Foundation super.encode(with: aCoder) } // sourcery:end + } diff --git a/SourceryRuntime/Sources/AST/AssociatedType.swift b/SourceryRuntime/Sources/AST/AssociatedType.swift index c15a93706..247d53efb 100644 --- a/SourceryRuntime/Sources/AST/AssociatedType.swift +++ b/SourceryRuntime/Sources/AST/AssociatedType.swift @@ -1,7 +1,10 @@ import Foundation /// Describes Swift AssociatedType -@objcMembers public final class AssociatedType: NSObject, SourceryModel { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class AssociatedType: NSObject, SourceryModel { /// Associated type name public let name: String @@ -19,11 +22,50 @@ import Foundation self.type = type } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "typeName = \(String(describing: self.typeName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? AssociatedType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? AssociatedType else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + return true + } + // sourcery:inline:AssociatedType.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name self.typeName = aDecoder.decode(forKey: "typeName") self.type = aDecoder.decode(forKey: "type") } diff --git a/SourceryRuntime/Sources/AST/AssociatedValue.swift b/SourceryRuntime/Sources/AST/AssociatedValue.swift new file mode 100644 index 000000000..be66733e0 --- /dev/null +++ b/SourceryRuntime/Sources/AST/AssociatedValue.swift @@ -0,0 +1,127 @@ +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// +#if canImport(ObjectiveC) +import Foundation + +/// Defines enum case associated value +@objcMembers +public final class AssociatedValue: NSObject, SourceryModel, AutoDescription, Typed, Annotated, Diffable { + + /// Associated value local name. + /// This is a name to be used to construct enum case value + public let localName: String? + + /// Associated value external name. + /// This is a name to be used to access value in value-bindig + public let externalName: String? + + /// Associated value type name + public let typeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Associated value type, if known + public var type: Type? + + /// Associated value default value + public let defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + + /// :nodoc: + public init(localName: String?, externalName: String?, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { + self.localName = localName + self.externalName = externalName + self.typeName = typeName + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + } + + convenience init(name: String? = nil, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { + self.init(localName: name, externalName: name, typeName: typeName, type: type, defaultValue: defaultValue, annotations: annotations) + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "localName = \(String(describing: self.localName)), " + string += "externalName = \(String(describing: self.externalName)), " + string += "typeName = \(String(describing: self.typeName)), " + string += "defaultValue = \(String(describing: self.defaultValue)), " + string += "annotations = \(String(describing: self.annotations))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? AssociatedValue else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) + results.append(contentsOf: DiffableResult(identifier: "externalName").trackDifference(actual: self.externalName, expected: castObject.externalName)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.localName) + hasher.combine(self.externalName) + hasher.combine(self.typeName) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? AssociatedValue else { return false } + if self.localName != rhs.localName { return false } + if self.externalName != rhs.externalName { return false } + if self.typeName != rhs.typeName { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true + } + +// sourcery:inline:AssociatedValue.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.localName = aDecoder.decode(forKey: "localName") + self.externalName = aDecoder.decode(forKey: "externalName") + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.type = aDecoder.decode(forKey: "type") + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.localName, forKey: "localName") + aCoder.encode(self.externalName, forKey: "externalName") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + } +// sourcery:end + +} +#endif diff --git a/SourceryRuntime/Sources/AST/AssociatedValue_Linux.swift b/SourceryRuntime/Sources/AST/AssociatedValue_Linux.swift new file mode 100644 index 000000000..8eea4491a --- /dev/null +++ b/SourceryRuntime/Sources/AST/AssociatedValue_Linux.swift @@ -0,0 +1,148 @@ +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// +#if !canImport(ObjectiveC) +import Foundation +// For DynamicMemberLookup we need to import Stencil, +// however, this is different from SourceryRuntime.content.generated.swift, because +// it cannot reference Stencil +import Stencil + +/// Defines enum case associated value +public final class AssociatedValue: NSObject, SourceryModel, AutoDescription, Typed, Annotated, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "externalName": + return externalName + case "localName": + return localName + case "typeName": + return typeName + case "type": + return type + case "defaultValue": + return defaultValue + case "annotations": + return annotations + default: + fatalError("unable to lookup: \(member) in \(self)") + } + } + + /// Associated value local name. + /// This is a name to be used to construct enum case value + public let localName: String? + + /// Associated value external name. + /// This is a name to be used to access value in value-bindig + public let externalName: String? + + /// Associated value type name + public let typeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Associated value type, if known + public var type: Type? + + /// Associated value default value + public let defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + + /// :nodoc: + public init(localName: String?, externalName: String?, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { + self.localName = localName + self.externalName = externalName + self.typeName = typeName + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + } + + convenience init(name: String? = nil, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { + self.init(localName: name, externalName: name, typeName: typeName, type: type, defaultValue: defaultValue, annotations: annotations) + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "localName = \(String(describing: self.localName)), " + string += "externalName = \(String(describing: self.externalName)), " + string += "typeName = \(String(describing: self.typeName)), " + string += "defaultValue = \(String(describing: self.defaultValue)), " + string += "annotations = \(String(describing: self.annotations))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? AssociatedValue else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) + results.append(contentsOf: DiffableResult(identifier: "externalName").trackDifference(actual: self.externalName, expected: castObject.externalName)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.localName) + hasher.combine(self.externalName) + hasher.combine(self.typeName) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? AssociatedValue else { return false } + if self.localName != rhs.localName { return false } + if self.externalName != rhs.externalName { return false } + if self.typeName != rhs.typeName { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true + } + +// sourcery:inline:AssociatedValue.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.localName = aDecoder.decode(forKey: "localName") + self.externalName = aDecoder.decode(forKey: "externalName") + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.type = aDecoder.decode(forKey: "type") + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.localName, forKey: "localName") + aCoder.encode(self.externalName, forKey: "externalName") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + } +// sourcery:end + +} +#endif diff --git a/SourceryRuntime/Sources/AST/Attribute.swift b/SourceryRuntime/Sources/AST/Attribute.swift index f0735f20d..1e0a2aac9 100644 --- a/SourceryRuntime/Sources/AST/Attribute.swift +++ b/SourceryRuntime/Sources/AST/Attribute.swift @@ -1,7 +1,10 @@ import Foundation /// Describes Swift attribute -@objcMembers public class Attribute: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport { +#if canImport(ObjectiveC) +@objcMembers +#endif +public class Attribute: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport, Diffable { /// Attribute name public let name: String @@ -147,13 +150,57 @@ import Foundation } } + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Attribute else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "arguments").trackDifference(actual: self.arguments, expected: castObject.arguments)) + results.append(contentsOf: DiffableResult(identifier: "_description").trackDifference(actual: self._description, expected: castObject._description)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.arguments) + hasher.combine(self._description) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Attribute else { return false } + if self.name != rhs.name { return false } + if self.arguments != rhs.arguments { return false } + if self._description != rhs._description { return false } + return true + } + // sourcery:inline:Attribute.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let arguments: [String: NSObject] = aDecoder.decode(forKey: "arguments") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["arguments"])); fatalError() }; self.arguments = arguments - guard let _description: String = aDecoder.decode(forKey: "_description") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["_description"])); fatalError() }; self._description = _description + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let arguments: [String: NSObject] = aDecoder.decode(forKey: "arguments") else { + withVaList(["arguments"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.arguments = arguments + guard let _description: String = aDecoder.decode(forKey: "_description") else { + withVaList(["_description"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self._description = _description } /// :nodoc: diff --git a/SourceryRuntime/Sources/AST/Class.swift b/SourceryRuntime/Sources/AST/Class.swift index d9aa090f4..08f088d64 100644 --- a/SourceryRuntime/Sources/AST/Class.swift +++ b/SourceryRuntime/Sources/AST/Class.swift @@ -1,7 +1,10 @@ import Foundation // sourcery: skipDescription /// Descibes Swift class -@objc(SwiftClass) @objcMembers public final class Class: Type { +#if canImport(ObjectiveC) +@objc(SwiftClass) @objcMembers +#endif +public final class Class: Type { /// Returns "class" public override var kind: String { return "class" } @@ -45,6 +48,37 @@ import Foundation ) } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \(String(describing: self.kind)), " + string += "isFinal = \(String(describing: self.isFinal))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Class else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Class else { return false } + return super.isEqual(rhs) + } + // sourcery:inline:Class.AutoCoding /// :nodoc: @@ -57,4 +91,5 @@ import Foundation super.encode(with: aCoder) } // sourcery:end + } diff --git a/SourceryRuntime/Sources/AST/ClosureParameter.swift b/SourceryRuntime/Sources/AST/ClosureParameter.swift new file mode 100644 index 000000000..6371a9504 --- /dev/null +++ b/SourceryRuntime/Sources/AST/ClosureParameter.swift @@ -0,0 +1,143 @@ +import Foundation + +// sourcery: skipDiffing +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class ClosureParameter: NSObject, SourceryModel, Typed, Annotated { + /// Parameter external name + public var argumentLabel: String? + + /// Parameter internal name + public let name: String? + + /// Parameter type name + public let typeName: TypeName + + /// Parameter flag whether it's inout or not + public let `inout`: Bool + + // sourcery: skipEquality, skipDescription + /// Parameter type, if known + public var type: Type? + + /// Parameter type attributes, i.e. `@escaping` + public var typeAttributes: AttributeList { + return typeName.attributes + } + + /// Method parameter default value expression + public var defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + + /// :nodoc: + public init(argumentLabel: String? = nil, name: String? = nil, typeName: TypeName, type: Type? = nil, + defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false) { + self.typeName = typeName + self.argumentLabel = argumentLabel + self.name = name + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + self.`inout` = isInout + } + + public var asSource: String { + let typeInfo = "\(`inout` ? "inout " : "")\(typeName.asSource)" + if argumentLabel?.nilIfNotValidParameterName == nil, name?.nilIfNotValidParameterName == nil { + return typeInfo + } + + let typeSuffix = ": \(typeInfo)" + guard argumentLabel != name else { + return name ?? "" + typeSuffix + } + + let labels = [argumentLabel ?? "_", name?.nilIfEmpty] + .compactMap { $0 } + .joined(separator: " ") + + return (labels.nilIfEmpty ?? "_") + typeSuffix + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.argumentLabel) + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.`inout`) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "argumentLabel = \(String(describing: self.argumentLabel)), " + string += "name = \(String(describing: self.name)), " + string += "typeName = \(String(describing: self.typeName)), " + string += "`inout` = \(String(describing: self.`inout`)), " + string += "typeAttributes = \(String(describing: self.typeAttributes)), " + string += "defaultValue = \(String(describing: self.defaultValue)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "asSource = \(String(describing: self.asSource))" + return string + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ClosureParameter else { return false } + if self.argumentLabel != rhs.argumentLabel { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.`inout` != rhs.`inout` { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true + } + + // sourcery:inline:ClosureParameter.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.argumentLabel = aDecoder.decode(forKey: "argumentLabel") + self.name = aDecoder.decode(forKey: "name") + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.`inout` = aDecoder.decode(forKey: "`inout`") + self.type = aDecoder.decode(forKey: "type") + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.argumentLabel, forKey: "argumentLabel") + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.`inout`, forKey: "`inout`") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + } + + // sourcery:end +} + +extension Array where Element == ClosureParameter { + public var asSource: String { + "(\(map { $0.asSource }.joined(separator: ", ")))" + } +} diff --git a/SourceryRuntime/Sources/AST/Enum.swift b/SourceryRuntime/Sources/AST/Enum.swift index 16a6b3186..10b59c0d2 100644 --- a/SourceryRuntime/Sources/AST/Enum.swift +++ b/SourceryRuntime/Sources/AST/Enum.swift @@ -3,138 +3,12 @@ // Copyright (c) 2016 Pixle. All rights reserved. // +#if canImport(ObjectiveC) import Foundation -/// Defines enum case associated value -@objcMembers public final class AssociatedValue: NSObject, SourceryModel, AutoDescription, Typed, Annotated { - - /// Associated value local name. - /// This is a name to be used to construct enum case value - public let localName: String? - - /// Associated value external name. - /// This is a name to be used to access value in value-bindig - public let externalName: String? - - /// Associated value type name - public let typeName: TypeName - - // sourcery: skipEquality, skipDescription - /// Associated value type, if known - public var type: Type? - - /// Associated value default value - public let defaultValue: String? - - /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 - public var annotations: Annotations = [:] - - /// :nodoc: - public init(localName: String?, externalName: String?, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { - self.localName = localName - self.externalName = externalName - self.typeName = typeName - self.type = type - self.defaultValue = defaultValue - self.annotations = annotations - } - - convenience init(name: String? = nil, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { - self.init(localName: name, externalName: name, typeName: typeName, type: type, defaultValue: defaultValue, annotations: annotations) - } - -// sourcery:inline:AssociatedValue.AutoCoding - - /// :nodoc: - required public init?(coder aDecoder: NSCoder) { - self.localName = aDecoder.decode(forKey: "localName") - self.externalName = aDecoder.decode(forKey: "externalName") - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName - self.type = aDecoder.decode(forKey: "type") - self.defaultValue = aDecoder.decode(forKey: "defaultValue") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - } - - /// :nodoc: - public func encode(with aCoder: NSCoder) { - aCoder.encode(self.localName, forKey: "localName") - aCoder.encode(self.externalName, forKey: "externalName") - aCoder.encode(self.typeName, forKey: "typeName") - aCoder.encode(self.type, forKey: "type") - aCoder.encode(self.defaultValue, forKey: "defaultValue") - aCoder.encode(self.annotations, forKey: "annotations") - } -// sourcery:end - -} - -/// Defines enum case -@objcMembers public final class EnumCase: NSObject, SourceryModel, AutoDescription, Annotated, Documented { - - /// Enum case name - public let name: String - - /// Enum case raw value, if any - public let rawValue: String? - - /// Enum case associated values - public let associatedValues: [AssociatedValue] - - /// Enum case annotations - public var annotations: Annotations = [:] - - public var documentation: Documentation = [] - - /// Whether enum case is indirect - public let indirect: Bool - - /// Whether enum case has associated value - public var hasAssociatedValue: Bool { - return !associatedValues.isEmpty - } - - // Underlying parser data, never to be used by anything else - // sourcery: skipEquality, skipDescription, skipCoding, skipJSExport - /// :nodoc: - public var __parserData: Any? - - /// :nodoc: - public init(name: String, rawValue: String? = nil, associatedValues: [AssociatedValue] = [], annotations: [String: NSObject] = [:], documentation: [String] = [], indirect: Bool = false) { - self.name = name - self.rawValue = rawValue - self.associatedValues = associatedValues - self.annotations = annotations - self.documentation = documentation - self.indirect = indirect - } - -// sourcery:inline:EnumCase.AutoCoding - - /// :nodoc: - required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - self.rawValue = aDecoder.decode(forKey: "rawValue") - guard let associatedValues: [AssociatedValue] = aDecoder.decode(forKey: "associatedValues") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["associatedValues"])); fatalError() }; self.associatedValues = associatedValues - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["documentation"])); fatalError() }; self.documentation = documentation - self.indirect = aDecoder.decode(forKey: "indirect") - } - - /// :nodoc: - public func encode(with aCoder: NSCoder) { - aCoder.encode(self.name, forKey: "name") - aCoder.encode(self.rawValue, forKey: "rawValue") - aCoder.encode(self.associatedValues, forKey: "associatedValues") - aCoder.encode(self.annotations, forKey: "annotations") - aCoder.encode(self.documentation, forKey: "documentation") - aCoder.encode(self.indirect, forKey: "indirect") - } -// sourcery:end -} - /// Defines Swift enum -@objcMembers public final class Enum: Type { - +@objcMembers +public final class Enum: Type { // sourcery: skipDescription /// Returns "enum" public override var kind: String { return "enum" } @@ -216,11 +90,54 @@ import Foundation } } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "cases = \(String(describing: self.cases)), " + string += "rawTypeName = \(String(describing: self.rawTypeName)), " + string += "hasAssociatedValues = \(String(describing: self.hasAssociatedValues))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Enum else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "cases").trackDifference(actual: self.cases, expected: castObject.cases)) + results.append(contentsOf: DiffableResult(identifier: "rawTypeName").trackDifference(actual: self.rawTypeName, expected: castObject.rawTypeName)) + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.cases) + hasher.combine(self.rawTypeName) + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Enum else { return false } + if self.cases != rhs.cases { return false } + if self.rawTypeName != rhs.rawTypeName { return false } + return super.isEqual(rhs) + } + // sourcery:inline:Enum.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let cases: [EnumCase] = aDecoder.decode(forKey: "cases") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["cases"])); fatalError() }; self.cases = cases + guard let cases: [EnumCase] = aDecoder.decode(forKey: "cases") else { + withVaList(["cases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.cases = cases self.rawTypeName = aDecoder.decode(forKey: "rawTypeName") self.hasRawType = aDecoder.decode(forKey: "hasRawType") self.rawType = aDecoder.decode(forKey: "rawType") @@ -237,3 +154,4 @@ import Foundation } // sourcery:end } +#endif diff --git a/SourceryRuntime/Sources/AST/EnumCase.swift b/SourceryRuntime/Sources/AST/EnumCase.swift new file mode 100644 index 000000000..b8d4ffd9b --- /dev/null +++ b/SourceryRuntime/Sources/AST/EnumCase.swift @@ -0,0 +1,143 @@ +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// +#if canImport(ObjectiveC) +import Foundation + +/// Defines enum case +@objcMembers +public final class EnumCase: NSObject, SourceryModel, AutoDescription, Annotated, Documented, Diffable { + + /// Enum case name + public let name: String + + /// Enum case raw value, if any + public let rawValue: String? + + /// Enum case associated values + public let associatedValues: [AssociatedValue] + + /// Enum case annotations + public var annotations: Annotations = [:] + + public var documentation: Documentation = [] + + /// Whether enum case is indirect + public let indirect: Bool + + /// Whether enum case has associated value + public var hasAssociatedValue: Bool { + return !associatedValues.isEmpty + } + + // Underlying parser data, never to be used by anything else + // sourcery: skipEquality, skipDescription, skipCoding, skipJSExport + /// :nodoc: + public var __parserData: Any? + + /// :nodoc: + public init(name: String, rawValue: String? = nil, associatedValues: [AssociatedValue] = [], annotations: [String: NSObject] = [:], documentation: [String] = [], indirect: Bool = false) { + self.name = name + self.rawValue = rawValue + self.associatedValues = associatedValues + self.annotations = annotations + self.documentation = documentation + self.indirect = indirect + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "rawValue = \(String(describing: self.rawValue)), " + string += "associatedValues = \(String(describing: self.associatedValues)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "documentation = \(String(describing: self.documentation)), " + string += "indirect = \(String(describing: self.indirect)), " + string += "hasAssociatedValue = \(String(describing: self.hasAssociatedValue))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? EnumCase else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "rawValue").trackDifference(actual: self.rawValue, expected: castObject.rawValue)) + results.append(contentsOf: DiffableResult(identifier: "associatedValues").trackDifference(actual: self.associatedValues, expected: castObject.associatedValues)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "indirect").trackDifference(actual: self.indirect, expected: castObject.indirect)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.rawValue) + hasher.combine(self.associatedValues) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.indirect) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? EnumCase else { return false } + if self.name != rhs.name { return false } + if self.rawValue != rhs.rawValue { return false } + if self.associatedValues != rhs.associatedValues { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.indirect != rhs.indirect { return false } + return true + } + +// sourcery:inline:EnumCase.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + self.rawValue = aDecoder.decode(forKey: "rawValue") + guard let associatedValues: [AssociatedValue] = aDecoder.decode(forKey: "associatedValues") else { + withVaList(["associatedValues"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.associatedValues = associatedValues + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + self.indirect = aDecoder.decode(forKey: "indirect") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.rawValue, forKey: "rawValue") + aCoder.encode(self.associatedValues, forKey: "associatedValues") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.indirect, forKey: "indirect") + } +// sourcery:end +} +#endif diff --git a/SourceryRuntime/Sources/AST/EnumCase_Linux.swift b/SourceryRuntime/Sources/AST/EnumCase_Linux.swift new file mode 100644 index 000000000..fa3349aa8 --- /dev/null +++ b/SourceryRuntime/Sources/AST/EnumCase_Linux.swift @@ -0,0 +1,163 @@ +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// +#if !canImport(ObjectiveC) +import Foundation +// For DynamicMemberLookup we need to import Stencil, +// however, this is different from SourceryRuntime.content.generated.swift, because +// it cannot reference Stencil +import Stencil + +/// Defines enum case +public final class EnumCase: NSObject, SourceryModel, AutoDescription, Annotated, Documented, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "name": + return name + case "hasAssociatedValue": + return hasAssociatedValue + case "associatedValues": + return associatedValues + case "indirect": + return indirect + case "annotations": + return annotations + case "rawValue": + return rawValue + default: + fatalError("unable to lookup: \(member) in \(self)") + } + } + /// Enum case name + public let name: String + + /// Enum case raw value, if any + public let rawValue: String? + + /// Enum case associated values + public let associatedValues: [AssociatedValue] + + /// Enum case annotations + public var annotations: Annotations = [:] + + public var documentation: Documentation = [] + + /// Whether enum case is indirect + public let indirect: Bool + + /// Whether enum case has associated value + public var hasAssociatedValue: Bool { + return !associatedValues.isEmpty + } + + // Underlying parser data, never to be used by anything else + // sourcery: skipEquality, skipDescription, skipCoding, skipJSExport + /// :nodoc: + public var __parserData: Any? + + /// :nodoc: + public init(name: String, rawValue: String? = nil, associatedValues: [AssociatedValue] = [], annotations: [String: NSObject] = [:], documentation: [String] = [], indirect: Bool = false) { + self.name = name + self.rawValue = rawValue + self.associatedValues = associatedValues + self.annotations = annotations + self.documentation = documentation + self.indirect = indirect + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "rawValue = \(String(describing: self.rawValue)), " + string += "associatedValues = \(String(describing: self.associatedValues)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "documentation = \(String(describing: self.documentation)), " + string += "indirect = \(String(describing: self.indirect)), " + string += "hasAssociatedValue = \(String(describing: self.hasAssociatedValue))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? EnumCase else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "rawValue").trackDifference(actual: self.rawValue, expected: castObject.rawValue)) + results.append(contentsOf: DiffableResult(identifier: "associatedValues").trackDifference(actual: self.associatedValues, expected: castObject.associatedValues)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "indirect").trackDifference(actual: self.indirect, expected: castObject.indirect)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.rawValue) + hasher.combine(self.associatedValues) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.indirect) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? EnumCase else { return false } + if self.name != rhs.name { return false } + if self.rawValue != rhs.rawValue { return false } + if self.associatedValues != rhs.associatedValues { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.indirect != rhs.indirect { return false } + return true + } + +// sourcery:inline:EnumCase.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + self.rawValue = aDecoder.decode(forKey: "rawValue") + guard let associatedValues: [AssociatedValue] = aDecoder.decode(forKey: "associatedValues") else { + withVaList(["associatedValues"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.associatedValues = associatedValues + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + self.indirect = aDecoder.decode(forKey: "indirect") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.rawValue, forKey: "rawValue") + aCoder.encode(self.associatedValues, forKey: "associatedValues") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.indirect, forKey: "indirect") + } +// sourcery:end +} +#endif diff --git a/SourceryRuntime/Sources/AST/Enum_Linux.swift b/SourceryRuntime/Sources/AST/Enum_Linux.swift new file mode 100644 index 000000000..3c9935e20 --- /dev/null +++ b/SourceryRuntime/Sources/AST/Enum_Linux.swift @@ -0,0 +1,167 @@ +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// + +#if !canImport(ObjectiveC) +import Foundation + +/// Defines Swift enum +public final class Enum: Type { + public override subscript(dynamicMember member: String) -> Any? { + switch member { + case "cases": + return cases + case "hasAssociatedValues": + return hasAssociatedValues + default: + return super[dynamicMember: member] + } + } + + // sourcery: skipDescription + /// Returns "enum" + public override var kind: String { return "enum" } + + /// Enum cases + public var cases: [EnumCase] + + /** + Enum raw value type name, if any. This type is removed from enum's `based` and `inherited` types collections. + + - important: Unless raw type is specified explicitly via type alias RawValue it will be set to the first type in the inheritance chain. + So if your enum does not have raw value but implements protocols you'll have to specify conformance to these protocols via extension to get enum with nil raw value type and all based and inherited types. + */ + public var rawTypeName: TypeName? { + didSet { + if let rawTypeName = rawTypeName { + hasRawType = true + if let index = inheritedTypes.firstIndex(of: rawTypeName.name) { + inheritedTypes.remove(at: index) + } + if based[rawTypeName.name] != nil { + based[rawTypeName.name] = nil + } + } else { + hasRawType = false + } + } + } + + // sourcery: skipDescription, skipEquality + /// :nodoc: + public private(set) var hasRawType: Bool + + // sourcery: skipDescription, skipEquality + /// Enum raw value type, if known + public var rawType: Type? + + // sourcery: skipEquality, skipDescription, skipCoding + /// Names of types or protocols this type inherits from, including unknown (not scanned) types + public override var based: [String: String] { + didSet { + if let rawTypeName = rawTypeName, based[rawTypeName.name] != nil { + based[rawTypeName.name] = nil + } + } + } + + /// Whether enum contains any associated values + public var hasAssociatedValues: Bool { + return cases.contains(where: { $0.hasAssociatedValue }) + } + + /// :nodoc: + public init(name: String = "", + parent: Type? = nil, + accessLevel: AccessLevel = .internal, + isExtension: Bool = false, + inheritedTypes: [String] = [], + rawTypeName: TypeName? = nil, + cases: [EnumCase] = [], + variables: [Variable] = [], + methods: [Method] = [], + containedTypes: [Type] = [], + typealiases: [Typealias] = [], + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + isGeneric: Bool = false) { + + self.cases = cases + self.rawTypeName = rawTypeName + self.hasRawType = rawTypeName != nil || !inheritedTypes.isEmpty + + super.init(name: name, parent: parent, accessLevel: accessLevel, isExtension: isExtension, variables: variables, methods: methods, inheritedTypes: inheritedTypes, containedTypes: containedTypes, typealiases: typealiases, attributes: attributes, modifiers: modifiers, annotations: annotations, documentation: documentation, isGeneric: isGeneric) + + if let rawTypeName = rawTypeName?.name, let index = self.inheritedTypes.firstIndex(of: rawTypeName) { + self.inheritedTypes.remove(at: index) + } + } + + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "cases = \(String(describing: self.cases)), " + string += "rawTypeName = \(String(describing: self.rawTypeName)), " + string += "hasAssociatedValues = \(String(describing: self.hasAssociatedValues))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Enum else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "cases").trackDifference(actual: self.cases, expected: castObject.cases)) + results.append(contentsOf: DiffableResult(identifier: "rawTypeName").trackDifference(actual: self.rawTypeName, expected: castObject.rawTypeName)) + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.cases) + hasher.combine(self.rawTypeName) + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Enum else { return false } + if self.cases != rhs.cases { return false } + if self.rawTypeName != rhs.rawTypeName { return false } + return super.isEqual(rhs) + } + +// sourcery:inline:Enum.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let cases: [EnumCase] = aDecoder.decode(forKey: "cases") else { + withVaList(["cases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.cases = cases + self.rawTypeName = aDecoder.decode(forKey: "rawTypeName") + self.hasRawType = aDecoder.decode(forKey: "hasRawType") + self.rawType = aDecoder.decode(forKey: "rawType") + super.init(coder: aDecoder) + } + + /// :nodoc: + override public func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + aCoder.encode(self.cases, forKey: "cases") + aCoder.encode(self.rawTypeName, forKey: "rawTypeName") + aCoder.encode(self.hasRawType, forKey: "hasRawType") + aCoder.encode(self.rawType, forKey: "rawType") + } +// sourcery:end +} +#endif diff --git a/SourceryRuntime/Sources/AST/GenericRequirement.swift b/SourceryRuntime/Sources/AST/GenericRequirement.swift index e966f4c87..b95bbec08 100644 --- a/SourceryRuntime/Sources/AST/GenericRequirement.swift +++ b/SourceryRuntime/Sources/AST/GenericRequirement.swift @@ -2,7 +2,10 @@ import Foundation /// modifier can be thing like `private`, `class`, `nonmutating` /// if a declaration has modifier like `private(set)` it's name will be `private` and detail will be `set` -@objcMembers public class GenericRequirement: NSObject, SourceryModel { +#if canImport(ObjectiveC) +@objcMembers +#endif +public class GenericRequirement: NSObject, SourceryModel, Diffable { public enum Relationship: String { case equals @@ -34,14 +37,76 @@ import Foundation self.relationshipSyntax = relationship.syntax } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "leftType = \(String(describing: self.leftType)), " + string += "rightType = \(String(describing: self.rightType)), " + string += "relationship = \(String(describing: self.relationship)), " + string += "relationshipSyntax = \(String(describing: self.relationshipSyntax))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? GenericRequirement else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "leftType").trackDifference(actual: self.leftType, expected: castObject.leftType)) + results.append(contentsOf: DiffableResult(identifier: "rightType").trackDifference(actual: self.rightType, expected: castObject.rightType)) + results.append(contentsOf: DiffableResult(identifier: "relationship").trackDifference(actual: self.relationship, expected: castObject.relationship)) + results.append(contentsOf: DiffableResult(identifier: "relationshipSyntax").trackDifference(actual: self.relationshipSyntax, expected: castObject.relationshipSyntax)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.leftType) + hasher.combine(self.rightType) + hasher.combine(self.relationship) + hasher.combine(self.relationshipSyntax) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? GenericRequirement else { return false } + if self.leftType != rhs.leftType { return false } + if self.rightType != rhs.rightType { return false } + if self.relationship != rhs.relationship { return false } + if self.relationshipSyntax != rhs.relationshipSyntax { return false } + return true + } + // sourcery:inline:GenericRequirement.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let leftType: AssociatedType = aDecoder.decode(forKey: "leftType") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["leftType"])); fatalError() }; self.leftType = leftType - guard let rightType: GenericTypeParameter = aDecoder.decode(forKey: "rightType") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["rightType"])); fatalError() }; self.rightType = rightType - guard let relationship: String = aDecoder.decode(forKey: "relationship") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["relationship"])); fatalError() }; self.relationship = relationship - guard let relationshipSyntax: String = aDecoder.decode(forKey: "relationshipSyntax") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["relationshipSyntax"])); fatalError() }; self.relationshipSyntax = relationshipSyntax + guard let leftType: AssociatedType = aDecoder.decode(forKey: "leftType") else { + withVaList(["leftType"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.leftType = leftType + guard let rightType: GenericTypeParameter = aDecoder.decode(forKey: "rightType") else { + withVaList(["rightType"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rightType = rightType + guard let relationship: String = aDecoder.decode(forKey: "relationship") else { + withVaList(["relationship"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.relationship = relationship + guard let relationshipSyntax: String = aDecoder.decode(forKey: "relationshipSyntax") else { + withVaList(["relationshipSyntax"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.relationshipSyntax = relationshipSyntax } /// :nodoc: diff --git a/SourceryRuntime/Sources/AST/Import.swift b/SourceryRuntime/Sources/AST/Import.swift index 90f5db1eb..ce46c576d 100644 --- a/SourceryRuntime/Sources/AST/Import.swift +++ b/SourceryRuntime/Sources/AST/Import.swift @@ -1,7 +1,10 @@ import Foundation /// Defines import type -@objcMembers public class Import: NSObject, SourceryModelWithoutDescription { +#if canImport(ObjectiveC) +@objcMembers +#endif +public class Import: NSObject, SourceryModelWithoutDescription, Diffable { /// Import kind, e.g. class, struct in `import class Module.ClassName` public var kind: String? @@ -36,12 +39,43 @@ import Foundation } } + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Import else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "kind").trackDifference(actual: self.kind, expected: castObject.kind)) + results.append(contentsOf: DiffableResult(identifier: "path").trackDifference(actual: self.path, expected: castObject.path)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.kind) + hasher.combine(self.path) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Import else { return false } + if self.kind != rhs.kind { return false } + if self.path != rhs.path { return false } + return true + } + // sourcery:inline:Import.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { self.kind = aDecoder.decode(forKey: "kind") - guard let path: String = aDecoder.decode(forKey: "path") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["path"])); fatalError() }; self.path = path + guard let path: String = aDecoder.decode(forKey: "path") else { + withVaList(["path"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.path = path } /// :nodoc: diff --git a/SourceryRuntime/Sources/AST/Method.swift b/SourceryRuntime/Sources/AST/Method.swift index ec9e85c63..9735277d9 100644 --- a/SourceryRuntime/Sources/AST/Method.swift +++ b/SourceryRuntime/Sources/AST/Method.swift @@ -1,207 +1,12 @@ +#if canImport(ObjectiveC) import Foundation /// :nodoc: public typealias SourceryMethod = Method -/// Describes method parameter -@objcMembers public class MethodParameter: NSObject, SourceryModel, Typed, Annotated { - /// Parameter external name - public var argumentLabel: String? - - // Note: although method parameter can have no name, this property is not optional, - // this is so to maintain compatibility with existing templates. - /// Parameter internal name - public let name: String - - /// Parameter type name - public let typeName: TypeName - - /// Parameter flag whether it's inout or not - public let `inout`: Bool - - /// Is this variadic parameter? - public let isVariadic: Bool - - // sourcery: skipEquality, skipDescription - /// Parameter type, if known - public var type: Type? - - /// Parameter type attributes, i.e. `@escaping` - public var typeAttributes: AttributeList { - return typeName.attributes - } - - /// Method parameter default value expression - public var defaultValue: String? - - /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 - public var annotations: Annotations = [:] - - /// :nodoc: - public init(argumentLabel: String?, name: String = "", typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false, isVariadic: Bool = false) { - self.typeName = typeName - self.argumentLabel = argumentLabel - self.name = name - self.type = type - self.defaultValue = defaultValue - self.annotations = annotations - self.`inout` = isInout - self.isVariadic = isVariadic - } - - /// :nodoc: - public init(name: String = "", typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false, isVariadic: Bool = false) { - self.typeName = typeName - self.argumentLabel = name - self.name = name - self.type = type - self.defaultValue = defaultValue - self.annotations = annotations - self.`inout` = isInout - self.isVariadic = isVariadic - } - - public var asSource: String { - let typeSuffix = ": \(`inout` ? "inout " : "")\(typeName.asSource)\(defaultValue.map { " = \($0)" } ?? "")" + (isVariadic ? "..." : "") - guard argumentLabel != name else { - return name + typeSuffix - } - - let labels = [argumentLabel ?? "_", name.nilIfEmpty] - .compactMap { $0 } - .joined(separator: " ") - - return (labels.nilIfEmpty ?? "_") + typeSuffix - } - -// sourcery:inline:MethodParameter.AutoCoding - - /// :nodoc: - required public init?(coder aDecoder: NSCoder) { - self.argumentLabel = aDecoder.decode(forKey: "argumentLabel") - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName - self.`inout` = aDecoder.decode(forKey: "`inout`") - self.isVariadic = aDecoder.decode(forKey: "isVariadic") - self.type = aDecoder.decode(forKey: "type") - self.defaultValue = aDecoder.decode(forKey: "defaultValue") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - } - - /// :nodoc: - public func encode(with aCoder: NSCoder) { - aCoder.encode(self.argumentLabel, forKey: "argumentLabel") - aCoder.encode(self.name, forKey: "name") - aCoder.encode(self.typeName, forKey: "typeName") - aCoder.encode(self.`inout`, forKey: "`inout`") - aCoder.encode(self.isVariadic, forKey: "isVariadic") - aCoder.encode(self.type, forKey: "type") - aCoder.encode(self.defaultValue, forKey: "defaultValue") - aCoder.encode(self.annotations, forKey: "annotations") - } -// sourcery:end -} - -extension Array where Element == MethodParameter { - public var asSource: String { - "(\(map { $0.asSource }.joined(separator: ", ")))" - } -} - -// sourcery: skipDiffing -@objcMembers public final class ClosureParameter: NSObject, SourceryModel, Typed, Annotated { - /// Parameter external name - public var argumentLabel: String? - - /// Parameter internal name - public let name: String? - - /// Parameter type name - public let typeName: TypeName - - /// Parameter flag whether it's inout or not - public let `inout`: Bool - - // sourcery: skipEquality, skipDescription - /// Parameter type, if known - public var type: Type? - - /// Parameter type attributes, i.e. `@escaping` - public var typeAttributes: AttributeList { - return typeName.attributes - } - - /// Method parameter default value expression - public var defaultValue: String? - - /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 - public var annotations: Annotations = [:] - - /// :nodoc: - public init(argumentLabel: String? = nil, name: String? = nil, typeName: TypeName, type: Type? = nil, - defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false) { - self.typeName = typeName - self.argumentLabel = argumentLabel - self.name = name - self.type = type - self.defaultValue = defaultValue - self.annotations = annotations - self.`inout` = isInout - } - - public var asSource: String { - let typeInfo = "\(`inout` ? "inout " : "")\(typeName.asSource)" - if argumentLabel?.nilIfNotValidParameterName == nil, name?.nilIfNotValidParameterName == nil { - return typeInfo - } - - let typeSuffix = ": \(typeInfo)" - guard argumentLabel != name else { - return name ?? "" + typeSuffix - } - - let labels = [argumentLabel ?? "_", name?.nilIfEmpty] - .compactMap { $0 } - .joined(separator: " ") - - return (labels.nilIfEmpty ?? "_") + typeSuffix - } - - // sourcery:inline:ClosureParameter.AutoCoding - - /// :nodoc: - required public init?(coder aDecoder: NSCoder) { - self.argumentLabel = aDecoder.decode(forKey: "argumentLabel") - self.name = aDecoder.decode(forKey: "name") - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName - self.`inout` = aDecoder.decode(forKey: "`inout`") - self.type = aDecoder.decode(forKey: "type") - self.defaultValue = aDecoder.decode(forKey: "defaultValue") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - } - - /// :nodoc: - public func encode(with aCoder: NSCoder) { - aCoder.encode(self.argumentLabel, forKey: "argumentLabel") - aCoder.encode(self.name, forKey: "name") - aCoder.encode(self.typeName, forKey: "typeName") - aCoder.encode(self.`inout`, forKey: "`inout`") - aCoder.encode(self.type, forKey: "type") - aCoder.encode(self.defaultValue, forKey: "defaultValue") - aCoder.encode(self.annotations, forKey: "annotations") - } - - // sourcery:end -} - -extension Array where Element == ClosureParameter { - public var asSource: String { - "(\(map { $0.asSource }.joined(separator: ", ")))" - } -} - /// Describes method -@objc(SwiftMethod) @objcMembers public final class Method: NSObject, SourceryModel, Annotated, Documented, Definition { +@objc(SwiftMethod) @objcMembers +public final class Method: NSObject, SourceryModel, Annotated, Documented, Definition, Diffable { /// Full method name, including generic constraints, i.e. `foo(bar: T)` public let name: String @@ -397,28 +202,163 @@ extension Array where Element == ClosureParameter { self.definedInTypeName = definedInTypeName } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "selectorName = \(String(describing: self.selectorName)), " + string += "parameters = \(String(describing: self.parameters)), " + string += "returnTypeName = \(String(describing: self.returnTypeName)), " + string += "isAsync = \(String(describing: self.isAsync)), " + string += "`throws` = \(String(describing: self.`throws`)), " + string += "`rethrows` = \(String(describing: self.`rethrows`)), " + string += "accessLevel = \(String(describing: self.accessLevel)), " + string += "isStatic = \(String(describing: self.isStatic)), " + string += "isClass = \(String(describing: self.isClass)), " + string += "isFailableInitializer = \(String(describing: self.isFailableInitializer)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "documentation = \(String(describing: self.documentation)), " + string += "definedInTypeName = \(String(describing: self.definedInTypeName)), " + string += "attributes = \(String(describing: self.attributes)), " + string += "modifiers = \(String(describing: self.modifiers))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Method else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "selectorName").trackDifference(actual: self.selectorName, expected: castObject.selectorName)) + results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) + results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "`rethrows`").trackDifference(actual: self.`rethrows`, expected: castObject.`rethrows`)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) + results.append(contentsOf: DiffableResult(identifier: "isClass").trackDifference(actual: self.isClass, expected: castObject.isClass)) + results.append(contentsOf: DiffableResult(identifier: "isFailableInitializer").trackDifference(actual: self.isFailableInitializer, expected: castObject.isFailableInitializer)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.selectorName) + hasher.combine(self.parameters) + hasher.combine(self.returnTypeName) + hasher.combine(self.isAsync) + hasher.combine(self.`throws`) + hasher.combine(self.`rethrows`) + hasher.combine(self.accessLevel) + hasher.combine(self.isStatic) + hasher.combine(self.isClass) + hasher.combine(self.isFailableInitializer) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.definedInTypeName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Method else { return false } + if self.name != rhs.name { return false } + if self.selectorName != rhs.selectorName { return false } + if self.parameters != rhs.parameters { return false } + if self.returnTypeName != rhs.returnTypeName { return false } + if self.isAsync != rhs.isAsync { return false } + if self.`throws` != rhs.`throws` { return false } + if self.`rethrows` != rhs.`rethrows` { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.isStatic != rhs.isStatic { return false } + if self.isClass != rhs.isClass { return false } + if self.isFailableInitializer != rhs.isFailableInitializer { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + return true + } + // sourcery:inline:Method.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let selectorName: String = aDecoder.decode(forKey: "selectorName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["selectorName"])); fatalError() }; self.selectorName = selectorName - guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["parameters"])); fatalError() }; self.parameters = parameters - guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["returnTypeName"])); fatalError() }; self.returnTypeName = returnTypeName + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let selectorName: String = aDecoder.decode(forKey: "selectorName") else { + withVaList(["selectorName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.selectorName = selectorName + guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { + withVaList(["parameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.parameters = parameters + guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { + withVaList(["returnTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.returnTypeName = returnTypeName self.returnType = aDecoder.decode(forKey: "returnType") self.isAsync = aDecoder.decode(forKey: "isAsync") self.`throws` = aDecoder.decode(forKey: "`throws`") self.`rethrows` = aDecoder.decode(forKey: "`rethrows`") - guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["accessLevel"])); fatalError() }; self.accessLevel = accessLevel + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel self.isStatic = aDecoder.decode(forKey: "isStatic") self.isClass = aDecoder.decode(forKey: "isClass") self.isFailableInitializer = aDecoder.decode(forKey: "isFailableInitializer") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["documentation"])); fatalError() }; self.documentation = documentation + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") self.definedInType = aDecoder.decode(forKey: "definedInType") - guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["attributes"])); fatalError() }; self.attributes = attributes - guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiers"])); fatalError() }; self.modifiers = modifiers + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers } /// :nodoc: @@ -444,3 +384,4 @@ extension Array where Element == ClosureParameter { } // sourcery:end } +#endif diff --git a/SourceryRuntime/Sources/AST/MethodParameter.swift b/SourceryRuntime/Sources/AST/MethodParameter.swift new file mode 100644 index 000000000..0ddaa1729 --- /dev/null +++ b/SourceryRuntime/Sources/AST/MethodParameter.swift @@ -0,0 +1,180 @@ +#if canImport(ObjectiveC) +import Foundation + +/// Describes method parameter +@objcMembers +public class MethodParameter: NSObject, SourceryModel, Typed, Annotated, Diffable { + /// Parameter external name + public var argumentLabel: String? + + // Note: although method parameter can have no name, this property is not optional, + // this is so to maintain compatibility with existing templates. + /// Parameter internal name + public let name: String + + /// Parameter type name + public let typeName: TypeName + + /// Parameter flag whether it's inout or not + public let `inout`: Bool + + /// Is this variadic parameter? + public let isVariadic: Bool + + // sourcery: skipEquality, skipDescription + /// Parameter type, if known + public var type: Type? + + /// Parameter type attributes, i.e. `@escaping` + public var typeAttributes: AttributeList { + return typeName.attributes + } + + /// Method parameter default value expression + public var defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + + /// :nodoc: + public init(argumentLabel: String?, name: String = "", typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false, isVariadic: Bool = false) { + self.typeName = typeName + self.argumentLabel = argumentLabel + self.name = name + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + self.`inout` = isInout + self.isVariadic = isVariadic + } + + /// :nodoc: + public init(name: String = "", typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false, isVariadic: Bool = false) { + self.typeName = typeName + self.argumentLabel = name + self.name = name + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + self.`inout` = isInout + self.isVariadic = isVariadic + } + + public var asSource: String { + let typeSuffix = ": \(`inout` ? "inout " : "")\(typeName.asSource)\(defaultValue.map { " = \($0)" } ?? "")" + (isVariadic ? "..." : "") + guard argumentLabel != name else { + return name + typeSuffix + } + + let labels = [argumentLabel ?? "_", name.nilIfEmpty] + .compactMap { $0 } + .joined(separator: " ") + + return (labels.nilIfEmpty ?? "_") + typeSuffix + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "argumentLabel = \(String(describing: self.argumentLabel)), " + string += "name = \(String(describing: self.name)), " + string += "typeName = \(String(describing: self.typeName)), " + string += "`inout` = \(String(describing: self.`inout`)), " + string += "isVariadic = \(String(describing: self.isVariadic)), " + string += "typeAttributes = \(String(describing: self.typeAttributes)), " + string += "defaultValue = \(String(describing: self.defaultValue)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "asSource = \(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? MethodParameter else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "argumentLabel").trackDifference(actual: self.argumentLabel, expected: castObject.argumentLabel)) + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "`inout`").trackDifference(actual: self.`inout`, expected: castObject.`inout`)) + results.append(contentsOf: DiffableResult(identifier: "isVariadic").trackDifference(actual: self.isVariadic, expected: castObject.isVariadic)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.argumentLabel) + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.`inout`) + hasher.combine(self.isVariadic) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? MethodParameter else { return false } + if self.argumentLabel != rhs.argumentLabel { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.`inout` != rhs.`inout` { return false } + if self.isVariadic != rhs.isVariadic { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true + } + +// sourcery:inline:MethodParameter.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.argumentLabel = aDecoder.decode(forKey: "argumentLabel") + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.`inout` = aDecoder.decode(forKey: "`inout`") + self.isVariadic = aDecoder.decode(forKey: "isVariadic") + self.type = aDecoder.decode(forKey: "type") + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.argumentLabel, forKey: "argumentLabel") + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.`inout`, forKey: "`inout`") + aCoder.encode(self.isVariadic, forKey: "isVariadic") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + } +// sourcery:end +} + +extension Array where Element == MethodParameter { + public var asSource: String { + "(\(map { $0.asSource }.joined(separator: ", ")))" + } +} +#endif diff --git a/SourceryRuntime/Sources/AST/MethodParameter_Linux.swift b/SourceryRuntime/Sources/AST/MethodParameter_Linux.swift new file mode 100644 index 000000000..262c561b3 --- /dev/null +++ b/SourceryRuntime/Sources/AST/MethodParameter_Linux.swift @@ -0,0 +1,199 @@ +#if !canImport(ObjectiveC) +import Foundation +// For DynamicMemberLookup we need to import Stencil, +// however, this is different from SourceryRuntime.content.generated.swift, because +// it cannot reference Stencil +import Stencil + +/// Describes method parameter +public class MethodParameter: NSObject, SourceryModel, Typed, Annotated, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "argumentLabel": + return argumentLabel + case "name": + return name + case "typeName": + return typeName + case "isClosure": + return isClosure + case "typeAttributes": + return typeAttributes + default: + fatalError("unable to lookup: \(member) in \(self)") + } + } + /// Parameter external name + public var argumentLabel: String? + + // Note: although method parameter can have no name, this property is not optional, + // this is so to maintain compatibility with existing templates. + /// Parameter internal name + public let name: String + + /// Parameter type name + public let typeName: TypeName + + /// Parameter flag whether it's inout or not + public let `inout`: Bool + + /// Is this variadic parameter? + public let isVariadic: Bool + + // sourcery: skipEquality, skipDescription + /// Parameter type, if known + public var type: Type? + + /// Parameter type attributes, i.e. `@escaping` + public var typeAttributes: AttributeList { + return typeName.attributes + } + + /// Method parameter default value expression + public var defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + + /// :nodoc: + public init(argumentLabel: String?, name: String = "", typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false, isVariadic: Bool = false) { + self.typeName = typeName + self.argumentLabel = argumentLabel + self.name = name + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + self.`inout` = isInout + self.isVariadic = isVariadic + } + + /// :nodoc: + public init(name: String = "", typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false, isVariadic: Bool = false) { + self.typeName = typeName + self.argumentLabel = name + self.name = name + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + self.`inout` = isInout + self.isVariadic = isVariadic + } + + public var asSource: String { + let typeSuffix = ": \(`inout` ? "inout " : "")\(typeName.asSource)\(defaultValue.map { " = \($0)" } ?? "")" + (isVariadic ? "..." : "") + guard argumentLabel != name else { + return name + typeSuffix + } + + let labels = [argumentLabel ?? "_", name.nilIfEmpty] + .compactMap { $0 } + .joined(separator: " ") + + return (labels.nilIfEmpty ?? "_") + typeSuffix + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "argumentLabel = \(String(describing: self.argumentLabel)), " + string += "name = \(String(describing: self.name)), " + string += "typeName = \(String(describing: self.typeName)), " + string += "`inout` = \(String(describing: self.`inout`)), " + string += "isVariadic = \(String(describing: self.isVariadic)), " + string += "typeAttributes = \(String(describing: self.typeAttributes)), " + string += "defaultValue = \(String(describing: self.defaultValue)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "asSource = \(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? MethodParameter else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "argumentLabel").trackDifference(actual: self.argumentLabel, expected: castObject.argumentLabel)) + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "`inout`").trackDifference(actual: self.`inout`, expected: castObject.`inout`)) + results.append(contentsOf: DiffableResult(identifier: "isVariadic").trackDifference(actual: self.isVariadic, expected: castObject.isVariadic)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.argumentLabel) + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.`inout`) + hasher.combine(self.isVariadic) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? MethodParameter else { return false } + if self.argumentLabel != rhs.argumentLabel { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.`inout` != rhs.`inout` { return false } + if self.isVariadic != rhs.isVariadic { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true + } + +// sourcery:inline:MethodParameter.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.argumentLabel = aDecoder.decode(forKey: "argumentLabel") + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.`inout` = aDecoder.decode(forKey: "`inout`") + self.isVariadic = aDecoder.decode(forKey: "isVariadic") + self.type = aDecoder.decode(forKey: "type") + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.argumentLabel, forKey: "argumentLabel") + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.`inout`, forKey: "`inout`") + aCoder.encode(self.isVariadic, forKey: "isVariadic") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + } +// sourcery:end +} + +extension Array where Element == MethodParameter { + public var asSource: String { + "(\(map { $0.asSource }.joined(separator: ", ")))" + } +} +#endif diff --git a/SourceryRuntime/Sources/AST/Method_Linux.swift b/SourceryRuntime/Sources/AST/Method_Linux.swift new file mode 100644 index 000000000..d2f4df2e9 --- /dev/null +++ b/SourceryRuntime/Sources/AST/Method_Linux.swift @@ -0,0 +1,424 @@ +#if !canImport(ObjectiveC) +import Foundation +// For DynamicMemberLookup we need to import Stencil, +// however, this is different from SourceryRuntime.content.generated.swift, because +// it cannot reference Stencil +import Stencil + +/// :nodoc: +public typealias SourceryMethod = Method + +/// Describes method +public final class Method: NSObject, SourceryModel, Annotated, Documented, Definition, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "definedInType": + return definedInType + case "shortName": + return shortName + case "name": + return name + case "selectorName": + return selectorName + case "callName": + return callName + case "parameters": + return parameters + case "throws": + return `throws` + case "isInitializer": + return isInitializer + case "accessLevel": + return accessLevel + case "isStatic": + return isStatic + case "returnTypeName": + return returnTypeName + case "isAsync": + return isAsync + case "attributes": + return attributes + case "isOptionalReturnType": + return isOptionalReturnType + default: + fatalError("unable to lookup: \(member) in \(self)") + } + } + + /// Full method name, including generic constraints, i.e. `foo(bar: T)` + public let name: String + + /// Method name including arguments names, i.e. `foo(bar:)` + public var selectorName: String + + // sourcery: skipEquality, skipDescription + /// Method name without arguments names and parenthesis, i.e. `foo` + public var shortName: String { + return name.range(of: "(").map({ String(name[..<$0.lowerBound]) }) ?? name + } + + // sourcery: skipEquality, skipDescription + /// Method name without arguments names, parenthesis and generic types, i.e. `foo` (can be used to generate code for method call) + public var callName: String { + return shortName.range(of: "<").map({ String(shortName[..<$0.lowerBound]) }) ?? shortName + } + + /// Method parameters + public var parameters: [MethodParameter] + + /// Return value type name used in declaration, including generic constraints, i.e. `where T: Equatable` + public var returnTypeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Actual return value type name if declaration uses typealias, otherwise just a `returnTypeName` + public var actualReturnTypeName: TypeName { + return returnTypeName.actualTypeName ?? returnTypeName + } + + // sourcery: skipEquality, skipDescription + /// Actual return value type, if known + public var returnType: Type? + + // sourcery: skipEquality, skipDescription + /// Whether return value type is optional + public var isOptionalReturnType: Bool { + return returnTypeName.isOptional || isFailableInitializer + } + + // sourcery: skipEquality, skipDescription + /// Whether return value type is implicitly unwrapped optional + public var isImplicitlyUnwrappedOptionalReturnType: Bool { + return returnTypeName.isImplicitlyUnwrappedOptional + } + + // sourcery: skipEquality, skipDescription + /// Return value type name without attributes and optional type information + public var unwrappedReturnTypeName: String { + return returnTypeName.unwrappedTypeName + } + + /// Whether method is async method + public let isAsync: Bool + + /// Whether method throws + public let `throws`: Bool + + /// Whether method rethrows + public let `rethrows`: Bool + + /// Method access level, i.e. `internal`, `private`, `fileprivate`, `public`, `open` + public let accessLevel: String + + /// Whether method is a static method + public let isStatic: Bool + + /// Whether method is a class method + public let isClass: Bool + + // sourcery: skipEquality, skipDescription + /// Whether method is an initializer + public var isInitializer: Bool { + return selectorName.hasPrefix("init(") || selectorName == "init" + } + + // sourcery: skipEquality, skipDescription + /// Whether method is an deinitializer + public var isDeinitializer: Bool { + return selectorName == "deinit" + } + + /// Whether method is a failable initializer + public let isFailableInitializer: Bool + + // sourcery: skipEquality, skipDescription + /// Whether method is a convenience initializer + public var isConvenienceInitializer: Bool { + modifiers.contains { $0.name == "convenience" } + } + + // sourcery: skipEquality, skipDescription + /// Whether method is required + public var isRequired: Bool { + modifiers.contains { $0.name == "required" } + } + + // sourcery: skipEquality, skipDescription + /// Whether method is final + public var isFinal: Bool { + modifiers.contains { $0.name == "final" } + } + + // sourcery: skipEquality, skipDescription + /// Whether method is mutating + public var isMutating: Bool { + modifiers.contains { $0.name == "mutating" } + } + + // sourcery: skipEquality, skipDescription + /// Whether method is generic + public var isGeneric: Bool { + shortName.hasSuffix(">") + } + + // sourcery: skipEquality, skipDescription + /// Whether method is optional (in an Objective-C protocol) + public var isOptional: Bool { + modifiers.contains { $0.name == "optional" } + } + + // sourcery: skipEquality, skipDescription + /// Whether method is nonisolated (this modifier only applies to actor methods) + public var isNonisolated: Bool { + modifiers.contains { $0.name == "nonisolated" } + } + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public let annotations: Annotations + + public let documentation: Documentation + + /// Reference to type name where the method is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc + public let definedInTypeName: TypeName? + + // sourcery: skipEquality, skipDescription + /// Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a `definedInTypeName` + public var actualDefinedInTypeName: TypeName? { + return definedInTypeName?.actualTypeName ?? definedInTypeName + } + + // sourcery: skipEquality, skipDescription + /// Reference to actual type where the object is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc or type is unknown + public var definedInType: Type? + + /// Method attributes, i.e. `@discardableResult` + public let attributes: AttributeList + + /// Method modifiers, i.e. `private` + public let modifiers: [SourceryModifier] + + // Underlying parser data, never to be used by anything else + // sourcery: skipEquality, skipDescription, skipCoding, skipJSExport + /// :nodoc: + public var __parserData: Any? + + /// :nodoc: + public init(name: String, + selectorName: String? = nil, + parameters: [MethodParameter] = [], + returnTypeName: TypeName = TypeName(name: "Void"), + isAsync: Bool = false, + throws: Bool = false, + rethrows: Bool = false, + accessLevel: AccessLevel = .internal, + isStatic: Bool = false, + isClass: Bool = false, + isFailableInitializer: Bool = false, + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + definedInTypeName: TypeName? = nil) { + + self.name = name + self.selectorName = selectorName ?? name + self.parameters = parameters + self.returnTypeName = returnTypeName + self.isAsync = isAsync + self.throws = `throws` + self.rethrows = `rethrows` + self.accessLevel = accessLevel.rawValue + self.isStatic = isStatic + self.isClass = isClass + self.isFailableInitializer = isFailableInitializer + self.attributes = attributes + self.modifiers = modifiers + self.annotations = annotations + self.documentation = documentation + self.definedInTypeName = definedInTypeName + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "selectorName = \(String(describing: self.selectorName)), " + string += "parameters = \(String(describing: self.parameters)), " + string += "returnTypeName = \(String(describing: self.returnTypeName)), " + string += "isAsync = \(String(describing: self.isAsync)), " + string += "`throws` = \(String(describing: self.`throws`)), " + string += "`rethrows` = \(String(describing: self.`rethrows`)), " + string += "accessLevel = \(String(describing: self.accessLevel)), " + string += "isStatic = \(String(describing: self.isStatic)), " + string += "isClass = \(String(describing: self.isClass)), " + string += "isFailableInitializer = \(String(describing: self.isFailableInitializer)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "documentation = \(String(describing: self.documentation)), " + string += "definedInTypeName = \(String(describing: self.definedInTypeName)), " + string += "attributes = \(String(describing: self.attributes)), " + string += "modifiers = \(String(describing: self.modifiers))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Method else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "selectorName").trackDifference(actual: self.selectorName, expected: castObject.selectorName)) + results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) + results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "`rethrows`").trackDifference(actual: self.`rethrows`, expected: castObject.`rethrows`)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) + results.append(contentsOf: DiffableResult(identifier: "isClass").trackDifference(actual: self.isClass, expected: castObject.isClass)) + results.append(contentsOf: DiffableResult(identifier: "isFailableInitializer").trackDifference(actual: self.isFailableInitializer, expected: castObject.isFailableInitializer)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.selectorName) + hasher.combine(self.parameters) + hasher.combine(self.returnTypeName) + hasher.combine(self.isAsync) + hasher.combine(self.`throws`) + hasher.combine(self.`rethrows`) + hasher.combine(self.accessLevel) + hasher.combine(self.isStatic) + hasher.combine(self.isClass) + hasher.combine(self.isFailableInitializer) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.definedInTypeName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Method else { return false } + if self.name != rhs.name { return false } + if self.selectorName != rhs.selectorName { return false } + if self.parameters != rhs.parameters { return false } + if self.returnTypeName != rhs.returnTypeName { return false } + if self.isAsync != rhs.isAsync { return false } + if self.`throws` != rhs.`throws` { return false } + if self.`rethrows` != rhs.`rethrows` { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.isStatic != rhs.isStatic { return false } + if self.isClass != rhs.isClass { return false } + if self.isFailableInitializer != rhs.isFailableInitializer { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + return true + } + +// sourcery:inline:Method.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let selectorName: String = aDecoder.decode(forKey: "selectorName") else { + withVaList(["selectorName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.selectorName = selectorName + guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { + withVaList(["parameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.parameters = parameters + guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { + withVaList(["returnTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.returnTypeName = returnTypeName + self.returnType = aDecoder.decode(forKey: "returnType") + self.isAsync = aDecoder.decode(forKey: "isAsync") + self.`throws` = aDecoder.decode(forKey: "`throws`") + self.`rethrows` = aDecoder.decode(forKey: "`rethrows`") + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel + self.isStatic = aDecoder.decode(forKey: "isStatic") + self.isClass = aDecoder.decode(forKey: "isClass") + self.isFailableInitializer = aDecoder.decode(forKey: "isFailableInitializer") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") + self.definedInType = aDecoder.decode(forKey: "definedInType") + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.selectorName, forKey: "selectorName") + aCoder.encode(self.parameters, forKey: "parameters") + aCoder.encode(self.returnTypeName, forKey: "returnTypeName") + aCoder.encode(self.returnType, forKey: "returnType") + aCoder.encode(self.isAsync, forKey: "isAsync") + aCoder.encode(self.`throws`, forKey: "`throws`") + aCoder.encode(self.`rethrows`, forKey: "`rethrows`") + aCoder.encode(self.accessLevel, forKey: "accessLevel") + aCoder.encode(self.isStatic, forKey: "isStatic") + aCoder.encode(self.isClass, forKey: "isClass") + aCoder.encode(self.isFailableInitializer, forKey: "isFailableInitializer") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.definedInTypeName, forKey: "definedInTypeName") + aCoder.encode(self.definedInType, forKey: "definedInType") + aCoder.encode(self.attributes, forKey: "attributes") + aCoder.encode(self.modifiers, forKey: "modifiers") + } +// sourcery:end +} +#endif diff --git a/SourceryRuntime/Sources/AST/Modifier.swift b/SourceryRuntime/Sources/AST/Modifier.swift index 10a88bb3d..26fd8502c 100644 --- a/SourceryRuntime/Sources/AST/Modifier.swift +++ b/SourceryRuntime/Sources/AST/Modifier.swift @@ -3,7 +3,10 @@ import Foundation public typealias SourceryModifier = Modifier /// modifier can be thing like `private`, `class`, `nonmutating` /// if a declaration has modifier like `private(set)` it's name will be `private` and detail will be `set` -@objcMembers public class Modifier: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport { +#if canImport(ObjectiveC) +@objcMembers +#endif +public class Modifier: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport, Diffable { /// The declaration modifier name. public let name: String @@ -24,11 +27,42 @@ public typealias SourceryModifier = Modifier } } + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Modifier else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "detail").trackDifference(actual: self.detail, expected: castObject.detail)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.detail) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Modifier else { return false } + if self.name != rhs.name { return false } + if self.detail != rhs.detail { return false } + return true + } + // sourcery:inline:Modifier.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name self.detail = aDecoder.decode(forKey: "detail") } diff --git a/SourceryRuntime/Sources/AST/NSException_Linux.swift b/SourceryRuntime/Sources/AST/NSException_Linux.swift new file mode 100644 index 000000000..5159647df --- /dev/null +++ b/SourceryRuntime/Sources/AST/NSException_Linux.swift @@ -0,0 +1,17 @@ +#if !canImport(ObjectiveC) +import Foundation + +public class NSException { + static func raise(_ name: String, format: String, arguments: CVaListPointer) { + fatalError ("\(name) exception: \(NSString(format: format, arguments: arguments))") + } + + static func raise(_ name: String) { + fatalError("\(name) exception") + } +} + +public extension NSExceptionName { + static var parseErrorException = "parseErrorException" +} +#endif diff --git a/SourceryRuntime/Sources/AST/Protocol.swift b/SourceryRuntime/Sources/AST/Protocol.swift index 6ca190b11..32dbb01b4 100644 --- a/SourceryRuntime/Sources/AST/Protocol.swift +++ b/SourceryRuntime/Sources/AST/Protocol.swift @@ -12,7 +12,10 @@ import Foundation public typealias SourceryProtocol = Protocol /// Describes Swift protocol -@objcMembers public final class Protocol: Type { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class Protocol: Type { /// Returns "protocol" public override var kind: String { return "protocol" } @@ -69,12 +72,60 @@ public typealias SourceryProtocol = Protocol ) } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \(String(describing: self.kind)), " + string += "associatedTypes = \(String(describing: self.associatedTypes)), " + string += "genericRequirements = \(String(describing: self.genericRequirements))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Protocol else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "associatedTypes").trackDifference(actual: self.associatedTypes, expected: castObject.associatedTypes)) + results.append(contentsOf: DiffableResult(identifier: "genericRequirements").trackDifference(actual: self.genericRequirements, expected: castObject.genericRequirements)) + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.associatedTypes) + hasher.combine(self.genericRequirements) + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Protocol else { return false } + if self.associatedTypes != rhs.associatedTypes { return false } + if self.genericRequirements != rhs.genericRequirements { return false } + return super.isEqual(rhs) + } + // sourcery:inline:Protocol.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let associatedTypes: [String: AssociatedType] = aDecoder.decode(forKey: "associatedTypes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["associatedTypes"])); fatalError() }; self.associatedTypes = associatedTypes - guard let genericRequirements: [GenericRequirement] = aDecoder.decode(forKey: "genericRequirements") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["genericRequirements"])); fatalError() }; self.genericRequirements = genericRequirements + guard let associatedTypes: [String: AssociatedType] = aDecoder.decode(forKey: "associatedTypes") else { + withVaList(["associatedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.associatedTypes = associatedTypes + guard let genericRequirements: [GenericRequirement] = aDecoder.decode(forKey: "genericRequirements") else { + withVaList(["genericRequirements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.genericRequirements = genericRequirements super.init(coder: aDecoder) } diff --git a/SourceryRuntime/Sources/AST/ProtocolComposition.swift b/SourceryRuntime/Sources/AST/ProtocolComposition.swift index 4cff7200f..4ad37c28f 100644 --- a/SourceryRuntime/Sources/AST/ProtocolComposition.swift +++ b/SourceryRuntime/Sources/AST/ProtocolComposition.swift @@ -4,7 +4,10 @@ import Foundation /// Describes a Swift [protocol composition](https://docs.swift.org/swift-book/ReferenceManual/Types.html#ID454). -@objcMembers public final class ProtocolComposition: Type { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class ProtocolComposition: Type { /// Returns "protocolComposition" public override var kind: String { return "protocolComposition" } @@ -50,11 +53,50 @@ import Foundation ) } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \(String(describing: self.kind)), " + string += "composedTypeNames = \(String(describing: self.composedTypeNames))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? ProtocolComposition else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "composedTypeNames").trackDifference(actual: self.composedTypeNames, expected: castObject.composedTypeNames)) + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.composedTypeNames) + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ProtocolComposition else { return false } + if self.composedTypeNames != rhs.composedTypeNames { return false } + return super.isEqual(rhs) + } + // sourcery:inline:ProtocolComposition.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let composedTypeNames: [TypeName] = aDecoder.decode(forKey: "composedTypeNames") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["composedTypeNames"])); fatalError() }; self.composedTypeNames = composedTypeNames + guard let composedTypeNames: [TypeName] = aDecoder.decode(forKey: "composedTypeNames") else { + withVaList(["composedTypeNames"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.composedTypeNames = composedTypeNames self.composedTypes = aDecoder.decode(forKey: "composedTypes") super.init(coder: aDecoder) } diff --git a/SourceryRuntime/Sources/AST/Struct.swift b/SourceryRuntime/Sources/AST/Struct.swift index ce5d002fd..e65f0b59a 100644 --- a/SourceryRuntime/Sources/AST/Struct.swift +++ b/SourceryRuntime/Sources/AST/Struct.swift @@ -10,7 +10,10 @@ import Foundation // sourcery: skipDescription /// Describes Swift struct -@objcMembers public final class Struct: Type { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class Struct: Type { /// Returns "struct" public override var kind: String { return "struct" } @@ -50,6 +53,36 @@ import Foundation ) } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \(String(describing: self.kind))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Struct else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Struct else { return false } + return super.isEqual(rhs) + } + // sourcery:inline:Struct.AutoCoding /// :nodoc: diff --git a/SourceryRuntime/Sources/AST/Subscript.swift b/SourceryRuntime/Sources/AST/Subscript.swift index 07e1cf14d..604513f1f 100644 --- a/SourceryRuntime/Sources/AST/Subscript.swift +++ b/SourceryRuntime/Sources/AST/Subscript.swift @@ -1,7 +1,10 @@ import Foundation /// Describes subscript -@objcMembers public final class Subscript: NSObject, SourceryModel, Annotated, Documented, Definition { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class Subscript: NSObject, SourceryModel, Annotated, Documented, Definition, Diffable { /// Method parameters public var parameters: [MethodParameter] @@ -104,21 +107,127 @@ import Foundation self.definedInTypeName = definedInTypeName } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "parameters = \(String(describing: self.parameters)), " + string += "returnTypeName = \(String(describing: self.returnTypeName)), " + string += "actualReturnTypeName = \(String(describing: self.actualReturnTypeName)), " + string += "isFinal = \(String(describing: self.isFinal)), " + string += "readAccess = \(String(describing: self.readAccess)), " + string += "writeAccess = \(String(describing: self.writeAccess)), " + string += "isMutable = \(String(describing: self.isMutable)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "documentation = \(String(describing: self.documentation)), " + string += "definedInTypeName = \(String(describing: self.definedInTypeName)), " + string += "actualDefinedInTypeName = \(String(describing: self.actualDefinedInTypeName)), " + string += "attributes = \(String(describing: self.attributes)), " + string += "modifiers = \(String(describing: self.modifiers))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Subscript else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) + results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) + results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) + results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.parameters) + hasher.combine(self.returnTypeName) + hasher.combine(self.readAccess) + hasher.combine(self.writeAccess) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.definedInTypeName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Subscript else { return false } + if self.parameters != rhs.parameters { return false } + if self.returnTypeName != rhs.returnTypeName { return false } + if self.readAccess != rhs.readAccess { return false } + if self.writeAccess != rhs.writeAccess { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + return true + } + // sourcery:inline:Subscript.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["parameters"])); fatalError() }; self.parameters = parameters - guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["returnTypeName"])); fatalError() }; self.returnTypeName = returnTypeName + guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { + withVaList(["parameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.parameters = parameters + guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { + withVaList(["returnTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.returnTypeName = returnTypeName self.returnType = aDecoder.decode(forKey: "returnType") - guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["readAccess"])); fatalError() }; self.readAccess = readAccess - guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["writeAccess"])); fatalError() }; self.writeAccess = writeAccess - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["documentation"])); fatalError() }; self.documentation = documentation + guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { + withVaList(["readAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.readAccess = readAccess + guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { + withVaList(["writeAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.writeAccess = writeAccess + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") self.definedInType = aDecoder.decode(forKey: "definedInType") - guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["attributes"])); fatalError() }; self.attributes = attributes - guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiers"])); fatalError() }; self.modifiers = modifiers + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers } /// :nodoc: diff --git a/SourceryRuntime/Sources/AST/Type.swift b/SourceryRuntime/Sources/AST/Type.swift index 898a7a79a..3659f715e 100644 --- a/SourceryRuntime/Sources/AST/Type.swift +++ b/SourceryRuntime/Sources/AST/Type.swift @@ -2,14 +2,17 @@ // Created by Krzysztof Zablocki on 11/09/2016. // Copyright (c) 2016 Pixle. All rights reserved. // - +#if canImport(ObjectiveC) import Foundation +import Stencil /// :nodoc: public typealias AttributeList = [String: [Attribute]] /// Defines Swift type -@objcMembers public class Type: NSObject, SourceryModel, Annotated, Documented { + +@objcMembers +public class Type: NSObject, SourceryModel, Annotated, Documented, Diffable { /// :nodoc: public var module: String? @@ -414,36 +417,246 @@ public typealias AttributeList = [String: [Attribute]] self.rawSubscripts += type.rawSubscripts } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "module = \(String(describing: self.module)), " + string += "imports = \(String(describing: self.imports)), " + string += "allImports = \(String(describing: self.allImports)), " + string += "typealiases = \(String(describing: self.typealiases)), " + string += "isExtension = \(String(describing: self.isExtension)), " + string += "kind = \(String(describing: self.kind)), " + string += "accessLevel = \(String(describing: self.accessLevel)), " + string += "name = \(String(describing: self.name)), " + string += "isUnknownExtension = \(String(describing: self.isUnknownExtension)), " + string += "isGeneric = \(String(describing: self.isGeneric)), " + string += "localName = \(String(describing: self.localName)), " + string += "rawVariables = \(String(describing: self.rawVariables)), " + string += "rawMethods = \(String(describing: self.rawMethods)), " + string += "rawSubscripts = \(String(describing: self.rawSubscripts)), " + string += "initializers = \(String(describing: self.initializers)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "documentation = \(String(describing: self.documentation)), " + string += "staticVariables = \(String(describing: self.staticVariables)), " + string += "staticMethods = \(String(describing: self.staticMethods)), " + string += "classMethods = \(String(describing: self.classMethods)), " + string += "instanceVariables = \(String(describing: self.instanceVariables)), " + string += "instanceMethods = \(String(describing: self.instanceMethods)), " + string += "computedVariables = \(String(describing: self.computedVariables)), " + string += "storedVariables = \(String(describing: self.storedVariables)), " + string += "inheritedTypes = \(String(describing: self.inheritedTypes)), " + string += "inherits = \(String(describing: self.inherits)), " + string += "containedTypes = \(String(describing: self.containedTypes)), " + string += "parentName = \(String(describing: self.parentName)), " + string += "parentTypes = \(String(describing: self.parentTypes)), " + string += "attributes = \(String(describing: self.attributes)), " + string += "modifiers = \(String(describing: self.modifiers)), " + string += "fileName = \(String(describing: self.fileName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Type else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) + results.append(contentsOf: DiffableResult(identifier: "imports").trackDifference(actual: self.imports, expected: castObject.imports)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + results.append(contentsOf: DiffableResult(identifier: "isExtension").trackDifference(actual: self.isExtension, expected: castObject.isExtension)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "isUnknownExtension").trackDifference(actual: self.isUnknownExtension, expected: castObject.isUnknownExtension)) + results.append(contentsOf: DiffableResult(identifier: "isGeneric").trackDifference(actual: self.isGeneric, expected: castObject.isGeneric)) + results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) + results.append(contentsOf: DiffableResult(identifier: "rawVariables").trackDifference(actual: self.rawVariables, expected: castObject.rawVariables)) + results.append(contentsOf: DiffableResult(identifier: "rawMethods").trackDifference(actual: self.rawMethods, expected: castObject.rawMethods)) + results.append(contentsOf: DiffableResult(identifier: "rawSubscripts").trackDifference(actual: self.rawSubscripts, expected: castObject.rawSubscripts)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "inheritedTypes").trackDifference(actual: self.inheritedTypes, expected: castObject.inheritedTypes)) + results.append(contentsOf: DiffableResult(identifier: "inherits").trackDifference(actual: self.inherits, expected: castObject.inherits)) + results.append(contentsOf: DiffableResult(identifier: "containedTypes").trackDifference(actual: self.containedTypes, expected: castObject.containedTypes)) + results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "fileName").trackDifference(actual: self.fileName, expected: castObject.fileName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.module) + hasher.combine(self.imports) + hasher.combine(self.typealiases) + hasher.combine(self.isExtension) + hasher.combine(self.accessLevel) + hasher.combine(self.isUnknownExtension) + hasher.combine(self.isGeneric) + hasher.combine(self.localName) + hasher.combine(self.rawVariables) + hasher.combine(self.rawMethods) + hasher.combine(self.rawSubscripts) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.inheritedTypes) + hasher.combine(self.inherits) + hasher.combine(self.containedTypes) + hasher.combine(self.parentName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.fileName) + hasher.combine(kind) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Type else { return false } + if self.module != rhs.module { return false } + if self.imports != rhs.imports { return false } + if self.typealiases != rhs.typealiases { return false } + if self.isExtension != rhs.isExtension { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.isUnknownExtension != rhs.isUnknownExtension { return false } + if self.isGeneric != rhs.isGeneric { return false } + if self.localName != rhs.localName { return false } + if self.rawVariables != rhs.rawVariables { return false } + if self.rawMethods != rhs.rawMethods { return false } + if self.rawSubscripts != rhs.rawSubscripts { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.inheritedTypes != rhs.inheritedTypes { return false } + if self.inherits != rhs.inherits { return false } + if self.containedTypes != rhs.containedTypes { return false } + if self.parentName != rhs.parentName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.fileName != rhs.fileName { return false } + if self.kind != rhs.kind { return false } + return true + } + // sourcery:inline:Type.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { self.module = aDecoder.decode(forKey: "module") - guard let imports: [Import] = aDecoder.decode(forKey: "imports") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["imports"])); fatalError() }; self.imports = imports - guard let typealiases: [String: Typealias] = aDecoder.decode(forKey: "typealiases") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typealiases"])); fatalError() }; self.typealiases = typealiases + guard let imports: [Import] = aDecoder.decode(forKey: "imports") else { + withVaList(["imports"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.imports = imports + guard let typealiases: [String: Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases self.isExtension = aDecoder.decode(forKey: "isExtension") - guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["accessLevel"])); fatalError() }; self.accessLevel = accessLevel + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel self.isGeneric = aDecoder.decode(forKey: "isGeneric") - guard let localName: String = aDecoder.decode(forKey: "localName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["localName"])); fatalError() }; self.localName = localName - guard let rawVariables: [Variable] = aDecoder.decode(forKey: "rawVariables") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["rawVariables"])); fatalError() }; self.rawVariables = rawVariables - guard let rawMethods: [Method] = aDecoder.decode(forKey: "rawMethods") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["rawMethods"])); fatalError() }; self.rawMethods = rawMethods - guard let rawSubscripts: [Subscript] = aDecoder.decode(forKey: "rawSubscripts") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["rawSubscripts"])); fatalError() }; self.rawSubscripts = rawSubscripts + guard let localName: String = aDecoder.decode(forKey: "localName") else { + withVaList(["localName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.localName = localName + guard let rawVariables: [Variable] = aDecoder.decode(forKey: "rawVariables") else { + withVaList(["rawVariables"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawVariables = rawVariables + guard let rawMethods: [Method] = aDecoder.decode(forKey: "rawMethods") else { + withVaList(["rawMethods"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawMethods = rawMethods + guard let rawSubscripts: [Subscript] = aDecoder.decode(forKey: "rawSubscripts") else { + withVaList(["rawSubscripts"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawSubscripts = rawSubscripts self.bodyBytesRange = aDecoder.decode(forKey: "bodyBytesRange") self.completeDeclarationRange = aDecoder.decode(forKey: "completeDeclarationRange") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["documentation"])); fatalError() }; self.documentation = documentation - guard let inheritedTypes: [String] = aDecoder.decode(forKey: "inheritedTypes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["inheritedTypes"])); fatalError() }; self.inheritedTypes = inheritedTypes - guard let based: [String: String] = aDecoder.decode(forKey: "based") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["based"])); fatalError() }; self.based = based - guard let basedTypes: [String: Type] = aDecoder.decode(forKey: "basedTypes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["basedTypes"])); fatalError() }; self.basedTypes = basedTypes - guard let inherits: [String: Type] = aDecoder.decode(forKey: "inherits") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["inherits"])); fatalError() }; self.inherits = inherits - guard let implements: [String: Type] = aDecoder.decode(forKey: "implements") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["implements"])); fatalError() }; self.implements = implements - guard let containedTypes: [Type] = aDecoder.decode(forKey: "containedTypes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["containedTypes"])); fatalError() }; self.containedTypes = containedTypes - guard let containedType: [String: Type] = aDecoder.decode(forKey: "containedType") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["containedType"])); fatalError() }; self.containedType = containedType + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + guard let inheritedTypes: [String] = aDecoder.decode(forKey: "inheritedTypes") else { + withVaList(["inheritedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inheritedTypes = inheritedTypes + guard let based: [String: String] = aDecoder.decode(forKey: "based") else { + withVaList(["based"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.based = based + guard let basedTypes: [String: Type] = aDecoder.decode(forKey: "basedTypes") else { + withVaList(["basedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.basedTypes = basedTypes + guard let inherits: [String: Type] = aDecoder.decode(forKey: "inherits") else { + withVaList(["inherits"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inherits = inherits + guard let implements: [String: Type] = aDecoder.decode(forKey: "implements") else { + withVaList(["implements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.implements = implements + guard let containedTypes: [Type] = aDecoder.decode(forKey: "containedTypes") else { + withVaList(["containedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.containedTypes = containedTypes + guard let containedType: [String: Type] = aDecoder.decode(forKey: "containedType") else { + withVaList(["containedType"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.containedType = containedType self.parentName = aDecoder.decode(forKey: "parentName") self.parent = aDecoder.decode(forKey: "parent") self.supertype = aDecoder.decode(forKey: "supertype") - guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["attributes"])); fatalError() }; self.attributes = attributes - guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiers"])); fatalError() }; self.modifiers = modifiers + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers self.path = aDecoder.decode(forKey: "path") self.fileName = aDecoder.decode(forKey: "fileName") } @@ -480,6 +693,7 @@ public typealias AttributeList = [String: [Attribute]] aCoder.encode(self.fileName, forKey: "fileName") } // sourcery:end + } extension Type { @@ -503,3 +717,4 @@ extension Type { return super.value(forUndefinedKey: key) } } +#endif diff --git a/SourceryRuntime/Sources/AST/TypeName/Array.swift b/SourceryRuntime/Sources/AST/TypeName/Array.swift index 76e0d16b8..9b8c25e98 100644 --- a/SourceryRuntime/Sources/AST/TypeName/Array.swift +++ b/SourceryRuntime/Sources/AST/TypeName/Array.swift @@ -1,8 +1,10 @@ import Foundation /// Describes array type -@objcMembers public final class ArrayType: NSObject, SourceryModel { - +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class ArrayType: NSObject, SourceryModel, Diffable { /// Type name used in declaration public var name: String @@ -31,12 +33,58 @@ import Foundation "[\(elementTypeName.asSource)]" } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "elementTypeName = \(String(describing: self.elementTypeName)), " + string += "asGeneric = \(String(describing: self.asGeneric)), " + string += "asSource = \(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? ArrayType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "elementTypeName").trackDifference(actual: self.elementTypeName, expected: castObject.elementTypeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.elementTypeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ArrayType else { return false } + if self.name != rhs.name { return false } + if self.elementTypeName != rhs.elementTypeName { return false } + return true + } + // sourcery:inline:ArrayType.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let elementTypeName: TypeName = aDecoder.decode(forKey: "elementTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["elementTypeName"])); fatalError() }; self.elementTypeName = elementTypeName + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let elementTypeName: TypeName = aDecoder.decode(forKey: "elementTypeName") else { + withVaList(["elementTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.elementTypeName = elementTypeName self.elementType = aDecoder.decode(forKey: "elementType") } diff --git a/SourceryRuntime/Sources/AST/TypeName/Closure.swift b/SourceryRuntime/Sources/AST/TypeName/Closure.swift index 9299932db..c5f15b052 100644 --- a/SourceryRuntime/Sources/AST/TypeName/Closure.swift +++ b/SourceryRuntime/Sources/AST/TypeName/Closure.swift @@ -1,7 +1,10 @@ import Foundation /// Describes closure type -@objcMembers public final class ClosureType: NSObject, SourceryModel { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class ClosureType: NSObject, SourceryModel, Diffable { /// Type name used in declaration with stripped whitespaces and new lines public let name: String @@ -67,13 +70,84 @@ import Foundation "\(parameters.asSource)\(asyncKeyword != nil ? " \(asyncKeyword!)" : "")\(throwsOrRethrowsKeyword != nil ? " \(throwsOrRethrowsKeyword!)" : "") -> \(returnTypeName.asSource)" } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "parameters = \(String(describing: self.parameters)), " + string += "returnTypeName = \(String(describing: self.returnTypeName)), " + string += "actualReturnTypeName = \(String(describing: self.actualReturnTypeName)), " + string += "isAsync = \(String(describing: self.isAsync)), " + string += "asyncKeyword = \(String(describing: self.asyncKeyword)), " + string += "`throws` = \(String(describing: self.`throws`)), " + string += "throwsOrRethrowsKeyword = \(String(describing: self.throwsOrRethrowsKeyword)), " + string += "asSource = \(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? ClosureType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) + results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "asyncKeyword").trackDifference(actual: self.asyncKeyword, expected: castObject.asyncKeyword)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "throwsOrRethrowsKeyword").trackDifference(actual: self.throwsOrRethrowsKeyword, expected: castObject.throwsOrRethrowsKeyword)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.parameters) + hasher.combine(self.returnTypeName) + hasher.combine(self.isAsync) + hasher.combine(self.asyncKeyword) + hasher.combine(self.`throws`) + hasher.combine(self.throwsOrRethrowsKeyword) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ClosureType else { return false } + if self.name != rhs.name { return false } + if self.parameters != rhs.parameters { return false } + if self.returnTypeName != rhs.returnTypeName { return false } + if self.isAsync != rhs.isAsync { return false } + if self.asyncKeyword != rhs.asyncKeyword { return false } + if self.`throws` != rhs.`throws` { return false } + if self.throwsOrRethrowsKeyword != rhs.throwsOrRethrowsKeyword { return false } + return true + } + // sourcery:inline:ClosureType.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let parameters: [ClosureParameter] = aDecoder.decode(forKey: "parameters") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["parameters"])); fatalError() }; self.parameters = parameters - guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["returnTypeName"])); fatalError() }; self.returnTypeName = returnTypeName + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let parameters: [ClosureParameter] = aDecoder.decode(forKey: "parameters") else { + withVaList(["parameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.parameters = parameters + guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { + withVaList(["returnTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.returnTypeName = returnTypeName self.returnType = aDecoder.decode(forKey: "returnType") self.isAsync = aDecoder.decode(forKey: "isAsync") self.asyncKeyword = aDecoder.decode(forKey: "asyncKeyword") diff --git a/SourceryRuntime/Sources/AST/TypeName/Dictionary.swift b/SourceryRuntime/Sources/AST/TypeName/Dictionary.swift index 1aa15e866..126657120 100644 --- a/SourceryRuntime/Sources/AST/TypeName/Dictionary.swift +++ b/SourceryRuntime/Sources/AST/TypeName/Dictionary.swift @@ -1,7 +1,10 @@ import Foundation /// Describes dictionary type -@objcMembers public final class DictionaryType: NSObject, SourceryModel { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class DictionaryType: NSObject, SourceryModel, Diffable { /// Type name used in declaration public var name: String @@ -40,14 +43,69 @@ import Foundation "[\(keyTypeName.asSource): \(valueTypeName.asSource)]" } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "valueTypeName = \(String(describing: self.valueTypeName)), " + string += "keyTypeName = \(String(describing: self.keyTypeName)), " + string += "asGeneric = \(String(describing: self.asGeneric)), " + string += "asSource = \(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? DictionaryType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "valueTypeName").trackDifference(actual: self.valueTypeName, expected: castObject.valueTypeName)) + results.append(contentsOf: DiffableResult(identifier: "keyTypeName").trackDifference(actual: self.keyTypeName, expected: castObject.keyTypeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.valueTypeName) + hasher.combine(self.keyTypeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? DictionaryType else { return false } + if self.name != rhs.name { return false } + if self.valueTypeName != rhs.valueTypeName { return false } + if self.keyTypeName != rhs.keyTypeName { return false } + return true + } + // sourcery:inline:DictionaryType.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let valueTypeName: TypeName = aDecoder.decode(forKey: "valueTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["valueTypeName"])); fatalError() }; self.valueTypeName = valueTypeName + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let valueTypeName: TypeName = aDecoder.decode(forKey: "valueTypeName") else { + withVaList(["valueTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.valueTypeName = valueTypeName self.valueType = aDecoder.decode(forKey: "valueType") - guard let keyTypeName: TypeName = aDecoder.decode(forKey: "keyTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["keyTypeName"])); fatalError() }; self.keyTypeName = keyTypeName + guard let keyTypeName: TypeName = aDecoder.decode(forKey: "keyTypeName") else { + withVaList(["keyTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.keyTypeName = keyTypeName self.keyType = aDecoder.decode(forKey: "keyType") } diff --git a/SourceryRuntime/Sources/AST/TypeName/Generic.swift b/SourceryRuntime/Sources/AST/TypeName/Generic.swift index c53794898..d1a6370bd 100644 --- a/SourceryRuntime/Sources/AST/TypeName/Generic.swift +++ b/SourceryRuntime/Sources/AST/TypeName/Generic.swift @@ -1,7 +1,10 @@ import Foundation /// Descibes Swift generic type -@objcMembers public final class GenericType: NSObject, SourceryModelWithoutDescription { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class GenericType: NSObject, SourceryModelWithoutDescription, Diffable { /// The name of the base type, i.e. `Array` for `Array` public var name: String @@ -25,12 +28,48 @@ import Foundation asSource } + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? GenericType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeParameters").trackDifference(actual: self.typeParameters, expected: castObject.typeParameters)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeParameters) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? GenericType else { return false } + if self.name != rhs.name { return false } + if self.typeParameters != rhs.typeParameters { return false } + return true + } + // sourcery:inline:GenericType.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let typeParameters: [GenericTypeParameter] = aDecoder.decode(forKey: "typeParameters") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeParameters"])); fatalError() }; self.typeParameters = typeParameters + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeParameters: [GenericTypeParameter] = aDecoder.decode(forKey: "typeParameters") else { + withVaList(["typeParameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeParameters = typeParameters } /// :nodoc: @@ -43,7 +82,10 @@ import Foundation } /// Descibes Swift generic type parameter -@objcMembers public final class GenericTypeParameter: NSObject, SourceryModel { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class GenericTypeParameter: NSObject, SourceryModel, Diffable { /// Generic parameter type name public var typeName: TypeName @@ -58,11 +100,46 @@ import Foundation self.type = type } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "typeName = \(String(describing: self.typeName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? GenericTypeParameter else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.typeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? GenericTypeParameter else { return false } + if self.typeName != rhs.typeName { return false } + return true + } + // sourcery:inline:GenericTypeParameter.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName self.type = aDecoder.decode(forKey: "type") } diff --git a/SourceryRuntime/Sources/AST/TypeName/Tuple.swift b/SourceryRuntime/Sources/AST/TypeName/Tuple.swift index 89fa509d5..7db544efb 100644 --- a/SourceryRuntime/Sources/AST/TypeName/Tuple.swift +++ b/SourceryRuntime/Sources/AST/TypeName/Tuple.swift @@ -1,7 +1,9 @@ +#if canImport(ObjectiveC) import Foundation /// Describes tuple type -@objcMembers public final class TupleType: NSObject, SourceryModel { +@objcMembers +public final class TupleType: NSObject, SourceryModel, Diffable { /// Type name used in declaration public var name: String @@ -21,12 +23,56 @@ import Foundation self.elements = elements } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "elements = \(String(describing: self.elements))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TupleType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "elements").trackDifference(actual: self.elements, expected: castObject.elements)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.elements) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TupleType else { return false } + if self.name != rhs.name { return false } + if self.elements != rhs.elements { return false } + return true + } + // sourcery:inline:TupleType.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let elements: [TupleElement] = aDecoder.decode(forKey: "elements") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["elements"])); fatalError() }; self.elements = elements + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let elements: [TupleElement] = aDecoder.decode(forKey: "elements") else { + withVaList(["elements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.elements = elements } /// :nodoc: @@ -38,7 +84,8 @@ import Foundation } /// Describes tuple type element -@objcMembers public final class TupleElement: NSObject, SourceryModel, Typed { +@objcMembers +public final class TupleElement: NSObject, SourceryModel, Typed, Diffable { /// Tuple element name public let name: String? @@ -62,12 +109,52 @@ import Foundation "\(name != nil ? "\(name!): " : "")\(typeName.asSource)" } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "typeName = \(String(describing: self.typeName)), " + string += "asSource = \(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TupleElement else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TupleElement else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + return true + } + // sourcery:inline:TupleElement.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { self.name = aDecoder.decode(forKey: "name") - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName self.type = aDecoder.decode(forKey: "type") } @@ -89,3 +176,4 @@ extension Array where Element == TupleElement { "(\(map { $0.typeName.asSource }.joined(separator: ", ")))" } } +#endif diff --git a/SourceryRuntime/Sources/AST/TypeName/Tuple_Linux.swift b/SourceryRuntime/Sources/AST/TypeName/Tuple_Linux.swift new file mode 100644 index 000000000..e1ed0fd8d --- /dev/null +++ b/SourceryRuntime/Sources/AST/TypeName/Tuple_Linux.swift @@ -0,0 +1,201 @@ +#if !canImport(ObjectiveC) +import Foundation +// For DynamicMemberLookup we need to import Stencil, +// however, this is different from SourceryRuntime.content.generated.swift, because +// it cannot reference Stencil +import Stencil + +/// Describes tuple type +public final class TupleType: NSObject, SourceryModel, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "elements": + return elements + default: + fatalError("unable to lookup: \(member) in \(self)") + } + } + + /// Type name used in declaration + public var name: String + + /// Tuple elements + public var elements: [TupleElement] + + /// :nodoc: + public init(name: String, elements: [TupleElement]) { + self.name = name + self.elements = elements + } + + /// :nodoc: + public init(elements: [TupleElement]) { + self.name = elements.asSource + self.elements = elements + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "elements = \(String(describing: self.elements))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TupleType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "elements").trackDifference(actual: self.elements, expected: castObject.elements)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.elements) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TupleType else { return false } + if self.name != rhs.name { return false } + if self.elements != rhs.elements { return false } + return true + } + +// sourcery:inline:TupleType.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let elements: [TupleElement] = aDecoder.decode(forKey: "elements") else { + withVaList(["elements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.elements = elements + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.elements, forKey: "elements") + } +// sourcery:end +} + +/// Describes tuple type element +public final class TupleElement: NSObject, SourceryModel, Typed, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "name": + return name + case "typeName": + return typeName + case "type": + return type + default: + fatalError("unable to lookup: \(member) in \(self)") + } + } + + /// Tuple element name + public let name: String? + + /// Tuple element type name + public var typeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Tuple element type, if known + public var type: Type? + + /// :nodoc: + public init(name: String? = nil, typeName: TypeName, type: Type? = nil) { + self.name = name + self.typeName = typeName + self.type = type + } + + public var asSource: String { + // swiftlint:disable:next force_unwrapping + "\(name != nil ? "\(name!): " : "")\(typeName.asSource)" + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "typeName = \(String(describing: self.typeName)), " + string += "asSource = \(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TupleElement else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TupleElement else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + return true + } + +// sourcery:inline:TupleElement.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.name = aDecoder.decode(forKey: "name") + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.type = aDecoder.decode(forKey: "type") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + } +// sourcery:end +} + +extension Array where Element == TupleElement { + public var asSource: String { + "(\(map { $0.asSource }.joined(separator: ", ")))" + } + + public var asTypeName: String { + "(\(map { $0.typeName.asSource }.joined(separator: ", ")))" + } +} +#endif diff --git a/SourceryRuntime/Sources/AST/TypeName/TypeName.swift b/SourceryRuntime/Sources/AST/TypeName/TypeName.swift index 982edb1d5..589d1b077 100644 --- a/SourceryRuntime/Sources/AST/TypeName/TypeName.swift +++ b/SourceryRuntime/Sources/AST/TypeName/TypeName.swift @@ -2,11 +2,12 @@ // Created by Krzysztof Zabłocki on 25/12/2016. // Copyright (c) 2016 Pixle. All rights reserved. // - +#if canImport(ObjectiveC) import Foundation /// Describes name of the type used in typed declaration (variable, method parameter or return value etc.) -@objcMembers public final class TypeName: NSObject, SourceryModelWithoutDescription, LosslessStringConvertible { +@objcMembers +public final class TypeName: NSObject, SourceryModelWithoutDescription, LosslessStringConvertible, Diffable { /// :nodoc: public init(name: String, actualTypeName: TypeName? = nil, @@ -166,19 +167,86 @@ import Foundation ).joined(separator: " ") } + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TypeName else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "generic").trackDifference(actual: self.generic, expected: castObject.generic)) + results.append(contentsOf: DiffableResult(identifier: "isProtocolComposition").trackDifference(actual: self.isProtocolComposition, expected: castObject.isProtocolComposition)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "tuple").trackDifference(actual: self.tuple, expected: castObject.tuple)) + results.append(contentsOf: DiffableResult(identifier: "array").trackDifference(actual: self.array, expected: castObject.array)) + results.append(contentsOf: DiffableResult(identifier: "dictionary").trackDifference(actual: self.dictionary, expected: castObject.dictionary)) + results.append(contentsOf: DiffableResult(identifier: "closure").trackDifference(actual: self.closure, expected: castObject.closure)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.generic) + hasher.combine(self.isProtocolComposition) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.tuple) + hasher.combine(self.array) + hasher.combine(self.dictionary) + hasher.combine(self.closure) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TypeName else { return false } + if self.name != rhs.name { return false } + if self.generic != rhs.generic { return false } + if self.isProtocolComposition != rhs.isProtocolComposition { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.tuple != rhs.tuple { return false } + if self.array != rhs.array { return false } + if self.dictionary != rhs.dictionary { return false } + if self.closure != rhs.closure { return false } + return true + } + // sourcery:inline:TypeName.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name self.generic = aDecoder.decode(forKey: "generic") self.isProtocolComposition = aDecoder.decode(forKey: "isProtocolComposition") self.actualTypeName = aDecoder.decode(forKey: "actualTypeName") - guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["attributes"])); fatalError() }; self.attributes = attributes - guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiers"])); fatalError() }; self.modifiers = modifiers + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers self.isOptional = aDecoder.decode(forKey: "isOptional") self.isImplicitlyUnwrappedOptional = aDecoder.decode(forKey: "isImplicitlyUnwrappedOptional") - guard let unwrappedTypeName: String = aDecoder.decode(forKey: "unwrappedTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["unwrappedTypeName"])); fatalError() }; self.unwrappedTypeName = unwrappedTypeName + guard let unwrappedTypeName: String = aDecoder.decode(forKey: "unwrappedTypeName") else { + withVaList(["unwrappedTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.unwrappedTypeName = unwrappedTypeName self.tuple = aDecoder.decode(forKey: "tuple") self.array = aDecoder.decode(forKey: "array") self.dictionary = aDecoder.decode(forKey: "dictionary") @@ -224,3 +292,4 @@ extension TypeName { return TypeName(name: "UnknownTypeSoAddTypeAttributionToVariable", attributes: attributes) } } +#endif diff --git a/SourceryRuntime/Sources/AST/TypeName/TypeName_Linux.swift b/SourceryRuntime/Sources/AST/TypeName/TypeName_Linux.swift new file mode 100644 index 000000000..9c742c521 --- /dev/null +++ b/SourceryRuntime/Sources/AST/TypeName/TypeName_Linux.swift @@ -0,0 +1,319 @@ +// +// Created by Krzysztof Zabłocki on 25/12/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// +#if !canImport(ObjectiveC) +import Foundation +// For DynamicMemberLookup we need to import Stencil, +// however, this is different from SourceryRuntime.content.generated.swift, because +// it cannot reference Stencil +import Stencil + +/// Describes name of the type used in typed declaration (variable, method parameter or return value etc.) +public final class TypeName: NSObject, SourceryModelWithoutDescription, LosslessStringConvertible, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "tuple": + return tuple + case "name": + return name + case "isOptional": + return isOptional + case "unwrappedTypeName": + return unwrappedTypeName + case "isProtocolComposition": + return isProtocolComposition + case "isVoid": + return isVoid + case "isClosure": + return isClosure + default: + fatalError("unable to lookup: \(member) in \(self)") + } + } + + /// :nodoc: + public init(name: String, + actualTypeName: TypeName? = nil, + unwrappedTypeName: String? = nil, + attributes: AttributeList = [:], + isOptional: Bool = false, + isImplicitlyUnwrappedOptional: Bool = false, + tuple: TupleType? = nil, + array: ArrayType? = nil, + dictionary: DictionaryType? = nil, + closure: ClosureType? = nil, + generic: GenericType? = nil, + isProtocolComposition: Bool = false) { + + let optionalSuffix: String + // TODO: TBR + if !name.hasPrefix("Optional<") && !name.contains(" where ") { + if isOptional { + optionalSuffix = "?" + } else if isImplicitlyUnwrappedOptional { + optionalSuffix = "!" + } else { + optionalSuffix = "" + } + } else { + optionalSuffix = "" + } + + self.name = name + optionalSuffix + self.actualTypeName = actualTypeName + self.unwrappedTypeName = unwrappedTypeName ?? name + self.tuple = tuple + self.array = array + self.dictionary = dictionary + self.closure = closure + self.generic = generic + self.isOptional = isOptional || isImplicitlyUnwrappedOptional + self.isImplicitlyUnwrappedOptional = isImplicitlyUnwrappedOptional + self.isProtocolComposition = isProtocolComposition + + self.attributes = attributes + self.modifiers = [] + super.init() + } + + /// Type name used in declaration + public var name: String + + /// The generics of this TypeName + public var generic: GenericType? + + /// Whether this TypeName is generic + public var isGeneric: Bool { + actualTypeName?.generic != nil || generic != nil + } + + /// Whether this TypeName is protocol composition + public var isProtocolComposition: Bool + + // sourcery: skipEquality + /// Actual type name if given type name is a typealias + public var actualTypeName: TypeName? + + /// Type name attributes, i.e. `@escaping` + public var attributes: AttributeList + + /// Modifiers, i.e. `escaping` + public var modifiers: [SourceryModifier] + + // sourcery: skipEquality + /// Whether type is optional + public let isOptional: Bool + + // sourcery: skipEquality + /// Whether type is implicitly unwrapped optional + public let isImplicitlyUnwrappedOptional: Bool + + // sourcery: skipEquality + /// Type name without attributes and optional type information + public var unwrappedTypeName: String + + // sourcery: skipEquality + /// Whether type is void (`Void` or `()`) + public var isVoid: Bool { + return name == "Void" || name == "()" || unwrappedTypeName == "Void" + } + + /// Whether type is a tuple + public var isTuple: Bool { + actualTypeName?.tuple != nil || tuple != nil + } + + /// Tuple type data + public var tuple: TupleType? + + /// Whether type is an array + public var isArray: Bool { + actualTypeName?.array != nil || array != nil + } + + /// Array type data + public var array: ArrayType? + + /// Whether type is a dictionary + public var isDictionary: Bool { + actualTypeName?.dictionary != nil || dictionary != nil + } + + /// Dictionary type data + public var dictionary: DictionaryType? + + /// Whether type is a closure + public var isClosure: Bool { + actualTypeName?.closure != nil || closure != nil + } + + /// Closure type data + public var closure: ClosureType? + + /// Prints typename as it would appear on definition + public var asSource: String { + // TODO: TBR special treatment + let specialTreatment = isOptional && name.hasPrefix("Optional<") + + var description = ( + attributes.flatMap({ $0.value }).map({ $0.asSource }).sorted() + + modifiers.map({ $0.asSource }) + + [specialTreatment ? name : unwrappedTypeName] + ).joined(separator: " ") + + if let _ = self.dictionary { // array and dictionary cases are covered by the unwrapped type name +// description.append(dictionary.asSource) + } else if let _ = self.array { +// description.append(array.asSource) + } else if let _ = self.generic { +// let arguments = generic.typeParameters +// .map({ $0.typeName.asSource }) +// .joined(separator: ", ") +// description.append("<\(arguments)>") + } + if !specialTreatment { + if isImplicitlyUnwrappedOptional { + description.append("!") + } else if isOptional { + description.append("?") + } + } + + return description + } + + public override var description: String { + ( + attributes.flatMap({ $0.value }).map({ $0.asSource }).sorted() + + modifiers.map({ $0.asSource }) + + [name] + ).joined(separator: " ") + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TypeName else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "generic").trackDifference(actual: self.generic, expected: castObject.generic)) + results.append(contentsOf: DiffableResult(identifier: "isProtocolComposition").trackDifference(actual: self.isProtocolComposition, expected: castObject.isProtocolComposition)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "tuple").trackDifference(actual: self.tuple, expected: castObject.tuple)) + results.append(contentsOf: DiffableResult(identifier: "array").trackDifference(actual: self.array, expected: castObject.array)) + results.append(contentsOf: DiffableResult(identifier: "dictionary").trackDifference(actual: self.dictionary, expected: castObject.dictionary)) + results.append(contentsOf: DiffableResult(identifier: "closure").trackDifference(actual: self.closure, expected: castObject.closure)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.generic) + hasher.combine(self.isProtocolComposition) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.tuple) + hasher.combine(self.array) + hasher.combine(self.dictionary) + hasher.combine(self.closure) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TypeName else { return false } + if self.name != rhs.name { return false } + if self.generic != rhs.generic { return false } + if self.isProtocolComposition != rhs.isProtocolComposition { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.tuple != rhs.tuple { return false } + if self.array != rhs.array { return false } + if self.dictionary != rhs.dictionary { return false } + if self.closure != rhs.closure { return false } + return true + } + +// sourcery:inline:TypeName.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + self.generic = aDecoder.decode(forKey: "generic") + self.isProtocolComposition = aDecoder.decode(forKey: "isProtocolComposition") + self.actualTypeName = aDecoder.decode(forKey: "actualTypeName") + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers + self.isOptional = aDecoder.decode(forKey: "isOptional") + self.isImplicitlyUnwrappedOptional = aDecoder.decode(forKey: "isImplicitlyUnwrappedOptional") + guard let unwrappedTypeName: String = aDecoder.decode(forKey: "unwrappedTypeName") else { + withVaList(["unwrappedTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.unwrappedTypeName = unwrappedTypeName + self.tuple = aDecoder.decode(forKey: "tuple") + self.array = aDecoder.decode(forKey: "array") + self.dictionary = aDecoder.decode(forKey: "dictionary") + self.closure = aDecoder.decode(forKey: "closure") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.generic, forKey: "generic") + aCoder.encode(self.isProtocolComposition, forKey: "isProtocolComposition") + aCoder.encode(self.actualTypeName, forKey: "actualTypeName") + aCoder.encode(self.attributes, forKey: "attributes") + aCoder.encode(self.modifiers, forKey: "modifiers") + aCoder.encode(self.isOptional, forKey: "isOptional") + aCoder.encode(self.isImplicitlyUnwrappedOptional, forKey: "isImplicitlyUnwrappedOptional") + aCoder.encode(self.unwrappedTypeName, forKey: "unwrappedTypeName") + aCoder.encode(self.tuple, forKey: "tuple") + aCoder.encode(self.array, forKey: "array") + aCoder.encode(self.dictionary, forKey: "dictionary") + aCoder.encode(self.closure, forKey: "closure") + } +// sourcery:end + + // sourcery: skipEquality, skipDescription + /// :nodoc: + public override var debugDescription: String { + return name + } + + public convenience init(_ description: String) { + self.init(name: description, actualTypeName: nil) + } +} + +extension TypeName { + public static func unknown(description: String?, attributes: AttributeList = [:]) -> TypeName { + if let description = description { + Log.astWarning("Unknown type, please add type attribution to \(description)") + } else { + Log.astWarning("Unknown type, please add type attribution") + } + return TypeName(name: "UnknownTypeSoAddTypeAttributionToVariable", attributes: attributes) + } +} +#endif diff --git a/SourceryRuntime/Sources/AST/Type_Linux.swift b/SourceryRuntime/Sources/AST/Type_Linux.swift new file mode 100644 index 000000000..4b3bdcd24 --- /dev/null +++ b/SourceryRuntime/Sources/AST/Type_Linux.swift @@ -0,0 +1,747 @@ +// +// Created by Krzysztof Zablocki on 11/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// +#if !canImport(ObjectiveC) +import Foundation +// For DynamicMemberLookup we need to import Stencil, +// however, this is different from SourceryRuntime.content.generated.swift, because +// it cannot reference Stencil +import Stencil + +/// :nodoc: +public typealias AttributeList = [String: [Attribute]] + +/// Defines Swift type +public class Type: NSObject, SourceryModel, Annotated, Documented, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "implements": + return implements + case "name": + return name + case "kind": + return kind + case "based": + return based + case "supertype": + return supertype + case "accessLevel": + return accessLevel + case "storedVariables": + return storedVariables + case "variables": + return variables + case "allVariables": + return allVariables + case "allMethods": + return allMethods + case "annotations": + return annotations + case "methods": + return methods + case "containedType": + return containedType + case "computedVariables": + return computedVariables + case "inherits": + return inherits + case "inheritedTypes": + return inheritedTypes + default: + fatalError("unable to lookup: \(member) in \(self)") + } + } + + /// :nodoc: + public var module: String? + + /// Imports that existed in the file that contained this type declaration + public var imports: [Import] = [] + + // sourcery: skipEquality + /// Imports existed in all files containing this type and all its super classes/protocols + public var allImports: [Import] { + return self.unique({ $0.gatherAllImports() }, filter: { $0 == $1 }) + } + + private func gatherAllImports() -> [Import] { + var allImports: [Import] = Array(self.imports) + + self.basedTypes.values.forEach { (basedType) in + allImports.append(contentsOf: basedType.imports) + } + return allImports + } + + // All local typealiases + // sourcery: skipJSExport + /// :nodoc: + public var typealiases: [String: Typealias] { + didSet { + typealiases.values.forEach { $0.parent = self } + } + } + + // sourcery: skipJSExport + /// Whether declaration is an extension of some type + public var isExtension: Bool + + // sourcery: forceEquality + /// Kind of type declaration, i.e. `enum`, `struct`, `class`, `protocol` or `extension` + public var kind: String { return isExtension ? "extension" : "unknown" } + + /// Type access level, i.e. `internal`, `private`, `fileprivate`, `public`, `open` + public let accessLevel: String + + /// Type name in global scope. For inner types includes the name of its containing type, i.e. `Type.Inner` + public var name: String { + guard let parentName = parent?.name else { return localName } + return "\(parentName).\(localName)" + } + + // sourcery: skipCoding + /// Whether the type has been resolved as unknown extension + public var isUnknownExtension: Bool = false + + // sourcery: skipDescription + /// Global type name including module name, unless it's an extension of unknown type + public var globalName: String { + guard let module = module, !isUnknownExtension else { return name } + return "\(module).\(name)" + } + + /// Whether type is generic + public var isGeneric: Bool + + /// Type name in its own scope. + public var localName: String + + // sourcery: skipEquality, skipDescription + /// Variables defined in this type only, inluding variables defined in its extensions, + /// but not including variables inherited from superclasses (for classes only) and protocols + public var variables: [Variable] { + unique({ $0.rawVariables }, filter: Self.uniqueVariableFilter) + } + + /// Unfiltered (can contain duplications from extensions) variables defined in this type only, inluding variables defined in its extensions, + /// but not including variables inherited from superclasses (for classes only) and protocols + public var rawVariables: [Variable] + + // sourcery: skipEquality, skipDescription + /// All variables defined for this type, including variables defined in extensions, + /// in superclasses (for classes only) and protocols + public var allVariables: [Variable] { + return flattenAll({ + return $0.variables + }, + isExtension: { $0.definedInType?.isExtension == true }, + filter: { all, extracted in + !all.contains(where: { Self.uniqueVariableFilter($0, rhs: extracted) }) + }) + } + + private static func uniqueVariableFilter(_ lhs: Variable, rhs: Variable) -> Bool { + return lhs.name == rhs.name && lhs.isStatic == rhs.isStatic && lhs.typeName == rhs.typeName + } + + // sourcery: skipEquality, skipDescription + /// Methods defined in this type only, inluding methods defined in its extensions, + /// but not including methods inherited from superclasses (for classes only) and protocols + public var methods: [Method] { + unique({ $0.rawMethods }, filter: Self.uniqueMethodFilter) + } + + /// Unfiltered (can contain duplications from extensions) methods defined in this type only, inluding methods defined in its extensions, + /// but not including methods inherited from superclasses (for classes only) and protocols + public var rawMethods: [Method] + + // sourcery: skipEquality, skipDescription + /// All methods defined for this type, including methods defined in extensions, + /// in superclasses (for classes only) and protocols + public var allMethods: [Method] { + return flattenAll({ + $0.methods + }, + isExtension: { $0.definedInType?.isExtension == true }, + filter: { all, extracted in + !all.contains(where: { Self.uniqueMethodFilter($0, rhs: extracted) }) + }) + } + + private static func uniqueMethodFilter(_ lhs: Method, rhs: Method) -> Bool { + return lhs.name == rhs.name && lhs.isStatic == rhs.isStatic && lhs.isClass == rhs.isClass && lhs.actualReturnTypeName == rhs.actualReturnTypeName + } + + // sourcery: skipEquality, skipDescription + /// Subscripts defined in this type only, inluding subscripts defined in its extensions, + /// but not including subscripts inherited from superclasses (for classes only) and protocols + public var subscripts: [Subscript] { + unique({ $0.rawSubscripts }, filter: Self.uniqueSubscriptFilter) + } + + /// Unfiltered (can contain duplications from extensions) Subscripts defined in this type only, inluding subscripts defined in its extensions, + /// but not including subscripts inherited from superclasses (for classes only) and protocols + public var rawSubscripts: [Subscript] + + // sourcery: skipEquality, skipDescription + /// All subscripts defined for this type, including subscripts defined in extensions, + /// in superclasses (for classes only) and protocols + public var allSubscripts: [Subscript] { + return flattenAll({ $0.subscripts }, + isExtension: { $0.definedInType?.isExtension == true }, + filter: { all, extracted in + !all.contains(where: { Self.uniqueSubscriptFilter($0, rhs: extracted) }) + }) + } + + private static func uniqueSubscriptFilter(_ lhs: Subscript, rhs: Subscript) -> Bool { + return lhs.parameters == rhs.parameters && lhs.returnTypeName == rhs.returnTypeName && lhs.readAccess == rhs.readAccess && lhs.writeAccess == rhs.writeAccess + } + + // sourcery: skipEquality, skipDescription, skipJSExport + /// Bytes position of the body of this type in its declaration file if available. + public var bodyBytesRange: BytesRange? + + // sourcery: skipEquality, skipDescription, skipJSExport + /// Bytes position of the whole declaration of this type in its declaration file if available. + public var completeDeclarationRange: BytesRange? + + private func flattenAll(_ extraction: @escaping (Type) -> [T], isExtension: (T) -> Bool, filter: ([T], T) -> Bool) -> [T] { + let all = NSMutableOrderedSet() + let allObjects = extraction(self) + + /// The order of importance for properties is: + /// Base class + /// Inheritance + /// Protocol conformance + /// Extension + + var extensions = [T]() + var baseObjects = [T]() + + allObjects.forEach { + if isExtension($0) { + extensions.append($0) + } else { + baseObjects.append($0) + } + } + + all.addObjects(from: baseObjects) + + func filteredExtraction(_ target: Type) -> [T] { + // swiftlint:disable:next force_cast + let all = all.array as! [T] + let extracted = extraction(target).filter({ filter(all, $0) }) + return extracted + } + + inherits.values.sorted(by: { $0.name < $1.name }).forEach { all.addObjects(from: filteredExtraction($0)) } + implements.values.sorted(by: { $0.name < $1.name }).forEach { all.addObjects(from: filteredExtraction($0)) } + + // swiftlint:disable:next force_cast + let array = all.array as! [T] + all.addObjects(from: extensions.filter({ filter(array, $0) })) + + return all.array.compactMap { $0 as? T } + } + + private func unique(_ extraction: @escaping (Type) -> [T], filter: (T, T) -> Bool) -> [T] { + let all = NSMutableOrderedSet() + for nextItem in extraction(self) { + // swiftlint:disable:next force_cast + if !all.contains(where: { filter($0 as! T, nextItem) }) { + all.add(nextItem) + } + } + + return all.array.compactMap { $0 as? T } + } + + /// All initializers defined in this type + public var initializers: [Method] { + return methods.filter { $0.isInitializer } + } + + /// All annotations for this type + public var annotations: Annotations = [:] + + public var documentation: Documentation = [] + + /// Static variables defined in this type + public var staticVariables: [Variable] { + return variables.filter { $0.isStatic } + } + + /// Static methods defined in this type + public var staticMethods: [Method] { + return methods.filter { $0.isStatic } + } + + /// Class methods defined in this type + public var classMethods: [Method] { + return methods.filter { $0.isClass } + } + + /// Instance variables defined in this type + public var instanceVariables: [Variable] { + return variables.filter { !$0.isStatic } + } + + /// Instance methods defined in this type + public var instanceMethods: [Method] { + return methods.filter { !$0.isStatic && !$0.isClass } + } + + /// Computed instance variables defined in this type + public var computedVariables: [Variable] { + return variables.filter { $0.isComputed && !$0.isStatic } + } + + /// Stored instance variables defined in this type + public var storedVariables: [Variable] { + return variables.filter { !$0.isComputed && !$0.isStatic } + } + + /// Names of types this type inherits from (for classes only) and protocols it implements, in order of definition + public var inheritedTypes: [String] { + didSet { + based.removeAll() + inheritedTypes.forEach { name in + self.based[name] = name + } + } + } + + // sourcery: skipEquality, skipDescription + /// Names of types or protocols this type inherits from, including unknown (not scanned) types + public var based = [String: String]() + + // sourcery: skipEquality, skipDescription + /// Types this type inherits from or implements, including unknown (not scanned) types with extensions defined + public var basedTypes = [String: Type]() + + /// Types this type inherits from + public var inherits = [String: Type]() + + // sourcery: skipEquality, skipDescription + /// Protocols this type implements + public var implements = [String: Type]() + + /// Contained types + public var containedTypes: [Type] { + didSet { + containedTypes.forEach { + containedType[$0.localName] = $0 + $0.parent = self + } + } + } + + // sourcery: skipEquality, skipDescription + /// Contained types groupd by their names + public private(set) var containedType: [String: Type] = [:] + + /// Name of parent type (for contained types only) + public private(set) var parentName: String? + + // sourcery: skipEquality, skipDescription + /// Parent type, if known (for contained types only) + public var parent: Type? { + didSet { + parentName = parent?.name + } + } + + // sourcery: skipJSExport + /// :nodoc: + public var parentTypes: AnyIterator { + var next: Type? = self + return AnyIterator { + next = next?.parent + return next + } + } + + // sourcery: skipEquality, skipDescription + /// Superclass type, if known (only for classes) + public var supertype: Type? + + /// Type attributes, i.e. `@objc` + public var attributes: AttributeList + + /// Type modifiers, i.e. `private`, `final` + public var modifiers: [SourceryModifier] + + /// Path to file where the type is defined + // sourcery: skipDescription, skipEquality, skipJSExport + public var path: String? { + didSet { + if let path = path { + fileName = (path as NSString).lastPathComponent + } + } + } + + /// Directory to file where the type is defined + // sourcery: skipDescription, skipEquality, skipJSExport + public var directory: String? { + get { + return (path as? NSString)?.deletingLastPathComponent + } + } + + /// File name where the type was defined + public var fileName: String? + + /// :nodoc: + public init(name: String = "", + parent: Type? = nil, + accessLevel: AccessLevel = .internal, + isExtension: Bool = false, + variables: [Variable] = [], + methods: [Method] = [], + subscripts: [Subscript] = [], + inheritedTypes: [String] = [], + containedTypes: [Type] = [], + typealiases: [Typealias] = [], + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + isGeneric: Bool = false) { + + self.localName = name + self.accessLevel = accessLevel.rawValue + self.isExtension = isExtension + self.rawVariables = variables + self.rawMethods = methods + self.rawSubscripts = subscripts + self.inheritedTypes = inheritedTypes + self.containedTypes = containedTypes + self.typealiases = [:] + self.parent = parent + self.parentName = parent?.name + self.attributes = attributes + self.modifiers = modifiers + self.annotations = annotations + self.documentation = documentation + self.isGeneric = isGeneric + + super.init() + containedTypes.forEach { + containedType[$0.localName] = $0 + $0.parent = self + } + inheritedTypes.forEach { name in + self.based[name] = name + } + typealiases.forEach({ + $0.parent = self + self.typealiases[$0.aliasName] = $0 + }) + } + + /// :nodoc: + public func extend(_ type: Type) { + type.annotations.forEach { self.annotations[$0.key] = $0.value } + type.inherits.forEach { self.inherits[$0.key] = $0.value } + type.implements.forEach { self.implements[$0.key] = $0.value } + self.inheritedTypes += type.inheritedTypes + self.containedTypes += type.containedTypes + + self.rawVariables += type.rawVariables + self.rawMethods += type.rawMethods + self.rawSubscripts += type.rawSubscripts + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "module = \(String(describing: self.module)), " + string += "imports = \(String(describing: self.imports)), " + string += "allImports = \(String(describing: self.allImports)), " + string += "typealiases = \(String(describing: self.typealiases)), " + string += "isExtension = \(String(describing: self.isExtension)), " + string += "kind = \(String(describing: self.kind)), " + string += "accessLevel = \(String(describing: self.accessLevel)), " + string += "name = \(String(describing: self.name)), " + string += "isUnknownExtension = \(String(describing: self.isUnknownExtension)), " + string += "isGeneric = \(String(describing: self.isGeneric)), " + string += "localName = \(String(describing: self.localName)), " + string += "rawVariables = \(String(describing: self.rawVariables)), " + string += "rawMethods = \(String(describing: self.rawMethods)), " + string += "rawSubscripts = \(String(describing: self.rawSubscripts)), " + string += "initializers = \(String(describing: self.initializers)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "documentation = \(String(describing: self.documentation)), " + string += "staticVariables = \(String(describing: self.staticVariables)), " + string += "staticMethods = \(String(describing: self.staticMethods)), " + string += "classMethods = \(String(describing: self.classMethods)), " + string += "instanceVariables = \(String(describing: self.instanceVariables)), " + string += "instanceMethods = \(String(describing: self.instanceMethods)), " + string += "computedVariables = \(String(describing: self.computedVariables)), " + string += "storedVariables = \(String(describing: self.storedVariables)), " + string += "inheritedTypes = \(String(describing: self.inheritedTypes)), " + string += "inherits = \(String(describing: self.inherits)), " + string += "containedTypes = \(String(describing: self.containedTypes)), " + string += "parentName = \(String(describing: self.parentName)), " + string += "parentTypes = \(String(describing: self.parentTypes)), " + string += "attributes = \(String(describing: self.attributes)), " + string += "modifiers = \(String(describing: self.modifiers)), " + string += "fileName = \(String(describing: self.fileName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Type else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) + results.append(contentsOf: DiffableResult(identifier: "imports").trackDifference(actual: self.imports, expected: castObject.imports)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + results.append(contentsOf: DiffableResult(identifier: "isExtension").trackDifference(actual: self.isExtension, expected: castObject.isExtension)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "isUnknownExtension").trackDifference(actual: self.isUnknownExtension, expected: castObject.isUnknownExtension)) + results.append(contentsOf: DiffableResult(identifier: "isGeneric").trackDifference(actual: self.isGeneric, expected: castObject.isGeneric)) + results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) + results.append(contentsOf: DiffableResult(identifier: "rawVariables").trackDifference(actual: self.rawVariables, expected: castObject.rawVariables)) + results.append(contentsOf: DiffableResult(identifier: "rawMethods").trackDifference(actual: self.rawMethods, expected: castObject.rawMethods)) + results.append(contentsOf: DiffableResult(identifier: "rawSubscripts").trackDifference(actual: self.rawSubscripts, expected: castObject.rawSubscripts)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "inheritedTypes").trackDifference(actual: self.inheritedTypes, expected: castObject.inheritedTypes)) + results.append(contentsOf: DiffableResult(identifier: "inherits").trackDifference(actual: self.inherits, expected: castObject.inherits)) + results.append(contentsOf: DiffableResult(identifier: "containedTypes").trackDifference(actual: self.containedTypes, expected: castObject.containedTypes)) + results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "fileName").trackDifference(actual: self.fileName, expected: castObject.fileName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.module) + hasher.combine(self.imports) + hasher.combine(self.typealiases) + hasher.combine(self.isExtension) + hasher.combine(self.accessLevel) + hasher.combine(self.isUnknownExtension) + hasher.combine(self.isGeneric) + hasher.combine(self.localName) + hasher.combine(self.rawVariables) + hasher.combine(self.rawMethods) + hasher.combine(self.rawSubscripts) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.inheritedTypes) + hasher.combine(self.inherits) + hasher.combine(self.containedTypes) + hasher.combine(self.parentName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.fileName) + hasher.combine(kind) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Type else { return false } + if self.module != rhs.module { return false } + if self.imports != rhs.imports { return false } + if self.typealiases != rhs.typealiases { return false } + if self.isExtension != rhs.isExtension { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.isUnknownExtension != rhs.isUnknownExtension { return false } + if self.isGeneric != rhs.isGeneric { return false } + if self.localName != rhs.localName { return false } + if self.rawVariables != rhs.rawVariables { return false } + if self.rawMethods != rhs.rawMethods { return false } + if self.rawSubscripts != rhs.rawSubscripts { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.inheritedTypes != rhs.inheritedTypes { return false } + if self.inherits != rhs.inherits { return false } + if self.containedTypes != rhs.containedTypes { return false } + if self.parentName != rhs.parentName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.fileName != rhs.fileName { return false } + if self.kind != rhs.kind { return false } + return true + } + +// sourcery:inline:Type.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.module = aDecoder.decode(forKey: "module") + guard let imports: [Import] = aDecoder.decode(forKey: "imports") else { + withVaList(["imports"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.imports = imports + guard let typealiases: [String: Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases + self.isExtension = aDecoder.decode(forKey: "isExtension") + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel + self.isGeneric = aDecoder.decode(forKey: "isGeneric") + guard let localName: String = aDecoder.decode(forKey: "localName") else { + withVaList(["localName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.localName = localName + guard let rawVariables: [Variable] = aDecoder.decode(forKey: "rawVariables") else { + withVaList(["rawVariables"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawVariables = rawVariables + guard let rawMethods: [Method] = aDecoder.decode(forKey: "rawMethods") else { + withVaList(["rawMethods"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawMethods = rawMethods + guard let rawSubscripts: [Subscript] = aDecoder.decode(forKey: "rawSubscripts") else { + withVaList(["rawSubscripts"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawSubscripts = rawSubscripts + self.bodyBytesRange = aDecoder.decode(forKey: "bodyBytesRange") + self.completeDeclarationRange = aDecoder.decode(forKey: "completeDeclarationRange") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + guard let inheritedTypes: [String] = aDecoder.decode(forKey: "inheritedTypes") else { + withVaList(["inheritedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inheritedTypes = inheritedTypes + guard let based: [String: String] = aDecoder.decode(forKey: "based") else { + withVaList(["based"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.based = based + guard let basedTypes: [String: Type] = aDecoder.decode(forKey: "basedTypes") else { + withVaList(["basedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.basedTypes = basedTypes + guard let inherits: [String: Type] = aDecoder.decode(forKey: "inherits") else { + withVaList(["inherits"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inherits = inherits + guard let implements: [String: Type] = aDecoder.decode(forKey: "implements") else { + withVaList(["implements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.implements = implements + guard let containedTypes: [Type] = aDecoder.decode(forKey: "containedTypes") else { + withVaList(["containedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.containedTypes = containedTypes + guard let containedType: [String: Type] = aDecoder.decode(forKey: "containedType") else { + withVaList(["containedType"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.containedType = containedType + self.parentName = aDecoder.decode(forKey: "parentName") + self.parent = aDecoder.decode(forKey: "parent") + self.supertype = aDecoder.decode(forKey: "supertype") + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers + self.path = aDecoder.decode(forKey: "path") + self.fileName = aDecoder.decode(forKey: "fileName") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.module, forKey: "module") + aCoder.encode(self.imports, forKey: "imports") + aCoder.encode(self.typealiases, forKey: "typealiases") + aCoder.encode(self.isExtension, forKey: "isExtension") + aCoder.encode(self.accessLevel, forKey: "accessLevel") + aCoder.encode(self.isGeneric, forKey: "isGeneric") + aCoder.encode(self.localName, forKey: "localName") + aCoder.encode(self.rawVariables, forKey: "rawVariables") + aCoder.encode(self.rawMethods, forKey: "rawMethods") + aCoder.encode(self.rawSubscripts, forKey: "rawSubscripts") + aCoder.encode(self.bodyBytesRange, forKey: "bodyBytesRange") + aCoder.encode(self.completeDeclarationRange, forKey: "completeDeclarationRange") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.inheritedTypes, forKey: "inheritedTypes") + aCoder.encode(self.based, forKey: "based") + aCoder.encode(self.basedTypes, forKey: "basedTypes") + aCoder.encode(self.inherits, forKey: "inherits") + aCoder.encode(self.implements, forKey: "implements") + aCoder.encode(self.containedTypes, forKey: "containedTypes") + aCoder.encode(self.containedType, forKey: "containedType") + aCoder.encode(self.parentName, forKey: "parentName") + aCoder.encode(self.parent, forKey: "parent") + aCoder.encode(self.supertype, forKey: "supertype") + aCoder.encode(self.attributes, forKey: "attributes") + aCoder.encode(self.modifiers, forKey: "modifiers") + aCoder.encode(self.path, forKey: "path") + aCoder.encode(self.fileName, forKey: "fileName") + } +// sourcery:end + +} + +extension Type { + + // sourcery: skipDescription, skipJSExport + /// :nodoc: + var isClass: Bool { + let isNotClass = self is Struct || self is Enum || self is Protocol + return !isNotClass && !isExtension + } +} +#endif diff --git a/SourceryRuntime/Sources/AST/Typealias.swift b/SourceryRuntime/Sources/AST/Typealias.swift index 2049eee9c..e42826b01 100644 --- a/SourceryRuntime/Sources/AST/Typealias.swift +++ b/SourceryRuntime/Sources/AST/Typealias.swift @@ -1,7 +1,10 @@ import Foundation /// :nodoc: -@objcMembers public final class Typealias: NSObject, Typed, SourceryModel { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class Typealias: NSObject, Typed, SourceryModel, Diffable { // New typealias name public let aliasName: String @@ -43,16 +46,78 @@ import Foundation self.module = module } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "aliasName = \(String(describing: self.aliasName)), " + string += "typeName = \(String(describing: self.typeName)), " + string += "module = \(String(describing: self.module)), " + string += "accessLevel = \(String(describing: self.accessLevel)), " + string += "parentName = \(String(describing: self.parentName)), " + string += "name = \(String(describing: self.name))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Typealias else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "aliasName").trackDifference(actual: self.aliasName, expected: castObject.aliasName)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.aliasName) + hasher.combine(self.typeName) + hasher.combine(self.module) + hasher.combine(self.accessLevel) + hasher.combine(self.parentName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Typealias else { return false } + if self.aliasName != rhs.aliasName { return false } + if self.typeName != rhs.typeName { return false } + if self.module != rhs.module { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.parentName != rhs.parentName { return false } + return true + } + // sourcery:inline:Typealias.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let aliasName: String = aDecoder.decode(forKey: "aliasName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["aliasName"])); fatalError() }; self.aliasName = aliasName - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName + guard let aliasName: String = aDecoder.decode(forKey: "aliasName") else { + withVaList(["aliasName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.aliasName = aliasName + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName self.type = aDecoder.decode(forKey: "type") self.module = aDecoder.decode(forKey: "module") self.parent = aDecoder.decode(forKey: "parent") - guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["accessLevel"])); fatalError() }; self.accessLevel = accessLevel + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel self.parentName = aDecoder.decode(forKey: "parentName") } diff --git a/SourceryRuntime/Sources/AST/Variable.swift b/SourceryRuntime/Sources/AST/Variable.swift index 20e9a74d4..2cf3c13d0 100644 --- a/SourceryRuntime/Sources/AST/Variable.swift +++ b/SourceryRuntime/Sources/AST/Variable.swift @@ -2,14 +2,17 @@ // Created by Krzysztof Zablocki on 13/09/2016. // Copyright (c) 2016 Pixle. All rights reserved. // - +#if canImport(ObjectiveC) import Foundation +import Stencil /// :nodoc: public typealias SourceryVariable = Variable /// Defines variable -@objcMembers public final class Variable: NSObject, SourceryModel, Typed, Annotated, Documented, Definition { +@objcMembers +public final class Variable: NSObject, SourceryModel, Typed, Annotated, Documented, Definition, Diffable { + /// Variable name public let name: String @@ -122,24 +125,151 @@ public typealias SourceryVariable = Variable self.definedInTypeName = definedInTypeName } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "typeName = \(String(describing: self.typeName)), " + string += "isComputed = \(String(describing: self.isComputed)), " + string += "isAsync = \(String(describing: self.isAsync)), " + string += "`throws` = \(String(describing: self.`throws`)), " + string += "isStatic = \(String(describing: self.isStatic)), " + string += "readAccess = \(String(describing: self.readAccess)), " + string += "writeAccess = \(String(describing: self.writeAccess)), " + string += "accessLevel = \(String(describing: self.accessLevel)), " + string += "isMutable = \(String(describing: self.isMutable)), " + string += "defaultValue = \(String(describing: self.defaultValue)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "documentation = \(String(describing: self.documentation)), " + string += "attributes = \(String(describing: self.attributes)), " + string += "modifiers = \(String(describing: self.modifiers)), " + string += "isFinal = \(String(describing: self.isFinal)), " + string += "isLazy = \(String(describing: self.isLazy)), " + string += "definedInTypeName = \(String(describing: self.definedInTypeName)), " + string += "actualDefinedInTypeName = \(String(describing: self.actualDefinedInTypeName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Variable else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "isComputed").trackDifference(actual: self.isComputed, expected: castObject.isComputed)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) + results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) + results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.isComputed) + hasher.combine(self.isAsync) + hasher.combine(self.`throws`) + hasher.combine(self.isStatic) + hasher.combine(self.readAccess) + hasher.combine(self.writeAccess) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.definedInTypeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Variable else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.isComputed != rhs.isComputed { return false } + if self.isAsync != rhs.isAsync { return false } + if self.`throws` != rhs.`throws` { return false } + if self.isStatic != rhs.isStatic { return false } + if self.readAccess != rhs.readAccess { return false } + if self.writeAccess != rhs.writeAccess { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + return true + } + // sourcery:inline:Variable.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName self.type = aDecoder.decode(forKey: "type") self.isComputed = aDecoder.decode(forKey: "isComputed") self.isAsync = aDecoder.decode(forKey: "isAsync") self.`throws` = aDecoder.decode(forKey: "`throws`") self.isStatic = aDecoder.decode(forKey: "isStatic") - guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["readAccess"])); fatalError() }; self.readAccess = readAccess - guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["writeAccess"])); fatalError() }; self.writeAccess = writeAccess + guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { + withVaList(["readAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.readAccess = readAccess + guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { + withVaList(["writeAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.writeAccess = writeAccess self.defaultValue = aDecoder.decode(forKey: "defaultValue") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["documentation"])); fatalError() }; self.documentation = documentation - guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["attributes"])); fatalError() }; self.attributes = attributes - guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiers"])); fatalError() }; self.modifiers = modifiers + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") self.definedInType = aDecoder.decode(forKey: "definedInType") } @@ -165,3 +295,4 @@ public typealias SourceryVariable = Variable } // sourcery:end } +#endif diff --git a/SourceryRuntime/Sources/AST/Variable_Linux.swift b/SourceryRuntime/Sources/AST/Variable_Linux.swift new file mode 100644 index 000000000..49615d629 --- /dev/null +++ b/SourceryRuntime/Sources/AST/Variable_Linux.swift @@ -0,0 +1,330 @@ +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// +#if !canImport(ObjectiveC) +import Foundation +// For DynamicMemberLookup we need to import Stencil, +// however, this is different from SourceryRuntime.content.generated.swift, because +// it cannot reference Stencil +import Stencil + +/// :nodoc: +public typealias SourceryVariable = Variable + +/// Defines variable +public final class Variable: NSObject, SourceryModel, Typed, Annotated, Documented, Definition, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "readAccess": + return readAccess + case "annotations": + return annotations + case "isOptional": + return isOptional + case "name": + return name + case "typeName": + return typeName + case "type": + return type + case "definedInType": + return definedInType + case "isStatic": + return isStatic + case "isAsync": + return isAsync + case "throws": + return `throws` + case "isArray": + return isArray + case "isDictionary": + return isDictionary + default: + fatalError("unable to lookup: \(member) in \(self)") + } + } + + /// Variable name + public let name: String + + /// Variable type name + public let typeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Variable type, if known, i.e. if the type is declared in the scanned sources. + /// For explanation, see + public var type: Type? + + /// Whether variable is computed and not stored + public let isComputed: Bool + + /// Whether variable is async + public let isAsync: Bool + + /// Whether variable throws + public let `throws`: Bool + + /// Whether variable is static + public let isStatic: Bool + + /// Variable read access level, i.e. `internal`, `private`, `fileprivate`, `public`, `open` + public let readAccess: String + + /// Variable write access, i.e. `internal`, `private`, `fileprivate`, `public`, `open`. + /// For immutable variables this value is empty string + public let writeAccess: String + + /// composed access level + /// sourcery: skipJSExport + public var accessLevel: (read: AccessLevel, write: AccessLevel) { + (read: AccessLevel(rawValue: readAccess) ?? .none, AccessLevel(rawValue: writeAccess) ?? .none) + } + + /// Whether variable is mutable or not + public var isMutable: Bool { + return writeAccess != AccessLevel.none.rawValue + } + + /// Variable default value expression + public var defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + + public var documentation: Documentation = [] + + /// Variable attributes, i.e. `@IBOutlet`, `@IBInspectable` + public var attributes: AttributeList + + /// Modifiers, i.e. `private` + public var modifiers: [SourceryModifier] + + /// Whether variable is final or not + public var isFinal: Bool { + return modifiers.contains { $0.name == "final" } + } + + /// Whether variable is lazy or not + public var isLazy: Bool { + return modifiers.contains { $0.name == "lazy" } + } + + /// Reference to type name where the variable is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc + public internal(set) var definedInTypeName: TypeName? + + /// Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a `definedInTypeName` + public var actualDefinedInTypeName: TypeName? { + return definedInTypeName?.actualTypeName ?? definedInTypeName + } + + // sourcery: skipEquality, skipDescription + /// Reference to actual type where the object is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc or type is unknown + public var definedInType: Type? + + /// :nodoc: + public init(name: String = "", + typeName: TypeName, + type: Type? = nil, + accessLevel: (read: AccessLevel, write: AccessLevel) = (.internal, .internal), + isComputed: Bool = false, + isAsync: Bool = false, + `throws`: Bool = false, + isStatic: Bool = false, + defaultValue: String? = nil, + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + definedInTypeName: TypeName? = nil) { + + self.name = name + self.typeName = typeName + self.type = type + self.isComputed = isComputed + self.isAsync = isAsync + self.`throws` = `throws` + self.isStatic = isStatic + self.defaultValue = defaultValue + self.readAccess = accessLevel.read.rawValue + self.writeAccess = accessLevel.write.rawValue + self.attributes = attributes + self.modifiers = modifiers + self.annotations = annotations + self.documentation = documentation + self.definedInTypeName = definedInTypeName + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "name = \(String(describing: self.name)), " + string += "typeName = \(String(describing: self.typeName)), " + string += "isComputed = \(String(describing: self.isComputed)), " + string += "isAsync = \(String(describing: self.isAsync)), " + string += "`throws` = \(String(describing: self.`throws`)), " + string += "isStatic = \(String(describing: self.isStatic)), " + string += "readAccess = \(String(describing: self.readAccess)), " + string += "writeAccess = \(String(describing: self.writeAccess)), " + string += "accessLevel = \(String(describing: self.accessLevel)), " + string += "isMutable = \(String(describing: self.isMutable)), " + string += "defaultValue = \(String(describing: self.defaultValue)), " + string += "annotations = \(String(describing: self.annotations)), " + string += "documentation = \(String(describing: self.documentation)), " + string += "attributes = \(String(describing: self.attributes)), " + string += "modifiers = \(String(describing: self.modifiers)), " + string += "isFinal = \(String(describing: self.isFinal)), " + string += "isLazy = \(String(describing: self.isLazy)), " + string += "definedInTypeName = \(String(describing: self.definedInTypeName)), " + string += "actualDefinedInTypeName = \(String(describing: self.actualDefinedInTypeName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Variable else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "isComputed").trackDifference(actual: self.isComputed, expected: castObject.isComputed)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) + results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) + results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.isComputed) + hasher.combine(self.isAsync) + hasher.combine(self.`throws`) + hasher.combine(self.isStatic) + hasher.combine(self.readAccess) + hasher.combine(self.writeAccess) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.definedInTypeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Variable else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.isComputed != rhs.isComputed { return false } + if self.isAsync != rhs.isAsync { return false } + if self.`throws` != rhs.`throws` { return false } + if self.isStatic != rhs.isStatic { return false } + if self.readAccess != rhs.readAccess { return false } + if self.writeAccess != rhs.writeAccess { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + return true + } + +// sourcery:inline:Variable.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.type = aDecoder.decode(forKey: "type") + self.isComputed = aDecoder.decode(forKey: "isComputed") + self.isAsync = aDecoder.decode(forKey: "isAsync") + self.`throws` = aDecoder.decode(forKey: "`throws`") + self.isStatic = aDecoder.decode(forKey: "isStatic") + guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { + withVaList(["readAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.readAccess = readAccess + guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { + withVaList(["writeAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.writeAccess = writeAccess + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers + self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") + self.definedInType = aDecoder.decode(forKey: "definedInType") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.isComputed, forKey: "isComputed") + aCoder.encode(self.isAsync, forKey: "isAsync") + aCoder.encode(self.`throws`, forKey: "`throws`") + aCoder.encode(self.isStatic, forKey: "isStatic") + aCoder.encode(self.readAccess, forKey: "readAccess") + aCoder.encode(self.writeAccess, forKey: "writeAccess") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.attributes, forKey: "attributes") + aCoder.encode(self.modifiers, forKey: "modifiers") + aCoder.encode(self.definedInTypeName, forKey: "definedInTypeName") + aCoder.encode(self.definedInType, forKey: "definedInType") + } +// sourcery:end +} +#endif diff --git a/SourceryRuntime/Sources/BytesRange.swift b/SourceryRuntime/Sources/BytesRange.swift index 5720ddca5..c0e45b2bc 100644 --- a/SourceryRuntime/Sources/BytesRange.swift +++ b/SourceryRuntime/Sources/BytesRange.swift @@ -6,7 +6,10 @@ import Foundation /// :nodoc: -@objcMembers public final class BytesRange: NSObject, SourceryModel { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class BytesRange: NSObject, SourceryModel, Diffable { public let offset: Int64 public let length: Int64 @@ -20,6 +23,40 @@ import Foundation self.init(offset: range.offset, length: range.length) } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "offset = \(String(describing: self.offset)), " + string += "length = \(String(describing: self.length))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? BytesRange else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "offset").trackDifference(actual: self.offset, expected: castObject.offset)) + results.append(contentsOf: DiffableResult(identifier: "length").trackDifference(actual: self.length, expected: castObject.length)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.offset) + hasher.combine(self.length) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? BytesRange else { return false } + if self.offset != rhs.offset { return false } + if self.length != rhs.length { return false } + return true + } + // sourcery:inline:BytesRange.AutoCoding /// :nodoc: diff --git a/SourceryRuntime/Sources/Composer/Composer.swift b/SourceryRuntime/Sources/Composer/Composer.swift index aeead6c7d..82b42dea3 100644 --- a/SourceryRuntime/Sources/Composer/Composer.swift +++ b/SourceryRuntime/Sources/Composer/Composer.swift @@ -6,7 +6,7 @@ import Foundation private func currentTimestamp() -> TimeInterval { - return CFAbsoluteTimeGetCurrent() + return Date().timeIntervalSince1970 } /// Responsible for composing results of `FileParser`. diff --git a/SourceryRuntime/Sources/Diffable.swift b/SourceryRuntime/Sources/Diffable.swift index fd93330e2..749fdd540 100644 --- a/SourceryRuntime/Sources/Diffable.swift +++ b/SourceryRuntime/Sources/Diffable.swift @@ -36,7 +36,10 @@ extension NSRange: Diffable { } } -@objcMembers public class DiffableResult: NSObject, AutoEquatable { +#if canImport(ObjectiveC) +@objcMembers +#endif +public class DiffableResult: NSObject, AutoEquatable { // sourcery: skipEquality private var results: [String] internal var identifier: String? @@ -58,6 +61,19 @@ extension NSRange: Diffable { var isEmpty: Bool { return results.isEmpty } + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.identifier) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? DiffableResult else { return false } + if self.identifier != rhs.identifier { return false } + return true + } + public override var description: String { guard !results.isEmpty else { return "" } return "\(identifier.flatMap { "\($0) " } ?? "")" + results.joined(separator: "\n") diff --git a/SourceryRuntime/Sources/FileParserResult.swift b/SourceryRuntime/Sources/FileParserResult.swift index 10f549353..ee2ae4c33 100644 --- a/SourceryRuntime/Sources/FileParserResult.swift +++ b/SourceryRuntime/Sources/FileParserResult.swift @@ -10,7 +10,10 @@ import Foundation // sourcery: skipJSExport /// :nodoc: -@objcMembers public final class FileParserResult: NSObject, SourceryModel { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class FileParserResult: NSObject, SourceryModel, Diffable { public let path: String? public let module: String? public var types = [Type]() { @@ -51,19 +54,117 @@ import Foundation } } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "path = \(String(describing: self.path)), " + string += "module = \(String(describing: self.module)), " + string += "types = \(String(describing: self.types)), " + string += "functions = \(String(describing: self.functions)), " + string += "typealiases = \(String(describing: self.typealiases)), " + string += "inlineRanges = \(String(describing: self.inlineRanges)), " + string += "inlineIndentations = \(String(describing: self.inlineIndentations)), " + string += "modifiedDate = \(String(describing: self.modifiedDate)), " + string += "sourceryVersion = \(String(describing: self.sourceryVersion)), " + string += "isEmpty = \(String(describing: self.isEmpty))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? FileParserResult else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "path").trackDifference(actual: self.path, expected: castObject.path)) + results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) + results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) + results.append(contentsOf: DiffableResult(identifier: "functions").trackDifference(actual: self.functions, expected: castObject.functions)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + results.append(contentsOf: DiffableResult(identifier: "inlineRanges").trackDifference(actual: self.inlineRanges, expected: castObject.inlineRanges)) + results.append(contentsOf: DiffableResult(identifier: "inlineIndentations").trackDifference(actual: self.inlineIndentations, expected: castObject.inlineIndentations)) + results.append(contentsOf: DiffableResult(identifier: "modifiedDate").trackDifference(actual: self.modifiedDate, expected: castObject.modifiedDate)) + results.append(contentsOf: DiffableResult(identifier: "sourceryVersion").trackDifference(actual: self.sourceryVersion, expected: castObject.sourceryVersion)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.path) + hasher.combine(self.module) + hasher.combine(self.types) + hasher.combine(self.functions) + hasher.combine(self.typealiases) + hasher.combine(self.inlineRanges) + hasher.combine(self.inlineIndentations) + hasher.combine(self.modifiedDate) + hasher.combine(self.sourceryVersion) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? FileParserResult else { return false } + if self.path != rhs.path { return false } + if self.module != rhs.module { return false } + if self.types != rhs.types { return false } + if self.functions != rhs.functions { return false } + if self.typealiases != rhs.typealiases { return false } + if self.inlineRanges != rhs.inlineRanges { return false } + if self.inlineIndentations != rhs.inlineIndentations { return false } + if self.modifiedDate != rhs.modifiedDate { return false } + if self.sourceryVersion != rhs.sourceryVersion { return false } + return true + } + // sourcery:inline:FileParserResult.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { self.path = aDecoder.decode(forKey: "path") self.module = aDecoder.decode(forKey: "module") - guard let types: [Type] = aDecoder.decode(forKey: "types") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["types"])); fatalError() }; self.types = types - guard let functions: [SourceryMethod] = aDecoder.decode(forKey: "functions") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["functions"])); fatalError() }; self.functions = functions - guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typealiases"])); fatalError() }; self.typealiases = typealiases - guard let inlineRanges: [String: NSRange] = aDecoder.decode(forKey: "inlineRanges") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["inlineRanges"])); fatalError() }; self.inlineRanges = inlineRanges - guard let inlineIndentations: [String: String] = aDecoder.decode(forKey: "inlineIndentations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["inlineIndentations"])); fatalError() }; self.inlineIndentations = inlineIndentations - guard let modifiedDate: Date = aDecoder.decode(forKey: "modifiedDate") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiedDate"])); fatalError() }; self.modifiedDate = modifiedDate - guard let sourceryVersion: String = aDecoder.decode(forKey: "sourceryVersion") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["sourceryVersion"])); fatalError() }; self.sourceryVersion = sourceryVersion + guard let types: [Type] = aDecoder.decode(forKey: "types") else { + withVaList(["types"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.types = types + guard let functions: [SourceryMethod] = aDecoder.decode(forKey: "functions") else { + withVaList(["functions"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.functions = functions + guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases + guard let inlineRanges: [String: NSRange] = aDecoder.decode(forKey: "inlineRanges") else { + withVaList(["inlineRanges"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inlineRanges = inlineRanges + guard let inlineIndentations: [String: String] = aDecoder.decode(forKey: "inlineIndentations") else { + withVaList(["inlineIndentations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inlineIndentations = inlineIndentations + guard let modifiedDate: Date = aDecoder.decode(forKey: "modifiedDate") else { + withVaList(["modifiedDate"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiedDate = modifiedDate + guard let sourceryVersion: String = aDecoder.decode(forKey: "sourceryVersion") else { + withVaList(["sourceryVersion"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.sourceryVersion = sourceryVersion } /// :nodoc: diff --git a/SourceryRuntime/Sources/Generated/Description.generated.swift b/SourceryRuntime/Sources/Generated/Description.generated.swift deleted file mode 100644 index a324acf01..000000000 --- a/SourceryRuntime/Sources/Generated/Description.generated.swift +++ /dev/null @@ -1,375 +0,0 @@ -// Generated using Sourcery 2.0.3 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT -// swiftlint:disable vertical_whitespace - - -extension Actor { - /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "isFinal = \(String(describing: self.isFinal))" - return string - } -} -extension ArrayType { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "name = \(String(describing: self.name)), " - string += "elementTypeName = \(String(describing: self.elementTypeName)), " - string += "asGeneric = \(String(describing: self.asGeneric)), " - string += "asSource = \(String(describing: self.asSource))" - return string - } -} -extension AssociatedType { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "name = \(String(describing: self.name)), " - string += "typeName = \(String(describing: self.typeName))" - return string - } -} -extension AssociatedValue { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "localName = \(String(describing: self.localName)), " - string += "externalName = \(String(describing: self.externalName)), " - string += "typeName = \(String(describing: self.typeName)), " - string += "defaultValue = \(String(describing: self.defaultValue)), " - string += "annotations = \(String(describing: self.annotations))" - return string - } -} -extension BytesRange { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "offset = \(String(describing: self.offset)), " - string += "length = \(String(describing: self.length))" - return string - } -} -extension Class { - /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "isFinal = \(String(describing: self.isFinal))" - return string - } -} -extension ClosureParameter { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "argumentLabel = \(String(describing: self.argumentLabel)), " - string += "name = \(String(describing: self.name)), " - string += "typeName = \(String(describing: self.typeName)), " - string += "`inout` = \(String(describing: self.`inout`)), " - string += "typeAttributes = \(String(describing: self.typeAttributes)), " - string += "defaultValue = \(String(describing: self.defaultValue)), " - string += "annotations = \(String(describing: self.annotations)), " - string += "asSource = \(String(describing: self.asSource))" - return string - } -} -extension ClosureType { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "name = \(String(describing: self.name)), " - string += "parameters = \(String(describing: self.parameters)), " - string += "returnTypeName = \(String(describing: self.returnTypeName)), " - string += "actualReturnTypeName = \(String(describing: self.actualReturnTypeName)), " - string += "isAsync = \(String(describing: self.isAsync)), " - string += "asyncKeyword = \(String(describing: self.asyncKeyword)), " - string += "`throws` = \(String(describing: self.`throws`)), " - string += "throwsOrRethrowsKeyword = \(String(describing: self.throwsOrRethrowsKeyword)), " - string += "asSource = \(String(describing: self.asSource))" - return string - } -} -extension DictionaryType { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "name = \(String(describing: self.name)), " - string += "valueTypeName = \(String(describing: self.valueTypeName)), " - string += "keyTypeName = \(String(describing: self.keyTypeName)), " - string += "asGeneric = \(String(describing: self.asGeneric)), " - string += "asSource = \(String(describing: self.asSource))" - return string - } -} -extension Enum { - /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "cases = \(String(describing: self.cases)), " - string += "rawTypeName = \(String(describing: self.rawTypeName)), " - string += "hasAssociatedValues = \(String(describing: self.hasAssociatedValues))" - return string - } -} -extension EnumCase { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "name = \(String(describing: self.name)), " - string += "rawValue = \(String(describing: self.rawValue)), " - string += "associatedValues = \(String(describing: self.associatedValues)), " - string += "annotations = \(String(describing: self.annotations)), " - string += "documentation = \(String(describing: self.documentation)), " - string += "indirect = \(String(describing: self.indirect)), " - string += "hasAssociatedValue = \(String(describing: self.hasAssociatedValue))" - return string - } -} -extension FileParserResult { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "path = \(String(describing: self.path)), " - string += "module = \(String(describing: self.module)), " - string += "types = \(String(describing: self.types)), " - string += "functions = \(String(describing: self.functions)), " - string += "typealiases = \(String(describing: self.typealiases)), " - string += "inlineRanges = \(String(describing: self.inlineRanges)), " - string += "inlineIndentations = \(String(describing: self.inlineIndentations)), " - string += "modifiedDate = \(String(describing: self.modifiedDate)), " - string += "sourceryVersion = \(String(describing: self.sourceryVersion)), " - string += "isEmpty = \(String(describing: self.isEmpty))" - return string - } -} -extension GenericRequirement { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "leftType = \(String(describing: self.leftType)), " - string += "rightType = \(String(describing: self.rightType)), " - string += "relationship = \(String(describing: self.relationship)), " - string += "relationshipSyntax = \(String(describing: self.relationshipSyntax))" - return string - } -} -extension GenericTypeParameter { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "typeName = \(String(describing: self.typeName))" - return string - } -} -extension Method { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "name = \(String(describing: self.name)), " - string += "selectorName = \(String(describing: self.selectorName)), " - string += "parameters = \(String(describing: self.parameters)), " - string += "returnTypeName = \(String(describing: self.returnTypeName)), " - string += "isAsync = \(String(describing: self.isAsync)), " - string += "`throws` = \(String(describing: self.`throws`)), " - string += "`rethrows` = \(String(describing: self.`rethrows`)), " - string += "accessLevel = \(String(describing: self.accessLevel)), " - string += "isStatic = \(String(describing: self.isStatic)), " - string += "isClass = \(String(describing: self.isClass)), " - string += "isFailableInitializer = \(String(describing: self.isFailableInitializer)), " - string += "annotations = \(String(describing: self.annotations)), " - string += "documentation = \(String(describing: self.documentation)), " - string += "definedInTypeName = \(String(describing: self.definedInTypeName)), " - string += "attributes = \(String(describing: self.attributes)), " - string += "modifiers = \(String(describing: self.modifiers))" - return string - } -} -extension MethodParameter { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "argumentLabel = \(String(describing: self.argumentLabel)), " - string += "name = \(String(describing: self.name)), " - string += "typeName = \(String(describing: self.typeName)), " - string += "`inout` = \(String(describing: self.`inout`)), " - string += "isVariadic = \(String(describing: self.isVariadic)), " - string += "typeAttributes = \(String(describing: self.typeAttributes)), " - string += "defaultValue = \(String(describing: self.defaultValue)), " - string += "annotations = \(String(describing: self.annotations)), " - string += "asSource = \(String(describing: self.asSource))" - return string - } -} -extension Protocol { - /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "kind = \(String(describing: self.kind)), " - string += "associatedTypes = \(String(describing: self.associatedTypes)), " - string += "genericRequirements = \(String(describing: self.genericRequirements))" - return string - } -} -extension ProtocolComposition { - /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "kind = \(String(describing: self.kind)), " - string += "composedTypeNames = \(String(describing: self.composedTypeNames))" - return string - } -} -extension Struct { - /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "kind = \(String(describing: self.kind))" - return string - } -} -extension Subscript { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "parameters = \(String(describing: self.parameters)), " - string += "returnTypeName = \(String(describing: self.returnTypeName)), " - string += "actualReturnTypeName = \(String(describing: self.actualReturnTypeName)), " - string += "isFinal = \(String(describing: self.isFinal)), " - string += "readAccess = \(String(describing: self.readAccess)), " - string += "writeAccess = \(String(describing: self.writeAccess)), " - string += "isMutable = \(String(describing: self.isMutable)), " - string += "annotations = \(String(describing: self.annotations)), " - string += "documentation = \(String(describing: self.documentation)), " - string += "definedInTypeName = \(String(describing: self.definedInTypeName)), " - string += "actualDefinedInTypeName = \(String(describing: self.actualDefinedInTypeName)), " - string += "attributes = \(String(describing: self.attributes)), " - string += "modifiers = \(String(describing: self.modifiers))" - return string - } -} -extension TemplateContext { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "parserResult = \(String(describing: self.parserResult)), " - string += "functions = \(String(describing: self.functions)), " - string += "types = \(String(describing: self.types)), " - string += "argument = \(String(describing: self.argument)), " - string += "stencilContext = \(String(describing: self.stencilContext))" - return string - } -} -extension TupleElement { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "name = \(String(describing: self.name)), " - string += "typeName = \(String(describing: self.typeName)), " - string += "asSource = \(String(describing: self.asSource))" - return string - } -} -extension TupleType { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "name = \(String(describing: self.name)), " - string += "elements = \(String(describing: self.elements))" - return string - } -} -extension Type { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "module = \(String(describing: self.module)), " - string += "imports = \(String(describing: self.imports)), " - string += "allImports = \(String(describing: self.allImports)), " - string += "typealiases = \(String(describing: self.typealiases)), " - string += "isExtension = \(String(describing: self.isExtension)), " - string += "kind = \(String(describing: self.kind)), " - string += "accessLevel = \(String(describing: self.accessLevel)), " - string += "name = \(String(describing: self.name)), " - string += "isUnknownExtension = \(String(describing: self.isUnknownExtension)), " - string += "isGeneric = \(String(describing: self.isGeneric)), " - string += "localName = \(String(describing: self.localName)), " - string += "rawVariables = \(String(describing: self.rawVariables)), " - string += "rawMethods = \(String(describing: self.rawMethods)), " - string += "rawSubscripts = \(String(describing: self.rawSubscripts)), " - string += "initializers = \(String(describing: self.initializers)), " - string += "annotations = \(String(describing: self.annotations)), " - string += "documentation = \(String(describing: self.documentation)), " - string += "staticVariables = \(String(describing: self.staticVariables)), " - string += "staticMethods = \(String(describing: self.staticMethods)), " - string += "classMethods = \(String(describing: self.classMethods)), " - string += "instanceVariables = \(String(describing: self.instanceVariables)), " - string += "instanceMethods = \(String(describing: self.instanceMethods)), " - string += "computedVariables = \(String(describing: self.computedVariables)), " - string += "storedVariables = \(String(describing: self.storedVariables)), " - string += "inheritedTypes = \(String(describing: self.inheritedTypes)), " - string += "inherits = \(String(describing: self.inherits)), " - string += "containedTypes = \(String(describing: self.containedTypes)), " - string += "parentName = \(String(describing: self.parentName)), " - string += "parentTypes = \(String(describing: self.parentTypes)), " - string += "attributes = \(String(describing: self.attributes)), " - string += "modifiers = \(String(describing: self.modifiers)), " - string += "fileName = \(String(describing: self.fileName))" - return string - } -} -extension Typealias { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "aliasName = \(String(describing: self.aliasName)), " - string += "typeName = \(String(describing: self.typeName)), " - string += "module = \(String(describing: self.module)), " - string += "accessLevel = \(String(describing: self.accessLevel)), " - string += "parentName = \(String(describing: self.parentName)), " - string += "name = \(String(describing: self.name))" - return string - } -} -extension Types { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "types = \(String(describing: self.types)), " - string += "typealiases = \(String(describing: self.typealiases))" - return string - } -} -extension Variable { - /// :nodoc: - override public var description: String { - var string = "\(Swift.type(of: self)): " - string += "name = \(String(describing: self.name)), " - string += "typeName = \(String(describing: self.typeName)), " - string += "isComputed = \(String(describing: self.isComputed)), " - string += "isAsync = \(String(describing: self.isAsync)), " - string += "`throws` = \(String(describing: self.`throws`)), " - string += "isStatic = \(String(describing: self.isStatic)), " - string += "readAccess = \(String(describing: self.readAccess)), " - string += "writeAccess = \(String(describing: self.writeAccess)), " - string += "accessLevel = \(String(describing: self.accessLevel)), " - string += "isMutable = \(String(describing: self.isMutable)), " - string += "defaultValue = \(String(describing: self.defaultValue)), " - string += "annotations = \(String(describing: self.annotations)), " - string += "documentation = \(String(describing: self.documentation)), " - string += "attributes = \(String(describing: self.attributes)), " - string += "modifiers = \(String(describing: self.modifiers)), " - string += "isFinal = \(String(describing: self.isFinal)), " - string += "isLazy = \(String(describing: self.isLazy)), " - string += "definedInTypeName = \(String(describing: self.definedInTypeName)), " - string += "actualDefinedInTypeName = \(String(describing: self.actualDefinedInTypeName))" - return string - } -} diff --git a/SourceryRuntime/Sources/Generated/Diffable.generated.swift b/SourceryRuntime/Sources/Generated/Diffable.generated.swift deleted file mode 100644 index ddeb8e3c9..000000000 --- a/SourceryRuntime/Sources/Generated/Diffable.generated.swift +++ /dev/null @@ -1,465 +0,0 @@ -// Generated using Sourcery 2.0.3 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT -import Foundation - -extension Actor { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Actor else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension ArrayType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? ArrayType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "elementTypeName").trackDifference(actual: self.elementTypeName, expected: castObject.elementTypeName)) - return results - } -} -extension AssociatedType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? AssociatedType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - return results - } -} -extension AssociatedValue: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? AssociatedValue else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) - results.append(contentsOf: DiffableResult(identifier: "externalName").trackDifference(actual: self.externalName, expected: castObject.externalName)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - return results - } -} -extension Attribute: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Attribute else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "arguments").trackDifference(actual: self.arguments, expected: castObject.arguments)) - results.append(contentsOf: DiffableResult(identifier: "_description").trackDifference(actual: self._description, expected: castObject._description)) - return results - } -} -extension BytesRange: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? BytesRange else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "offset").trackDifference(actual: self.offset, expected: castObject.offset)) - results.append(contentsOf: DiffableResult(identifier: "length").trackDifference(actual: self.length, expected: castObject.length)) - return results - } -} -extension Class { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Class else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension ClosureType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? ClosureType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) - results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) - results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) - results.append(contentsOf: DiffableResult(identifier: "asyncKeyword").trackDifference(actual: self.asyncKeyword, expected: castObject.asyncKeyword)) - results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) - results.append(contentsOf: DiffableResult(identifier: "throwsOrRethrowsKeyword").trackDifference(actual: self.throwsOrRethrowsKeyword, expected: castObject.throwsOrRethrowsKeyword)) - return results - } -} -extension DictionaryType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? DictionaryType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "valueTypeName").trackDifference(actual: self.valueTypeName, expected: castObject.valueTypeName)) - results.append(contentsOf: DiffableResult(identifier: "keyTypeName").trackDifference(actual: self.keyTypeName, expected: castObject.keyTypeName)) - return results - } -} -extension Enum { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Enum else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "cases").trackDifference(actual: self.cases, expected: castObject.cases)) - results.append(contentsOf: DiffableResult(identifier: "rawTypeName").trackDifference(actual: self.rawTypeName, expected: castObject.rawTypeName)) - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension EnumCase: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? EnumCase else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "rawValue").trackDifference(actual: self.rawValue, expected: castObject.rawValue)) - results.append(contentsOf: DiffableResult(identifier: "associatedValues").trackDifference(actual: self.associatedValues, expected: castObject.associatedValues)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) - results.append(contentsOf: DiffableResult(identifier: "indirect").trackDifference(actual: self.indirect, expected: castObject.indirect)) - return results - } -} -extension FileParserResult: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? FileParserResult else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "path").trackDifference(actual: self.path, expected: castObject.path)) - results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) - results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) - results.append(contentsOf: DiffableResult(identifier: "functions").trackDifference(actual: self.functions, expected: castObject.functions)) - results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) - results.append(contentsOf: DiffableResult(identifier: "inlineRanges").trackDifference(actual: self.inlineRanges, expected: castObject.inlineRanges)) - results.append(contentsOf: DiffableResult(identifier: "inlineIndentations").trackDifference(actual: self.inlineIndentations, expected: castObject.inlineIndentations)) - results.append(contentsOf: DiffableResult(identifier: "modifiedDate").trackDifference(actual: self.modifiedDate, expected: castObject.modifiedDate)) - results.append(contentsOf: DiffableResult(identifier: "sourceryVersion").trackDifference(actual: self.sourceryVersion, expected: castObject.sourceryVersion)) - return results - } -} -extension GenericRequirement: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? GenericRequirement else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "leftType").trackDifference(actual: self.leftType, expected: castObject.leftType)) - results.append(contentsOf: DiffableResult(identifier: "rightType").trackDifference(actual: self.rightType, expected: castObject.rightType)) - results.append(contentsOf: DiffableResult(identifier: "relationship").trackDifference(actual: self.relationship, expected: castObject.relationship)) - results.append(contentsOf: DiffableResult(identifier: "relationshipSyntax").trackDifference(actual: self.relationshipSyntax, expected: castObject.relationshipSyntax)) - return results - } -} -extension GenericType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? GenericType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "typeParameters").trackDifference(actual: self.typeParameters, expected: castObject.typeParameters)) - return results - } -} -extension GenericTypeParameter: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? GenericTypeParameter else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - return results - } -} -extension Import: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Import else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "kind").trackDifference(actual: self.kind, expected: castObject.kind)) - results.append(contentsOf: DiffableResult(identifier: "path").trackDifference(actual: self.path, expected: castObject.path)) - return results - } -} -extension Method: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Method else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "selectorName").trackDifference(actual: self.selectorName, expected: castObject.selectorName)) - results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) - results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) - results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) - results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) - results.append(contentsOf: DiffableResult(identifier: "`rethrows`").trackDifference(actual: self.`rethrows`, expected: castObject.`rethrows`)) - results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) - results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) - results.append(contentsOf: DiffableResult(identifier: "isClass").trackDifference(actual: self.isClass, expected: castObject.isClass)) - results.append(contentsOf: DiffableResult(identifier: "isFailableInitializer").trackDifference(actual: self.isFailableInitializer, expected: castObject.isFailableInitializer)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) - results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) - results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) - results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) - return results - } -} -extension MethodParameter: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? MethodParameter else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "argumentLabel").trackDifference(actual: self.argumentLabel, expected: castObject.argumentLabel)) - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - results.append(contentsOf: DiffableResult(identifier: "`inout`").trackDifference(actual: self.`inout`, expected: castObject.`inout`)) - results.append(contentsOf: DiffableResult(identifier: "isVariadic").trackDifference(actual: self.isVariadic, expected: castObject.isVariadic)) - results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - return results - } -} -extension Modifier: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Modifier else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "detail").trackDifference(actual: self.detail, expected: castObject.detail)) - return results - } -} -extension Protocol { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Protocol else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "associatedTypes").trackDifference(actual: self.associatedTypes, expected: castObject.associatedTypes)) - results.append(contentsOf: DiffableResult(identifier: "genericRequirements").trackDifference(actual: self.genericRequirements, expected: castObject.genericRequirements)) - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension ProtocolComposition { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? ProtocolComposition else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "composedTypeNames").trackDifference(actual: self.composedTypeNames, expected: castObject.composedTypeNames)) - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension Struct { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Struct else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension Subscript: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Subscript else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) - results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) - results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) - results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) - results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) - results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) - results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) - return results - } -} -extension TemplateContext: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? TemplateContext else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "parserResult").trackDifference(actual: self.parserResult, expected: castObject.parserResult)) - results.append(contentsOf: DiffableResult(identifier: "functions").trackDifference(actual: self.functions, expected: castObject.functions)) - results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) - results.append(contentsOf: DiffableResult(identifier: "argument").trackDifference(actual: self.argument, expected: castObject.argument)) - return results - } -} -extension TupleElement: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? TupleElement else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - return results - } -} -extension TupleType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? TupleType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "elements").trackDifference(actual: self.elements, expected: castObject.elements)) - return results - } -} -extension Type: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Type else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) - results.append(contentsOf: DiffableResult(identifier: "imports").trackDifference(actual: self.imports, expected: castObject.imports)) - results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) - results.append(contentsOf: DiffableResult(identifier: "isExtension").trackDifference(actual: self.isExtension, expected: castObject.isExtension)) - results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) - results.append(contentsOf: DiffableResult(identifier: "isUnknownExtension").trackDifference(actual: self.isUnknownExtension, expected: castObject.isUnknownExtension)) - results.append(contentsOf: DiffableResult(identifier: "isGeneric").trackDifference(actual: self.isGeneric, expected: castObject.isGeneric)) - results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) - results.append(contentsOf: DiffableResult(identifier: "rawVariables").trackDifference(actual: self.rawVariables, expected: castObject.rawVariables)) - results.append(contentsOf: DiffableResult(identifier: "rawMethods").trackDifference(actual: self.rawMethods, expected: castObject.rawMethods)) - results.append(contentsOf: DiffableResult(identifier: "rawSubscripts").trackDifference(actual: self.rawSubscripts, expected: castObject.rawSubscripts)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) - results.append(contentsOf: DiffableResult(identifier: "inheritedTypes").trackDifference(actual: self.inheritedTypes, expected: castObject.inheritedTypes)) - results.append(contentsOf: DiffableResult(identifier: "inherits").trackDifference(actual: self.inherits, expected: castObject.inherits)) - results.append(contentsOf: DiffableResult(identifier: "containedTypes").trackDifference(actual: self.containedTypes, expected: castObject.containedTypes)) - results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) - results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) - results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) - results.append(contentsOf: DiffableResult(identifier: "fileName").trackDifference(actual: self.fileName, expected: castObject.fileName)) - return results - } -} -extension TypeName: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? TypeName else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "generic").trackDifference(actual: self.generic, expected: castObject.generic)) - results.append(contentsOf: DiffableResult(identifier: "isProtocolComposition").trackDifference(actual: self.isProtocolComposition, expected: castObject.isProtocolComposition)) - results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) - results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) - results.append(contentsOf: DiffableResult(identifier: "tuple").trackDifference(actual: self.tuple, expected: castObject.tuple)) - results.append(contentsOf: DiffableResult(identifier: "array").trackDifference(actual: self.array, expected: castObject.array)) - results.append(contentsOf: DiffableResult(identifier: "dictionary").trackDifference(actual: self.dictionary, expected: castObject.dictionary)) - results.append(contentsOf: DiffableResult(identifier: "closure").trackDifference(actual: self.closure, expected: castObject.closure)) - return results - } -} -extension Typealias: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Typealias else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "aliasName").trackDifference(actual: self.aliasName, expected: castObject.aliasName)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) - results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) - results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) - return results - } -} -extension Types: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Types else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) - results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) - return results - } -} -extension Variable: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Variable else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - results.append(contentsOf: DiffableResult(identifier: "isComputed").trackDifference(actual: self.isComputed, expected: castObject.isComputed)) - results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) - results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) - results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) - results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) - results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) - results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) - results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) - results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) - results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) - return results - } -} diff --git a/SourceryRuntime/Sources/Generated/Equality.generated.swift b/SourceryRuntime/Sources/Generated/Equality.generated.swift deleted file mode 100644 index d86cc9556..000000000 --- a/SourceryRuntime/Sources/Generated/Equality.generated.swift +++ /dev/null @@ -1,780 +0,0 @@ -// Generated using Sourcery 2.0.3 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT -// swiftlint:disable vertical_whitespace - - -extension Actor { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Actor else { return false } - return super.isEqual(rhs) - } -} -extension ArrayType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? ArrayType else { return false } - if self.name != rhs.name { return false } - if self.elementTypeName != rhs.elementTypeName { return false } - return true - } -} -extension AssociatedType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? AssociatedType else { return false } - if self.name != rhs.name { return false } - if self.typeName != rhs.typeName { return false } - return true - } -} -extension AssociatedValue { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? AssociatedValue else { return false } - if self.localName != rhs.localName { return false } - if self.externalName != rhs.externalName { return false } - if self.typeName != rhs.typeName { return false } - if self.defaultValue != rhs.defaultValue { return false } - if self.annotations != rhs.annotations { return false } - return true - } -} -extension Attribute { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Attribute else { return false } - if self.name != rhs.name { return false } - if self.arguments != rhs.arguments { return false } - if self._description != rhs._description { return false } - return true - } -} -extension BytesRange { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? BytesRange else { return false } - if self.offset != rhs.offset { return false } - if self.length != rhs.length { return false } - return true - } -} -extension Class { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Class else { return false } - return super.isEqual(rhs) - } -} -extension ClosureParameter { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? ClosureParameter else { return false } - if self.argumentLabel != rhs.argumentLabel { return false } - if self.name != rhs.name { return false } - if self.typeName != rhs.typeName { return false } - if self.`inout` != rhs.`inout` { return false } - if self.defaultValue != rhs.defaultValue { return false } - if self.annotations != rhs.annotations { return false } - return true - } -} -extension ClosureType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? ClosureType else { return false } - if self.name != rhs.name { return false } - if self.parameters != rhs.parameters { return false } - if self.returnTypeName != rhs.returnTypeName { return false } - if self.isAsync != rhs.isAsync { return false } - if self.asyncKeyword != rhs.asyncKeyword { return false } - if self.`throws` != rhs.`throws` { return false } - if self.throwsOrRethrowsKeyword != rhs.throwsOrRethrowsKeyword { return false } - return true - } -} -extension DictionaryType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? DictionaryType else { return false } - if self.name != rhs.name { return false } - if self.valueTypeName != rhs.valueTypeName { return false } - if self.keyTypeName != rhs.keyTypeName { return false } - return true - } -} -extension DiffableResult { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? DiffableResult else { return false } - if self.identifier != rhs.identifier { return false } - return true - } -} -extension Enum { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Enum else { return false } - if self.cases != rhs.cases { return false } - if self.rawTypeName != rhs.rawTypeName { return false } - return super.isEqual(rhs) - } -} -extension EnumCase { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? EnumCase else { return false } - if self.name != rhs.name { return false } - if self.rawValue != rhs.rawValue { return false } - if self.associatedValues != rhs.associatedValues { return false } - if self.annotations != rhs.annotations { return false } - if self.documentation != rhs.documentation { return false } - if self.indirect != rhs.indirect { return false } - return true - } -} -extension FileParserResult { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? FileParserResult else { return false } - if self.path != rhs.path { return false } - if self.module != rhs.module { return false } - if self.types != rhs.types { return false } - if self.functions != rhs.functions { return false } - if self.typealiases != rhs.typealiases { return false } - if self.inlineRanges != rhs.inlineRanges { return false } - if self.inlineIndentations != rhs.inlineIndentations { return false } - if self.modifiedDate != rhs.modifiedDate { return false } - if self.sourceryVersion != rhs.sourceryVersion { return false } - return true - } -} -extension GenericRequirement { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? GenericRequirement else { return false } - if self.leftType != rhs.leftType { return false } - if self.rightType != rhs.rightType { return false } - if self.relationship != rhs.relationship { return false } - if self.relationshipSyntax != rhs.relationshipSyntax { return false } - return true - } -} -extension GenericType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? GenericType else { return false } - if self.name != rhs.name { return false } - if self.typeParameters != rhs.typeParameters { return false } - return true - } -} -extension GenericTypeParameter { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? GenericTypeParameter else { return false } - if self.typeName != rhs.typeName { return false } - return true - } -} -extension Import { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Import else { return false } - if self.kind != rhs.kind { return false } - if self.path != rhs.path { return false } - return true - } -} -extension Method { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Method else { return false } - if self.name != rhs.name { return false } - if self.selectorName != rhs.selectorName { return false } - if self.parameters != rhs.parameters { return false } - if self.returnTypeName != rhs.returnTypeName { return false } - if self.isAsync != rhs.isAsync { return false } - if self.`throws` != rhs.`throws` { return false } - if self.`rethrows` != rhs.`rethrows` { return false } - if self.accessLevel != rhs.accessLevel { return false } - if self.isStatic != rhs.isStatic { return false } - if self.isClass != rhs.isClass { return false } - if self.isFailableInitializer != rhs.isFailableInitializer { return false } - if self.annotations != rhs.annotations { return false } - if self.documentation != rhs.documentation { return false } - if self.definedInTypeName != rhs.definedInTypeName { return false } - if self.attributes != rhs.attributes { return false } - if self.modifiers != rhs.modifiers { return false } - return true - } -} -extension MethodParameter { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? MethodParameter else { return false } - if self.argumentLabel != rhs.argumentLabel { return false } - if self.name != rhs.name { return false } - if self.typeName != rhs.typeName { return false } - if self.`inout` != rhs.`inout` { return false } - if self.isVariadic != rhs.isVariadic { return false } - if self.defaultValue != rhs.defaultValue { return false } - if self.annotations != rhs.annotations { return false } - return true - } -} -extension Modifier { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Modifier else { return false } - if self.name != rhs.name { return false } - if self.detail != rhs.detail { return false } - return true - } -} -extension Protocol { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Protocol else { return false } - if self.associatedTypes != rhs.associatedTypes { return false } - if self.genericRequirements != rhs.genericRequirements { return false } - return super.isEqual(rhs) - } -} -extension ProtocolComposition { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? ProtocolComposition else { return false } - if self.composedTypeNames != rhs.composedTypeNames { return false } - return super.isEqual(rhs) - } -} -extension Struct { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Struct else { return false } - return super.isEqual(rhs) - } -} -extension Subscript { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Subscript else { return false } - if self.parameters != rhs.parameters { return false } - if self.returnTypeName != rhs.returnTypeName { return false } - if self.readAccess != rhs.readAccess { return false } - if self.writeAccess != rhs.writeAccess { return false } - if self.annotations != rhs.annotations { return false } - if self.documentation != rhs.documentation { return false } - if self.definedInTypeName != rhs.definedInTypeName { return false } - if self.attributes != rhs.attributes { return false } - if self.modifiers != rhs.modifiers { return false } - return true - } -} -extension TemplateContext { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? TemplateContext else { return false } - if self.parserResult != rhs.parserResult { return false } - if self.functions != rhs.functions { return false } - if self.types != rhs.types { return false } - if self.argument != rhs.argument { return false } - return true - } -} -extension TupleElement { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? TupleElement else { return false } - if self.name != rhs.name { return false } - if self.typeName != rhs.typeName { return false } - return true - } -} -extension TupleType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? TupleType else { return false } - if self.name != rhs.name { return false } - if self.elements != rhs.elements { return false } - return true - } -} -extension Type { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Type else { return false } - if self.module != rhs.module { return false } - if self.imports != rhs.imports { return false } - if self.typealiases != rhs.typealiases { return false } - if self.isExtension != rhs.isExtension { return false } - if self.accessLevel != rhs.accessLevel { return false } - if self.isUnknownExtension != rhs.isUnknownExtension { return false } - if self.isGeneric != rhs.isGeneric { return false } - if self.localName != rhs.localName { return false } - if self.rawVariables != rhs.rawVariables { return false } - if self.rawMethods != rhs.rawMethods { return false } - if self.rawSubscripts != rhs.rawSubscripts { return false } - if self.annotations != rhs.annotations { return false } - if self.documentation != rhs.documentation { return false } - if self.inheritedTypes != rhs.inheritedTypes { return false } - if self.inherits != rhs.inherits { return false } - if self.containedTypes != rhs.containedTypes { return false } - if self.parentName != rhs.parentName { return false } - if self.attributes != rhs.attributes { return false } - if self.modifiers != rhs.modifiers { return false } - if self.fileName != rhs.fileName { return false } - if self.kind != rhs.kind { return false } - return true - } -} -extension TypeName { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? TypeName else { return false } - if self.name != rhs.name { return false } - if self.generic != rhs.generic { return false } - if self.isProtocolComposition != rhs.isProtocolComposition { return false } - if self.attributes != rhs.attributes { return false } - if self.modifiers != rhs.modifiers { return false } - if self.tuple != rhs.tuple { return false } - if self.array != rhs.array { return false } - if self.dictionary != rhs.dictionary { return false } - if self.closure != rhs.closure { return false } - return true - } -} -extension Typealias { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Typealias else { return false } - if self.aliasName != rhs.aliasName { return false } - if self.typeName != rhs.typeName { return false } - if self.module != rhs.module { return false } - if self.accessLevel != rhs.accessLevel { return false } - if self.parentName != rhs.parentName { return false } - return true - } -} -extension Types { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Types else { return false } - if self.types != rhs.types { return false } - if self.typealiases != rhs.typealiases { return false } - return true - } -} -extension Variable { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Variable else { return false } - if self.name != rhs.name { return false } - if self.typeName != rhs.typeName { return false } - if self.isComputed != rhs.isComputed { return false } - if self.isAsync != rhs.isAsync { return false } - if self.`throws` != rhs.`throws` { return false } - if self.isStatic != rhs.isStatic { return false } - if self.readAccess != rhs.readAccess { return false } - if self.writeAccess != rhs.writeAccess { return false } - if self.defaultValue != rhs.defaultValue { return false } - if self.annotations != rhs.annotations { return false } - if self.documentation != rhs.documentation { return false } - if self.attributes != rhs.attributes { return false } - if self.modifiers != rhs.modifiers { return false } - if self.definedInTypeName != rhs.definedInTypeName { return false } - return true - } -} - -// MARK: - Actor AutoHashable -extension Actor { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - ArrayType AutoHashable -extension ArrayType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.elementTypeName) - return hasher.finalize() - } -} -// MARK: - AssociatedType AutoHashable -extension AssociatedType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.typeName) - return hasher.finalize() - } -} -// MARK: - AssociatedValue AutoHashable -extension AssociatedValue { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.localName) - hasher.combine(self.externalName) - hasher.combine(self.typeName) - hasher.combine(self.defaultValue) - hasher.combine(self.annotations) - return hasher.finalize() - } -} -// MARK: - Attribute AutoHashable -extension Attribute { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.arguments) - hasher.combine(self._description) - return hasher.finalize() - } -} -// MARK: - BytesRange AutoHashable -extension BytesRange { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.offset) - hasher.combine(self.length) - return hasher.finalize() - } -} -// MARK: - Class AutoHashable -extension Class { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - ClosureParameter AutoHashable -extension ClosureParameter { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.argumentLabel) - hasher.combine(self.name) - hasher.combine(self.typeName) - hasher.combine(self.`inout`) - hasher.combine(self.defaultValue) - hasher.combine(self.annotations) - return hasher.finalize() - } -} -// MARK: - ClosureType AutoHashable -extension ClosureType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.parameters) - hasher.combine(self.returnTypeName) - hasher.combine(self.isAsync) - hasher.combine(self.asyncKeyword) - hasher.combine(self.`throws`) - hasher.combine(self.throwsOrRethrowsKeyword) - return hasher.finalize() - } -} -// MARK: - DictionaryType AutoHashable -extension DictionaryType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.valueTypeName) - hasher.combine(self.keyTypeName) - return hasher.finalize() - } -} -// MARK: - DiffableResult AutoHashable -extension DiffableResult { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.identifier) - return hasher.finalize() - } -} -// MARK: - Enum AutoHashable -extension Enum { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.cases) - hasher.combine(self.rawTypeName) - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - EnumCase AutoHashable -extension EnumCase { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.rawValue) - hasher.combine(self.associatedValues) - hasher.combine(self.annotations) - hasher.combine(self.documentation) - hasher.combine(self.indirect) - return hasher.finalize() - } -} -// MARK: - FileParserResult AutoHashable -extension FileParserResult { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.path) - hasher.combine(self.module) - hasher.combine(self.types) - hasher.combine(self.functions) - hasher.combine(self.typealiases) - hasher.combine(self.inlineRanges) - hasher.combine(self.inlineIndentations) - hasher.combine(self.modifiedDate) - hasher.combine(self.sourceryVersion) - return hasher.finalize() - } -} -// MARK: - GenericRequirement AutoHashable -extension GenericRequirement { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.leftType) - hasher.combine(self.rightType) - hasher.combine(self.relationship) - hasher.combine(self.relationshipSyntax) - return hasher.finalize() - } -} -// MARK: - GenericType AutoHashable -extension GenericType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.typeParameters) - return hasher.finalize() - } -} -// MARK: - GenericTypeParameter AutoHashable -extension GenericTypeParameter { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.typeName) - return hasher.finalize() - } -} -// MARK: - Import AutoHashable -extension Import { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.kind) - hasher.combine(self.path) - return hasher.finalize() - } -} -// MARK: - Method AutoHashable -extension Method { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.selectorName) - hasher.combine(self.parameters) - hasher.combine(self.returnTypeName) - hasher.combine(self.isAsync) - hasher.combine(self.`throws`) - hasher.combine(self.`rethrows`) - hasher.combine(self.accessLevel) - hasher.combine(self.isStatic) - hasher.combine(self.isClass) - hasher.combine(self.isFailableInitializer) - hasher.combine(self.annotations) - hasher.combine(self.documentation) - hasher.combine(self.definedInTypeName) - hasher.combine(self.attributes) - hasher.combine(self.modifiers) - return hasher.finalize() - } -} -// MARK: - MethodParameter AutoHashable -extension MethodParameter { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.argumentLabel) - hasher.combine(self.name) - hasher.combine(self.typeName) - hasher.combine(self.`inout`) - hasher.combine(self.isVariadic) - hasher.combine(self.defaultValue) - hasher.combine(self.annotations) - return hasher.finalize() - } -} -// MARK: - Modifier AutoHashable -extension Modifier { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.detail) - return hasher.finalize() - } -} -// MARK: - Protocol AutoHashable -extension Protocol { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.associatedTypes) - hasher.combine(self.genericRequirements) - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - ProtocolComposition AutoHashable -extension ProtocolComposition { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.composedTypeNames) - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - Struct AutoHashable -extension Struct { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - Subscript AutoHashable -extension Subscript { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.parameters) - hasher.combine(self.returnTypeName) - hasher.combine(self.readAccess) - hasher.combine(self.writeAccess) - hasher.combine(self.annotations) - hasher.combine(self.documentation) - hasher.combine(self.definedInTypeName) - hasher.combine(self.attributes) - hasher.combine(self.modifiers) - return hasher.finalize() - } -} -// MARK: - TemplateContext AutoHashable -extension TemplateContext { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.parserResult) - hasher.combine(self.functions) - hasher.combine(self.types) - hasher.combine(self.argument) - return hasher.finalize() - } -} -// MARK: - TupleElement AutoHashable -extension TupleElement { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.typeName) - return hasher.finalize() - } -} -// MARK: - TupleType AutoHashable -extension TupleType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.elements) - return hasher.finalize() - } -} -// MARK: - Type AutoHashable -extension Type { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.module) - hasher.combine(self.imports) - hasher.combine(self.typealiases) - hasher.combine(self.isExtension) - hasher.combine(self.accessLevel) - hasher.combine(self.isUnknownExtension) - hasher.combine(self.isGeneric) - hasher.combine(self.localName) - hasher.combine(self.rawVariables) - hasher.combine(self.rawMethods) - hasher.combine(self.rawSubscripts) - hasher.combine(self.annotations) - hasher.combine(self.documentation) - hasher.combine(self.inheritedTypes) - hasher.combine(self.inherits) - hasher.combine(self.containedTypes) - hasher.combine(self.parentName) - hasher.combine(self.attributes) - hasher.combine(self.modifiers) - hasher.combine(self.fileName) - hasher.combine(kind) - return hasher.finalize() - } -} -// MARK: - TypeName AutoHashable -extension TypeName { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.generic) - hasher.combine(self.isProtocolComposition) - hasher.combine(self.attributes) - hasher.combine(self.modifiers) - hasher.combine(self.tuple) - hasher.combine(self.array) - hasher.combine(self.dictionary) - hasher.combine(self.closure) - return hasher.finalize() - } -} -// MARK: - Typealias AutoHashable -extension Typealias { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.aliasName) - hasher.combine(self.typeName) - hasher.combine(self.module) - hasher.combine(self.accessLevel) - hasher.combine(self.parentName) - return hasher.finalize() - } -} -// MARK: - Types AutoHashable -extension Types { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.types) - hasher.combine(self.typealiases) - return hasher.finalize() - } -} -// MARK: - Variable AutoHashable -extension Variable { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.typeName) - hasher.combine(self.isComputed) - hasher.combine(self.isAsync) - hasher.combine(self.`throws`) - hasher.combine(self.isStatic) - hasher.combine(self.readAccess) - hasher.combine(self.writeAccess) - hasher.combine(self.defaultValue) - hasher.combine(self.annotations) - hasher.combine(self.documentation) - hasher.combine(self.attributes) - hasher.combine(self.modifiers) - hasher.combine(self.definedInTypeName) - return hasher.finalize() - } -} diff --git a/SourceryRuntime/Sources/Generated/JSExport.generated.swift b/SourceryRuntime/Sources/Generated/JSExport.generated.swift index 355f26a6f..eff03fbb1 100644 --- a/SourceryRuntime/Sources/Generated/JSExport.generated.swift +++ b/SourceryRuntime/Sources/Generated/JSExport.generated.swift @@ -1,7 +1,7 @@ // Generated using Sourcery 2.0.3 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT // swiftlint:disable vertical_whitespace trailing_newline - +#if canImport(JavaScriptCore) import JavaScriptCore @objc protocol ActorAutoJSExport: JSExport { @@ -684,3 +684,4 @@ extension TypesCollection: TypesCollectionAutoJSExport {} extension Variable: VariableAutoJSExport {} +#endif diff --git a/SourceryRuntime/Sources/Log.swift b/SourceryRuntime/Sources/Log.swift index 6df579b32..dc9f11545 100644 --- a/SourceryRuntime/Sources/Log.swift +++ b/SourceryRuntime/Sources/Log.swift @@ -1,4 +1,4 @@ -import Darwin +//import Darwin import Foundation /// :nodoc: @@ -21,7 +21,7 @@ public enum Log { public static func error(_ message: Any) { log(level: .errors, "error: \(message)") // to return error when running swift templates which is done in a different process - if ProcessInfo().processName != "Sourcery" { + if ProcessInfo.processInfo.processName != "Sourcery" { fputs("\(message)", stderr) } } diff --git a/SourceryRuntime/Sources/TemplateContext.swift b/SourceryRuntime/Sources/TemplateContext.swift index 1412931f2..3440fdab8 100644 --- a/SourceryRuntime/Sources/TemplateContext.swift +++ b/SourceryRuntime/Sources/TemplateContext.swift @@ -7,7 +7,10 @@ import Foundation /// :nodoc: // sourcery: skipCoding -@objcMembers public final class TemplateContext: NSObject, SourceryModel, NSCoding { +#if canImport(ObjectiveC) +@objcMembers +#endif +public final class TemplateContext: NSObject, SourceryModel, NSCoding, Diffable { // sourcery: skipJSExport public let parserResult: FileParserResult? public let functions: [SourceryMethod] @@ -28,8 +31,18 @@ import Foundation /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let parserResult: FileParserResult = aDecoder.decode(forKey: "parserResult") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found. FileParserResults are required for template context that needs persisting.", arguments: getVaList(["parserResult"])); fatalError() } - guard let argument: [String: NSObject] = aDecoder.decode(forKey: "argument") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["argument"])); fatalError() } + guard let parserResult: FileParserResult = aDecoder.decode(forKey: "parserResult") else { + withVaList(["parserResult"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found. FileParserResults are required for template context that needs persisting.", arguments: arguments) + } + fatalError() + } + guard let argument: [String: NSObject] = aDecoder.decode(forKey: "argument") else { + withVaList(["argument"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + } // if we want to support multiple cycles of encode / decode we need deep copy because composer changes reference types let fileParserResultCopy: FileParserResult? = nil @@ -58,6 +71,49 @@ import Foundation ] } + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "parserResult = \(String(describing: self.parserResult)), " + string += "functions = \(String(describing: self.functions)), " + string += "types = \(String(describing: self.types)), " + string += "argument = \(String(describing: self.argument)), " + string += "stencilContext = \(String(describing: self.stencilContext))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TemplateContext else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "parserResult").trackDifference(actual: self.parserResult, expected: castObject.parserResult)) + results.append(contentsOf: DiffableResult(identifier: "functions").trackDifference(actual: self.functions, expected: castObject.functions)) + results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) + results.append(contentsOf: DiffableResult(identifier: "argument").trackDifference(actual: self.argument, expected: castObject.argument)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.parserResult) + hasher.combine(self.functions) + hasher.combine(self.types) + hasher.combine(self.argument) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TemplateContext else { return false } + if self.parserResult != rhs.parserResult { return false } + if self.functions != rhs.functions { return false } + if self.types != rhs.types { return false } + if self.argument != rhs.argument { return false } + return true + } + // sourcery: skipDescription, skipEquality public var jsContext: [String: Any] { return [ @@ -72,7 +128,7 @@ import Foundation "inheriting": types.inheriting, "implementing": types.implementing, "protocolCompositions": types.protocolCompositions - ], + ] as [String : Any], "functions": functions, "type": types.typesByName, "argument": argument @@ -87,208 +143,3 @@ extension ProcessInfo { return NSKeyedUnarchiver.unarchiveObject(withFile: arguments[1]) as? TemplateContext } } - -// sourcery: skipJSExport -/// Collection of scanned types for accessing in templates -@objcMembers public final class Types: NSObject, SourceryModel { - - /// :nodoc: - public let types: [Type] - - /// All known typealiases - public let typealiases: [Typealias] - - /// :nodoc: - public init(types: [Type], typealiases: [Typealias] = []) { - self.types = types - self.typealiases = typealiases - } - -// sourcery:inline:Types.AutoCoding - - /// :nodoc: - required public init?(coder aDecoder: NSCoder) { - guard let types: [Type] = aDecoder.decode(forKey: "types") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["types"])); fatalError() }; self.types = types - guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typealiases"])); fatalError() }; self.typealiases = typealiases - } - - /// :nodoc: - public func encode(with aCoder: NSCoder) { - aCoder.encode(self.types, forKey: "types") - aCoder.encode(self.typealiases, forKey: "typealiases") - } -// sourcery:end - - // sourcery: skipDescription, skipEquality, skipCoding - /// :nodoc: - public lazy internal(set) var typesByName: [String: Type] = { - var typesByName = [String: Type]() - self.types.forEach { typesByName[$0.globalName] = $0 } - return typesByName - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// :nodoc: - public lazy internal(set) var typesaliasesByName: [String: Typealias] = { - var typesaliasesByName = [String: Typealias]() - self.typealiases.forEach { typesaliasesByName[$0.name] = $0 } - return typesaliasesByName - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// All known types, excluding protocols or protocol compositions. - public lazy internal(set) var all: [Type] = { - return self.types.filter { !($0 is Protocol || $0 is ProtocolComposition) } - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// All known protocols - public lazy internal(set) var protocols: [Protocol] = { - return self.types.compactMap { $0 as? Protocol } - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// All known protocol compositions - public lazy internal(set) var protocolCompositions: [ProtocolComposition] = { - return self.types.compactMap { $0 as? ProtocolComposition } - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// All known classes - public lazy internal(set) var classes: [Class] = { - return self.all.compactMap { $0 as? Class } - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// All known structs - public lazy internal(set) var structs: [Struct] = { - return self.all.compactMap { $0 as? Struct } - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// All known enums - public lazy internal(set) var enums: [Enum] = { - return self.all.compactMap { $0 as? Enum } - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// All known extensions - public lazy internal(set) var extensions: [Type] = { - return self.all.compactMap { $0.isExtension ? $0 : nil } - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// Types based on any other type, grouped by its name, even if they are not known. - /// `types.based.MyType` returns list of types based on `MyType` - public lazy internal(set) var based: TypesCollection = { - TypesCollection( - types: self.types, - collection: { Array($0.based.keys) } - ) - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// Classes inheriting from any known class, grouped by its name. - /// `types.inheriting.MyClass` returns list of types inheriting from `MyClass` - public lazy internal(set) var inheriting: TypesCollection = { - TypesCollection( - types: self.types, - collection: { Array($0.inherits.keys) }, - validate: { type in - guard type is Class else { - throw "\(type.name) is not a class and should be used with `implementing` or `based`" - } - }) - }() - - // sourcery: skipDescription, skipEquality, skipCoding - /// Types implementing known protocol, grouped by its name. - /// `types.implementing.MyProtocol` returns list of types implementing `MyProtocol` - public lazy internal(set) var implementing: TypesCollection = { - TypesCollection( - types: self.types, - collection: { Array($0.implements.keys) }, - validate: { type in - guard type is Protocol else { - throw "\(type.name) is a class and should be used with `inheriting` or `based`" - } - }) - }() -} - -/// :nodoc: -@objcMembers public class TypesCollection: NSObject, AutoJSExport { - - // sourcery:begin: skipJSExport - let all: [Type] - let types: [String: [Type]] - let validate: ((Type) throws -> Void)? - // sourcery:end - - init(types: [Type], collection: (Type) -> [String], validate: ((Type) throws -> Void)? = nil) { - self.all = types - var content = [String: [Type]]() - self.all.forEach { type in - collection(type).forEach { name in - var list = content[name] ?? [Type]() - list.append(type) - content[name] = list - } - } - self.types = content - self.validate = validate - } - - public func types(forKey key: String) throws -> [Type] { - // In some configurations, the types are keyed by "ModuleName.TypeName" - var longKey: String? - - if let validate = validate { - guard let type = all.first(where: { $0.name == key }) else { - throw "Unknown type \(key), should be used with `based`" - } - - try validate(type) - - if let module = type.module { - longKey = [module, type.name].joined(separator: ".") - } - } - - // If we find the types directly, return them - if let types = types[key] { - return types - } - - // if we find a types for the longKey, return them - if let longKey = longKey, let types = types[longKey] { - return types - } - - return [] - } - - /// :nodoc: - public override func value(forKey key: String) -> Any? { - do { - return try types(forKey: key) - } catch { - Log.error(error) - return nil - } - } - - /// :nodoc: - public subscript(_ key: String) -> [Type] { - do { - return try types(forKey: key) - } catch { - Log.error(error) - return [] - } - } - - public override func responds(to aSelector: Selector!) -> Bool { - return true - } -} diff --git a/SourceryRuntime/Sources/Types.swift b/SourceryRuntime/Sources/Types.swift new file mode 100644 index 000000000..32bced8cd --- /dev/null +++ b/SourceryRuntime/Sources/Types.swift @@ -0,0 +1,181 @@ +// +// Created by Krzysztof Zablocki on 31/12/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// + +#if canImport(ObjectiveC) +import Foundation + +// sourcery: skipJSExport +/// Collection of scanned types for accessing in templates +@objcMembers +public final class Types: NSObject, SourceryModel, Diffable { + + /// :nodoc: + public let types: [Type] + + /// All known typealiases + public let typealiases: [Typealias] + + /// :nodoc: + public init(types: [Type], typealiases: [Typealias] = []) { + self.types = types + self.typealiases = typealiases + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "types = \(String(describing: self.types)), " + string += "typealiases = \(String(describing: self.typealiases))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Types else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.types) + hasher.combine(self.typealiases) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Types else { return false } + if self.types != rhs.types { return false } + if self.typealiases != rhs.typealiases { return false } + return true + } + +// sourcery:inline:Types.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let types: [Type] = aDecoder.decode(forKey: "types") else { + withVaList(["types"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.types = types + guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.types, forKey: "types") + aCoder.encode(self.typealiases, forKey: "typealiases") + } +// sourcery:end + + // sourcery: skipDescription, skipEquality, skipCoding + /// :nodoc: + public lazy internal(set) var typesByName: [String: Type] = { + var typesByName = [String: Type]() + self.types.forEach { typesByName[$0.globalName] = $0 } + return typesByName + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// :nodoc: + public lazy internal(set) var typesaliasesByName: [String: Typealias] = { + var typesaliasesByName = [String: Typealias]() + self.typealiases.forEach { typesaliasesByName[$0.name] = $0 } + return typesaliasesByName + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known types, excluding protocols or protocol compositions. + public lazy internal(set) var all: [Type] = { + return self.types.filter { !($0 is Protocol || $0 is ProtocolComposition) } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known protocols + public lazy internal(set) var protocols: [Protocol] = { + return self.types.compactMap { $0 as? Protocol } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known protocol compositions + public lazy internal(set) var protocolCompositions: [ProtocolComposition] = { + return self.types.compactMap { $0 as? ProtocolComposition } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known classes + public lazy internal(set) var classes: [Class] = { + return self.all.compactMap { $0 as? Class } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known structs + public lazy internal(set) var structs: [Struct] = { + return self.all.compactMap { $0 as? Struct } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known enums + public lazy internal(set) var enums: [Enum] = { + return self.all.compactMap { $0 as? Enum } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known extensions + public lazy internal(set) var extensions: [Type] = { + return self.all.compactMap { $0.isExtension ? $0 : nil } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// Types based on any other type, grouped by its name, even if they are not known. + /// `types.based.MyType` returns list of types based on `MyType` + public lazy internal(set) var based: TypesCollection = { + TypesCollection( + types: self.types, + collection: { Array($0.based.keys) } + ) + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// Classes inheriting from any known class, grouped by its name. + /// `types.inheriting.MyClass` returns list of types inheriting from `MyClass` + public lazy internal(set) var inheriting: TypesCollection = { + TypesCollection( + types: self.types, + collection: { Array($0.inherits.keys) }, + validate: { type in + guard type is Class else { + throw "\(type.name) is not a class and should be used with `implementing` or `based`" + } + }) + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// Types implementing known protocol, grouped by its name. + /// `types.implementing.MyProtocol` returns list of types implementing `MyProtocol` + public lazy internal(set) var implementing: TypesCollection = { + TypesCollection( + types: self.types, + collection: { Array($0.implements.keys) }, + validate: { type in + guard type is Protocol else { + throw "\(type.name) is a class and should be used with `inheriting` or `based`" + } + }) + }() +} +#endif diff --git a/SourceryRuntime/Sources/TypesCollection.swift b/SourceryRuntime/Sources/TypesCollection.swift new file mode 100644 index 000000000..41e7a08bb --- /dev/null +++ b/SourceryRuntime/Sources/TypesCollection.swift @@ -0,0 +1,84 @@ +// +// Created by Krzysztof Zablocki on 31/12/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// +#if canImport(ObjectiveC) +import Foundation + +/// :nodoc: +@objcMembers +public class TypesCollection: NSObject, AutoJSExport { + // sourcery:begin: skipJSExport + let all: [Type] + let types: [String: [Type]] + let validate: ((Type) throws -> Void)? + // sourcery:end + + init(types: [Type], collection: (Type) -> [String], validate: ((Type) throws -> Void)? = nil) { + self.all = types + var content = [String: [Type]]() + self.all.forEach { type in + collection(type).forEach { name in + var list = content[name] ?? [Type]() + list.append(type) + content[name] = list + } + } + self.types = content + self.validate = validate + } + + public func types(forKey key: String) throws -> [Type] { + // In some configurations, the types are keyed by "ModuleName.TypeName" + var longKey: String? + + if let validate = validate { + guard let type = all.first(where: { $0.name == key }) else { + throw "Unknown type \(key), should be used with `based`" + } + + try validate(type) + + if let module = type.module { + longKey = [module, type.name].joined(separator: ".") + } + } + + // If we find the types directly, return them + if let types = types[key] { + return types + } + + // if we find a types for the longKey, return them + if let longKey = longKey, let types = types[longKey] { + return types + } + + return [] + } + + /// :nodoc: + override public func value(forKey key: String) -> Any? { + do { + return try types(forKey: key) + } catch { + Log.error(error) + return nil + } + } + + /// :nodoc: + public subscript(_ key: String) -> [Type] { + do { + return try types(forKey: key) + } catch { + Log.error(error) + return [] + } + } + + override public func responds(to aSelector: Selector!) -> Bool { + return true + } +} +#endif diff --git a/SourceryRuntime/Sources/TypesCollection_Linux.swift b/SourceryRuntime/Sources/TypesCollection_Linux.swift new file mode 100644 index 000000000..d1a7b3710 --- /dev/null +++ b/SourceryRuntime/Sources/TypesCollection_Linux.swift @@ -0,0 +1,87 @@ +// +// Created by Krzysztof Zablocki on 31/12/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// +#if !canImport(ObjectiveC) +import Foundation +// For DynamicMemberLookup we need to import Stencil, +// however, this is different from SourceryRuntime.content.generated.swift, because +// it cannot reference Stencil +import Stencil + +/// :nodoc: +public class TypesCollection: NSObject, AutoJSExport, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + return try? types(forKey: member) + } + + // sourcery:begin: skipJSExport + let all: [Type] + let types: [String: [Type]] + let validate: ((Type) throws -> Void)? + // sourcery:end + + init(types: [Type], collection: (Type) -> [String], validate: ((Type) throws -> Void)? = nil) { + self.all = types + var content = [String: [Type]]() + self.all.forEach { type in + collection(type).forEach { name in + var list = content[name] ?? [Type]() + list.append(type) + content[name] = list + } + } + self.types = content + self.validate = validate + } + + public func types(forKey key: String) throws -> [Type] { + // In some configurations, the types are keyed by "ModuleName.TypeName" + var longKey: String? + + if let validate = validate { + guard let type = all.first(where: { $0.name == key }) else { + throw "Unknown type \(key), should be used with `based`" + } + + try validate(type) + + if let module = type.module { + longKey = [module, type.name].joined(separator: ".") + } + } + + // If we find the types directly, return them + if let types = types[key] { + return types + } + + // if we find a types for the longKey, return them + if let longKey = longKey, let types = types[longKey] { + return types + } + + return [] + } + + /// :nodoc: + public func value(forKey key: String) -> Any? { + do { + return try types(forKey: key) + } catch { + Log.error(error) + return nil + } + } + + /// :nodoc: + public subscript(_ key: String) -> [Type] { + do { + return try types(forKey: key) + } catch { + Log.error(error) + return [] + } + } +} +#endif diff --git a/SourceryRuntime/Sources/Types_Linux.swift b/SourceryRuntime/Sources/Types_Linux.swift new file mode 100644 index 000000000..fd5b1b45b --- /dev/null +++ b/SourceryRuntime/Sources/Types_Linux.swift @@ -0,0 +1,209 @@ +// +// Created by Krzysztof Zablocki on 31/12/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// +#if !canImport(ObjectiveC) +import Foundation +// For DynamicMemberLookup we need to import Stencil, +// however, this is different from SourceryRuntime.content.generated.swift, because +// it cannot reference Stencil +import Stencil + +// sourcery: skipJSExport +/// Collection of scanned types for accessing in templates +public final class Types: NSObject, SourceryModel, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "types": + return types + case "enums": + return enums + case "all": + return all + case "protocols": + return protocols + case "classes": + return classes + case "structs": + return structs + case "extensions": + return extensions + case "implementing": + return implementing + case "inheriting": + return inheriting + case "based": + return based + default: + fatalError("unable to lookup: \(member) in \(self)") + } + } + + /// :nodoc: + public let types: [Type] + + /// All known typealiases + public let typealiases: [Typealias] + + /// :nodoc: + public init(types: [Type], typealiases: [Typealias] = []) { + self.types = types + self.typealiases = typealiases + } + + /// :nodoc: + override public var description: String { + var string = "\(Swift.type(of: self)): " + string += "types = \(String(describing: self.types)), " + string += "typealiases = \(String(describing: self.typealiases))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Types else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.types) + hasher.combine(self.typealiases) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Types else { return false } + if self.types != rhs.types { return false } + if self.typealiases != rhs.typealiases { return false } + return true + } + +// sourcery:inline:Types.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let types: [Type] = aDecoder.decode(forKey: "types") else { + withVaList(["types"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.types = types + guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.types, forKey: "types") + aCoder.encode(self.typealiases, forKey: "typealiases") + } +// sourcery:end + + // sourcery: skipDescription, skipEquality, skipCoding + /// :nodoc: + public lazy internal(set) var typesByName: [String: Type] = { + var typesByName = [String: Type]() + self.types.forEach { typesByName[$0.globalName] = $0 } + return typesByName + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// :nodoc: + public lazy internal(set) var typesaliasesByName: [String: Typealias] = { + var typesaliasesByName = [String: Typealias]() + self.typealiases.forEach { typesaliasesByName[$0.name] = $0 } + return typesaliasesByName + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known types, excluding protocols or protocol compositions. + public lazy internal(set) var all: [Type] = { + return self.types.filter { !($0 is Protocol || $0 is ProtocolComposition) } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known protocols + public lazy internal(set) var protocols: [Protocol] = { + return self.types.compactMap { $0 as? Protocol } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known protocol compositions + public lazy internal(set) var protocolCompositions: [ProtocolComposition] = { + return self.types.compactMap { $0 as? ProtocolComposition } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known classes + public lazy internal(set) var classes: [Class] = { + return self.all.compactMap { $0 as? Class } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known structs + public lazy internal(set) var structs: [Struct] = { + return self.all.compactMap { $0 as? Struct } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known enums + public lazy internal(set) var enums: [Enum] = { + return self.all.compactMap { $0 as? Enum } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known extensions + public lazy internal(set) var extensions: [Type] = { + return self.all.compactMap { $0.isExtension ? $0 : nil } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// Types based on any other type, grouped by its name, even if they are not known. + /// `types.based.MyType` returns list of types based on `MyType` + public lazy internal(set) var based: TypesCollection = { + TypesCollection( + types: self.types, + collection: { Array($0.based.keys) } + ) + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// Classes inheriting from any known class, grouped by its name. + /// `types.inheriting.MyClass` returns list of types inheriting from `MyClass` + public lazy internal(set) var inheriting: TypesCollection = { + TypesCollection( + types: self.types, + collection: { Array($0.inherits.keys) }, + validate: { type in + guard type is Class else { + throw "\(type.name) is not a class and should be used with `implementing` or `based`" + } + }) + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// Types implementing known protocol, grouped by its name. + /// `types.implementing.MyProtocol` returns list of types implementing `MyProtocol` + public lazy internal(set) var implementing: TypesCollection = { + TypesCollection( + types: self.types, + collection: { Array($0.implements.keys) }, + validate: { type in + guard type is Protocol else { + throw "\(type.name) is a class and should be used with `inheriting` or `based`" + } + }) + }() +} +#endif diff --git a/SourceryStencil/Sources/StencilTemplate.swift b/SourceryStencil/Sources/StencilTemplate.swift index 0b5d22003..873ac51f0 100644 --- a/SourceryStencil/Sources/StencilTemplate.swift +++ b/SourceryStencil/Sources/StencilTemplate.swift @@ -87,10 +87,16 @@ public final class StencilTemplate: StencilSwiftKit.StencilSwiftTemplate { ext.registerFilter("reversed", filter: reversed) ext.registerFilter("toArray", filter: toArray) + #if canImport(ObjectiveC) ext.registerFilterWithArguments("sorted") { (array, propertyName: String) -> Any? in switch array { case let array as NSArray: - let sortDescriptor = NSSortDescriptor(key: propertyName, ascending: true, selector: #selector(NSString.caseInsensitiveCompare)) + let sortDescriptor = NSSortDescriptor(key: propertyName, ascending: true, comparator: { + guard let arg1 = $0 as? String, let arg2 = $1 as? String else { + return .orderedAscending + } + return arg1.caseInsensitiveCompare(arg2) + }) return array.sortedArray(using: [sortDescriptor]) default: return nil @@ -100,12 +106,46 @@ public final class StencilTemplate: StencilSwiftKit.StencilSwiftTemplate { ext.registerFilterWithArguments("sortedDescending") { (array, propertyName: String) -> Any? in switch array { case let array as NSArray: - let sortDescriptor = NSSortDescriptor(key: propertyName, ascending: false, selector: #selector(NSString.caseInsensitiveCompare)) + let sortDescriptor = NSSortDescriptor(key: propertyName, ascending: false, comparator: { + guard let arg1 = $0 as? String, let arg2 = $1 as? String else { + return .orderedDescending + } + return arg1.caseInsensitiveCompare(arg2) + }) return array.sortedArray(using: [sortDescriptor]) default: return nil } } + #else + ext.registerFilterWithArguments("sorted") { (array, propertyName: String) -> Any? in + switch array { + case let array as NSArray: + return array.sortedArray { + guard let arg1 = $0 as? String, let arg2 = $1 as? String else { + return .orderedAscending + } + return arg1.caseInsensitiveCompare(arg2) + } + default: + return nil + } + } + + ext.registerFilterWithArguments("sortedDescending") { (array, propertyName: String) -> Any? in + switch array { + case let array as NSArray: + return array.sortedArray { + guard let arg1 = $0 as? String, let arg2 = $1 as? String else { + return .orderedDescending + } + return arg2.caseInsensitiveCompare(arg1) + } + default: + return nil + } + } + #endif ext.registerBoolFilter("initializer", filter: { (m: SourceryMethod) in m.isInitializer }) ext.registerBoolFilterOr("class", diff --git a/SourcerySwift/Sources/SourceryRuntime.content.generated.swift b/SourcerySwift/Sources/SourceryRuntime.content.generated.swift index 19dfe1963..27c360d6b 100644 --- a/SourcerySwift/Sources/SourceryRuntime.content.generated.swift +++ b/SourcerySwift/Sources/SourceryRuntime.content.generated.swift @@ -1,3 +1,4 @@ +#if canImport(ObjectiveC) let sourceryRuntimeFiles: [FolderSynchronizer.File] = [ .init(name: "AccessLevel.swift", content: """ @@ -25,7 +26,8 @@ import Foundation // sourcery: skipDescription /// Descibes Swift actor -@objc(SwiftActor) @objcMembers public final class Actor: Type { +@objc(SwiftActor) @objcMembers +public final class Actor: Type { /// Returns "actor" public override var kind: String { return "actor" } @@ -69,6 +71,37 @@ import Foundation ) } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \\(String(describing: self.kind)), " + string += "isFinal = \\(String(describing: self.isFinal))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Actor else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Actor else { return false } + return super.isEqual(rhs) + } + // sourcery:inline:Actor.AutoCoding /// :nodoc: @@ -81,6 +114,7 @@ import Foundation super.encode(with: aCoder) } // sourcery:end + } """), @@ -155,8 +189,8 @@ public extension Array { import Foundation /// Describes array type -@objcMembers public final class ArrayType: NSObject, SourceryModel { - +@objcMembers +public final class ArrayType: NSObject, SourceryModel, Diffable { /// Type name used in declaration public var name: String @@ -185,12 +219,58 @@ import Foundation "[\\(elementTypeName.asSource)]" } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "elementTypeName = \\(String(describing: self.elementTypeName)), " + string += "asGeneric = \\(String(describing: self.asGeneric)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? ArrayType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "elementTypeName").trackDifference(actual: self.elementTypeName, expected: castObject.elementTypeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.elementTypeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ArrayType else { return false } + if self.name != rhs.name { return false } + if self.elementTypeName != rhs.elementTypeName { return false } + return true + } + // sourcery:inline:ArrayType.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let elementTypeName: TypeName = aDecoder.decode(forKey: "elementTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["elementTypeName"])); fatalError() }; self.elementTypeName = elementTypeName + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let elementTypeName: TypeName = aDecoder.decode(forKey: "elementTypeName") else { + withVaList(["elementTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.elementTypeName = elementTypeName self.elementType = aDecoder.decode(forKey: "elementType") } @@ -209,7 +289,8 @@ import Foundation import Foundation /// Describes Swift AssociatedType -@objcMembers public final class AssociatedType: NSObject, SourceryModel { +@objcMembers +public final class AssociatedType: NSObject, SourceryModel { /// Associated type name public let name: String @@ -227,11 +308,50 @@ import Foundation self.type = type } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "typeName = \\(String(describing: self.typeName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? AssociatedType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? AssociatedType else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + return true + } + // sourcery:inline:AssociatedType.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name self.typeName = aDecoder.decode(forKey: "typeName") self.type = aDecoder.decode(forKey: "type") } @@ -251,7 +371,8 @@ import Foundation import Foundation /// Describes Swift attribute -@objcMembers public class Attribute: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport { +@objcMembers +public class Attribute: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport, Diffable { /// Attribute name public let name: String @@ -397,13 +518,57 @@ import Foundation } } + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Attribute else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "arguments").trackDifference(actual: self.arguments, expected: castObject.arguments)) + results.append(contentsOf: DiffableResult(identifier: "_description").trackDifference(actual: self._description, expected: castObject._description)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.arguments) + hasher.combine(self._description) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Attribute else { return false } + if self.name != rhs.name { return false } + if self.arguments != rhs.arguments { return false } + if self._description != rhs._description { return false } + return true + } + // sourcery:inline:Attribute.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let arguments: [String: NSObject] = aDecoder.decode(forKey: "arguments") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["arguments"])); fatalError() }; self.arguments = arguments - guard let _description: String = aDecoder.decode(forKey: "_description") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["_description"])); fatalError() }; self._description = _description + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let arguments: [String: NSObject] = aDecoder.decode(forKey: "arguments") else { + withVaList(["arguments"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.arguments = arguments + guard let _description: String = aDecoder.decode(forKey: "_description") else { + withVaList(["_description"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self._description = _description } /// :nodoc: @@ -439,7 +604,8 @@ import Foundation import Foundation /// :nodoc: -@objcMembers public final class BytesRange: NSObject, SourceryModel { +@objcMembers +public final class BytesRange: NSObject, SourceryModel, Diffable { public let offset: Int64 public let length: Int64 @@ -453,6 +619,40 @@ import Foundation self.init(offset: range.offset, length: range.length) } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "offset = \\(String(describing: self.offset)), " + string += "length = \\(String(describing: self.length))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? BytesRange else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "offset").trackDifference(actual: self.offset, expected: castObject.offset)) + results.append(contentsOf: DiffableResult(identifier: "length").trackDifference(actual: self.length, expected: castObject.length)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.offset) + hasher.combine(self.length) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? BytesRange else { return false } + if self.offset != rhs.offset { return false } + if self.length != rhs.length { return false } + return true + } + // sourcery:inline:BytesRange.AutoCoding /// :nodoc: @@ -475,11 +675,12 @@ import Foundation import Foundation // sourcery: skipDescription /// Descibes Swift class -@objc(SwiftClass) @objcMembers public final class Class: Type { +@objc(SwiftClass) @objcMembers +public final class Class: Type { /// Returns "class" public override var kind: String { return "class" } - /// Whether type is final + /// Whether type is final public var isFinal: Bool { return modifiers.contains { $0.name == "final" } } @@ -519,6 +720,37 @@ import Foundation ) } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \\(String(describing: self.kind)), " + string += "isFinal = \\(String(describing: self.isFinal))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Class else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Class else { return false } + return super.isEqual(rhs) + } + // sourcery:inline:Class.AutoCoding /// :nodoc: @@ -531,6 +763,7 @@ import Foundation super.encode(with: aCoder) } // sourcery:end + } """), @@ -539,7 +772,8 @@ import Foundation import Foundation /// Describes closure type -@objcMembers public final class ClosureType: NSObject, SourceryModel { +@objcMembers +public final class ClosureType: NSObject, SourceryModel, Diffable { /// Type name used in declaration with stripped whitespaces and new lines public let name: String @@ -576,7 +810,7 @@ import Foundation public var unwrappedReturnTypeName: String { return returnTypeName.unwrappedTypeName } - + /// Whether method is async method public let isAsync: Bool @@ -605,32 +839,103 @@ import Foundation "\\(parameters.asSource)\\(asyncKeyword != nil ? " \\(asyncKeyword!)" : "")\\(throwsOrRethrowsKeyword != nil ? " \\(throwsOrRethrowsKeyword!)" : "") -> \\(returnTypeName.asSource)" } -// sourcery:inline:ClosureType.AutoCoding - - /// :nodoc: - required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let parameters: [ClosureParameter] = aDecoder.decode(forKey: "parameters") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["parameters"])); fatalError() }; self.parameters = parameters - guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["returnTypeName"])); fatalError() }; self.returnTypeName = returnTypeName - self.returnType = aDecoder.decode(forKey: "returnType") - self.isAsync = aDecoder.decode(forKey: "isAsync") - self.asyncKeyword = aDecoder.decode(forKey: "asyncKeyword") - self.`throws` = aDecoder.decode(forKey: "`throws`") - self.throwsOrRethrowsKeyword = aDecoder.decode(forKey: "throwsOrRethrowsKeyword") - } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "parameters = \\(String(describing: self.parameters)), " + string += "returnTypeName = \\(String(describing: self.returnTypeName)), " + string += "actualReturnTypeName = \\(String(describing: self.actualReturnTypeName)), " + string += "isAsync = \\(String(describing: self.isAsync)), " + string += "asyncKeyword = \\(String(describing: self.asyncKeyword)), " + string += "`throws` = \\(String(describing: self.`throws`)), " + string += "throwsOrRethrowsKeyword = \\(String(describing: self.throwsOrRethrowsKeyword)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } - /// :nodoc: - public func encode(with aCoder: NSCoder) { - aCoder.encode(self.name, forKey: "name") - aCoder.encode(self.parameters, forKey: "parameters") - aCoder.encode(self.returnTypeName, forKey: "returnTypeName") - aCoder.encode(self.returnType, forKey: "returnType") - aCoder.encode(self.isAsync, forKey: "isAsync") - aCoder.encode(self.asyncKeyword, forKey: "asyncKeyword") - aCoder.encode(self.`throws`, forKey: "`throws`") - aCoder.encode(self.throwsOrRethrowsKeyword, forKey: "throwsOrRethrowsKeyword") + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? ClosureType else { + results.append("Incorrect type ") + return results } -// sourcery:end + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) + results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "asyncKeyword").trackDifference(actual: self.asyncKeyword, expected: castObject.asyncKeyword)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "throwsOrRethrowsKeyword").trackDifference(actual: self.throwsOrRethrowsKeyword, expected: castObject.throwsOrRethrowsKeyword)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.parameters) + hasher.combine(self.returnTypeName) + hasher.combine(self.isAsync) + hasher.combine(self.asyncKeyword) + hasher.combine(self.`throws`) + hasher.combine(self.throwsOrRethrowsKeyword) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ClosureType else { return false } + if self.name != rhs.name { return false } + if self.parameters != rhs.parameters { return false } + if self.returnTypeName != rhs.returnTypeName { return false } + if self.isAsync != rhs.isAsync { return false } + if self.asyncKeyword != rhs.asyncKeyword { return false } + if self.`throws` != rhs.`throws` { return false } + if self.throwsOrRethrowsKeyword != rhs.throwsOrRethrowsKeyword { return false } + return true + } + +// sourcery:inline:ClosureType.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let parameters: [ClosureParameter] = aDecoder.decode(forKey: "parameters") else { + withVaList(["parameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.parameters = parameters + guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { + withVaList(["returnTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.returnTypeName = returnTypeName + self.returnType = aDecoder.decode(forKey: "returnType") + self.isAsync = aDecoder.decode(forKey: "isAsync") + self.asyncKeyword = aDecoder.decode(forKey: "asyncKeyword") + self.`throws` = aDecoder.decode(forKey: "`throws`") + self.throwsOrRethrowsKeyword = aDecoder.decode(forKey: "throwsOrRethrowsKeyword") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.parameters, forKey: "parameters") + aCoder.encode(self.returnTypeName, forKey: "returnTypeName") + aCoder.encode(self.returnType, forKey: "returnType") + aCoder.encode(self.isAsync, forKey: "isAsync") + aCoder.encode(self.asyncKeyword, forKey: "asyncKeyword") + aCoder.encode(self.`throws`, forKey: "`throws`") + aCoder.encode(self.throwsOrRethrowsKeyword, forKey: "throwsOrRethrowsKeyword") + } +// sourcery:end } @@ -747,7 +1052,7 @@ extension Variable: NSCoding {} import Foundation private func currentTimestamp() -> TimeInterval { - return CFAbsoluteTimeGetCurrent() + return Date().timeIntervalSince1970 } /// Responsible for composing results of `FileParser`. @@ -1007,2168 +1312,773 @@ public protocol Definition: AnyObject { } """), - .init(name: "Description.generated.swift", content: + .init(name: "Dictionary.swift", content: """ -// Generated using Sourcery 2.0.3 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT -// swiftlint:disable vertical_whitespace +import Foundation + +/// Describes dictionary type +@objcMembers +public final class DictionaryType: NSObject, SourceryModel, Diffable { + /// Type name used in declaration + public var name: String + + /// Dictionary value type name + public var valueTypeName: TypeName + // sourcery: skipEquality, skipDescription + /// Dictionary value type, if known + public var valueType: Type? + + /// Dictionary key type name + public var keyTypeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Dictionary key type, if known + public var keyType: Type? -extension Actor { /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "isFinal = \\(String(describing: self.isFinal))" - return string + public init(name: String, valueTypeName: TypeName, valueType: Type? = nil, keyTypeName: TypeName, keyType: Type? = nil) { + self.name = name + self.valueTypeName = valueTypeName + self.valueType = valueType + self.keyTypeName = keyTypeName + self.keyType = keyType } -} -extension ArrayType { + + /// Returns dictionary as generic type + public var asGeneric: GenericType { + GenericType(name: "Dictionary", typeParameters: [ + .init(typeName: keyTypeName), + .init(typeName: valueTypeName) + ]) + } + + public var asSource: String { + "[\\(keyTypeName.asSource): \\(valueTypeName.asSource)]" + } + /// :nodoc: override public var description: String { var string = "\\(Swift.type(of: self)): " string += "name = \\(String(describing: self.name)), " - string += "elementTypeName = \\(String(describing: self.elementTypeName)), " + string += "valueTypeName = \\(String(describing: self.valueTypeName)), " + string += "keyTypeName = \\(String(describing: self.keyTypeName)), " string += "asGeneric = \\(String(describing: self.asGeneric)), " string += "asSource = \\(String(describing: self.asSource))" return string } -} -extension AssociatedType { + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? DictionaryType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "valueTypeName").trackDifference(actual: self.valueTypeName, expected: castObject.valueTypeName)) + results.append(contentsOf: DiffableResult(identifier: "keyTypeName").trackDifference(actual: self.keyTypeName, expected: castObject.keyTypeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.valueTypeName) + hasher.combine(self.keyTypeName) + return hasher.finalize() + } + /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "name = \\(String(describing: self.name)), " - string += "typeName = \\(String(describing: self.typeName))" - return string + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? DictionaryType else { return false } + if self.name != rhs.name { return false } + if self.valueTypeName != rhs.valueTypeName { return false } + if self.keyTypeName != rhs.keyTypeName { return false } + return true } + +// sourcery:inline:DictionaryType.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let valueTypeName: TypeName = aDecoder.decode(forKey: "valueTypeName") else { + withVaList(["valueTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.valueTypeName = valueTypeName + self.valueType = aDecoder.decode(forKey: "valueType") + guard let keyTypeName: TypeName = aDecoder.decode(forKey: "keyTypeName") else { + withVaList(["keyTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.keyTypeName = keyTypeName + self.keyType = aDecoder.decode(forKey: "keyType") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.valueTypeName, forKey: "valueTypeName") + aCoder.encode(self.valueType, forKey: "valueType") + aCoder.encode(self.keyTypeName, forKey: "keyTypeName") + aCoder.encode(self.keyType, forKey: "keyType") + } +// sourcery:end } -extension AssociatedValue { + +"""), + .init(name: "Diffable.swift", content: +""" +// +// Diffable.swift +// Sourcery +// +// Created by Krzysztof Zabłocki on 22/12/2016. +// Copyright © 2016 Pixle. All rights reserved. +// + +import Foundation + +public protocol Diffable { + + /// Returns `DiffableResult` for the given objects. + /// + /// - Parameter object: Object to diff against. + /// - Returns: Diffable results. + func diffAgainst(_ object: Any?) -> DiffableResult +} + +/// :nodoc: +extension NSRange: Diffable { /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "localName = \\(String(describing: self.localName)), " - string += "externalName = \\(String(describing: self.externalName)), " - string += "typeName = \\(String(describing: self.typeName)), " - string += "defaultValue = \\(String(describing: self.defaultValue)), " - string += "annotations = \\(String(describing: self.annotations))" - return string + public static func == (lhs: NSRange, rhs: NSRange) -> Bool { + return NSEqualRanges(lhs, rhs) + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let rhs = object as? NSRange else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "location").trackDifference(actual: self.location, expected: rhs.location)) + results.append(contentsOf: DiffableResult(identifier: "length").trackDifference(actual: self.length, expected: rhs.length)) + return results } } -extension BytesRange { - /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "offset = \\(String(describing: self.offset)), " - string += "length = \\(String(describing: self.length))" - return string + +@objcMembers +public class DiffableResult: NSObject, AutoEquatable { + // sourcery: skipEquality + private var results: [String] + internal var identifier: String? + + init(results: [String] = [], identifier: String? = nil) { + self.results = results + self.identifier = identifier + } + + func append(_ element: String) { + results.append(element) + } + + func append(contentsOf contents: DiffableResult) { + if !contents.isEmpty { + results.append(contents.description) + } + } + + var isEmpty: Bool { return results.isEmpty } + + public override var description: String { + guard !results.isEmpty else { return "" } + return "\\(identifier.flatMap { "\\($0) " } ?? "")" + results.joined(separator: "\\n") } } -extension Class { + +public extension DiffableResult { + +#if swift(>=4.1) +#else /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "isFinal = \\(String(describing: self.isFinal))" - return string + @discardableResult func trackDifference(actual: T, expected: T) -> DiffableResult { + if actual != expected { + let result = DiffableResult(results: [""]) + append(contentsOf: result) + } + return self } -} -extension ClosureParameter { +#endif + /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "argumentLabel = \\(String(describing: self.argumentLabel)), " - string += "name = \\(String(describing: self.name)), " - string += "typeName = \\(String(describing: self.typeName)), " - string += "`inout` = \\(String(describing: self.`inout`)), " - string += "typeAttributes = \\(String(describing: self.typeAttributes)), " - string += "defaultValue = \\(String(describing: self.defaultValue)), " - string += "annotations = \\(String(describing: self.annotations)), " - string += "asSource = \\(String(describing: self.asSource))" - return string + @discardableResult func trackDifference(actual: T?, expected: T?) -> DiffableResult { + if actual != expected { + let result = DiffableResult(results: [""]) + append(contentsOf: result) + } + return self } -} -extension ClosureType { + /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "name = \\(String(describing: self.name)), " - string += "parameters = \\(String(describing: self.parameters)), " - string += "returnTypeName = \\(String(describing: self.returnTypeName)), " - string += "actualReturnTypeName = \\(String(describing: self.actualReturnTypeName)), " - string += "isAsync = \\(String(describing: self.isAsync)), " - string += "asyncKeyword = \\(String(describing: self.asyncKeyword)), " - string += "`throws` = \\(String(describing: self.`throws`)), " - string += "throwsOrRethrowsKeyword = \\(String(describing: self.throwsOrRethrowsKeyword)), " - string += "asSource = \\(String(describing: self.asSource))" - return string + @discardableResult func trackDifference(actual: T, expected: T) -> DiffableResult where T: Diffable { + let diffResult = actual.diffAgainst(expected) + append(contentsOf: diffResult) + return self } -} -extension DictionaryType { + /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "name = \\(String(describing: self.name)), " - string += "valueTypeName = \\(String(describing: self.valueTypeName)), " - string += "keyTypeName = \\(String(describing: self.keyTypeName)), " - string += "asGeneric = \\(String(describing: self.asGeneric)), " - string += "asSource = \\(String(describing: self.asSource))" - return string + @discardableResult func trackDifference(actual: [T], expected: [T]) -> DiffableResult where T: Diffable { + let diffResult = DiffableResult() + defer { append(contentsOf: diffResult) } + + guard actual.count == expected.count else { + diffResult.append("Different count, expected: \\(expected.count), received: \\(actual.count)") + return self + } + + for (idx, item) in actual.enumerated() { + let diff = DiffableResult() + diff.trackDifference(actual: item, expected: expected[idx]) + if !diff.isEmpty { + let string = "idx \\(idx): \\(diff)" + diffResult.append(string) + } + } + + return self } -} -extension Enum { + /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "cases = \\(String(describing: self.cases)), " - string += "rawTypeName = \\(String(describing: self.rawTypeName)), " - string += "hasAssociatedValues = \\(String(describing: self.hasAssociatedValues))" - return string + @discardableResult func trackDifference(actual: [T], expected: [T]) -> DiffableResult { + let diffResult = DiffableResult() + defer { append(contentsOf: diffResult) } + + guard actual.count == expected.count else { + diffResult.append("Different count, expected: \\(expected.count), received: \\(actual.count)") + return self + } + + for (idx, item) in actual.enumerated() where item != expected[idx] { + let string = "idx \\(idx): " + diffResult.append(string) + } + + return self } -} -extension EnumCase { + /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "name = \\(String(describing: self.name)), " - string += "rawValue = \\(String(describing: self.rawValue)), " - string += "associatedValues = \\(String(describing: self.associatedValues)), " - string += "annotations = \\(String(describing: self.annotations)), " - string += "documentation = \\(String(describing: self.documentation)), " - string += "indirect = \\(String(describing: self.indirect)), " - string += "hasAssociatedValue = \\(String(describing: self.hasAssociatedValue))" - return string + @discardableResult func trackDifference(actual: [K: T], expected: [K: T]) -> DiffableResult where T: Diffable { + let diffResult = DiffableResult() + defer { append(contentsOf: diffResult) } + + guard actual.count == expected.count else { + append("Different count, expected: \\(expected.count), received: \\(actual.count)") + + if expected.count > actual.count { + let missingKeys = Array(expected.keys.filter { + actual[$0] == nil + }.map { + String(describing: $0) + }) + diffResult.append("Missing keys: \\(missingKeys.joined(separator: ", "))") + } + return self + } + + for (key, actualElement) in actual { + guard let expectedElement = expected[key] else { + diffResult.append("Missing key \\"\\(key)\\"") + continue + } + + let diff = DiffableResult() + diff.trackDifference(actual: actualElement, expected: expectedElement) + if !diff.isEmpty { + let string = "key \\"\\(key)\\": \\(diff)" + diffResult.append(string) + } + } + + return self } -} -extension FileParserResult { + +// MARK: - NSObject diffing + /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "path = \\(String(describing: self.path)), " - string += "module = \\(String(describing: self.module)), " - string += "types = \\(String(describing: self.types)), " - string += "functions = \\(String(describing: self.functions)), " - string += "typealiases = \\(String(describing: self.typealiases)), " - string += "inlineRanges = \\(String(describing: self.inlineRanges)), " - string += "inlineIndentations = \\(String(describing: self.inlineIndentations)), " - string += "modifiedDate = \\(String(describing: self.modifiedDate)), " - string += "sourceryVersion = \\(String(describing: self.sourceryVersion)), " - string += "isEmpty = \\(String(describing: self.isEmpty))" - return string + @discardableResult func trackDifference(actual: [K: T], expected: [K: T]) -> DiffableResult { + let diffResult = DiffableResult() + defer { append(contentsOf: diffResult) } + + guard actual.count == expected.count else { + append("Different count, expected: \\(expected.count), received: \\(actual.count)") + + if expected.count > actual.count { + let missingKeys = Array(expected.keys.filter { + actual[$0] == nil + }.map { + String(describing: $0) + }) + diffResult.append("Missing keys: \\(missingKeys.joined(separator: ", "))") + } + return self + } + + for (key, actualElement) in actual { + guard let expectedElement = expected[key] else { + diffResult.append("Missing key \\"\\(key)\\"") + continue + } + + if !actualElement.isEqual(expectedElement) { + diffResult.append("key \\"\\(key)\\": ") + } + } + + return self } } -extension GenericRequirement { + +"""), + .init(name: "Documentation.swift", content: +""" +import Foundation + +public typealias Documentation = [String] + +/// Describes a declaration with documentation, i.e. type, method, variable, enum case +public protocol Documented { + var documentation: Documentation { get } +} + +"""), + .init(name: "AssociatedValue.swift", content: +""" +import Foundation + +/// Defines enum case associated value +@objcMembers +public final class AssociatedValue: NSObject, SourceryModel, AutoDescription, Typed, Annotated, Diffable { + + /// Associated value local name. + /// This is a name to be used to construct enum case value + public let localName: String? + + /// Associated value external name. + /// This is a name to be used to access value in value-bindig + public let externalName: String? + + /// Associated value type name + public let typeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Associated value type, if known + public var type: Type? + + /// Associated value default value + public let defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "leftType = \\(String(describing: self.leftType)), " - string += "rightType = \\(String(describing: self.rightType)), " - string += "relationship = \\(String(describing: self.relationship)), " - string += "relationshipSyntax = \\(String(describing: self.relationshipSyntax))" - return string + public init(localName: String?, externalName: String?, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { + self.localName = localName + self.externalName = externalName + self.typeName = typeName + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations } -} -extension GenericTypeParameter { + + convenience init(name: String? = nil, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { + self.init(localName: name, externalName: name, typeName: typeName, type: type, defaultValue: defaultValue, annotations: annotations) + } + /// :nodoc: override public var description: String { var string = "\\(Swift.type(of: self)): " - string += "typeName = \\(String(describing: self.typeName))" + string += "localName = \\(String(describing: self.localName)), " + string += "externalName = \\(String(describing: self.externalName)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "defaultValue = \\(String(describing: self.defaultValue)), " + string += "annotations = \\(String(describing: self.annotations))" return string } -} -extension Method { - /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "name = \\(String(describing: self.name)), " - string += "selectorName = \\(String(describing: self.selectorName)), " - string += "parameters = \\(String(describing: self.parameters)), " - string += "returnTypeName = \\(String(describing: self.returnTypeName)), " - string += "isAsync = \\(String(describing: self.isAsync)), " - string += "`throws` = \\(String(describing: self.`throws`)), " - string += "`rethrows` = \\(String(describing: self.`rethrows`)), " - string += "accessLevel = \\(String(describing: self.accessLevel)), " - string += "isStatic = \\(String(describing: self.isStatic)), " - string += "isClass = \\(String(describing: self.isClass)), " - string += "isFailableInitializer = \\(String(describing: self.isFailableInitializer)), " - string += "annotations = \\(String(describing: self.annotations)), " - string += "documentation = \\(String(describing: self.documentation)), " - string += "definedInTypeName = \\(String(describing: self.definedInTypeName)), " - string += "attributes = \\(String(describing: self.attributes)), " - string += "modifiers = \\(String(describing: self.modifiers))" - return string + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? AssociatedValue else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) + results.append(contentsOf: DiffableResult(identifier: "externalName").trackDifference(actual: self.externalName, expected: castObject.externalName)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + return results } -} -extension MethodParameter { - /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "argumentLabel = \\(String(describing: self.argumentLabel)), " - string += "name = \\(String(describing: self.name)), " - string += "typeName = \\(String(describing: self.typeName)), " - string += "`inout` = \\(String(describing: self.`inout`)), " - string += "isVariadic = \\(String(describing: self.isVariadic)), " - string += "typeAttributes = \\(String(describing: self.typeAttributes)), " - string += "defaultValue = \\(String(describing: self.defaultValue)), " - string += "annotations = \\(String(describing: self.annotations)), " - string += "asSource = \\(String(describing: self.asSource))" - return string + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.localName) + hasher.combine(self.externalName) + hasher.combine(self.typeName) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() } -} -extension Protocol { + /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "kind = \\(String(describing: self.kind)), " - string += "associatedTypes = \\(String(describing: self.associatedTypes)), " - string += "genericRequirements = \\(String(describing: self.genericRequirements))" - return string + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? AssociatedValue else { return false } + if self.localName != rhs.localName { return false } + if self.externalName != rhs.externalName { return false } + if self.typeName != rhs.typeName { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true } + +// sourcery:inline:AssociatedValue.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.localName = aDecoder.decode(forKey: "localName") + self.externalName = aDecoder.decode(forKey: "externalName") + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.type = aDecoder.decode(forKey: "type") + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.localName, forKey: "localName") + aCoder.encode(self.externalName, forKey: "externalName") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + } +// sourcery:end + } -extension ProtocolComposition { - /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "kind = \\(String(describing: self.kind)), " - string += "composedTypeNames = \\(String(describing: self.composedTypeNames))" - return string +"""), + .init(name: "EnumCase.swift", content: +""" +import Foundation + +/// Defines enum case +@objcMembers +public final class EnumCase: NSObject, SourceryModel, AutoDescription, Annotated, Documented, Diffable { + + /// Enum case name + public let name: String + + /// Enum case raw value, if any + public let rawValue: String? + + /// Enum case associated values + public let associatedValues: [AssociatedValue] + + /// Enum case annotations + public var annotations: Annotations = [:] + + public var documentation: Documentation = [] + + /// Whether enum case is indirect + public let indirect: Bool + + /// Whether enum case has associated value + public var hasAssociatedValue: Bool { + return !associatedValues.isEmpty } -} -extension Struct { + + // Underlying parser data, never to be used by anything else + // sourcery: skipEquality, skipDescription, skipCoding, skipJSExport /// :nodoc: - override public var description: String { - var string = super.description - string += ", " - string += "kind = \\(String(describing: self.kind))" - return string + public var __parserData: Any? + + /// :nodoc: + public init(name: String, rawValue: String? = nil, associatedValues: [AssociatedValue] = [], annotations: [String: NSObject] = [:], documentation: [String] = [], indirect: Bool = false) { + self.name = name + self.rawValue = rawValue + self.associatedValues = associatedValues + self.annotations = annotations + self.documentation = documentation + self.indirect = indirect } -} -extension Subscript { + /// :nodoc: override public var description: String { var string = "\\(Swift.type(of: self)): " - string += "parameters = \\(String(describing: self.parameters)), " - string += "returnTypeName = \\(String(describing: self.returnTypeName)), " - string += "actualReturnTypeName = \\(String(describing: self.actualReturnTypeName)), " - string += "isFinal = \\(String(describing: self.isFinal)), " - string += "readAccess = \\(String(describing: self.readAccess)), " - string += "writeAccess = \\(String(describing: self.writeAccess)), " - string += "isMutable = \\(String(describing: self.isMutable)), " + string += "name = \\(String(describing: self.name)), " + string += "rawValue = \\(String(describing: self.rawValue)), " + string += "associatedValues = \\(String(describing: self.associatedValues)), " string += "annotations = \\(String(describing: self.annotations)), " string += "documentation = \\(String(describing: self.documentation)), " - string += "definedInTypeName = \\(String(describing: self.definedInTypeName)), " - string += "actualDefinedInTypeName = \\(String(describing: self.actualDefinedInTypeName)), " - string += "attributes = \\(String(describing: self.attributes)), " - string += "modifiers = \\(String(describing: self.modifiers))" + string += "indirect = \\(String(describing: self.indirect)), " + string += "hasAssociatedValue = \\(String(describing: self.hasAssociatedValue))" return string } -} -extension TemplateContext { - /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "parserResult = \\(String(describing: self.parserResult)), " - string += "functions = \\(String(describing: self.functions)), " - string += "types = \\(String(describing: self.types)), " - string += "argument = \\(String(describing: self.argument)), " - string += "stencilContext = \\(String(describing: self.stencilContext))" - return string + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? EnumCase else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "rawValue").trackDifference(actual: self.rawValue, expected: castObject.rawValue)) + results.append(contentsOf: DiffableResult(identifier: "associatedValues").trackDifference(actual: self.associatedValues, expected: castObject.associatedValues)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "indirect").trackDifference(actual: self.indirect, expected: castObject.indirect)) + return results } -} -extension TupleElement { - /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "name = \\(String(describing: self.name)), " - string += "typeName = \\(String(describing: self.typeName)), " - string += "asSource = \\(String(describing: self.asSource))" - return string + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.rawValue) + hasher.combine(self.associatedValues) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.indirect) + return hasher.finalize() } -} -extension TupleType { + /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "name = \\(String(describing: self.name)), " - string += "elements = \\(String(describing: self.elements))" - return string + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? EnumCase else { return false } + if self.name != rhs.name { return false } + if self.rawValue != rhs.rawValue { return false } + if self.associatedValues != rhs.associatedValues { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.indirect != rhs.indirect { return false } + return true } + +// sourcery:inline:EnumCase.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + self.rawValue = aDecoder.decode(forKey: "rawValue") + guard let associatedValues: [AssociatedValue] = aDecoder.decode(forKey: "associatedValues") else { + withVaList(["associatedValues"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.associatedValues = associatedValues + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + self.indirect = aDecoder.decode(forKey: "indirect") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.rawValue, forKey: "rawValue") + aCoder.encode(self.associatedValues, forKey: "associatedValues") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.indirect, forKey: "indirect") + } +// sourcery:end } -extension Type { - /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "module = \\(String(describing: self.module)), " - string += "imports = \\(String(describing: self.imports)), " - string += "allImports = \\(String(describing: self.allImports)), " - string += "typealiases = \\(String(describing: self.typealiases)), " - string += "isExtension = \\(String(describing: self.isExtension)), " - string += "kind = \\(String(describing: self.kind)), " - string += "accessLevel = \\(String(describing: self.accessLevel)), " - string += "name = \\(String(describing: self.name)), " - string += "isUnknownExtension = \\(String(describing: self.isUnknownExtension)), " - string += "isGeneric = \\(String(describing: self.isGeneric)), " - string += "localName = \\(String(describing: self.localName)), " - string += "rawVariables = \\(String(describing: self.rawVariables)), " - string += "rawMethods = \\(String(describing: self.rawMethods)), " - string += "rawSubscripts = \\(String(describing: self.rawSubscripts)), " - string += "initializers = \\(String(describing: self.initializers)), " - string += "annotations = \\(String(describing: self.annotations)), " - string += "documentation = \\(String(describing: self.documentation)), " - string += "staticVariables = \\(String(describing: self.staticVariables)), " - string += "staticMethods = \\(String(describing: self.staticMethods)), " - string += "classMethods = \\(String(describing: self.classMethods)), " - string += "instanceVariables = \\(String(describing: self.instanceVariables)), " - string += "instanceMethods = \\(String(describing: self.instanceMethods)), " - string += "computedVariables = \\(String(describing: self.computedVariables)), " - string += "storedVariables = \\(String(describing: self.storedVariables)), " - string += "inheritedTypes = \\(String(describing: self.inheritedTypes)), " - string += "inherits = \\(String(describing: self.inherits)), " - string += "containedTypes = \\(String(describing: self.containedTypes)), " - string += "parentName = \\(String(describing: self.parentName)), " - string += "parentTypes = \\(String(describing: self.parentTypes)), " - string += "attributes = \\(String(describing: self.attributes)), " - string += "modifiers = \\(String(describing: self.modifiers)), " - string += "fileName = \\(String(describing: self.fileName))" - return string - } -} -extension Typealias { - /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "aliasName = \\(String(describing: self.aliasName)), " - string += "typeName = \\(String(describing: self.typeName)), " - string += "module = \\(String(describing: self.module)), " - string += "accessLevel = \\(String(describing: self.accessLevel)), " - string += "parentName = \\(String(describing: self.parentName)), " - string += "name = \\(String(describing: self.name))" - return string - } -} -extension Types { - /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "types = \\(String(describing: self.types)), " - string += "typealiases = \\(String(describing: self.typealiases))" - return string - } -} -extension Variable { - /// :nodoc: - override public var description: String { - var string = "\\(Swift.type(of: self)): " - string += "name = \\(String(describing: self.name)), " - string += "typeName = \\(String(describing: self.typeName)), " - string += "isComputed = \\(String(describing: self.isComputed)), " - string += "isAsync = \\(String(describing: self.isAsync)), " - string += "`throws` = \\(String(describing: self.`throws`)), " - string += "isStatic = \\(String(describing: self.isStatic)), " - string += "readAccess = \\(String(describing: self.readAccess)), " - string += "writeAccess = \\(String(describing: self.writeAccess)), " - string += "accessLevel = \\(String(describing: self.accessLevel)), " - string += "isMutable = \\(String(describing: self.isMutable)), " - string += "defaultValue = \\(String(describing: self.defaultValue)), " - string += "annotations = \\(String(describing: self.annotations)), " - string += "documentation = \\(String(describing: self.documentation)), " - string += "attributes = \\(String(describing: self.attributes)), " - string += "modifiers = \\(String(describing: self.modifiers)), " - string += "isFinal = \\(String(describing: self.isFinal)), " - string += "isLazy = \\(String(describing: self.isLazy)), " - string += "definedInTypeName = \\(String(describing: self.definedInTypeName)), " - string += "actualDefinedInTypeName = \\(String(describing: self.actualDefinedInTypeName))" - return string - } -} - """), - .init(name: "Dictionary.swift", content: + .init(name: "Enum.swift", content: """ -import Foundation - -/// Describes dictionary type -@objcMembers public final class DictionaryType: NSObject, SourceryModel { - /// Type name used in declaration - public var name: String - - /// Dictionary value type name - public var valueTypeName: TypeName - - // sourcery: skipEquality, skipDescription - /// Dictionary value type, if known - public var valueType: Type? - - /// Dictionary key type name - public var keyTypeName: TypeName - - // sourcery: skipEquality, skipDescription - /// Dictionary key type, if known - public var keyType: Type? +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// - /// :nodoc: - public init(name: String, valueTypeName: TypeName, valueType: Type? = nil, keyTypeName: TypeName, keyType: Type? = nil) { - self.name = name - self.valueTypeName = valueTypeName - self.valueType = valueType - self.keyTypeName = keyTypeName - self.keyType = keyType - } +import Foundation - /// Returns dictionary as generic type - public var asGeneric: GenericType { - GenericType(name: "Dictionary", typeParameters: [ - .init(typeName: keyTypeName), - .init(typeName: valueTypeName) - ]) - } +/// Defines Swift enum +@objcMembers +public final class Enum: Type { + // sourcery: skipDescription + /// Returns "enum" + public override var kind: String { return "enum" } - public var asSource: String { - "[\\(keyTypeName.asSource): \\(valueTypeName.asSource)]" - } + /// Enum cases + public var cases: [EnumCase] -// sourcery:inline:DictionaryType.AutoCoding + /** + Enum raw value type name, if any. This type is removed from enum's `based` and `inherited` types collections. - /// :nodoc: - required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let valueTypeName: TypeName = aDecoder.decode(forKey: "valueTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["valueTypeName"])); fatalError() }; self.valueTypeName = valueTypeName - self.valueType = aDecoder.decode(forKey: "valueType") - guard let keyTypeName: TypeName = aDecoder.decode(forKey: "keyTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["keyTypeName"])); fatalError() }; self.keyTypeName = keyTypeName - self.keyType = aDecoder.decode(forKey: "keyType") + - important: Unless raw type is specified explicitly via type alias RawValue it will be set to the first type in the inheritance chain. + So if your enum does not have raw value but implements protocols you'll have to specify conformance to these protocols via extension to get enum with nil raw value type and all based and inherited types. + */ + public var rawTypeName: TypeName? { + didSet { + if let rawTypeName = rawTypeName { + hasRawType = true + if let index = inheritedTypes.firstIndex(of: rawTypeName.name) { + inheritedTypes.remove(at: index) + } + if based[rawTypeName.name] != nil { + based[rawTypeName.name] = nil + } + } else { + hasRawType = false + } } + } - /// :nodoc: - public func encode(with aCoder: NSCoder) { - aCoder.encode(self.name, forKey: "name") - aCoder.encode(self.valueTypeName, forKey: "valueTypeName") - aCoder.encode(self.valueType, forKey: "valueType") - aCoder.encode(self.keyTypeName, forKey: "keyTypeName") - aCoder.encode(self.keyType, forKey: "keyType") - } -// sourcery:end -} + // sourcery: skipDescription, skipEquality + /// :nodoc: + public private(set) var hasRawType: Bool -"""), - .init(name: "Diffable.generated.swift", content: -""" -// Generated using Sourcery 2.0.3 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT -import Foundation + // sourcery: skipDescription, skipEquality + /// Enum raw value type, if known + public var rawType: Type? -extension Actor { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Actor else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension ArrayType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? ArrayType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "elementTypeName").trackDifference(actual: self.elementTypeName, expected: castObject.elementTypeName)) - return results - } -} -extension AssociatedType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? AssociatedType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - return results - } -} -extension AssociatedValue: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? AssociatedValue else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) - results.append(contentsOf: DiffableResult(identifier: "externalName").trackDifference(actual: self.externalName, expected: castObject.externalName)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - return results - } -} -extension Attribute: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Attribute else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "arguments").trackDifference(actual: self.arguments, expected: castObject.arguments)) - results.append(contentsOf: DiffableResult(identifier: "_description").trackDifference(actual: self._description, expected: castObject._description)) - return results - } -} -extension BytesRange: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? BytesRange else { - results.append("Incorrect type ") - return results + // sourcery: skipEquality, skipDescription, skipCoding + /// Names of types or protocols this type inherits from, including unknown (not scanned) types + public override var based: [String: String] { + didSet { + if let rawTypeName = rawTypeName, based[rawTypeName.name] != nil { + based[rawTypeName.name] = nil + } } - results.append(contentsOf: DiffableResult(identifier: "offset").trackDifference(actual: self.offset, expected: castObject.offset)) - results.append(contentsOf: DiffableResult(identifier: "length").trackDifference(actual: self.length, expected: castObject.length)) - return results } -} -extension Class { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Class else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: super.diffAgainst(castObject)) - return results + + /// Whether enum contains any associated values + public var hasAssociatedValues: Bool { + return cases.contains(where: { $0.hasAssociatedValue }) } -} -extension ClosureType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? ClosureType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) - results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) - results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) - results.append(contentsOf: DiffableResult(identifier: "asyncKeyword").trackDifference(actual: self.asyncKeyword, expected: castObject.asyncKeyword)) - results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) - results.append(contentsOf: DiffableResult(identifier: "throwsOrRethrowsKeyword").trackDifference(actual: self.throwsOrRethrowsKeyword, expected: castObject.throwsOrRethrowsKeyword)) - return results - } -} -extension DictionaryType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? DictionaryType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "valueTypeName").trackDifference(actual: self.valueTypeName, expected: castObject.valueTypeName)) - results.append(contentsOf: DiffableResult(identifier: "keyTypeName").trackDifference(actual: self.keyTypeName, expected: castObject.keyTypeName)) - return results - } -} -extension Enum { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Enum else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "cases").trackDifference(actual: self.cases, expected: castObject.cases)) - results.append(contentsOf: DiffableResult(identifier: "rawTypeName").trackDifference(actual: self.rawTypeName, expected: castObject.rawTypeName)) - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension EnumCase: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? EnumCase else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "rawValue").trackDifference(actual: self.rawValue, expected: castObject.rawValue)) - results.append(contentsOf: DiffableResult(identifier: "associatedValues").trackDifference(actual: self.associatedValues, expected: castObject.associatedValues)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) - results.append(contentsOf: DiffableResult(identifier: "indirect").trackDifference(actual: self.indirect, expected: castObject.indirect)) - return results - } -} -extension FileParserResult: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? FileParserResult else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "path").trackDifference(actual: self.path, expected: castObject.path)) - results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) - results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) - results.append(contentsOf: DiffableResult(identifier: "functions").trackDifference(actual: self.functions, expected: castObject.functions)) - results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) - results.append(contentsOf: DiffableResult(identifier: "inlineRanges").trackDifference(actual: self.inlineRanges, expected: castObject.inlineRanges)) - results.append(contentsOf: DiffableResult(identifier: "inlineIndentations").trackDifference(actual: self.inlineIndentations, expected: castObject.inlineIndentations)) - results.append(contentsOf: DiffableResult(identifier: "modifiedDate").trackDifference(actual: self.modifiedDate, expected: castObject.modifiedDate)) - results.append(contentsOf: DiffableResult(identifier: "sourceryVersion").trackDifference(actual: self.sourceryVersion, expected: castObject.sourceryVersion)) - return results - } -} -extension GenericRequirement: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? GenericRequirement else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "leftType").trackDifference(actual: self.leftType, expected: castObject.leftType)) - results.append(contentsOf: DiffableResult(identifier: "rightType").trackDifference(actual: self.rightType, expected: castObject.rightType)) - results.append(contentsOf: DiffableResult(identifier: "relationship").trackDifference(actual: self.relationship, expected: castObject.relationship)) - results.append(contentsOf: DiffableResult(identifier: "relationshipSyntax").trackDifference(actual: self.relationshipSyntax, expected: castObject.relationshipSyntax)) - return results - } -} -extension GenericType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? GenericType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "typeParameters").trackDifference(actual: self.typeParameters, expected: castObject.typeParameters)) - return results - } -} -extension GenericTypeParameter: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? GenericTypeParameter else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - return results - } -} -extension Import: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Import else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "kind").trackDifference(actual: self.kind, expected: castObject.kind)) - results.append(contentsOf: DiffableResult(identifier: "path").trackDifference(actual: self.path, expected: castObject.path)) - return results - } -} -extension Method: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Method else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "selectorName").trackDifference(actual: self.selectorName, expected: castObject.selectorName)) - results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) - results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) - results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) - results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) - results.append(contentsOf: DiffableResult(identifier: "`rethrows`").trackDifference(actual: self.`rethrows`, expected: castObject.`rethrows`)) - results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) - results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) - results.append(contentsOf: DiffableResult(identifier: "isClass").trackDifference(actual: self.isClass, expected: castObject.isClass)) - results.append(contentsOf: DiffableResult(identifier: "isFailableInitializer").trackDifference(actual: self.isFailableInitializer, expected: castObject.isFailableInitializer)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) - results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) - results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) - results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) - return results - } -} -extension MethodParameter: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? MethodParameter else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "argumentLabel").trackDifference(actual: self.argumentLabel, expected: castObject.argumentLabel)) - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - results.append(contentsOf: DiffableResult(identifier: "`inout`").trackDifference(actual: self.`inout`, expected: castObject.`inout`)) - results.append(contentsOf: DiffableResult(identifier: "isVariadic").trackDifference(actual: self.isVariadic, expected: castObject.isVariadic)) - results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - return results - } -} -extension Modifier: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Modifier else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "detail").trackDifference(actual: self.detail, expected: castObject.detail)) - return results - } -} -extension Protocol { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Protocol else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "associatedTypes").trackDifference(actual: self.associatedTypes, expected: castObject.associatedTypes)) - results.append(contentsOf: DiffableResult(identifier: "genericRequirements").trackDifference(actual: self.genericRequirements, expected: castObject.genericRequirements)) - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension ProtocolComposition { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? ProtocolComposition else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "composedTypeNames").trackDifference(actual: self.composedTypeNames, expected: castObject.composedTypeNames)) - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension Struct { - override public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Struct else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: super.diffAgainst(castObject)) - return results - } -} -extension Subscript: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Subscript else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) - results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) - results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) - results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) - results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) - results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) - results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) - return results - } -} -extension TemplateContext: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? TemplateContext else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "parserResult").trackDifference(actual: self.parserResult, expected: castObject.parserResult)) - results.append(contentsOf: DiffableResult(identifier: "functions").trackDifference(actual: self.functions, expected: castObject.functions)) - results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) - results.append(contentsOf: DiffableResult(identifier: "argument").trackDifference(actual: self.argument, expected: castObject.argument)) - return results - } -} -extension TupleElement: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? TupleElement else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - return results - } -} -extension TupleType: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? TupleType else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "elements").trackDifference(actual: self.elements, expected: castObject.elements)) - return results - } -} -extension Type: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Type else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) - results.append(contentsOf: DiffableResult(identifier: "imports").trackDifference(actual: self.imports, expected: castObject.imports)) - results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) - results.append(contentsOf: DiffableResult(identifier: "isExtension").trackDifference(actual: self.isExtension, expected: castObject.isExtension)) - results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) - results.append(contentsOf: DiffableResult(identifier: "isUnknownExtension").trackDifference(actual: self.isUnknownExtension, expected: castObject.isUnknownExtension)) - results.append(contentsOf: DiffableResult(identifier: "isGeneric").trackDifference(actual: self.isGeneric, expected: castObject.isGeneric)) - results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) - results.append(contentsOf: DiffableResult(identifier: "rawVariables").trackDifference(actual: self.rawVariables, expected: castObject.rawVariables)) - results.append(contentsOf: DiffableResult(identifier: "rawMethods").trackDifference(actual: self.rawMethods, expected: castObject.rawMethods)) - results.append(contentsOf: DiffableResult(identifier: "rawSubscripts").trackDifference(actual: self.rawSubscripts, expected: castObject.rawSubscripts)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) - results.append(contentsOf: DiffableResult(identifier: "inheritedTypes").trackDifference(actual: self.inheritedTypes, expected: castObject.inheritedTypes)) - results.append(contentsOf: DiffableResult(identifier: "inherits").trackDifference(actual: self.inherits, expected: castObject.inherits)) - results.append(contentsOf: DiffableResult(identifier: "containedTypes").trackDifference(actual: self.containedTypes, expected: castObject.containedTypes)) - results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) - results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) - results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) - results.append(contentsOf: DiffableResult(identifier: "fileName").trackDifference(actual: self.fileName, expected: castObject.fileName)) - return results - } -} -extension TypeName: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? TypeName else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "generic").trackDifference(actual: self.generic, expected: castObject.generic)) - results.append(contentsOf: DiffableResult(identifier: "isProtocolComposition").trackDifference(actual: self.isProtocolComposition, expected: castObject.isProtocolComposition)) - results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) - results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) - results.append(contentsOf: DiffableResult(identifier: "tuple").trackDifference(actual: self.tuple, expected: castObject.tuple)) - results.append(contentsOf: DiffableResult(identifier: "array").trackDifference(actual: self.array, expected: castObject.array)) - results.append(contentsOf: DiffableResult(identifier: "dictionary").trackDifference(actual: self.dictionary, expected: castObject.dictionary)) - results.append(contentsOf: DiffableResult(identifier: "closure").trackDifference(actual: self.closure, expected: castObject.closure)) - return results - } -} -extension Typealias: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Typealias else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "aliasName").trackDifference(actual: self.aliasName, expected: castObject.aliasName)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) - results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) - results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) - return results - } -} -extension Types: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Types else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) - results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) - return results - } -} -extension Variable: Diffable { - @objc public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let castObject = object as? Variable else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) - results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) - results.append(contentsOf: DiffableResult(identifier: "isComputed").trackDifference(actual: self.isComputed, expected: castObject.isComputed)) - results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) - results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) - results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) - results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) - results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) - results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) - results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) - results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) - results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) - results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) - results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) - return results - } -} - -"""), - .init(name: "Diffable.swift", content: -""" -// -// Diffable.swift -// Sourcery -// -// Created by Krzysztof Zabłocki on 22/12/2016. -// Copyright © 2016 Pixle. All rights reserved. -// - -import Foundation - -public protocol Diffable { - - /// Returns `DiffableResult` for the given objects. - /// - /// - Parameter object: Object to diff against. - /// - Returns: Diffable results. - func diffAgainst(_ object: Any?) -> DiffableResult -} - -/// :nodoc: -extension NSRange: Diffable { - /// :nodoc: - public static func == (lhs: NSRange, rhs: NSRange) -> Bool { - return NSEqualRanges(lhs, rhs) - } - - public func diffAgainst(_ object: Any?) -> DiffableResult { - let results = DiffableResult() - guard let rhs = object as? NSRange else { - results.append("Incorrect type ") - return results - } - results.append(contentsOf: DiffableResult(identifier: "location").trackDifference(actual: self.location, expected: rhs.location)) - results.append(contentsOf: DiffableResult(identifier: "length").trackDifference(actual: self.length, expected: rhs.length)) - return results - } -} - -@objcMembers public class DiffableResult: NSObject, AutoEquatable { - // sourcery: skipEquality - private var results: [String] - internal var identifier: String? - - init(results: [String] = [], identifier: String? = nil) { - self.results = results - self.identifier = identifier - } - - func append(_ element: String) { - results.append(element) - } - - func append(contentsOf contents: DiffableResult) { - if !contents.isEmpty { - results.append(contents.description) - } - } - - var isEmpty: Bool { return results.isEmpty } - - public override var description: String { - guard !results.isEmpty else { return "" } - return "\\(identifier.flatMap { "\\($0) " } ?? "")" + results.joined(separator: "\\n") - } -} - -public extension DiffableResult { - -#if swift(>=4.1) -#else - /// :nodoc: - @discardableResult func trackDifference(actual: T, expected: T) -> DiffableResult { - if actual != expected { - let result = DiffableResult(results: [""]) - append(contentsOf: result) - } - return self - } -#endif - - /// :nodoc: - @discardableResult func trackDifference(actual: T?, expected: T?) -> DiffableResult { - if actual != expected { - let result = DiffableResult(results: [""]) - append(contentsOf: result) - } - return self - } - - /// :nodoc: - @discardableResult func trackDifference(actual: T, expected: T) -> DiffableResult where T: Diffable { - let diffResult = actual.diffAgainst(expected) - append(contentsOf: diffResult) - return self - } - - /// :nodoc: - @discardableResult func trackDifference(actual: [T], expected: [T]) -> DiffableResult where T: Diffable { - let diffResult = DiffableResult() - defer { append(contentsOf: diffResult) } - - guard actual.count == expected.count else { - diffResult.append("Different count, expected: \\(expected.count), received: \\(actual.count)") - return self - } - - for (idx, item) in actual.enumerated() { - let diff = DiffableResult() - diff.trackDifference(actual: item, expected: expected[idx]) - if !diff.isEmpty { - let string = "idx \\(idx): \\(diff)" - diffResult.append(string) - } - } - - return self - } - - /// :nodoc: - @discardableResult func trackDifference(actual: [T], expected: [T]) -> DiffableResult { - let diffResult = DiffableResult() - defer { append(contentsOf: diffResult) } - - guard actual.count == expected.count else { - diffResult.append("Different count, expected: \\(expected.count), received: \\(actual.count)") - return self - } - - for (idx, item) in actual.enumerated() where item != expected[idx] { - let string = "idx \\(idx): " - diffResult.append(string) - } - - return self - } - - /// :nodoc: - @discardableResult func trackDifference(actual: [K: T], expected: [K: T]) -> DiffableResult where T: Diffable { - let diffResult = DiffableResult() - defer { append(contentsOf: diffResult) } - - guard actual.count == expected.count else { - append("Different count, expected: \\(expected.count), received: \\(actual.count)") - - if expected.count > actual.count { - let missingKeys = Array(expected.keys.filter { - actual[$0] == nil - }.map { - String(describing: $0) - }) - diffResult.append("Missing keys: \\(missingKeys.joined(separator: ", "))") - } - return self - } - - for (key, actualElement) in actual { - guard let expectedElement = expected[key] else { - diffResult.append("Missing key \\"\\(key)\\"") - continue - } - - let diff = DiffableResult() - diff.trackDifference(actual: actualElement, expected: expectedElement) - if !diff.isEmpty { - let string = "key \\"\\(key)\\": \\(diff)" - diffResult.append(string) - } - } - - return self - } - -// MARK: - NSObject diffing - - /// :nodoc: - @discardableResult func trackDifference(actual: [K: T], expected: [K: T]) -> DiffableResult { - let diffResult = DiffableResult() - defer { append(contentsOf: diffResult) } - - guard actual.count == expected.count else { - append("Different count, expected: \\(expected.count), received: \\(actual.count)") - - if expected.count > actual.count { - let missingKeys = Array(expected.keys.filter { - actual[$0] == nil - }.map { - String(describing: $0) - }) - diffResult.append("Missing keys: \\(missingKeys.joined(separator: ", "))") - } - return self - } - - for (key, actualElement) in actual { - guard let expectedElement = expected[key] else { - diffResult.append("Missing key \\"\\(key)\\"") - continue - } - - if !actualElement.isEqual(expectedElement) { - diffResult.append("key \\"\\(key)\\": ") - } - } - - return self - } -} - -"""), - .init(name: "Documentation.swift", content: -""" -import Foundation - -public typealias Documentation = [String] - -/// Describes a declaration with documentation, i.e. type, method, variable, enum case -public protocol Documented { - var documentation: Documentation { get } -} - -"""), - .init(name: "Enum.swift", content: -""" -// -// Created by Krzysztof Zablocki on 13/09/2016. -// Copyright (c) 2016 Pixle. All rights reserved. -// - -import Foundation - -/// Defines enum case associated value -@objcMembers public final class AssociatedValue: NSObject, SourceryModel, AutoDescription, Typed, Annotated { - - /// Associated value local name. - /// This is a name to be used to construct enum case value - public let localName: String? - - /// Associated value external name. - /// This is a name to be used to access value in value-bindig - public let externalName: String? - - /// Associated value type name - public let typeName: TypeName - - // sourcery: skipEquality, skipDescription - /// Associated value type, if known - public var type: Type? - - /// Associated value default value - public let defaultValue: String? - - /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 - public var annotations: Annotations = [:] - - /// :nodoc: - public init(localName: String?, externalName: String?, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { - self.localName = localName - self.externalName = externalName - self.typeName = typeName - self.type = type - self.defaultValue = defaultValue - self.annotations = annotations - } - - convenience init(name: String? = nil, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { - self.init(localName: name, externalName: name, typeName: typeName, type: type, defaultValue: defaultValue, annotations: annotations) - } - -// sourcery:inline:AssociatedValue.AutoCoding - - /// :nodoc: - required public init?(coder aDecoder: NSCoder) { - self.localName = aDecoder.decode(forKey: "localName") - self.externalName = aDecoder.decode(forKey: "externalName") - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName - self.type = aDecoder.decode(forKey: "type") - self.defaultValue = aDecoder.decode(forKey: "defaultValue") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - } - - /// :nodoc: - public func encode(with aCoder: NSCoder) { - aCoder.encode(self.localName, forKey: "localName") - aCoder.encode(self.externalName, forKey: "externalName") - aCoder.encode(self.typeName, forKey: "typeName") - aCoder.encode(self.type, forKey: "type") - aCoder.encode(self.defaultValue, forKey: "defaultValue") - aCoder.encode(self.annotations, forKey: "annotations") - } -// sourcery:end - -} - -/// Defines enum case -@objcMembers public final class EnumCase: NSObject, SourceryModel, AutoDescription, Annotated, Documented { - - /// Enum case name - public let name: String - - /// Enum case raw value, if any - public let rawValue: String? - - /// Enum case associated values - public let associatedValues: [AssociatedValue] - - /// Enum case annotations - public var annotations: Annotations = [:] - - public var documentation: Documentation = [] - - /// Whether enum case is indirect - public let indirect: Bool - - /// Whether enum case has associated value - public var hasAssociatedValue: Bool { - return !associatedValues.isEmpty - } - - // Underlying parser data, never to be used by anything else - // sourcery: skipEquality, skipDescription, skipCoding, skipJSExport - /// :nodoc: - public var __parserData: Any? - - /// :nodoc: - public init(name: String, rawValue: String? = nil, associatedValues: [AssociatedValue] = [], annotations: [String: NSObject] = [:], documentation: [String] = [], indirect: Bool = false) { - self.name = name - self.rawValue = rawValue - self.associatedValues = associatedValues - self.annotations = annotations - self.documentation = documentation - self.indirect = indirect - } - -// sourcery:inline:EnumCase.AutoCoding - - /// :nodoc: - required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - self.rawValue = aDecoder.decode(forKey: "rawValue") - guard let associatedValues: [AssociatedValue] = aDecoder.decode(forKey: "associatedValues") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["associatedValues"])); fatalError() }; self.associatedValues = associatedValues - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["documentation"])); fatalError() }; self.documentation = documentation - self.indirect = aDecoder.decode(forKey: "indirect") - } - - /// :nodoc: - public func encode(with aCoder: NSCoder) { - aCoder.encode(self.name, forKey: "name") - aCoder.encode(self.rawValue, forKey: "rawValue") - aCoder.encode(self.associatedValues, forKey: "associatedValues") - aCoder.encode(self.annotations, forKey: "annotations") - aCoder.encode(self.documentation, forKey: "documentation") - aCoder.encode(self.indirect, forKey: "indirect") - } -// sourcery:end -} - -/// Defines Swift enum -@objcMembers public final class Enum: Type { - - // sourcery: skipDescription - /// Returns "enum" - public override var kind: String { return "enum" } - - /// Enum cases - public var cases: [EnumCase] - - /** - Enum raw value type name, if any. This type is removed from enum's `based` and `inherited` types collections. - - - important: Unless raw type is specified explicitly via type alias RawValue it will be set to the first type in the inheritance chain. - So if your enum does not have raw value but implements protocols you'll have to specify conformance to these protocols via extension to get enum with nil raw value type and all based and inherited types. - */ - public var rawTypeName: TypeName? { - didSet { - if let rawTypeName = rawTypeName { - hasRawType = true - if let index = inheritedTypes.firstIndex(of: rawTypeName.name) { - inheritedTypes.remove(at: index) - } - if based[rawTypeName.name] != nil { - based[rawTypeName.name] = nil - } - } else { - hasRawType = false - } - } - } - - // sourcery: skipDescription, skipEquality - /// :nodoc: - public private(set) var hasRawType: Bool - - // sourcery: skipDescription, skipEquality - /// Enum raw value type, if known - public var rawType: Type? - - // sourcery: skipEquality, skipDescription, skipCoding - /// Names of types or protocols this type inherits from, including unknown (not scanned) types - public override var based: [String: String] { - didSet { - if let rawTypeName = rawTypeName, based[rawTypeName.name] != nil { - based[rawTypeName.name] = nil - } - } - } - - /// Whether enum contains any associated values - public var hasAssociatedValues: Bool { - return cases.contains(where: { $0.hasAssociatedValue }) - } - - /// :nodoc: - public init(name: String = "", - parent: Type? = nil, - accessLevel: AccessLevel = .internal, - isExtension: Bool = false, - inheritedTypes: [String] = [], - rawTypeName: TypeName? = nil, - cases: [EnumCase] = [], - variables: [Variable] = [], - methods: [Method] = [], - containedTypes: [Type] = [], - typealiases: [Typealias] = [], - attributes: AttributeList = [:], - modifiers: [SourceryModifier] = [], - annotations: [String: NSObject] = [:], - documentation: [String] = [], - isGeneric: Bool = false) { - - self.cases = cases - self.rawTypeName = rawTypeName - self.hasRawType = rawTypeName != nil || !inheritedTypes.isEmpty - - super.init(name: name, parent: parent, accessLevel: accessLevel, isExtension: isExtension, variables: variables, methods: methods, inheritedTypes: inheritedTypes, containedTypes: containedTypes, typealiases: typealiases, attributes: attributes, modifiers: modifiers, annotations: annotations, documentation: documentation, isGeneric: isGeneric) - - if let rawTypeName = rawTypeName?.name, let index = self.inheritedTypes.firstIndex(of: rawTypeName) { - self.inheritedTypes.remove(at: index) - } - } - -// sourcery:inline:Enum.AutoCoding - - /// :nodoc: - required public init?(coder aDecoder: NSCoder) { - guard let cases: [EnumCase] = aDecoder.decode(forKey: "cases") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["cases"])); fatalError() }; self.cases = cases - self.rawTypeName = aDecoder.decode(forKey: "rawTypeName") - self.hasRawType = aDecoder.decode(forKey: "hasRawType") - self.rawType = aDecoder.decode(forKey: "rawType") - super.init(coder: aDecoder) - } - - /// :nodoc: - override public func encode(with aCoder: NSCoder) { - super.encode(with: aCoder) - aCoder.encode(self.cases, forKey: "cases") - aCoder.encode(self.rawTypeName, forKey: "rawTypeName") - aCoder.encode(self.hasRawType, forKey: "hasRawType") - aCoder.encode(self.rawType, forKey: "rawType") - } -// sourcery:end -} - -"""), - .init(name: "Equality.generated.swift", content: -""" -// Generated using Sourcery 2.0.3 — https://github.com/krzysztofzablocki/Sourcery -// DO NOT EDIT -// swiftlint:disable vertical_whitespace - - -extension Actor { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Actor else { return false } - return super.isEqual(rhs) - } -} -extension ArrayType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? ArrayType else { return false } - if self.name != rhs.name { return false } - if self.elementTypeName != rhs.elementTypeName { return false } - return true - } -} -extension AssociatedType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? AssociatedType else { return false } - if self.name != rhs.name { return false } - if self.typeName != rhs.typeName { return false } - return true - } -} -extension AssociatedValue { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? AssociatedValue else { return false } - if self.localName != rhs.localName { return false } - if self.externalName != rhs.externalName { return false } - if self.typeName != rhs.typeName { return false } - if self.defaultValue != rhs.defaultValue { return false } - if self.annotations != rhs.annotations { return false } - return true - } -} -extension Attribute { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Attribute else { return false } - if self.name != rhs.name { return false } - if self.arguments != rhs.arguments { return false } - if self._description != rhs._description { return false } - return true - } -} -extension BytesRange { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? BytesRange else { return false } - if self.offset != rhs.offset { return false } - if self.length != rhs.length { return false } - return true - } -} -extension Class { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Class else { return false } - return super.isEqual(rhs) - } -} -extension ClosureParameter { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? ClosureParameter else { return false } - if self.argumentLabel != rhs.argumentLabel { return false } - if self.name != rhs.name { return false } - if self.typeName != rhs.typeName { return false } - if self.`inout` != rhs.`inout` { return false } - if self.defaultValue != rhs.defaultValue { return false } - if self.annotations != rhs.annotations { return false } - return true - } -} -extension ClosureType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? ClosureType else { return false } - if self.name != rhs.name { return false } - if self.parameters != rhs.parameters { return false } - if self.returnTypeName != rhs.returnTypeName { return false } - if self.isAsync != rhs.isAsync { return false } - if self.asyncKeyword != rhs.asyncKeyword { return false } - if self.`throws` != rhs.`throws` { return false } - if self.throwsOrRethrowsKeyword != rhs.throwsOrRethrowsKeyword { return false } - return true - } -} -extension DictionaryType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? DictionaryType else { return false } - if self.name != rhs.name { return false } - if self.valueTypeName != rhs.valueTypeName { return false } - if self.keyTypeName != rhs.keyTypeName { return false } - return true - } -} -extension DiffableResult { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? DiffableResult else { return false } - if self.identifier != rhs.identifier { return false } - return true - } -} -extension Enum { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Enum else { return false } - if self.cases != rhs.cases { return false } - if self.rawTypeName != rhs.rawTypeName { return false } - return super.isEqual(rhs) - } -} -extension EnumCase { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? EnumCase else { return false } - if self.name != rhs.name { return false } - if self.rawValue != rhs.rawValue { return false } - if self.associatedValues != rhs.associatedValues { return false } - if self.annotations != rhs.annotations { return false } - if self.documentation != rhs.documentation { return false } - if self.indirect != rhs.indirect { return false } - return true - } -} -extension FileParserResult { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? FileParserResult else { return false } - if self.path != rhs.path { return false } - if self.module != rhs.module { return false } - if self.types != rhs.types { return false } - if self.functions != rhs.functions { return false } - if self.typealiases != rhs.typealiases { return false } - if self.inlineRanges != rhs.inlineRanges { return false } - if self.inlineIndentations != rhs.inlineIndentations { return false } - if self.modifiedDate != rhs.modifiedDate { return false } - if self.sourceryVersion != rhs.sourceryVersion { return false } - return true - } -} -extension GenericRequirement { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? GenericRequirement else { return false } - if self.leftType != rhs.leftType { return false } - if self.rightType != rhs.rightType { return false } - if self.relationship != rhs.relationship { return false } - if self.relationshipSyntax != rhs.relationshipSyntax { return false } - return true - } -} -extension GenericType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? GenericType else { return false } - if self.name != rhs.name { return false } - if self.typeParameters != rhs.typeParameters { return false } - return true - } -} -extension GenericTypeParameter { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? GenericTypeParameter else { return false } - if self.typeName != rhs.typeName { return false } - return true - } -} -extension Import { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Import else { return false } - if self.kind != rhs.kind { return false } - if self.path != rhs.path { return false } - return true - } -} -extension Method { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Method else { return false } - if self.name != rhs.name { return false } - if self.selectorName != rhs.selectorName { return false } - if self.parameters != rhs.parameters { return false } - if self.returnTypeName != rhs.returnTypeName { return false } - if self.isAsync != rhs.isAsync { return false } - if self.`throws` != rhs.`throws` { return false } - if self.`rethrows` != rhs.`rethrows` { return false } - if self.accessLevel != rhs.accessLevel { return false } - if self.isStatic != rhs.isStatic { return false } - if self.isClass != rhs.isClass { return false } - if self.isFailableInitializer != rhs.isFailableInitializer { return false } - if self.annotations != rhs.annotations { return false } - if self.documentation != rhs.documentation { return false } - if self.definedInTypeName != rhs.definedInTypeName { return false } - if self.attributes != rhs.attributes { return false } - if self.modifiers != rhs.modifiers { return false } - return true - } -} -extension MethodParameter { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? MethodParameter else { return false } - if self.argumentLabel != rhs.argumentLabel { return false } - if self.name != rhs.name { return false } - if self.typeName != rhs.typeName { return false } - if self.`inout` != rhs.`inout` { return false } - if self.isVariadic != rhs.isVariadic { return false } - if self.defaultValue != rhs.defaultValue { return false } - if self.annotations != rhs.annotations { return false } - return true - } -} -extension Modifier { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Modifier else { return false } - if self.name != rhs.name { return false } - if self.detail != rhs.detail { return false } - return true - } -} -extension Protocol { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Protocol else { return false } - if self.associatedTypes != rhs.associatedTypes { return false } - if self.genericRequirements != rhs.genericRequirements { return false } - return super.isEqual(rhs) - } -} -extension ProtocolComposition { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? ProtocolComposition else { return false } - if self.composedTypeNames != rhs.composedTypeNames { return false } - return super.isEqual(rhs) - } -} -extension Struct { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Struct else { return false } - return super.isEqual(rhs) - } -} -extension Subscript { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Subscript else { return false } - if self.parameters != rhs.parameters { return false } - if self.returnTypeName != rhs.returnTypeName { return false } - if self.readAccess != rhs.readAccess { return false } - if self.writeAccess != rhs.writeAccess { return false } - if self.annotations != rhs.annotations { return false } - if self.documentation != rhs.documentation { return false } - if self.definedInTypeName != rhs.definedInTypeName { return false } - if self.attributes != rhs.attributes { return false } - if self.modifiers != rhs.modifiers { return false } - return true - } -} -extension TemplateContext { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? TemplateContext else { return false } - if self.parserResult != rhs.parserResult { return false } - if self.functions != rhs.functions { return false } - if self.types != rhs.types { return false } - if self.argument != rhs.argument { return false } - return true - } -} -extension TupleElement { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? TupleElement else { return false } - if self.name != rhs.name { return false } - if self.typeName != rhs.typeName { return false } - return true - } -} -extension TupleType { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? TupleType else { return false } - if self.name != rhs.name { return false } - if self.elements != rhs.elements { return false } - return true - } -} -extension Type { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Type else { return false } - if self.module != rhs.module { return false } - if self.imports != rhs.imports { return false } - if self.typealiases != rhs.typealiases { return false } - if self.isExtension != rhs.isExtension { return false } - if self.accessLevel != rhs.accessLevel { return false } - if self.isUnknownExtension != rhs.isUnknownExtension { return false } - if self.isGeneric != rhs.isGeneric { return false } - if self.localName != rhs.localName { return false } - if self.rawVariables != rhs.rawVariables { return false } - if self.rawMethods != rhs.rawMethods { return false } - if self.rawSubscripts != rhs.rawSubscripts { return false } - if self.annotations != rhs.annotations { return false } - if self.documentation != rhs.documentation { return false } - if self.inheritedTypes != rhs.inheritedTypes { return false } - if self.inherits != rhs.inherits { return false } - if self.containedTypes != rhs.containedTypes { return false } - if self.parentName != rhs.parentName { return false } - if self.attributes != rhs.attributes { return false } - if self.modifiers != rhs.modifiers { return false } - if self.fileName != rhs.fileName { return false } - if self.kind != rhs.kind { return false } - return true - } -} -extension TypeName { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? TypeName else { return false } - if self.name != rhs.name { return false } - if self.generic != rhs.generic { return false } - if self.isProtocolComposition != rhs.isProtocolComposition { return false } - if self.attributes != rhs.attributes { return false } - if self.modifiers != rhs.modifiers { return false } - if self.tuple != rhs.tuple { return false } - if self.array != rhs.array { return false } - if self.dictionary != rhs.dictionary { return false } - if self.closure != rhs.closure { return false } - return true - } -} -extension Typealias { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Typealias else { return false } - if self.aliasName != rhs.aliasName { return false } - if self.typeName != rhs.typeName { return false } - if self.module != rhs.module { return false } - if self.accessLevel != rhs.accessLevel { return false } - if self.parentName != rhs.parentName { return false } - return true - } -} -extension Types { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Types else { return false } - if self.types != rhs.types { return false } - if self.typealiases != rhs.typealiases { return false } - return true - } -} -extension Variable { - /// :nodoc: - public override func isEqual(_ object: Any?) -> Bool { - guard let rhs = object as? Variable else { return false } - if self.name != rhs.name { return false } - if self.typeName != rhs.typeName { return false } - if self.isComputed != rhs.isComputed { return false } - if self.isAsync != rhs.isAsync { return false } - if self.`throws` != rhs.`throws` { return false } - if self.isStatic != rhs.isStatic { return false } - if self.readAccess != rhs.readAccess { return false } - if self.writeAccess != rhs.writeAccess { return false } - if self.defaultValue != rhs.defaultValue { return false } - if self.annotations != rhs.annotations { return false } - if self.documentation != rhs.documentation { return false } - if self.attributes != rhs.attributes { return false } - if self.modifiers != rhs.modifiers { return false } - if self.definedInTypeName != rhs.definedInTypeName { return false } - return true - } -} - -// MARK: - Actor AutoHashable -extension Actor { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - ArrayType AutoHashable -extension ArrayType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.elementTypeName) - return hasher.finalize() - } -} -// MARK: - AssociatedType AutoHashable -extension AssociatedType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.typeName) - return hasher.finalize() - } -} -// MARK: - AssociatedValue AutoHashable -extension AssociatedValue { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.localName) - hasher.combine(self.externalName) - hasher.combine(self.typeName) - hasher.combine(self.defaultValue) - hasher.combine(self.annotations) - return hasher.finalize() - } -} -// MARK: - Attribute AutoHashable -extension Attribute { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.arguments) - hasher.combine(self._description) - return hasher.finalize() - } -} -// MARK: - BytesRange AutoHashable -extension BytesRange { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.offset) - hasher.combine(self.length) - return hasher.finalize() - } -} -// MARK: - Class AutoHashable -extension Class { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - ClosureParameter AutoHashable -extension ClosureParameter { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.argumentLabel) - hasher.combine(self.name) - hasher.combine(self.typeName) - hasher.combine(self.`inout`) - hasher.combine(self.defaultValue) - hasher.combine(self.annotations) - return hasher.finalize() - } -} -// MARK: - ClosureType AutoHashable -extension ClosureType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.parameters) - hasher.combine(self.returnTypeName) - hasher.combine(self.isAsync) - hasher.combine(self.asyncKeyword) - hasher.combine(self.`throws`) - hasher.combine(self.throwsOrRethrowsKeyword) - return hasher.finalize() - } -} -// MARK: - DictionaryType AutoHashable -extension DictionaryType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.valueTypeName) - hasher.combine(self.keyTypeName) - return hasher.finalize() - } -} -// MARK: - DiffableResult AutoHashable -extension DiffableResult { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.identifier) - return hasher.finalize() - } -} -// MARK: - Enum AutoHashable -extension Enum { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.cases) - hasher.combine(self.rawTypeName) - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - EnumCase AutoHashable -extension EnumCase { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.rawValue) - hasher.combine(self.associatedValues) - hasher.combine(self.annotations) - hasher.combine(self.documentation) - hasher.combine(self.indirect) - return hasher.finalize() - } -} -// MARK: - FileParserResult AutoHashable -extension FileParserResult { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.path) - hasher.combine(self.module) - hasher.combine(self.types) - hasher.combine(self.functions) - hasher.combine(self.typealiases) - hasher.combine(self.inlineRanges) - hasher.combine(self.inlineIndentations) - hasher.combine(self.modifiedDate) - hasher.combine(self.sourceryVersion) - return hasher.finalize() - } -} -// MARK: - GenericRequirement AutoHashable -extension GenericRequirement { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.leftType) - hasher.combine(self.rightType) - hasher.combine(self.relationship) - hasher.combine(self.relationshipSyntax) - return hasher.finalize() - } -} -// MARK: - GenericType AutoHashable -extension GenericType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.typeParameters) - return hasher.finalize() - } -} -// MARK: - GenericTypeParameter AutoHashable -extension GenericTypeParameter { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.typeName) - return hasher.finalize() - } -} -// MARK: - Import AutoHashable -extension Import { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.kind) - hasher.combine(self.path) - return hasher.finalize() - } -} -// MARK: - Method AutoHashable -extension Method { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.selectorName) - hasher.combine(self.parameters) - hasher.combine(self.returnTypeName) - hasher.combine(self.isAsync) - hasher.combine(self.`throws`) - hasher.combine(self.`rethrows`) - hasher.combine(self.accessLevel) - hasher.combine(self.isStatic) - hasher.combine(self.isClass) - hasher.combine(self.isFailableInitializer) - hasher.combine(self.annotations) - hasher.combine(self.documentation) - hasher.combine(self.definedInTypeName) - hasher.combine(self.attributes) - hasher.combine(self.modifiers) - return hasher.finalize() - } -} -// MARK: - MethodParameter AutoHashable -extension MethodParameter { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.argumentLabel) - hasher.combine(self.name) - hasher.combine(self.typeName) - hasher.combine(self.`inout`) - hasher.combine(self.isVariadic) - hasher.combine(self.defaultValue) - hasher.combine(self.annotations) - return hasher.finalize() - } -} -// MARK: - Modifier AutoHashable -extension Modifier { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.detail) - return hasher.finalize() - } -} -// MARK: - Protocol AutoHashable -extension Protocol { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.associatedTypes) - hasher.combine(self.genericRequirements) - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - ProtocolComposition AutoHashable -extension ProtocolComposition { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.composedTypeNames) - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - Struct AutoHashable -extension Struct { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(super.hash) - return hasher.finalize() - } -} -// MARK: - Subscript AutoHashable -extension Subscript { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.parameters) - hasher.combine(self.returnTypeName) - hasher.combine(self.readAccess) - hasher.combine(self.writeAccess) - hasher.combine(self.annotations) - hasher.combine(self.documentation) - hasher.combine(self.definedInTypeName) - hasher.combine(self.attributes) - hasher.combine(self.modifiers) - return hasher.finalize() - } -} -// MARK: - TemplateContext AutoHashable -extension TemplateContext { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.parserResult) - hasher.combine(self.functions) - hasher.combine(self.types) - hasher.combine(self.argument) - return hasher.finalize() - } -} -// MARK: - TupleElement AutoHashable -extension TupleElement { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.typeName) - return hasher.finalize() - } -} -// MARK: - TupleType AutoHashable -extension TupleType { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.elements) - return hasher.finalize() - } -} -// MARK: - Type AutoHashable -extension Type { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.module) - hasher.combine(self.imports) - hasher.combine(self.typealiases) - hasher.combine(self.isExtension) - hasher.combine(self.accessLevel) - hasher.combine(self.isUnknownExtension) - hasher.combine(self.isGeneric) - hasher.combine(self.localName) - hasher.combine(self.rawVariables) - hasher.combine(self.rawMethods) - hasher.combine(self.rawSubscripts) - hasher.combine(self.annotations) - hasher.combine(self.documentation) - hasher.combine(self.inheritedTypes) - hasher.combine(self.inherits) - hasher.combine(self.containedTypes) - hasher.combine(self.parentName) - hasher.combine(self.attributes) - hasher.combine(self.modifiers) - hasher.combine(self.fileName) - hasher.combine(kind) - return hasher.finalize() - } -} -// MARK: - TypeName AutoHashable -extension TypeName { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.generic) - hasher.combine(self.isProtocolComposition) - hasher.combine(self.attributes) - hasher.combine(self.modifiers) - hasher.combine(self.tuple) - hasher.combine(self.array) - hasher.combine(self.dictionary) - hasher.combine(self.closure) - return hasher.finalize() + + /// :nodoc: + public init(name: String = "", + parent: Type? = nil, + accessLevel: AccessLevel = .internal, + isExtension: Bool = false, + inheritedTypes: [String] = [], + rawTypeName: TypeName? = nil, + cases: [EnumCase] = [], + variables: [Variable] = [], + methods: [Method] = [], + containedTypes: [Type] = [], + typealiases: [Typealias] = [], + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + isGeneric: Bool = false) { + + self.cases = cases + self.rawTypeName = rawTypeName + self.hasRawType = rawTypeName != nil || !inheritedTypes.isEmpty + + super.init(name: name, parent: parent, accessLevel: accessLevel, isExtension: isExtension, variables: variables, methods: methods, inheritedTypes: inheritedTypes, containedTypes: containedTypes, typealiases: typealiases, attributes: attributes, modifiers: modifiers, annotations: annotations, documentation: documentation, isGeneric: isGeneric) + + if let rawTypeName = rawTypeName?.name, let index = self.inheritedTypes.firstIndex(of: rawTypeName) { + self.inheritedTypes.remove(at: index) + } } -} -// MARK: - Typealias AutoHashable -extension Typealias { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.aliasName) - hasher.combine(self.typeName) - hasher.combine(self.module) - hasher.combine(self.accessLevel) - hasher.combine(self.parentName) - return hasher.finalize() + + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "cases = \\(String(describing: self.cases)), " + string += "rawTypeName = \\(String(describing: self.rawTypeName)), " + string += "hasAssociatedValues = \\(String(describing: self.hasAssociatedValues))" + return string } -} -// MARK: - Types AutoHashable -extension Types { - public override var hash: Int { - var hasher = Hasher() - hasher.combine(self.types) - hasher.combine(self.typealiases) - return hasher.finalize() + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Enum else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "cases").trackDifference(actual: self.cases, expected: castObject.cases)) + results.append(contentsOf: DiffableResult(identifier: "rawTypeName").trackDifference(actual: self.rawTypeName, expected: castObject.rawTypeName)) + results.append(contentsOf: super.diffAgainst(castObject)) + return results } -} -// MARK: - Variable AutoHashable -extension Variable { + public override var hash: Int { var hasher = Hasher() - hasher.combine(self.name) - hasher.combine(self.typeName) - hasher.combine(self.isComputed) - hasher.combine(self.isAsync) - hasher.combine(self.`throws`) - hasher.combine(self.isStatic) - hasher.combine(self.readAccess) - hasher.combine(self.writeAccess) - hasher.combine(self.defaultValue) - hasher.combine(self.annotations) - hasher.combine(self.documentation) - hasher.combine(self.attributes) - hasher.combine(self.modifiers) - hasher.combine(self.definedInTypeName) + hasher.combine(self.cases) + hasher.combine(self.rawTypeName) + hasher.combine(super.hash) return hasher.finalize() } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Enum else { return false } + if self.cases != rhs.cases { return false } + if self.rawTypeName != rhs.rawTypeName { return false } + return super.isEqual(rhs) + } + +// sourcery:inline:Enum.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let cases: [EnumCase] = aDecoder.decode(forKey: "cases") else { + withVaList(["cases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.cases = cases + self.rawTypeName = aDecoder.decode(forKey: "rawTypeName") + self.hasRawType = aDecoder.decode(forKey: "hasRawType") + self.rawType = aDecoder.decode(forKey: "rawType") + super.init(coder: aDecoder) + } + + /// :nodoc: + override public func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + aCoder.encode(self.cases, forKey: "cases") + aCoder.encode(self.rawTypeName, forKey: "rawTypeName") + aCoder.encode(self.hasRawType, forKey: "hasRawType") + aCoder.encode(self.rawType, forKey: "rawType") + } +// sourcery:end } """), @@ -3397,7 +2307,7 @@ public extension String { public extension NSString { /// :nodoc: - var entireRange: NSRange { + var entireRange: NSRange {5 return NSRange(location: 0, length: self.length) } } @@ -3417,7 +2327,8 @@ import Foundation // sourcery: skipJSExport /// :nodoc: -@objcMembers public final class FileParserResult: NSObject, SourceryModel { +@objcMembers +public final class FileParserResult: NSObject, SourceryModel, Diffable { public let path: String? public let module: String? public var types = [Type]() { @@ -3458,19 +2369,117 @@ import Foundation } } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "path = \\(String(describing: self.path)), " + string += "module = \\(String(describing: self.module)), " + string += "types = \\(String(describing: self.types)), " + string += "functions = \\(String(describing: self.functions)), " + string += "typealiases = \\(String(describing: self.typealiases)), " + string += "inlineRanges = \\(String(describing: self.inlineRanges)), " + string += "inlineIndentations = \\(String(describing: self.inlineIndentations)), " + string += "modifiedDate = \\(String(describing: self.modifiedDate)), " + string += "sourceryVersion = \\(String(describing: self.sourceryVersion)), " + string += "isEmpty = \\(String(describing: self.isEmpty))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? FileParserResult else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "path").trackDifference(actual: self.path, expected: castObject.path)) + results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) + results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) + results.append(contentsOf: DiffableResult(identifier: "functions").trackDifference(actual: self.functions, expected: castObject.functions)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + results.append(contentsOf: DiffableResult(identifier: "inlineRanges").trackDifference(actual: self.inlineRanges, expected: castObject.inlineRanges)) + results.append(contentsOf: DiffableResult(identifier: "inlineIndentations").trackDifference(actual: self.inlineIndentations, expected: castObject.inlineIndentations)) + results.append(contentsOf: DiffableResult(identifier: "modifiedDate").trackDifference(actual: self.modifiedDate, expected: castObject.modifiedDate)) + results.append(contentsOf: DiffableResult(identifier: "sourceryVersion").trackDifference(actual: self.sourceryVersion, expected: castObject.sourceryVersion)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.path) + hasher.combine(self.module) + hasher.combine(self.types) + hasher.combine(self.functions) + hasher.combine(self.typealiases) + hasher.combine(self.inlineRanges) + hasher.combine(self.inlineIndentations) + hasher.combine(self.modifiedDate) + hasher.combine(self.sourceryVersion) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? FileParserResult else { return false } + if self.path != rhs.path { return false } + if self.module != rhs.module { return false } + if self.types != rhs.types { return false } + if self.functions != rhs.functions { return false } + if self.typealiases != rhs.typealiases { return false } + if self.inlineRanges != rhs.inlineRanges { return false } + if self.inlineIndentations != rhs.inlineIndentations { return false } + if self.modifiedDate != rhs.modifiedDate { return false } + if self.sourceryVersion != rhs.sourceryVersion { return false } + return true + } + // sourcery:inline:FileParserResult.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { self.path = aDecoder.decode(forKey: "path") self.module = aDecoder.decode(forKey: "module") - guard let types: [Type] = aDecoder.decode(forKey: "types") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["types"])); fatalError() }; self.types = types - guard let functions: [SourceryMethod] = aDecoder.decode(forKey: "functions") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["functions"])); fatalError() }; self.functions = functions - guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typealiases"])); fatalError() }; self.typealiases = typealiases - guard let inlineRanges: [String: NSRange] = aDecoder.decode(forKey: "inlineRanges") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["inlineRanges"])); fatalError() }; self.inlineRanges = inlineRanges - guard let inlineIndentations: [String: String] = aDecoder.decode(forKey: "inlineIndentations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["inlineIndentations"])); fatalError() }; self.inlineIndentations = inlineIndentations - guard let modifiedDate: Date = aDecoder.decode(forKey: "modifiedDate") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiedDate"])); fatalError() }; self.modifiedDate = modifiedDate - guard let sourceryVersion: String = aDecoder.decode(forKey: "sourceryVersion") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["sourceryVersion"])); fatalError() }; self.sourceryVersion = sourceryVersion + guard let types: [Type] = aDecoder.decode(forKey: "types") else { + withVaList(["types"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.types = types + guard let functions: [SourceryMethod] = aDecoder.decode(forKey: "functions") else { + withVaList(["functions"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.functions = functions + guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases + guard let inlineRanges: [String: NSRange] = aDecoder.decode(forKey: "inlineRanges") else { + withVaList(["inlineRanges"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inlineRanges = inlineRanges + guard let inlineIndentations: [String: String] = aDecoder.decode(forKey: "inlineIndentations") else { + withVaList(["inlineIndentations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inlineIndentations = inlineIndentations + guard let modifiedDate: Date = aDecoder.decode(forKey: "modifiedDate") else { + withVaList(["modifiedDate"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiedDate = modifiedDate + guard let sourceryVersion: String = aDecoder.decode(forKey: "sourceryVersion") else { + withVaList(["sourceryVersion"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.sourceryVersion = sourceryVersion } /// :nodoc: @@ -3494,7 +2503,8 @@ import Foundation import Foundation /// Descibes Swift generic type -@objcMembers public final class GenericType: NSObject, SourceryModelWithoutDescription { +@objcMembers +public final class GenericType: NSObject, SourceryModelWithoutDescription, Diffable { /// The name of the base type, i.e. `Array` for `Array` public var name: String @@ -3518,12 +2528,48 @@ import Foundation asSource } + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? GenericType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeParameters").trackDifference(actual: self.typeParameters, expected: castObject.typeParameters)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeParameters) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? GenericType else { return false } + if self.name != rhs.name { return false } + if self.typeParameters != rhs.typeParameters { return false } + return true + } + // sourcery:inline:GenericType.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let typeParameters: [GenericTypeParameter] = aDecoder.decode(forKey: "typeParameters") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeParameters"])); fatalError() }; self.typeParameters = typeParameters + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeParameters: [GenericTypeParameter] = aDecoder.decode(forKey: "typeParameters") else { + withVaList(["typeParameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeParameters = typeParameters } /// :nodoc: @@ -3536,7 +2582,8 @@ import Foundation } /// Descibes Swift generic type parameter -@objcMembers public final class GenericTypeParameter: NSObject, SourceryModel { +@objcMembers +public final class GenericTypeParameter: NSObject, SourceryModel, Diffable { /// Generic parameter type name public var typeName: TypeName @@ -3551,11 +2598,46 @@ import Foundation self.type = type } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "typeName = \\(String(describing: self.typeName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? GenericTypeParameter else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.typeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? GenericTypeParameter else { return false } + if self.typeName != rhs.typeName { return false } + return true + } + // sourcery:inline:GenericTypeParameter.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName self.type = aDecoder.decode(forKey: "type") } @@ -3575,7 +2657,8 @@ import Foundation /// modifier can be thing like `private`, `class`, `nonmutating` /// if a declaration has modifier like `private(set)` it's name will be `private` and detail will be `set` -@objcMembers public class GenericRequirement: NSObject, SourceryModel { +@objcMembers +public class GenericRequirement: NSObject, SourceryModel, Diffable { public enum Relationship: String { case equals @@ -3597,24 +2680,86 @@ import Foundation /// relationship name public let relationship: String - /// Syntax e.g. `==` or `:` - public let relationshipSyntax: String + /// Syntax e.g. `==` or `:` + public let relationshipSyntax: String + + public init(leftType: AssociatedType, rightType: GenericTypeParameter, relationship: Relationship) { + self.leftType = leftType + self.rightType = rightType + self.relationship = relationship.rawValue + self.relationshipSyntax = relationship.syntax + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "leftType = \\(String(describing: self.leftType)), " + string += "rightType = \\(String(describing: self.rightType)), " + string += "relationship = \\(String(describing: self.relationship)), " + string += "relationshipSyntax = \\(String(describing: self.relationshipSyntax))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? GenericRequirement else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "leftType").trackDifference(actual: self.leftType, expected: castObject.leftType)) + results.append(contentsOf: DiffableResult(identifier: "rightType").trackDifference(actual: self.rightType, expected: castObject.rightType)) + results.append(contentsOf: DiffableResult(identifier: "relationship").trackDifference(actual: self.relationship, expected: castObject.relationship)) + results.append(contentsOf: DiffableResult(identifier: "relationshipSyntax").trackDifference(actual: self.relationshipSyntax, expected: castObject.relationshipSyntax)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.leftType) + hasher.combine(self.rightType) + hasher.combine(self.relationship) + hasher.combine(self.relationshipSyntax) + return hasher.finalize() + } - public init(leftType: AssociatedType, rightType: GenericTypeParameter, relationship: Relationship) { - self.leftType = leftType - self.rightType = rightType - self.relationship = relationship.rawValue - self.relationshipSyntax = relationship.syntax + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? GenericRequirement else { return false } + if self.leftType != rhs.leftType { return false } + if self.rightType != rhs.rightType { return false } + if self.relationship != rhs.relationship { return false } + if self.relationshipSyntax != rhs.relationshipSyntax { return false } + return true } // sourcery:inline:GenericRequirement.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let leftType: AssociatedType = aDecoder.decode(forKey: "leftType") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["leftType"])); fatalError() }; self.leftType = leftType - guard let rightType: GenericTypeParameter = aDecoder.decode(forKey: "rightType") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["rightType"])); fatalError() }; self.rightType = rightType - guard let relationship: String = aDecoder.decode(forKey: "relationship") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["relationship"])); fatalError() }; self.relationship = relationship - guard let relationshipSyntax: String = aDecoder.decode(forKey: "relationshipSyntax") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["relationshipSyntax"])); fatalError() }; self.relationshipSyntax = relationshipSyntax + guard let leftType: AssociatedType = aDecoder.decode(forKey: "leftType") else { + withVaList(["leftType"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.leftType = leftType + guard let rightType: GenericTypeParameter = aDecoder.decode(forKey: "rightType") else { + withVaList(["rightType"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rightType = rightType + guard let relationship: String = aDecoder.decode(forKey: "relationship") else { + withVaList(["relationship"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.relationship = relationship + guard let relationshipSyntax: String = aDecoder.decode(forKey: "relationshipSyntax") else { + withVaList(["relationshipSyntax"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.relationshipSyntax = relationshipSyntax } /// :nodoc: @@ -3633,7 +2778,8 @@ import Foundation import Foundation /// Defines import type -@objcMembers public class Import: NSObject, SourceryModelWithoutDescription { +@objcMembers +public class Import: NSObject, SourceryModelWithoutDescription, Diffable { /// Import kind, e.g. class, struct in `import class Module.ClassName` public var kind: String? @@ -3668,12 +2814,43 @@ import Foundation } } + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Import else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "kind").trackDifference(actual: self.kind, expected: castObject.kind)) + results.append(contentsOf: DiffableResult(identifier: "path").trackDifference(actual: self.path, expected: castObject.path)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.kind) + hasher.combine(self.path) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Import else { return false } + if self.kind != rhs.kind { return false } + if self.path != rhs.path { return false } + return true + } + // sourcery:inline:Import.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { self.kind = aDecoder.decode(forKey: "kind") - guard let path: String = aDecoder.decode(forKey: "path") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["path"])); fatalError() }; self.path = path + guard let path: String = aDecoder.decode(forKey: "path") else { + withVaList(["path"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.path = path } /// :nodoc: @@ -4311,7 +3488,6 @@ extension TypesCollection: TypesCollectionAutoJSExport {} extension Variable: VariableAutoJSExport {} - """), .init(name: "Log.swift", content: """ @@ -4338,7 +3514,7 @@ public enum Log { public static func error(_ message: Any) { log(level: .errors, "error: \\(message)") // to return error when running swift templates which is done in a different process - if ProcessInfo().processName != "Sourcery" { + if ProcessInfo.processInfo.processName != "Sourcery" { fputs("\\(message)", stderr) } } @@ -4391,15 +3567,13 @@ public enum Log { extension String: Error {} """), - .init(name: "Method.swift", content: + .init(name: "MethodParameter.swift", content: """ import Foundation -/// :nodoc: -public typealias SourceryMethod = Method - /// Describes method parameter -@objcMembers public class MethodParameter: NSObject, SourceryModel, Typed, Annotated { +@objcMembers +public class MethodParameter: NSObject, SourceryModel, Typed, Annotated, Diffable { /// Parameter external name public var argumentLabel: String? @@ -4413,7 +3587,7 @@ public typealias SourceryMethod = Method /// Parameter flag whether it's inout or not public let `inout`: Bool - + /// Is this variadic parameter? public let isVariadic: Bool @@ -4469,18 +3643,89 @@ public typealias SourceryMethod = Method return (labels.nilIfEmpty ?? "_") + typeSuffix } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "argumentLabel = \\(String(describing: self.argumentLabel)), " + string += "name = \\(String(describing: self.name)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "`inout` = \\(String(describing: self.`inout`)), " + string += "isVariadic = \\(String(describing: self.isVariadic)), " + string += "typeAttributes = \\(String(describing: self.typeAttributes)), " + string += "defaultValue = \\(String(describing: self.defaultValue)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? MethodParameter else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "argumentLabel").trackDifference(actual: self.argumentLabel, expected: castObject.argumentLabel)) + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "`inout`").trackDifference(actual: self.`inout`, expected: castObject.`inout`)) + results.append(contentsOf: DiffableResult(identifier: "isVariadic").trackDifference(actual: self.isVariadic, expected: castObject.isVariadic)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.argumentLabel) + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.`inout`) + hasher.combine(self.isVariadic) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? MethodParameter else { return false } + if self.argumentLabel != rhs.argumentLabel { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.`inout` != rhs.`inout` { return false } + if self.isVariadic != rhs.isVariadic { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true + } + // sourcery:inline:MethodParameter.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { self.argumentLabel = aDecoder.decode(forKey: "argumentLabel") - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName self.`inout` = aDecoder.decode(forKey: "`inout`") self.isVariadic = aDecoder.decode(forKey: "isVariadic") self.type = aDecoder.decode(forKey: "type") self.defaultValue = aDecoder.decode(forKey: "defaultValue") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations } /// :nodoc: @@ -4503,8 +3748,14 @@ extension Array where Element == MethodParameter { } } +"""), + .init(name: "ClosureParameter.swift", content: +""" +import Foundation + // sourcery: skipDiffing -@objcMembers public final class ClosureParameter: NSObject, SourceryModel, Typed, Annotated { +@objcMembers +public final class ClosureParameter: NSObject, SourceryModel, Typed, Annotated { /// Parameter external name public var argumentLabel: String? @@ -4562,17 +3813,64 @@ extension Array where Element == MethodParameter { return (labels.nilIfEmpty ?? "_") + typeSuffix } + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.argumentLabel) + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.`inout`) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "argumentLabel = \\(String(describing: self.argumentLabel)), " + string += "name = \\(String(describing: self.name)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "`inout` = \\(String(describing: self.`inout`)), " + string += "typeAttributes = \\(String(describing: self.typeAttributes)), " + string += "defaultValue = \\(String(describing: self.defaultValue)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ClosureParameter else { return false } + if self.argumentLabel != rhs.argumentLabel { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.`inout` != rhs.`inout` { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true + } + // sourcery:inline:ClosureParameter.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { self.argumentLabel = aDecoder.decode(forKey: "argumentLabel") self.name = aDecoder.decode(forKey: "name") - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName self.`inout` = aDecoder.decode(forKey: "`inout`") self.type = aDecoder.decode(forKey: "type") self.defaultValue = aDecoder.decode(forKey: "defaultValue") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations } /// :nodoc: @@ -4594,9 +3892,17 @@ extension Array where Element == ClosureParameter { "(\\(map { $0.asSource }.joined(separator: ", ")))" } } +"""), + .init(name: "Method.swift", content: +""" +import Foundation + +/// :nodoc: +public typealias SourceryMethod = Method /// Describes method -@objc(SwiftMethod) @objcMembers public final class Method: NSObject, SourceryModel, Annotated, Documented, Definition { +@objc(SwiftMethod) @objcMembers +public final class Method: NSObject, SourceryModel, Annotated, Documented, Definition, Diffable { /// Full method name, including generic constraints, i.e. `foo(bar: T)` public let name: String @@ -4792,28 +4098,163 @@ extension Array where Element == ClosureParameter { self.definedInTypeName = definedInTypeName } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "selectorName = \\(String(describing: self.selectorName)), " + string += "parameters = \\(String(describing: self.parameters)), " + string += "returnTypeName = \\(String(describing: self.returnTypeName)), " + string += "isAsync = \\(String(describing: self.isAsync)), " + string += "`throws` = \\(String(describing: self.`throws`)), " + string += "`rethrows` = \\(String(describing: self.`rethrows`)), " + string += "accessLevel = \\(String(describing: self.accessLevel)), " + string += "isStatic = \\(String(describing: self.isStatic)), " + string += "isClass = \\(String(describing: self.isClass)), " + string += "isFailableInitializer = \\(String(describing: self.isFailableInitializer)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "documentation = \\(String(describing: self.documentation)), " + string += "definedInTypeName = \\(String(describing: self.definedInTypeName)), " + string += "attributes = \\(String(describing: self.attributes)), " + string += "modifiers = \\(String(describing: self.modifiers))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Method else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "selectorName").trackDifference(actual: self.selectorName, expected: castObject.selectorName)) + results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) + results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "`rethrows`").trackDifference(actual: self.`rethrows`, expected: castObject.`rethrows`)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) + results.append(contentsOf: DiffableResult(identifier: "isClass").trackDifference(actual: self.isClass, expected: castObject.isClass)) + results.append(contentsOf: DiffableResult(identifier: "isFailableInitializer").trackDifference(actual: self.isFailableInitializer, expected: castObject.isFailableInitializer)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.selectorName) + hasher.combine(self.parameters) + hasher.combine(self.returnTypeName) + hasher.combine(self.isAsync) + hasher.combine(self.`throws`) + hasher.combine(self.`rethrows`) + hasher.combine(self.accessLevel) + hasher.combine(self.isStatic) + hasher.combine(self.isClass) + hasher.combine(self.isFailableInitializer) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.definedInTypeName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Method else { return false } + if self.name != rhs.name { return false } + if self.selectorName != rhs.selectorName { return false } + if self.parameters != rhs.parameters { return false } + if self.returnTypeName != rhs.returnTypeName { return false } + if self.isAsync != rhs.isAsync { return false } + if self.`throws` != rhs.`throws` { return false } + if self.`rethrows` != rhs.`rethrows` { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.isStatic != rhs.isStatic { return false } + if self.isClass != rhs.isClass { return false } + if self.isFailableInitializer != rhs.isFailableInitializer { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + return true + } + // sourcery:inline:Method.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let selectorName: String = aDecoder.decode(forKey: "selectorName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["selectorName"])); fatalError() }; self.selectorName = selectorName - guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["parameters"])); fatalError() }; self.parameters = parameters - guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["returnTypeName"])); fatalError() }; self.returnTypeName = returnTypeName + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let selectorName: String = aDecoder.decode(forKey: "selectorName") else { + withVaList(["selectorName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.selectorName = selectorName + guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { + withVaList(["parameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.parameters = parameters + guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { + withVaList(["returnTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.returnTypeName = returnTypeName self.returnType = aDecoder.decode(forKey: "returnType") self.isAsync = aDecoder.decode(forKey: "isAsync") self.`throws` = aDecoder.decode(forKey: "`throws`") self.`rethrows` = aDecoder.decode(forKey: "`rethrows`") - guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["accessLevel"])); fatalError() }; self.accessLevel = accessLevel + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel self.isStatic = aDecoder.decode(forKey: "isStatic") self.isClass = aDecoder.decode(forKey: "isClass") self.isFailableInitializer = aDecoder.decode(forKey: "isFailableInitializer") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["documentation"])); fatalError() }; self.documentation = documentation + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") self.definedInType = aDecoder.decode(forKey: "definedInType") - guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["attributes"])); fatalError() }; self.attributes = attributes - guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiers"])); fatalError() }; self.modifiers = modifiers + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers } /// :nodoc: @@ -4848,7 +4289,8 @@ import Foundation public typealias SourceryModifier = Modifier /// modifier can be thing like `private`, `class`, `nonmutating` /// if a declaration has modifier like `private(set)` it's name will be `private` and detail will be `set` -@objcMembers public class Modifier: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport { +@objcMembers +public class Modifier: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport, Diffable { /// The declaration modifier name. public let name: String @@ -4869,11 +4311,42 @@ public typealias SourceryModifier = Modifier } } + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Modifier else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "detail").trackDifference(actual: self.detail, expected: castObject.detail)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.detail) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Modifier else { return false } + if self.name != rhs.name { return false } + if self.detail != rhs.detail { return false } + return true + } + // sourcery:inline:Modifier.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name self.detail = aDecoder.decode(forKey: "detail") } @@ -4885,6 +4358,7 @@ public typealias SourceryModifier = Modifier // sourcery:end } + """), .init(name: "ParserResultsComposed.swift", content: """ @@ -5433,7 +4907,8 @@ import Foundation public typealias SourceryProtocol = Protocol /// Describes Swift protocol -@objcMembers public final class Protocol: Type { +@objcMembers +public final class Protocol: Type { /// Returns "protocol" public override var kind: String { return "protocol" } @@ -5490,12 +4965,60 @@ public typealias SourceryProtocol = Protocol ) } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \\(String(describing: self.kind)), " + string += "associatedTypes = \\(String(describing: self.associatedTypes)), " + string += "genericRequirements = \\(String(describing: self.genericRequirements))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Protocol else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "associatedTypes").trackDifference(actual: self.associatedTypes, expected: castObject.associatedTypes)) + results.append(contentsOf: DiffableResult(identifier: "genericRequirements").trackDifference(actual: self.genericRequirements, expected: castObject.genericRequirements)) + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.associatedTypes) + hasher.combine(self.genericRequirements) + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Protocol else { return false } + if self.associatedTypes != rhs.associatedTypes { return false } + if self.genericRequirements != rhs.genericRequirements { return false } + return super.isEqual(rhs) + } + // sourcery:inline:Protocol.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let associatedTypes: [String: AssociatedType] = aDecoder.decode(forKey: "associatedTypes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["associatedTypes"])); fatalError() }; self.associatedTypes = associatedTypes - guard let genericRequirements: [GenericRequirement] = aDecoder.decode(forKey: "genericRequirements") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["genericRequirements"])); fatalError() }; self.genericRequirements = genericRequirements + guard let associatedTypes: [String: AssociatedType] = aDecoder.decode(forKey: "associatedTypes") else { + withVaList(["associatedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.associatedTypes = associatedTypes + guard let genericRequirements: [GenericRequirement] = aDecoder.decode(forKey: "genericRequirements") else { + withVaList(["genericRequirements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.genericRequirements = genericRequirements super.init(coder: aDecoder) } @@ -5518,7 +5041,8 @@ import Foundation // sourcery: skipJSExport /// Describes a Swift [protocol composition](https://docs.swift.org/swift-book/ReferenceManual/Types.html#ID454). -@objcMembers public final class ProtocolComposition: Type { +@objcMembers +public final class ProtocolComposition: Type { /// Returns "protocolComposition" public override var kind: String { return "protocolComposition" } @@ -5564,11 +5088,50 @@ import Foundation ) } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \\(String(describing: self.kind)), " + string += "composedTypeNames = \\(String(describing: self.composedTypeNames))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? ProtocolComposition else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "composedTypeNames").trackDifference(actual: self.composedTypeNames, expected: castObject.composedTypeNames)) + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.composedTypeNames) + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ProtocolComposition else { return false } + if self.composedTypeNames != rhs.composedTypeNames { return false } + return super.isEqual(rhs) + } + // sourcery:inline:ProtocolComposition.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let composedTypeNames: [TypeName] = aDecoder.decode(forKey: "composedTypeNames") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["composedTypeNames"])); fatalError() }; self.composedTypeNames = composedTypeNames + guard let composedTypeNames: [TypeName] = aDecoder.decode(forKey: "composedTypeNames") else { + withVaList(["composedTypeNames"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.composedTypeNames = composedTypeNames self.composedTypes = aDecoder.decode(forKey: "composedTypes") super.init(coder: aDecoder) } @@ -5598,7 +5161,8 @@ import Foundation // sourcery: skipDescription /// Describes Swift struct -@objcMembers public final class Struct: Type { +@objcMembers +public final class Struct: Type { /// Returns "struct" public override var kind: String { return "struct" } @@ -5638,6 +5202,36 @@ import Foundation ) } + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \\(String(describing: self.kind))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Struct else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Struct else { return false } + return super.isEqual(rhs) + } + // sourcery:inline:Struct.AutoCoding /// :nodoc: @@ -5658,7 +5252,8 @@ import Foundation import Foundation /// Describes subscript -@objcMembers public final class Subscript: NSObject, SourceryModel, Annotated, Documented, Definition { +@objcMembers +public final class Subscript: NSObject, SourceryModel, Annotated, Documented, Definition, Diffable { /// Method parameters public var parameters: [MethodParameter] @@ -5761,21 +5356,127 @@ import Foundation self.definedInTypeName = definedInTypeName } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "parameters = \\(String(describing: self.parameters)), " + string += "returnTypeName = \\(String(describing: self.returnTypeName)), " + string += "actualReturnTypeName = \\(String(describing: self.actualReturnTypeName)), " + string += "isFinal = \\(String(describing: self.isFinal)), " + string += "readAccess = \\(String(describing: self.readAccess)), " + string += "writeAccess = \\(String(describing: self.writeAccess)), " + string += "isMutable = \\(String(describing: self.isMutable)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "documentation = \\(String(describing: self.documentation)), " + string += "definedInTypeName = \\(String(describing: self.definedInTypeName)), " + string += "actualDefinedInTypeName = \\(String(describing: self.actualDefinedInTypeName)), " + string += "attributes = \\(String(describing: self.attributes)), " + string += "modifiers = \\(String(describing: self.modifiers))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Subscript else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) + results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) + results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) + results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.parameters) + hasher.combine(self.returnTypeName) + hasher.combine(self.readAccess) + hasher.combine(self.writeAccess) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.definedInTypeName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Subscript else { return false } + if self.parameters != rhs.parameters { return false } + if self.returnTypeName != rhs.returnTypeName { return false } + if self.readAccess != rhs.readAccess { return false } + if self.writeAccess != rhs.writeAccess { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + return true + } + // sourcery:inline:Subscript.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["parameters"])); fatalError() }; self.parameters = parameters - guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["returnTypeName"])); fatalError() }; self.returnTypeName = returnTypeName + guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { + withVaList(["parameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.parameters = parameters + guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { + withVaList(["returnTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.returnTypeName = returnTypeName self.returnType = aDecoder.decode(forKey: "returnType") - guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["readAccess"])); fatalError() }; self.readAccess = readAccess - guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["writeAccess"])); fatalError() }; self.writeAccess = writeAccess - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["documentation"])); fatalError() }; self.documentation = documentation + guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { + withVaList(["readAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.readAccess = readAccess + guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { + withVaList(["writeAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.writeAccess = writeAccess + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") self.definedInType = aDecoder.decode(forKey: "definedInType") - guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["attributes"])); fatalError() }; self.attributes = attributes - guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiers"])); fatalError() }; self.modifiers = modifiers + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers } /// :nodoc: @@ -5808,7 +5509,8 @@ import Foundation /// :nodoc: // sourcery: skipCoding -@objcMembers public final class TemplateContext: NSObject, SourceryModel, NSCoding { +@objcMembers +public final class TemplateContext: NSObject, SourceryModel, NSCoding, Diffable { // sourcery: skipJSExport public let parserResult: FileParserResult? public let functions: [SourceryMethod] @@ -5829,8 +5531,18 @@ import Foundation /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let parserResult: FileParserResult = aDecoder.decode(forKey: "parserResult") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found. FileParserResults are required for template context that needs persisting.", arguments: getVaList(["parserResult"])); fatalError() } - guard let argument: [String: NSObject] = aDecoder.decode(forKey: "argument") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["argument"])); fatalError() } + guard let parserResult: FileParserResult = aDecoder.decode(forKey: "parserResult") else { + withVaList(["parserResult"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found. FileParserResults are required for template context that needs persisting.", arguments: arguments) + } + fatalError() + } + guard let argument: [String: NSObject] = aDecoder.decode(forKey: "argument") else { + withVaList(["argument"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + } // if we want to support multiple cycles of encode / decode we need deep copy because composer changes reference types let fileParserResultCopy: FileParserResult? = nil @@ -5844,19 +5556,62 @@ import Foundation self.argument = argument } - /// :nodoc: - public func encode(with aCoder: NSCoder) { - aCoder.encode(self.parserResult, forKey: "parserResult") - aCoder.encode(self.argument, forKey: "argument") + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.parserResult, forKey: "parserResult") + aCoder.encode(self.argument, forKey: "argument") + } + + public var stencilContext: [String: Any] { + return [ + "types": types, + "functions": functions, + "type": types.typesByName, + "argument": argument + ] + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "parserResult = \\(String(describing: self.parserResult)), " + string += "functions = \\(String(describing: self.functions)), " + string += "types = \\(String(describing: self.types)), " + string += "argument = \\(String(describing: self.argument)), " + string += "stencilContext = \\(String(describing: self.stencilContext))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TemplateContext else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "parserResult").trackDifference(actual: self.parserResult, expected: castObject.parserResult)) + results.append(contentsOf: DiffableResult(identifier: "functions").trackDifference(actual: self.functions, expected: castObject.functions)) + results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) + results.append(contentsOf: DiffableResult(identifier: "argument").trackDifference(actual: self.argument, expected: castObject.argument)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.parserResult) + hasher.combine(self.functions) + hasher.combine(self.types) + hasher.combine(self.argument) + return hasher.finalize() } - public var stencilContext: [String: Any] { - return [ - "types": types, - "functions": functions, - "type": types.typesByName, - "argument": argument - ] + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TemplateContext else { return false } + if self.parserResult != rhs.parserResult { return false } + if self.functions != rhs.functions { return false } + if self.types != rhs.types { return false } + if self.argument != rhs.argument { return false } + return true } // sourcery: skipDescription, skipEquality @@ -5872,7 +5627,7 @@ import Foundation "based": types.based, "inheriting": types.inheriting, "implementing": types.implementing - ], + ] as [String : Any], "functions": functions, "type": types.typesByName, "argument": argument @@ -5888,9 +5643,15 @@ extension ProcessInfo { } } +"""), + .init(name: "Types.swift", content: +""" +import Foundation + // sourcery: skipJSExport /// Collection of scanned types for accessing in templates -@objcMembers public final class Types: NSObject, SourceryModel { +@objcMembers +public final class Types: NSObject, SourceryModel, Diffable { /// :nodoc: public let types: [Type] @@ -5904,12 +5665,56 @@ extension ProcessInfo { self.typealiases = typealiases } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "types = \\(String(describing: self.types)), " + string += "typealiases = \\(String(describing: self.typealiases))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Types else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.types) + hasher.combine(self.typealiases) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Types else { return false } + if self.types != rhs.types { return false } + if self.typealiases != rhs.typealiases { return false } + return true + } + // sourcery:inline:Types.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let types: [Type] = aDecoder.decode(forKey: "types") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["types"])); fatalError() }; self.types = types - guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typealiases"])); fatalError() }; self.typealiases = typealiases + guard let types: [Type] = aDecoder.decode(forKey: "types") else { + withVaList(["types"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.types = types + guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases } /// :nodoc: @@ -6016,9 +5821,14 @@ extension ProcessInfo { }() } -/// :nodoc: -@objcMembers public class TypesCollection: NSObject, AutoJSExport { +"""), + .init(name: "TypesCollection.swift", content: +""" +import Foundation +/// :nodoc: +@objcMembers +public class TypesCollection: NSObject, AutoJSExport { // sourcery:begin: skipJSExport let all: [Type] let types: [String: [Type]] @@ -6069,7 +5879,7 @@ extension ProcessInfo { } /// :nodoc: - public override func value(forKey key: String) -> Any? { + override public func value(forKey key: String) -> Any? { do { return try types(forKey: key) } catch { @@ -6088,7 +5898,7 @@ extension ProcessInfo { } } - public override func responds(to aSelector: Selector!) -> Bool { + override public func responds(to aSelector: Selector!) -> Bool { return true } } @@ -6099,7 +5909,8 @@ extension ProcessInfo { import Foundation /// Describes tuple type -@objcMembers public final class TupleType: NSObject, SourceryModel { +@objcMembers +public final class TupleType: NSObject, SourceryModel, Diffable { /// Type name used in declaration public var name: String @@ -6119,12 +5930,56 @@ import Foundation self.elements = elements } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "elements = \\(String(describing: self.elements))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TupleType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "elements").trackDifference(actual: self.elements, expected: castObject.elements)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.elements) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TupleType else { return false } + if self.name != rhs.name { return false } + if self.elements != rhs.elements { return false } + return true + } + // sourcery:inline:TupleType.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let elements: [TupleElement] = aDecoder.decode(forKey: "elements") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["elements"])); fatalError() }; self.elements = elements + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let elements: [TupleElement] = aDecoder.decode(forKey: "elements") else { + withVaList(["elements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.elements = elements } /// :nodoc: @@ -6136,7 +5991,8 @@ import Foundation } /// Describes tuple type element -@objcMembers public final class TupleElement: NSObject, SourceryModel, Typed { +@objcMembers +public final class TupleElement: NSObject, SourceryModel, Typed, Diffable { /// Tuple element name public let name: String? @@ -6160,12 +6016,52 @@ import Foundation "\\(name != nil ? "\\(name!): " : "")\\(typeName.asSource)" } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TupleElement else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TupleElement else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + return true + } + // sourcery:inline:TupleElement.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { self.name = aDecoder.decode(forKey: "name") - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName self.type = aDecoder.decode(forKey: "type") } @@ -6202,7 +6098,8 @@ import Foundation public typealias AttributeList = [String: [Attribute]] /// Defines Swift type -@objcMembers public class Type: NSObject, SourceryModel, Annotated, Documented { +@objcMembers +public class Type: NSObject, SourceryModel, Annotated, Documented, Diffable { /// :nodoc: public var module: String? @@ -6595,16 +6492,136 @@ public typealias AttributeList = [String: [Attribute]] } /// :nodoc: - public func extend(_ type: Type) { - type.annotations.forEach { self.annotations[$0.key] = $0.value } - type.inherits.forEach { self.inherits[$0.key] = $0.value } - type.implements.forEach { self.implements[$0.key] = $0.value } - self.inheritedTypes += type.inheritedTypes - self.containedTypes += type.containedTypes - - self.rawVariables += type.rawVariables - self.rawMethods += type.rawMethods - self.rawSubscripts += type.rawSubscripts + public func extend(_ type: Type) { + type.annotations.forEach { self.annotations[$0.key] = $0.value } + type.inherits.forEach { self.inherits[$0.key] = $0.value } + type.implements.forEach { self.implements[$0.key] = $0.value } + self.inheritedTypes += type.inheritedTypes + self.containedTypes += type.containedTypes + + self.rawVariables += type.rawVariables + self.rawMethods += type.rawMethods + self.rawSubscripts += type.rawSubscripts + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "module = \\(String(describing: self.module)), " + string += "imports = \\(String(describing: self.imports)), " + string += "allImports = \\(String(describing: self.allImports)), " + string += "typealiases = \\(String(describing: self.typealiases)), " + string += "isExtension = \\(String(describing: self.isExtension)), " + string += "kind = \\(String(describing: self.kind)), " + string += "accessLevel = \\(String(describing: self.accessLevel)), " + string += "name = \\(String(describing: self.name)), " + string += "isUnknownExtension = \\(String(describing: self.isUnknownExtension)), " + string += "isGeneric = \\(String(describing: self.isGeneric)), " + string += "localName = \\(String(describing: self.localName)), " + string += "rawVariables = \\(String(describing: self.rawVariables)), " + string += "rawMethods = \\(String(describing: self.rawMethods)), " + string += "rawSubscripts = \\(String(describing: self.rawSubscripts)), " + string += "initializers = \\(String(describing: self.initializers)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "documentation = \\(String(describing: self.documentation)), " + string += "staticVariables = \\(String(describing: self.staticVariables)), " + string += "staticMethods = \\(String(describing: self.staticMethods)), " + string += "classMethods = \\(String(describing: self.classMethods)), " + string += "instanceVariables = \\(String(describing: self.instanceVariables)), " + string += "instanceMethods = \\(String(describing: self.instanceMethods)), " + string += "computedVariables = \\(String(describing: self.computedVariables)), " + string += "storedVariables = \\(String(describing: self.storedVariables)), " + string += "inheritedTypes = \\(String(describing: self.inheritedTypes)), " + string += "inherits = \\(String(describing: self.inherits)), " + string += "containedTypes = \\(String(describing: self.containedTypes)), " + string += "parentName = \\(String(describing: self.parentName)), " + string += "parentTypes = \\(String(describing: self.parentTypes)), " + string += "attributes = \\(String(describing: self.attributes)), " + string += "modifiers = \\(String(describing: self.modifiers)), " + string += "fileName = \\(String(describing: self.fileName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Type else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) + results.append(contentsOf: DiffableResult(identifier: "imports").trackDifference(actual: self.imports, expected: castObject.imports)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + results.append(contentsOf: DiffableResult(identifier: "isExtension").trackDifference(actual: self.isExtension, expected: castObject.isExtension)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "isUnknownExtension").trackDifference(actual: self.isUnknownExtension, expected: castObject.isUnknownExtension)) + results.append(contentsOf: DiffableResult(identifier: "isGeneric").trackDifference(actual: self.isGeneric, expected: castObject.isGeneric)) + results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) + results.append(contentsOf: DiffableResult(identifier: "rawVariables").trackDifference(actual: self.rawVariables, expected: castObject.rawVariables)) + results.append(contentsOf: DiffableResult(identifier: "rawMethods").trackDifference(actual: self.rawMethods, expected: castObject.rawMethods)) + results.append(contentsOf: DiffableResult(identifier: "rawSubscripts").trackDifference(actual: self.rawSubscripts, expected: castObject.rawSubscripts)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "inheritedTypes").trackDifference(actual: self.inheritedTypes, expected: castObject.inheritedTypes)) + results.append(contentsOf: DiffableResult(identifier: "inherits").trackDifference(actual: self.inherits, expected: castObject.inherits)) + results.append(contentsOf: DiffableResult(identifier: "containedTypes").trackDifference(actual: self.containedTypes, expected: castObject.containedTypes)) + results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "fileName").trackDifference(actual: self.fileName, expected: castObject.fileName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.module) + hasher.combine(self.imports) + hasher.combine(self.typealiases) + hasher.combine(self.isExtension) + hasher.combine(self.accessLevel) + hasher.combine(self.isUnknownExtension) + hasher.combine(self.isGeneric) + hasher.combine(self.localName) + hasher.combine(self.rawVariables) + hasher.combine(self.rawMethods) + hasher.combine(self.rawSubscripts) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.inheritedTypes) + hasher.combine(self.inherits) + hasher.combine(self.containedTypes) + hasher.combine(self.parentName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.fileName) + hasher.combine(kind) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Type else { return false } + if self.module != rhs.module { return false } + if self.imports != rhs.imports { return false } + if self.typealiases != rhs.typealiases { return false } + if self.isExtension != rhs.isExtension { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.isUnknownExtension != rhs.isUnknownExtension { return false } + if self.isGeneric != rhs.isGeneric { return false } + if self.localName != rhs.localName { return false } + if self.rawVariables != rhs.rawVariables { return false } + if self.rawMethods != rhs.rawMethods { return false } + if self.rawSubscripts != rhs.rawSubscripts { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.inheritedTypes != rhs.inheritedTypes { return false } + if self.inherits != rhs.inherits { return false } + if self.containedTypes != rhs.containedTypes { return false } + if self.parentName != rhs.parentName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.fileName != rhs.fileName { return false } + if self.kind != rhs.kind { return false } + return true } // sourcery:inline:Type.AutoCoding @@ -6612,31 +6629,121 @@ public typealias AttributeList = [String: [Attribute]] /// :nodoc: required public init?(coder aDecoder: NSCoder) { self.module = aDecoder.decode(forKey: "module") - guard let imports: [Import] = aDecoder.decode(forKey: "imports") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["imports"])); fatalError() }; self.imports = imports - guard let typealiases: [String: Typealias] = aDecoder.decode(forKey: "typealiases") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typealiases"])); fatalError() }; self.typealiases = typealiases + guard let imports: [Import] = aDecoder.decode(forKey: "imports") else { + withVaList(["imports"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.imports = imports + guard let typealiases: [String: Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases self.isExtension = aDecoder.decode(forKey: "isExtension") - guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["accessLevel"])); fatalError() }; self.accessLevel = accessLevel + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel self.isGeneric = aDecoder.decode(forKey: "isGeneric") - guard let localName: String = aDecoder.decode(forKey: "localName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["localName"])); fatalError() }; self.localName = localName - guard let rawVariables: [Variable] = aDecoder.decode(forKey: "rawVariables") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["rawVariables"])); fatalError() }; self.rawVariables = rawVariables - guard let rawMethods: [Method] = aDecoder.decode(forKey: "rawMethods") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["rawMethods"])); fatalError() }; self.rawMethods = rawMethods - guard let rawSubscripts: [Subscript] = aDecoder.decode(forKey: "rawSubscripts") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["rawSubscripts"])); fatalError() }; self.rawSubscripts = rawSubscripts + guard let localName: String = aDecoder.decode(forKey: "localName") else { + withVaList(["localName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.localName = localName + guard let rawVariables: [Variable] = aDecoder.decode(forKey: "rawVariables") else { + withVaList(["rawVariables"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawVariables = rawVariables + guard let rawMethods: [Method] = aDecoder.decode(forKey: "rawMethods") else { + withVaList(["rawMethods"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawMethods = rawMethods + guard let rawSubscripts: [Subscript] = aDecoder.decode(forKey: "rawSubscripts") else { + withVaList(["rawSubscripts"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawSubscripts = rawSubscripts self.bodyBytesRange = aDecoder.decode(forKey: "bodyBytesRange") self.completeDeclarationRange = aDecoder.decode(forKey: "completeDeclarationRange") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["documentation"])); fatalError() }; self.documentation = documentation - guard let inheritedTypes: [String] = aDecoder.decode(forKey: "inheritedTypes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["inheritedTypes"])); fatalError() }; self.inheritedTypes = inheritedTypes - guard let based: [String: String] = aDecoder.decode(forKey: "based") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["based"])); fatalError() }; self.based = based - guard let basedTypes: [String: Type] = aDecoder.decode(forKey: "basedTypes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["basedTypes"])); fatalError() }; self.basedTypes = basedTypes - guard let inherits: [String: Type] = aDecoder.decode(forKey: "inherits") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["inherits"])); fatalError() }; self.inherits = inherits - guard let implements: [String: Type] = aDecoder.decode(forKey: "implements") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["implements"])); fatalError() }; self.implements = implements - guard let containedTypes: [Type] = aDecoder.decode(forKey: "containedTypes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["containedTypes"])); fatalError() }; self.containedTypes = containedTypes - guard let containedType: [String: Type] = aDecoder.decode(forKey: "containedType") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["containedType"])); fatalError() }; self.containedType = containedType + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + guard let inheritedTypes: [String] = aDecoder.decode(forKey: "inheritedTypes") else { + withVaList(["inheritedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inheritedTypes = inheritedTypes + guard let based: [String: String] = aDecoder.decode(forKey: "based") else { + withVaList(["based"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.based = based + guard let basedTypes: [String: Type] = aDecoder.decode(forKey: "basedTypes") else { + withVaList(["basedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.basedTypes = basedTypes + guard let inherits: [String: Type] = aDecoder.decode(forKey: "inherits") else { + withVaList(["inherits"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inherits = inherits + guard let implements: [String: Type] = aDecoder.decode(forKey: "implements") else { + withVaList(["implements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.implements = implements + guard let containedTypes: [Type] = aDecoder.decode(forKey: "containedTypes") else { + withVaList(["containedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.containedTypes = containedTypes + guard let containedType: [String: Type] = aDecoder.decode(forKey: "containedType") else { + withVaList(["containedType"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.containedType = containedType self.parentName = aDecoder.decode(forKey: "parentName") self.parent = aDecoder.decode(forKey: "parent") self.supertype = aDecoder.decode(forKey: "supertype") - guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["attributes"])); fatalError() }; self.attributes = attributes - guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiers"])); fatalError() }; self.modifiers = modifiers + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers self.path = aDecoder.decode(forKey: "path") self.fileName = aDecoder.decode(forKey: "fileName") } @@ -6673,6 +6780,7 @@ public typealias AttributeList = [String: [Attribute]] aCoder.encode(self.fileName, forKey: "fileName") } // sourcery:end + } extension Type { @@ -6708,7 +6816,8 @@ extension Type { import Foundation /// Describes name of the type used in typed declaration (variable, method parameter or return value etc.) -@objcMembers public final class TypeName: NSObject, SourceryModelWithoutDescription, LosslessStringConvertible { +@objcMembers +public final class TypeName: NSObject, SourceryModelWithoutDescription, LosslessStringConvertible, Diffable { /// :nodoc: public init(name: String, actualTypeName: TypeName? = nil, @@ -6868,19 +6977,86 @@ import Foundation ).joined(separator: " ") } + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TypeName else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "generic").trackDifference(actual: self.generic, expected: castObject.generic)) + results.append(contentsOf: DiffableResult(identifier: "isProtocolComposition").trackDifference(actual: self.isProtocolComposition, expected: castObject.isProtocolComposition)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "tuple").trackDifference(actual: self.tuple, expected: castObject.tuple)) + results.append(contentsOf: DiffableResult(identifier: "array").trackDifference(actual: self.array, expected: castObject.array)) + results.append(contentsOf: DiffableResult(identifier: "dictionary").trackDifference(actual: self.dictionary, expected: castObject.dictionary)) + results.append(contentsOf: DiffableResult(identifier: "closure").trackDifference(actual: self.closure, expected: castObject.closure)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.generic) + hasher.combine(self.isProtocolComposition) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.tuple) + hasher.combine(self.array) + hasher.combine(self.dictionary) + hasher.combine(self.closure) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TypeName else { return false } + if self.name != rhs.name { return false } + if self.generic != rhs.generic { return false } + if self.isProtocolComposition != rhs.isProtocolComposition { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.tuple != rhs.tuple { return false } + if self.array != rhs.array { return false } + if self.dictionary != rhs.dictionary { return false } + if self.closure != rhs.closure { return false } + return true + } + // sourcery:inline:TypeName.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name self.generic = aDecoder.decode(forKey: "generic") self.isProtocolComposition = aDecoder.decode(forKey: "isProtocolComposition") self.actualTypeName = aDecoder.decode(forKey: "actualTypeName") - guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["attributes"])); fatalError() }; self.attributes = attributes - guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiers"])); fatalError() }; self.modifiers = modifiers + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers self.isOptional = aDecoder.decode(forKey: "isOptional") self.isImplicitlyUnwrappedOptional = aDecoder.decode(forKey: "isImplicitlyUnwrappedOptional") - guard let unwrappedTypeName: String = aDecoder.decode(forKey: "unwrappedTypeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["unwrappedTypeName"])); fatalError() }; self.unwrappedTypeName = unwrappedTypeName + guard let unwrappedTypeName: String = aDecoder.decode(forKey: "unwrappedTypeName") else { + withVaList(["unwrappedTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.unwrappedTypeName = unwrappedTypeName self.tuple = aDecoder.decode(forKey: "tuple") self.array = aDecoder.decode(forKey: "array") self.dictionary = aDecoder.decode(forKey: "dictionary") @@ -6934,7 +7110,8 @@ import Foundation // sourcery: skipJSExport /// :nodoc: -@objcMembers public final class Typealias: NSObject, Typed, SourceryModel { +@objcMembers +public final class Typealias: NSObject, Typed, SourceryModel, Diffable { // New typealias name public let aliasName: String @@ -6976,16 +7153,78 @@ import Foundation self.module = module } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "aliasName = \\(String(describing: self.aliasName)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "module = \\(String(describing: self.module)), " + string += "accessLevel = \\(String(describing: self.accessLevel)), " + string += "parentName = \\(String(describing: self.parentName)), " + string += "name = \\(String(describing: self.name))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Typealias else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "aliasName").trackDifference(actual: self.aliasName, expected: castObject.aliasName)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.aliasName) + hasher.combine(self.typeName) + hasher.combine(self.module) + hasher.combine(self.accessLevel) + hasher.combine(self.parentName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Typealias else { return false } + if self.aliasName != rhs.aliasName { return false } + if self.typeName != rhs.typeName { return false } + if self.module != rhs.module { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.parentName != rhs.parentName { return false } + return true + } + // sourcery:inline:Typealias.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let aliasName: String = aDecoder.decode(forKey: "aliasName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["aliasName"])); fatalError() }; self.aliasName = aliasName - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName + guard let aliasName: String = aDecoder.decode(forKey: "aliasName") else { + withVaList(["aliasName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.aliasName = aliasName + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName self.type = aDecoder.decode(forKey: "type") self.module = aDecoder.decode(forKey: "module") self.parent = aDecoder.decode(forKey: "parent") - guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["accessLevel"])); fatalError() }; self.accessLevel = accessLevel + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel self.parentName = aDecoder.decode(forKey: "parentName") } @@ -7162,7 +7401,9 @@ import Foundation public typealias SourceryVariable = Variable /// Defines variable -@objcMembers public final class Variable: NSObject, SourceryModel, Typed, Annotated, Documented, Definition { +@objcMembers +public final class Variable: NSObject, SourceryModel, Typed, Annotated, Documented, Definition, Diffable { + /// Variable name public let name: String @@ -7176,10 +7417,10 @@ public typealias SourceryVariable = Variable /// Whether variable is computed and not stored public let isComputed: Bool - + /// Whether variable is async public let isAsync: Bool - + /// Whether variable throws public let `throws`: Bool @@ -7275,24 +7516,151 @@ public typealias SourceryVariable = Variable self.definedInTypeName = definedInTypeName } + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "isComputed = \\(String(describing: self.isComputed)), " + string += "isAsync = \\(String(describing: self.isAsync)), " + string += "`throws` = \\(String(describing: self.`throws`)), " + string += "isStatic = \\(String(describing: self.isStatic)), " + string += "readAccess = \\(String(describing: self.readAccess)), " + string += "writeAccess = \\(String(describing: self.writeAccess)), " + string += "accessLevel = \\(String(describing: self.accessLevel)), " + string += "isMutable = \\(String(describing: self.isMutable)), " + string += "defaultValue = \\(String(describing: self.defaultValue)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "documentation = \\(String(describing: self.documentation)), " + string += "attributes = \\(String(describing: self.attributes)), " + string += "modifiers = \\(String(describing: self.modifiers)), " + string += "isFinal = \\(String(describing: self.isFinal)), " + string += "isLazy = \\(String(describing: self.isLazy)), " + string += "definedInTypeName = \\(String(describing: self.definedInTypeName)), " + string += "actualDefinedInTypeName = \\(String(describing: self.actualDefinedInTypeName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Variable else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "isComputed").trackDifference(actual: self.isComputed, expected: castObject.isComputed)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) + results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) + results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.isComputed) + hasher.combine(self.isAsync) + hasher.combine(self.`throws`) + hasher.combine(self.isStatic) + hasher.combine(self.readAccess) + hasher.combine(self.writeAccess) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.definedInTypeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Variable else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.isComputed != rhs.isComputed { return false } + if self.isAsync != rhs.isAsync { return false } + if self.`throws` != rhs.`throws` { return false } + if self.isStatic != rhs.isStatic { return false } + if self.readAccess != rhs.readAccess { return false } + if self.writeAccess != rhs.writeAccess { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + return true + } + // sourcery:inline:Variable.AutoCoding /// :nodoc: required public init?(coder aDecoder: NSCoder) { - guard let name: String = aDecoder.decode(forKey: "name") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["name"])); fatalError() }; self.name = name - guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["typeName"])); fatalError() }; self.typeName = typeName + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName self.type = aDecoder.decode(forKey: "type") self.isComputed = aDecoder.decode(forKey: "isComputed") self.isAsync = aDecoder.decode(forKey: "isAsync") self.`throws` = aDecoder.decode(forKey: "`throws`") self.isStatic = aDecoder.decode(forKey: "isStatic") - guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["readAccess"])); fatalError() }; self.readAccess = readAccess - guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["writeAccess"])); fatalError() }; self.writeAccess = writeAccess + guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { + withVaList(["readAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.readAccess = readAccess + guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { + withVaList(["writeAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.writeAccess = writeAccess self.defaultValue = aDecoder.decode(forKey: "defaultValue") - guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["annotations"])); fatalError() }; self.annotations = annotations - guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["documentation"])); fatalError() }; self.documentation = documentation - guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["attributes"])); fatalError() }; self.attributes = attributes - guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: getVaList(["modifiers"])); fatalError() }; self.modifiers = modifiers + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") self.definedInType = aDecoder.decode(forKey: "definedInType") } @@ -7321,3 +7689,4 @@ public typealias SourceryVariable = Variable """), ] +#endif diff --git a/SourcerySwift/Sources/SourceryRuntime_Linux.content.generated.swift b/SourcerySwift/Sources/SourceryRuntime_Linux.content.generated.swift new file mode 100644 index 000000000..44dde6b95 --- /dev/null +++ b/SourcerySwift/Sources/SourceryRuntime_Linux.content.generated.swift @@ -0,0 +1,7298 @@ +#if !canImport(ObjectiveC) +let sourceryRuntimeFiles: [FolderSynchronizer.File] = [ + .init(name: "AccessLevel.swift", content: +""" +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// + +import Foundation + +/// :nodoc: +public enum AccessLevel: String { + case `internal` = "internal" + case `private` = "private" + case `fileprivate` = "fileprivate" + case `public` = "public" + case `open` = "open" + case none = "" +} + +"""), + .init(name: "Actor.swift", content: +""" +import Foundation + +// sourcery: skipDescription +/// Descibes Swift actor +public final class Actor: Type { + /// Returns "actor" + public override var kind: String { return "actor" } + + /// Whether type is final + public var isFinal: Bool { + return modifiers.contains { $0.name == "final" } + } + + /// :nodoc: + public override init(name: String = "", + parent: Type? = nil, + accessLevel: AccessLevel = .internal, + isExtension: Bool = false, + variables: [Variable] = [], + methods: [Method] = [], + subscripts: [Subscript] = [], + inheritedTypes: [String] = [], + containedTypes: [Type] = [], + typealiases: [Typealias] = [], + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + isGeneric: Bool = false) { + super.init( + name: name, + parent: parent, + accessLevel: accessLevel, + isExtension: isExtension, + variables: variables, + methods: methods, + subscripts: subscripts, + inheritedTypes: inheritedTypes, + containedTypes: containedTypes, + typealiases: typealiases, + attributes: attributes, + modifiers: modifiers, + annotations: annotations, + documentation: documentation, + isGeneric: isGeneric + ) + } + + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \\(String(describing: self.kind)), " + string += "isFinal = \\(String(describing: self.isFinal))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Actor else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Actor else { return false } + return super.isEqual(rhs) + } + +// sourcery:inline:Actor.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + /// :nodoc: + override public func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + } +// sourcery:end + +} + +"""), + .init(name: "Annotations.swift", content: +""" +import Foundation + +public typealias Annotations = [String: NSObject] + +/// Describes annotated declaration, i.e. type, method, variable, enum case +public protocol Annotated { + /** + All annotations of declaration stored by their name. Value can be `bool`, `String`, float `NSNumber` + or array of those types if you use several annotations with the same name. + + **Example:** + + ``` + //sourcery: booleanAnnotation + //sourcery: stringAnnotation = "value" + //sourcery: numericAnnotation = 0.5 + + [ + "booleanAnnotation": true, + "stringAnnotation": "value", + "numericAnnotation": 0.5 + ] + ``` + */ + var annotations: Annotations { get } +} + +"""), + .init(name: "Array+Parallel.swift", content: +""" +// +// Created by Krzysztof Zablocki on 06/01/2017. +// Copyright (c) 2017 Pixle. All rights reserved. +// + +import Foundation + +public extension Array { + func parallelFlatMap(transform: (Element) -> [T]) -> [T] { + return parallelMap(transform: transform).flatMap { $0 } + } + + func parallelCompactMap(transform: (Element) -> T?) -> [T] { + return parallelMap(transform: transform).compactMap { $0 } + } + + func parallelMap(transform: (Element) -> T) -> [T] { + var result = ContiguousArray(repeating: nil, count: count) + return result.withUnsafeMutableBufferPointer { buffer in + DispatchQueue.concurrentPerform(iterations: buffer.count) { idx in + buffer[idx] = transform(self[idx]) + } + return buffer.map { $0! } + } + } + + func parallelPerform(transform: (Element) -> Void) { + DispatchQueue.concurrentPerform(iterations: count) { idx in + transform(self[idx]) + } + } +} + +"""), + .init(name: "Array.swift", content: +""" +import Foundation + +/// Describes array type +public final class ArrayType: NSObject, SourceryModel, Diffable { + /// Type name used in declaration + public var name: String + + /// Array element type name + public var elementTypeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Array element type, if known + public var elementType: Type? + + /// :nodoc: + public init(name: String, elementTypeName: TypeName, elementType: Type? = nil) { + self.name = name + self.elementTypeName = elementTypeName + self.elementType = elementType + } + + /// Returns array as generic type + public var asGeneric: GenericType { + GenericType(name: "Array", typeParameters: [ + .init(typeName: elementTypeName) + ]) + } + + public var asSource: String { + "[\\(elementTypeName.asSource)]" + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "elementTypeName = \\(String(describing: self.elementTypeName)), " + string += "asGeneric = \\(String(describing: self.asGeneric)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? ArrayType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "elementTypeName").trackDifference(actual: self.elementTypeName, expected: castObject.elementTypeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.elementTypeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ArrayType else { return false } + if self.name != rhs.name { return false } + if self.elementTypeName != rhs.elementTypeName { return false } + return true + } + +// sourcery:inline:ArrayType.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let elementTypeName: TypeName = aDecoder.decode(forKey: "elementTypeName") else { + withVaList(["elementTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.elementTypeName = elementTypeName + self.elementType = aDecoder.decode(forKey: "elementType") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.elementTypeName, forKey: "elementTypeName") + aCoder.encode(self.elementType, forKey: "elementType") + } +// sourcery:end +} + +"""), + .init(name: "NSException_Linux.swift", content: +""" +import Foundation + +public class NSException { + static func raise(_ name: String, format: String, arguments: CVaListPointer) { + fatalError ("\\(name) exception: \\(NSString(format: format, arguments: arguments))") + } + + static func raise(_ name: String) { + fatalError("\\(name) exception") + } +} + +public extension NSExceptionName { + static var parseErrorException = "parseErrorException" +} + +"""), + .init(name: "AssociatedType.swift", content: +""" +import Foundation + +/// Describes Swift AssociatedType +public final class AssociatedType: NSObject, SourceryModel { + /// Associated type name + public let name: String + + /// Associated type type constraint name, if specified + public let typeName: TypeName? + + // sourcery: skipEquality, skipDescription + /// Associated type constrained type, if known, i.e. if the type is declared in the scanned sources. + public var type: Type? + + /// :nodoc: + public init(name: String, typeName: TypeName? = nil, type: Type? = nil) { + self.name = name + self.typeName = typeName + self.type = type + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "typeName = \\(String(describing: self.typeName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? AssociatedType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? AssociatedType else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + return true + } + +// sourcery:inline:AssociatedType.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + self.typeName = aDecoder.decode(forKey: "typeName") + self.type = aDecoder.decode(forKey: "type") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + } +// sourcery:end +} + +"""), + .init(name: "Attribute.swift", content: +""" +import Foundation + +/// Describes Swift attribute +public class Attribute: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport, Diffable { + + /// Attribute name + public let name: String + + /// Attribute arguments + public let arguments: [String: NSObject] + + // sourcery: skipJSExport + let _description: String + + // sourcery: skipEquality, skipDescription, skipCoding, skipJSExport + /// :nodoc: + public var __parserData: Any? + + /// :nodoc: + public init(name: String, arguments: [String: NSObject] = [:], description: String? = nil) { + self.name = name + self.arguments = arguments + self._description = description ?? "@\\(name)" + } + + /// TODO: unify `asSource` / `description`? + public var asSource: String { + description + } + + /// Attribute description that can be used in a template. + public override var description: String { + return _description + } + + /// :nodoc: + public enum Identifier: String { + case convenience + case required + case available + case discardableResult + case GKInspectable = "gkinspectable" + case objc + case objcMembers + case nonobjc + case NSApplicationMain + case NSCopying + case NSManaged + case UIApplicationMain + case IBOutlet = "iboutlet" + case IBInspectable = "ibinspectable" + case IBDesignable = "ibdesignable" + case autoclosure + case convention + case mutating + case escaping + case final + case open + case lazy + case `public` = "public" + case `internal` = "internal" + case `private` = "private" + case `fileprivate` = "fileprivate" + case publicSetter = "setter_access.public" + case internalSetter = "setter_access.internal" + case privateSetter = "setter_access.private" + case fileprivateSetter = "setter_access.fileprivate" + case optional + + public init?(identifier: String) { + let identifier = identifier.trimmingPrefix("source.decl.attribute.") + if identifier == "objc.name" { + self.init(rawValue: "objc") + } else { + self.init(rawValue: identifier) + } + } + + public static func from(string: String) -> Identifier? { + switch string { + case "GKInspectable": + return Identifier.GKInspectable + case "objc": + return .objc + case "IBOutlet": + return .IBOutlet + case "IBInspectable": + return .IBInspectable + case "IBDesignable": + return .IBDesignable + default: + return Identifier(rawValue: string) + } + } + + public var name: String { + switch self { + case .GKInspectable: + return "GKInspectable" + case .objc: + return "objc" + case .IBOutlet: + return "IBOutlet" + case .IBInspectable: + return "IBInspectable" + case .IBDesignable: + return "IBDesignable" + case .fileprivateSetter: + return "fileprivate" + case .privateSetter: + return "private" + case .internalSetter: + return "internal" + case .publicSetter: + return "public" + default: + return rawValue + } + } + + public var description: String { + return hasAtPrefix ? "@\\(name)" : name + } + + public var hasAtPrefix: Bool { + switch self { + case .available, + .discardableResult, + .GKInspectable, + .objc, + .objcMembers, + .nonobjc, + .NSApplicationMain, + .NSCopying, + .NSManaged, + .UIApplicationMain, + .IBOutlet, + .IBInspectable, + .IBDesignable, + .autoclosure, + .convention, + .escaping: + return true + default: + return false + } + } + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Attribute else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "arguments").trackDifference(actual: self.arguments, expected: castObject.arguments)) + results.append(contentsOf: DiffableResult(identifier: "_description").trackDifference(actual: self._description, expected: castObject._description)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.arguments) + hasher.combine(self._description) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Attribute else { return false } + if self.name != rhs.name { return false } + if self.arguments != rhs.arguments { return false } + if self._description != rhs._description { return false } + return true + } + +// sourcery:inline:Attribute.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let arguments: [String: NSObject] = aDecoder.decode(forKey: "arguments") else { + withVaList(["arguments"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.arguments = arguments + guard let _description: String = aDecoder.decode(forKey: "_description") else { + withVaList(["_description"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self._description = _description + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.arguments, forKey: "arguments") + aCoder.encode(self._description, forKey: "_description") + } +// sourcery:end + +} + +"""), + .init(name: "AutoHashable.generated.swift", content: +""" +// Generated using Sourcery 1.3.1 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +// swiftlint:disable all + + +// MARK: - AutoHashable for classes, protocols, structs + +// MARK: - AutoHashable for Enums + +"""), + .init(name: "BytesRange.swift", content: +""" +// +// Created by Sébastien Duperron on 03/01/2018. +// Copyright © 2018 Pixle. All rights reserved. +// + +import Foundation + +/// :nodoc: +public final class BytesRange: NSObject, SourceryModel, Diffable { + + public let offset: Int64 + public let length: Int64 + + public init(offset: Int64, length: Int64) { + self.offset = offset + self.length = length + } + + public convenience init(range: (offset: Int64, length: Int64)) { + self.init(offset: range.offset, length: range.length) + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "offset = \\(String(describing: self.offset)), " + string += "length = \\(String(describing: self.length))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? BytesRange else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "offset").trackDifference(actual: self.offset, expected: castObject.offset)) + results.append(contentsOf: DiffableResult(identifier: "length").trackDifference(actual: self.length, expected: castObject.length)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.offset) + hasher.combine(self.length) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? BytesRange else { return false } + if self.offset != rhs.offset { return false } + if self.length != rhs.length { return false } + return true + } + +// sourcery:inline:BytesRange.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.offset = aDecoder.decodeInt64(forKey: "offset") + self.length = aDecoder.decodeInt64(forKey: "length") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.offset, forKey: "offset") + aCoder.encode(self.length, forKey: "length") + } +// sourcery:end +} + +"""), + .init(name: "Class.swift", content: +""" +import Foundation +// sourcery: skipDescription +/// Descibes Swift class +public final class Class: Type { + /// Returns "class" + public override var kind: String { return "class" } + + /// Whether type is final + public var isFinal: Bool { + return modifiers.contains { $0.name == "final" } + } + + /// :nodoc: + public override init(name: String = "", + parent: Type? = nil, + accessLevel: AccessLevel = .internal, + isExtension: Bool = false, + variables: [Variable] = [], + methods: [Method] = [], + subscripts: [Subscript] = [], + inheritedTypes: [String] = [], + containedTypes: [Type] = [], + typealiases: [Typealias] = [], + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + isGeneric: Bool = false) { + super.init( + name: name, + parent: parent, + accessLevel: accessLevel, + isExtension: isExtension, + variables: variables, + methods: methods, + subscripts: subscripts, + inheritedTypes: inheritedTypes, + containedTypes: containedTypes, + typealiases: typealiases, + attributes: attributes, + modifiers: modifiers, + annotations: annotations, + documentation: documentation, + isGeneric: isGeneric + ) + } + + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \\(String(describing: self.kind)), " + string += "isFinal = \\(String(describing: self.isFinal))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Class else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Class else { return false } + return super.isEqual(rhs) + } + +// sourcery:inline:Class.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + /// :nodoc: + override public func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + } +// sourcery:end + +} + +"""), + .init(name: "Closure.swift", content: +""" +import Foundation + +/// Describes closure type +public final class ClosureType: NSObject, SourceryModel, Diffable { + + /// Type name used in declaration with stripped whitespaces and new lines + public let name: String + + /// List of closure parameters + public let parameters: [ClosureParameter] + + /// Return value type name + public let returnTypeName: TypeName + + /// Actual return value type name if declaration uses typealias, otherwise just a `returnTypeName` + public var actualReturnTypeName: TypeName { + return returnTypeName.actualTypeName ?? returnTypeName + } + + // sourcery: skipEquality, skipDescription + /// Actual return value type, if known + public var returnType: Type? + + // sourcery: skipEquality, skipDescription + /// Whether return value type is optional + public var isOptionalReturnType: Bool { + return returnTypeName.isOptional + } + + // sourcery: skipEquality, skipDescription + /// Whether return value type is implicitly unwrapped optional + public var isImplicitlyUnwrappedOptionalReturnType: Bool { + return returnTypeName.isImplicitlyUnwrappedOptional + } + + // sourcery: skipEquality, skipDescription + /// Return value type name without attributes and optional type information + public var unwrappedReturnTypeName: String { + return returnTypeName.unwrappedTypeName + } + + /// Whether method is async method + public let isAsync: Bool + + /// async keyword + public let asyncKeyword: String? + + /// Whether closure throws + public let `throws`: Bool + + /// throws or rethrows keyword + public let throwsOrRethrowsKeyword: String? + + /// :nodoc: + public init(name: String, parameters: [ClosureParameter], returnTypeName: TypeName, returnType: Type? = nil, asyncKeyword: String? = nil, throwsOrRethrowsKeyword: String? = nil) { + self.name = name + self.parameters = parameters + self.returnTypeName = returnTypeName + self.returnType = returnType + self.asyncKeyword = asyncKeyword + self.isAsync = asyncKeyword != nil + self.throwsOrRethrowsKeyword = throwsOrRethrowsKeyword + self.`throws` = throwsOrRethrowsKeyword != nil + } + + public var asSource: String { + "\\(parameters.asSource)\\(asyncKeyword != nil ? " \\(asyncKeyword!)" : "")\\(throwsOrRethrowsKeyword != nil ? " \\(throwsOrRethrowsKeyword!)" : "") -> \\(returnTypeName.asSource)" + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "parameters = \\(String(describing: self.parameters)), " + string += "returnTypeName = \\(String(describing: self.returnTypeName)), " + string += "actualReturnTypeName = \\(String(describing: self.actualReturnTypeName)), " + string += "isAsync = \\(String(describing: self.isAsync)), " + string += "asyncKeyword = \\(String(describing: self.asyncKeyword)), " + string += "`throws` = \\(String(describing: self.`throws`)), " + string += "throwsOrRethrowsKeyword = \\(String(describing: self.throwsOrRethrowsKeyword)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? ClosureType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) + results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "asyncKeyword").trackDifference(actual: self.asyncKeyword, expected: castObject.asyncKeyword)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "throwsOrRethrowsKeyword").trackDifference(actual: self.throwsOrRethrowsKeyword, expected: castObject.throwsOrRethrowsKeyword)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.parameters) + hasher.combine(self.returnTypeName) + hasher.combine(self.isAsync) + hasher.combine(self.asyncKeyword) + hasher.combine(self.`throws`) + hasher.combine(self.throwsOrRethrowsKeyword) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ClosureType else { return false } + if self.name != rhs.name { return false } + if self.parameters != rhs.parameters { return false } + if self.returnTypeName != rhs.returnTypeName { return false } + if self.isAsync != rhs.isAsync { return false } + if self.asyncKeyword != rhs.asyncKeyword { return false } + if self.`throws` != rhs.`throws` { return false } + if self.throwsOrRethrowsKeyword != rhs.throwsOrRethrowsKeyword { return false } + return true + } + +// sourcery:inline:ClosureType.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let parameters: [ClosureParameter] = aDecoder.decode(forKey: "parameters") else { + withVaList(["parameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.parameters = parameters + guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { + withVaList(["returnTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.returnTypeName = returnTypeName + self.returnType = aDecoder.decode(forKey: "returnType") + self.isAsync = aDecoder.decode(forKey: "isAsync") + self.asyncKeyword = aDecoder.decode(forKey: "asyncKeyword") + self.`throws` = aDecoder.decode(forKey: "`throws`") + self.throwsOrRethrowsKeyword = aDecoder.decode(forKey: "throwsOrRethrowsKeyword") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.parameters, forKey: "parameters") + aCoder.encode(self.returnTypeName, forKey: "returnTypeName") + aCoder.encode(self.returnType, forKey: "returnType") + aCoder.encode(self.isAsync, forKey: "isAsync") + aCoder.encode(self.asyncKeyword, forKey: "asyncKeyword") + aCoder.encode(self.`throws`, forKey: "`throws`") + aCoder.encode(self.throwsOrRethrowsKeyword, forKey: "throwsOrRethrowsKeyword") + } +// sourcery:end + +} + +"""), + .init(name: "Coding.generated.swift", content: +""" +// Generated using Sourcery 2.0.3 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +// swiftlint:disable vertical_whitespace trailing_newline + +import Foundation + + +extension NSCoder { + + @nonobjc func decode(forKey: String) -> String? { + return self.maybeDecode(forKey: forKey) as String? + } + + @nonobjc func decode(forKey: String) -> TypeName? { + return self.maybeDecode(forKey: forKey) as TypeName? + } + + @nonobjc func decode(forKey: String) -> AccessLevel? { + return self.maybeDecode(forKey: forKey) as AccessLevel? + } + + @nonobjc func decode(forKey: String) -> Bool { + return self.decodeBool(forKey: forKey) + } + + @nonobjc func decode(forKey: String) -> Int { + return self.decodeInteger(forKey: forKey) + } + + func decode(forKey: String) -> E? { + return maybeDecode(forKey: forKey) as E? + } + + fileprivate func maybeDecode(forKey: String) -> E? { + guard let object = self.decodeObject(forKey: forKey) else { + return nil + } + + return object as? E + } + +} + +extension ArrayType: NSCoding {} + +extension AssociatedType: NSCoding {} + +extension AssociatedValue: NSCoding {} + +extension Attribute: NSCoding {} + +extension BytesRange: NSCoding {} + + +extension ClosureParameter: NSCoding {} + +extension ClosureType: NSCoding {} + +extension DictionaryType: NSCoding {} + + +extension EnumCase: NSCoding {} + +extension FileParserResult: NSCoding {} + +extension GenericRequirement: NSCoding {} + +extension GenericType: NSCoding {} + +extension GenericTypeParameter: NSCoding {} + +extension Import: NSCoding {} + +extension Method: NSCoding {} + +extension MethodParameter: NSCoding {} + +extension Modifier: NSCoding {} + + + + +extension Subscript: NSCoding {} + +extension TupleElement: NSCoding {} + +extension TupleType: NSCoding {} + +extension Type: NSCoding {} + +extension TypeName: NSCoding {} + +extension Typealias: NSCoding {} + +extension Types: NSCoding {} + +extension Variable: NSCoding {} + + +"""), + .init(name: "Composer.swift", content: +""" +// +// Created by Krzysztof Zablocki on 31/12/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// + +import Foundation + +private func currentTimestamp() -> TimeInterval { + return Date().timeIntervalSince1970 +} + +/// Responsible for composing results of `FileParser`. +public enum Composer { + + /// Performs final processing of discovered types: + /// - extends types with their corresponding extensions; + /// - replaces typealiases with actual types + /// - finds actual types for variables and enums raw values + /// - filters out any private types and extensions + /// + /// - Parameter parserResult: Result of parsing source code. + /// - Returns: Final types and extensions of unknown types. + public static func uniqueTypesAndFunctions(_ parserResult: FileParserResult) -> (types: [Type], functions: [SourceryMethod], typealiases: [Typealias]) { + let composed = ParserResultsComposed(parserResult: parserResult) + + let resolveType = { (typeName: TypeName, containingType: Type?) -> Type? in + return composed.resolveType(typeName: typeName, containingType: containingType) + } + + composed.types.parallelPerform { type in + type.variables.forEach { + resolveVariableTypes($0, of: type, resolve: resolveType) + } + type.methods.forEach { + resolveMethodTypes($0, of: type, resolve: resolveType) + } + type.subscripts.forEach { + resolveSubscriptTypes($0, of: type, resolve: resolveType) + } + + if let enumeration = type as? Enum { + resolveEnumTypes(enumeration, types: composed.typeMap, resolve: resolveType) + } + + if let composition = type as? ProtocolComposition { + resolveProtocolCompositionTypes(composition, resolve: resolveType) + } + + if let sourceryProtocol = type as? SourceryProtocol { + resolveProtocolTypes(sourceryProtocol, resolve: resolveType) + } + } + + composed.functions.parallelPerform { function in + resolveMethodTypes(function, of: nil, resolve: resolveType) + } + + updateTypeRelationships(types: composed.types) + + return ( + types: composed.types.sorted { $0.globalName < $1.globalName }, + functions: composed.functions.sorted { $0.name < $1.name }, + typealiases: composed.unresolvedTypealiases.values.sorted(by: { $0.name < $1.name }) + ) + } + + typealias TypeResolver = (TypeName, Type?) -> Type? + + private static func resolveVariableTypes(_ variable: Variable, of type: Type, resolve: TypeResolver) { + variable.type = resolve(variable.typeName, type) + + /// The actual `definedInType` is assigned in `uniqueTypes` but we still + /// need to resolve the type to correctly parse typealiases + /// @see https://github.com/krzysztofzablocki/Sourcery/pull/374 + if let definedInTypeName = variable.definedInTypeName { + _ = resolve(definedInTypeName, type) + } + } + + private static func resolveSubscriptTypes(_ subscript: Subscript, of type: Type, resolve: TypeResolver) { + `subscript`.parameters.forEach { (parameter) in + parameter.type = resolve(parameter.typeName, type) + } + + `subscript`.returnType = resolve(`subscript`.returnTypeName, type) + if let definedInTypeName = `subscript`.definedInTypeName { + _ = resolve(definedInTypeName, type) + } + } + + private static func resolveMethodTypes(_ method: SourceryMethod, of type: Type?, resolve: TypeResolver) { + method.parameters.forEach { parameter in + parameter.type = resolve(parameter.typeName, type) + } + + /// The actual `definedInType` is assigned in `uniqueTypes` but we still + /// need to resolve the type to correctly parse typealiases + /// @see https://github.com/krzysztofzablocki/Sourcery/pull/374 + var definedInType: Type? + if let definedInTypeName = method.definedInTypeName { + definedInType = resolve(definedInTypeName, type) + } + + guard !method.returnTypeName.isVoid else { return } + + if method.isInitializer || method.isFailableInitializer { + method.returnType = definedInType + if let type = method.actualDefinedInTypeName { + if method.isFailableInitializer { + method.returnTypeName = TypeName( + name: type.name, + isOptional: true, + isImplicitlyUnwrappedOptional: false, + tuple: type.tuple, + array: type.array, + dictionary: type.dictionary, + closure: type.closure, + generic: type.generic, + isProtocolComposition: type.isProtocolComposition + ) + } else if method.isInitializer { + method.returnTypeName = type + } + } + } else { + method.returnType = resolve(method.returnTypeName, type) + } + } + + private static func resolveEnumTypes(_ enumeration: Enum, types: [String: Type], resolve: TypeResolver) { + enumeration.cases.forEach { enumCase in + enumCase.associatedValues.forEach { associatedValue in + associatedValue.type = resolve(associatedValue.typeName, enumeration) + } + } + + guard enumeration.hasRawType else { return } + + if let rawValueVariable = enumeration.variables.first(where: { $0.name == "rawValue" && !$0.isStatic }) { + enumeration.rawTypeName = rawValueVariable.actualTypeName + enumeration.rawType = rawValueVariable.type + } else if let rawTypeName = enumeration.inheritedTypes.first { + // enums with no cases or enums with cases that contain associated values can't have raw type + guard !enumeration.cases.isEmpty, + !enumeration.hasAssociatedValues else { + return enumeration.rawTypeName = nil + } + + if let rawTypeCandidate = types[rawTypeName] { + if !((rawTypeCandidate is SourceryProtocol) || (rawTypeCandidate is ProtocolComposition)) { + enumeration.rawTypeName = TypeName(rawTypeName) + enumeration.rawType = rawTypeCandidate + } + } else { + enumeration.rawTypeName = TypeName(rawTypeName) + } + } + } + + private static func resolveProtocolCompositionTypes(_ protocolComposition: ProtocolComposition, resolve: TypeResolver) { + let composedTypes = protocolComposition.composedTypeNames.compactMap { typeName in + resolve(typeName, protocolComposition) + } + + protocolComposition.composedTypes = composedTypes + } + + private static func resolveProtocolTypes(_ sourceryProtocol: SourceryProtocol, resolve: TypeResolver) { + sourceryProtocol.associatedTypes.forEach { (_, value) in + guard let typeName = value.typeName, + let type = resolve(typeName, sourceryProtocol) + else { return } + value.type = type + } + + sourceryProtocol.genericRequirements.forEach { requirment in + if let knownAssociatedType = sourceryProtocol.associatedTypes[requirment.leftType.name] { + requirment.leftType = knownAssociatedType + } + requirment.rightType.type = resolve(requirment.rightType.typeName, sourceryProtocol) + } + } + + private static func updateTypeRelationships(types: [Type]) { + var typesByName = [String: Type]() + types.forEach { typesByName[$0.globalName] = $0 } + + var processed = [String: Bool]() + types.forEach { type in + if let type = type as? Class, let supertype = type.inheritedTypes.first.flatMap({ typesByName[$0] }) as? Class { + type.supertype = supertype + } + processed[type.globalName] = true + updateTypeRelationship(for: type, typesByName: typesByName, processed: &processed) + } + } + + private static func findBaseType(for type: Type, name: String, typesByName: [String: Type]) -> Type? { + if let baseType = typesByName[name] { + return baseType + } + if let module = type.module, let baseType = typesByName["\\(module).\\(name)"] { + return baseType + } + for importModule in type.imports { + if let baseType = typesByName["\\(importModule).\\(name)"] { + return baseType + } + } + return nil + } + + private static func updateTypeRelationship(for type: Type, typesByName: [String: Type], processed: inout [String: Bool]) { + type.based.keys.forEach { name in + guard let baseType = findBaseType(for: type, name: name, typesByName: typesByName) else { return } + let globalName = baseType.globalName + if processed[globalName] != true { + processed[globalName] = true + updateTypeRelationship(for: baseType, typesByName: typesByName, processed: &processed) + } + + baseType.based.keys.forEach { type.based[$0] = $0 } + baseType.basedTypes.forEach { type.basedTypes[$0.key] = $0.value } + baseType.inherits.forEach { type.inherits[$0.key] = $0.value } + baseType.implements.forEach { type.implements[$0.key] = $0.value } + + if baseType is Class { + type.inherits[globalName] = baseType + } else if let baseProtocol = baseType as? SourceryProtocol { + type.implements[globalName] = baseProtocol + if let extendingProtocol = type as? SourceryProtocol { + baseProtocol.associatedTypes.forEach { + if extendingProtocol.associatedTypes[$0.key] == nil { + extendingProtocol.associatedTypes[$0.key] = $0.value + } + } + } + } else if baseType is ProtocolComposition { + // TODO: associated types? + type.implements[globalName] = baseType + } + + type.basedTypes[globalName] = baseType + } + } +} + +"""), + .init(name: "Definition.swift", content: +""" +import Foundation + +/// Describes that the object is defined in a context of some `Type` +public protocol Definition: AnyObject { + /// Reference to type name where the object is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc + var definedInTypeName: TypeName? { get } + + /// Reference to actual type where the object is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc or type is unknown + var definedInType: Type? { get } + + // sourcery: skipJSExport + /// Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a `definedInTypeName` + var actualDefinedInTypeName: TypeName? { get } +} + +"""), + .init(name: "Dictionary.swift", content: +""" +import Foundation + +/// Describes dictionary type +public final class DictionaryType: NSObject, SourceryModel, Diffable { + /// Type name used in declaration + public var name: String + + /// Dictionary value type name + public var valueTypeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Dictionary value type, if known + public var valueType: Type? + + /// Dictionary key type name + public var keyTypeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Dictionary key type, if known + public var keyType: Type? + + /// :nodoc: + public init(name: String, valueTypeName: TypeName, valueType: Type? = nil, keyTypeName: TypeName, keyType: Type? = nil) { + self.name = name + self.valueTypeName = valueTypeName + self.valueType = valueType + self.keyTypeName = keyTypeName + self.keyType = keyType + } + + /// Returns dictionary as generic type + public var asGeneric: GenericType { + GenericType(name: "Dictionary", typeParameters: [ + .init(typeName: keyTypeName), + .init(typeName: valueTypeName) + ]) + } + + public var asSource: String { + "[\\(keyTypeName.asSource): \\(valueTypeName.asSource)]" + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "valueTypeName = \\(String(describing: self.valueTypeName)), " + string += "keyTypeName = \\(String(describing: self.keyTypeName)), " + string += "asGeneric = \\(String(describing: self.asGeneric)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? DictionaryType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "valueTypeName").trackDifference(actual: self.valueTypeName, expected: castObject.valueTypeName)) + results.append(contentsOf: DiffableResult(identifier: "keyTypeName").trackDifference(actual: self.keyTypeName, expected: castObject.keyTypeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.valueTypeName) + hasher.combine(self.keyTypeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? DictionaryType else { return false } + if self.name != rhs.name { return false } + if self.valueTypeName != rhs.valueTypeName { return false } + if self.keyTypeName != rhs.keyTypeName { return false } + return true + } + +// sourcery:inline:DictionaryType.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let valueTypeName: TypeName = aDecoder.decode(forKey: "valueTypeName") else { + withVaList(["valueTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.valueTypeName = valueTypeName + self.valueType = aDecoder.decode(forKey: "valueType") + guard let keyTypeName: TypeName = aDecoder.decode(forKey: "keyTypeName") else { + withVaList(["keyTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.keyTypeName = keyTypeName + self.keyType = aDecoder.decode(forKey: "keyType") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.valueTypeName, forKey: "valueTypeName") + aCoder.encode(self.valueType, forKey: "valueType") + aCoder.encode(self.keyTypeName, forKey: "keyTypeName") + aCoder.encode(self.keyType, forKey: "keyType") + } +// sourcery:end +} + +"""), + .init(name: "Diffable.swift", content: +""" +// +// Diffable.swift +// Sourcery +// +// Created by Krzysztof Zabłocki on 22/12/2016. +// Copyright © 2016 Pixle. All rights reserved. +// + +import Foundation + +public protocol Diffable { + + /// Returns `DiffableResult` for the given objects. + /// + /// - Parameter object: Object to diff against. + /// - Returns: Diffable results. + func diffAgainst(_ object: Any?) -> DiffableResult +} + +/// :nodoc: +extension NSRange: Diffable { + /// :nodoc: + public static func == (lhs: NSRange, rhs: NSRange) -> Bool { + return NSEqualRanges(lhs, rhs) + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let rhs = object as? NSRange else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "location").trackDifference(actual: self.location, expected: rhs.location)) + results.append(contentsOf: DiffableResult(identifier: "length").trackDifference(actual: self.length, expected: rhs.length)) + return results + } +} + +public class DiffableResult: NSObject, AutoEquatable { + // sourcery: skipEquality + private var results: [String] + internal var identifier: String? + + init(results: [String] = [], identifier: String? = nil) { + self.results = results + self.identifier = identifier + } + + func append(_ element: String) { + results.append(element) + } + + func append(contentsOf contents: DiffableResult) { + if !contents.isEmpty { + results.append(contents.description) + } + } + + var isEmpty: Bool { return results.isEmpty } + + public override var description: String { + guard !results.isEmpty else { return "" } + return "\\(identifier.flatMap { "\\($0) " } ?? "")" + results.joined(separator: "\\n") + } +} + +public extension DiffableResult { + +#if swift(>=4.1) +#else + /// :nodoc: + @discardableResult func trackDifference(actual: T, expected: T) -> DiffableResult { + if actual != expected { + let result = DiffableResult(results: [""]) + append(contentsOf: result) + } + return self + } +#endif + + /// :nodoc: + @discardableResult func trackDifference(actual: T?, expected: T?) -> DiffableResult { + if actual != expected { + let result = DiffableResult(results: [""]) + append(contentsOf: result) + } + return self + } + + /// :nodoc: + @discardableResult func trackDifference(actual: T, expected: T) -> DiffableResult where T: Diffable { + let diffResult = actual.diffAgainst(expected) + append(contentsOf: diffResult) + return self + } + + /// :nodoc: + @discardableResult func trackDifference(actual: [T], expected: [T]) -> DiffableResult where T: Diffable { + let diffResult = DiffableResult() + defer { append(contentsOf: diffResult) } + + guard actual.count == expected.count else { + diffResult.append("Different count, expected: \\(expected.count), received: \\(actual.count)") + return self + } + + for (idx, item) in actual.enumerated() { + let diff = DiffableResult() + diff.trackDifference(actual: item, expected: expected[idx]) + if !diff.isEmpty { + let string = "idx \\(idx): \\(diff)" + diffResult.append(string) + } + } + + return self + } + + /// :nodoc: + @discardableResult func trackDifference(actual: [T], expected: [T]) -> DiffableResult { + let diffResult = DiffableResult() + defer { append(contentsOf: diffResult) } + + guard actual.count == expected.count else { + diffResult.append("Different count, expected: \\(expected.count), received: \\(actual.count)") + return self + } + + for (idx, item) in actual.enumerated() where item != expected[idx] { + let string = "idx \\(idx): " + diffResult.append(string) + } + + return self + } + + /// :nodoc: + @discardableResult func trackDifference(actual: [K: T], expected: [K: T]) -> DiffableResult where T: Diffable { + let diffResult = DiffableResult() + defer { append(contentsOf: diffResult) } + + guard actual.count == expected.count else { + append("Different count, expected: \\(expected.count), received: \\(actual.count)") + + if expected.count > actual.count { + let missingKeys = Array(expected.keys.filter { + actual[$0] == nil + }.map { + String(describing: $0) + }) + diffResult.append("Missing keys: \\(missingKeys.joined(separator: ", "))") + } + return self + } + + for (key, actualElement) in actual { + guard let expectedElement = expected[key] else { + diffResult.append("Missing key \\"\\(key)\\"") + continue + } + + let diff = DiffableResult() + diff.trackDifference(actual: actualElement, expected: expectedElement) + if !diff.isEmpty { + let string = "key \\"\\(key)\\": \\(diff)" + diffResult.append(string) + } + } + + return self + } + +// MARK: - NSObject diffing + + /// :nodoc: + @discardableResult func trackDifference(actual: [K: T], expected: [K: T]) -> DiffableResult { + let diffResult = DiffableResult() + defer { append(contentsOf: diffResult) } + + guard actual.count == expected.count else { + append("Different count, expected: \\(expected.count), received: \\(actual.count)") + + if expected.count > actual.count { + let missingKeys = Array(expected.keys.filter { + actual[$0] == nil + }.map { + String(describing: $0) + }) + diffResult.append("Missing keys: \\(missingKeys.joined(separator: ", "))") + } + return self + } + + for (key, actualElement) in actual { + guard let expectedElement = expected[key] else { + diffResult.append("Missing key \\"\\(key)\\"") + continue + } + + if !actualElement.isEqual(expectedElement) { + diffResult.append("key \\"\\(key)\\": ") + } + } + + return self + } +} + +"""), + .init(name: "Documentation.swift", content: +""" +import Foundation + +public typealias Documentation = [String] + +/// Describes a declaration with documentation, i.e. type, method, variable, enum case +public protocol Documented { + var documentation: Documentation { get } +} + +"""), + .init(name: "EnumCase.swift", content: +""" +import Foundation + +/// Defines enum case +public final class EnumCase: NSObject, SourceryModel, AutoDescription, Annotated, Documented, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "name": + return name + case "hasAssociatedValue": + return hasAssociatedValue + case "associatedValues": + return associatedValues + case "indirect": + return indirect + case "annotations": + return annotations + case "rawValue": + return rawValue + default: + fatalError("unable to lookup: \\(member) in \\(self)") + } + } + + /// Enum case name + public let name: String + + /// Enum case raw value, if any + public let rawValue: String? + + /// Enum case associated values + public let associatedValues: [AssociatedValue] + + /// Enum case annotations + public var annotations: Annotations = [:] + + public var documentation: Documentation = [] + + /// Whether enum case is indirect + public let indirect: Bool + + /// Whether enum case has associated value + public var hasAssociatedValue: Bool { + return !associatedValues.isEmpty + } + + // Underlying parser data, never to be used by anything else + // sourcery: skipEquality, skipDescription, skipCoding, skipJSExport + /// :nodoc: + public var __parserData: Any? + + /// :nodoc: + public init(name: String, rawValue: String? = nil, associatedValues: [AssociatedValue] = [], annotations: [String: NSObject] = [:], documentation: [String] = [], indirect: Bool = false) { + self.name = name + self.rawValue = rawValue + self.associatedValues = associatedValues + self.annotations = annotations + self.documentation = documentation + self.indirect = indirect + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "rawValue = \\(String(describing: self.rawValue)), " + string += "associatedValues = \\(String(describing: self.associatedValues)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "documentation = \\(String(describing: self.documentation)), " + string += "indirect = \\(String(describing: self.indirect)), " + string += "hasAssociatedValue = \\(String(describing: self.hasAssociatedValue))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? EnumCase else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "rawValue").trackDifference(actual: self.rawValue, expected: castObject.rawValue)) + results.append(contentsOf: DiffableResult(identifier: "associatedValues").trackDifference(actual: self.associatedValues, expected: castObject.associatedValues)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "indirect").trackDifference(actual: self.indirect, expected: castObject.indirect)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.rawValue) + hasher.combine(self.associatedValues) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.indirect) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? EnumCase else { return false } + if self.name != rhs.name { return false } + if self.rawValue != rhs.rawValue { return false } + if self.associatedValues != rhs.associatedValues { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.indirect != rhs.indirect { return false } + return true + } + +// sourcery:inline:EnumCase.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + self.rawValue = aDecoder.decode(forKey: "rawValue") + guard let associatedValues: [AssociatedValue] = aDecoder.decode(forKey: "associatedValues") else { + withVaList(["associatedValues"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.associatedValues = associatedValues + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + self.indirect = aDecoder.decode(forKey: "indirect") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.rawValue, forKey: "rawValue") + aCoder.encode(self.associatedValues, forKey: "associatedValues") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.indirect, forKey: "indirect") + } +// sourcery:end +} + +"""), + .init(name: "AssociatedValue.swift", content: +""" +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// + +import Foundation + +/// Defines enum case associated value +public final class AssociatedValue: NSObject, SourceryModel, AutoDescription, Typed, Annotated, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "externalName": + return externalName + case "localName": + return localName + case "typeName": + return typeName + case "type": + return type + case "defaultValue": + return defaultValue + case "annotations": + return annotations + default: + fatalError("unable to lookup: \\(member) in \\(self)") + } + } + + /// Associated value local name. + /// This is a name to be used to construct enum case value + public let localName: String? + + /// Associated value external name. + /// This is a name to be used to access value in value-bindig + public let externalName: String? + + /// Associated value type name + public let typeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Associated value type, if known + public var type: Type? + + /// Associated value default value + public let defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + + /// :nodoc: + public init(localName: String?, externalName: String?, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { + self.localName = localName + self.externalName = externalName + self.typeName = typeName + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + } + + convenience init(name: String? = nil, typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:]) { + self.init(localName: name, externalName: name, typeName: typeName, type: type, defaultValue: defaultValue, annotations: annotations) + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "localName = \\(String(describing: self.localName)), " + string += "externalName = \\(String(describing: self.externalName)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "defaultValue = \\(String(describing: self.defaultValue)), " + string += "annotations = \\(String(describing: self.annotations))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? AssociatedValue else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) + results.append(contentsOf: DiffableResult(identifier: "externalName").trackDifference(actual: self.externalName, expected: castObject.externalName)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.localName) + hasher.combine(self.externalName) + hasher.combine(self.typeName) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? AssociatedValue else { return false } + if self.localName != rhs.localName { return false } + if self.externalName != rhs.externalName { return false } + if self.typeName != rhs.typeName { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true + } + +// sourcery:inline:AssociatedValue.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.localName = aDecoder.decode(forKey: "localName") + self.externalName = aDecoder.decode(forKey: "externalName") + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.type = aDecoder.decode(forKey: "type") + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.localName, forKey: "localName") + aCoder.encode(self.externalName, forKey: "externalName") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + } +// sourcery:end + +} + +"""), + .init(name: "Enum.swift", content: +""" +import Foundation + +/// Defines Swift enum +public final class Enum: Type { + public override subscript(dynamicMember member: String) -> Any? { + switch member { + case "cases": + return cases + default: + return super[dynamicMember: member] + } + } + + // sourcery: skipDescription + /// Returns "enum" + public override var kind: String { return "enum" } + + /// Enum cases + public var cases: [EnumCase] + + /** + Enum raw value type name, if any. This type is removed from enum's `based` and `inherited` types collections. + + - important: Unless raw type is specified explicitly via type alias RawValue it will be set to the first type in the inheritance chain. + So if your enum does not have raw value but implements protocols you'll have to specify conformance to these protocols via extension to get enum with nil raw value type and all based and inherited types. + */ + public var rawTypeName: TypeName? { + didSet { + if let rawTypeName = rawTypeName { + hasRawType = true + if let index = inheritedTypes.firstIndex(of: rawTypeName.name) { + inheritedTypes.remove(at: index) + } + if based[rawTypeName.name] != nil { + based[rawTypeName.name] = nil + } + } else { + hasRawType = false + } + } + } + + // sourcery: skipDescription, skipEquality + /// :nodoc: + public private(set) var hasRawType: Bool + + // sourcery: skipDescription, skipEquality + /// Enum raw value type, if known + public var rawType: Type? + + // sourcery: skipEquality, skipDescription, skipCoding + /// Names of types or protocols this type inherits from, including unknown (not scanned) types + public override var based: [String: String] { + didSet { + if let rawTypeName = rawTypeName, based[rawTypeName.name] != nil { + based[rawTypeName.name] = nil + } + } + } + + /// Whether enum contains any associated values + public var hasAssociatedValues: Bool { + return cases.contains(where: { $0.hasAssociatedValue }) + } + + /// :nodoc: + public init(name: String = "", + parent: Type? = nil, + accessLevel: AccessLevel = .internal, + isExtension: Bool = false, + inheritedTypes: [String] = [], + rawTypeName: TypeName? = nil, + cases: [EnumCase] = [], + variables: [Variable] = [], + methods: [Method] = [], + containedTypes: [Type] = [], + typealiases: [Typealias] = [], + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + isGeneric: Bool = false) { + + self.cases = cases + self.rawTypeName = rawTypeName + self.hasRawType = rawTypeName != nil || !inheritedTypes.isEmpty + + super.init(name: name, parent: parent, accessLevel: accessLevel, isExtension: isExtension, variables: variables, methods: methods, inheritedTypes: inheritedTypes, containedTypes: containedTypes, typealiases: typealiases, attributes: attributes, modifiers: modifiers, annotations: annotations, documentation: documentation, isGeneric: isGeneric) + + if let rawTypeName = rawTypeName?.name, let index = self.inheritedTypes.firstIndex(of: rawTypeName) { + self.inheritedTypes.remove(at: index) + } + } + + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "cases = \\(String(describing: self.cases)), " + string += "rawTypeName = \\(String(describing: self.rawTypeName)), " + string += "hasAssociatedValues = \\(String(describing: self.hasAssociatedValues))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Enum else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "cases").trackDifference(actual: self.cases, expected: castObject.cases)) + results.append(contentsOf: DiffableResult(identifier: "rawTypeName").trackDifference(actual: self.rawTypeName, expected: castObject.rawTypeName)) + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.cases) + hasher.combine(self.rawTypeName) + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Enum else { return false } + if self.cases != rhs.cases { return false } + if self.rawTypeName != rhs.rawTypeName { return false } + return super.isEqual(rhs) + } + +// sourcery:inline:Enum.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let cases: [EnumCase] = aDecoder.decode(forKey: "cases") else { + withVaList(["cases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.cases = cases + self.rawTypeName = aDecoder.decode(forKey: "rawTypeName") + self.hasRawType = aDecoder.decode(forKey: "hasRawType") + self.rawType = aDecoder.decode(forKey: "rawType") + super.init(coder: aDecoder) + } + + /// :nodoc: + override public func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + aCoder.encode(self.cases, forKey: "cases") + aCoder.encode(self.rawTypeName, forKey: "rawTypeName") + aCoder.encode(self.hasRawType, forKey: "hasRawType") + aCoder.encode(self.rawType, forKey: "rawType") + } +// sourcery:end +} + +"""), + .init(name: "Extensions.swift", content: +""" +import Foundation + +public extension StringProtocol { + /// Trimms leading and trailing whitespaces and newlines + var trimmed: String { + self.trimmingCharacters(in: .whitespacesAndNewlines) + } +} + +public extension String { + + /// Returns nil if string is empty + var nilIfEmpty: String? { + if isEmpty { + return nil + } + + return self + } + + /// Returns nil if string is empty or contains `_` character + var nilIfNotValidParameterName: String? { + if isEmpty { + return nil + } + + if self == "_" { + return nil + } + + return self + } + + /// :nodoc: + /// - Parameter substring: Instance of a substring + /// - Returns: Returns number of times a substring appears in self + func countInstances(of substring: String) -> Int { + guard !substring.isEmpty else { return 0 } + var count = 0 + var searchRange: Range? + while let foundRange = range(of: substring, options: [], range: searchRange) { + count += 1 + searchRange = Range(uncheckedBounds: (lower: foundRange.upperBound, upper: endIndex)) + } + return count + } + + /// :nodoc: + /// Removes leading and trailing whitespace from str. Returns false if str was not altered. + @discardableResult + mutating func strip() -> Bool { + let strippedString = stripped() + guard strippedString != self else { return false } + self = strippedString + return true + } + + /// :nodoc: + /// Returns a copy of str with leading and trailing whitespace removed. + func stripped() -> String { + return String(self.trimmingCharacters(in: .whitespaces)) + } + + /// :nodoc: + @discardableResult + mutating func trimPrefix(_ prefix: String) -> Bool { + guard hasPrefix(prefix) else { return false } + self = String(self.suffix(self.count - prefix.count)) + return true + } + + /// :nodoc: + func trimmingPrefix(_ prefix: String) -> String { + guard hasPrefix(prefix) else { return self } + return String(self.suffix(self.count - prefix.count)) + } + + /// :nodoc: + @discardableResult + mutating func trimSuffix(_ suffix: String) -> Bool { + guard hasSuffix(suffix) else { return false } + self = String(self.prefix(self.count - suffix.count)) + return true + } + + /// :nodoc: + func trimmingSuffix(_ suffix: String) -> String { + guard hasSuffix(suffix) else { return self } + return String(self.prefix(self.count - suffix.count)) + } + + /// :nodoc: + func dropFirstAndLast(_ n: Int = 1) -> String { + return drop(first: n, last: n) + } + + /// :nodoc: + func drop(first: Int, last: Int) -> String { + return String(self.dropFirst(first).dropLast(last)) + } + + /// :nodoc: + /// Wraps brackets if needed to make a valid type name + func bracketsBalancing() -> String { + if hasPrefix("(") && hasSuffix(")") { + let unwrapped = dropFirstAndLast() + return unwrapped.commaSeparated().count == 1 ? unwrapped.bracketsBalancing() : self + } else { + let wrapped = "(\\(self))" + return wrapped.isValidTupleName() || !isBracketsBalanced() ? wrapped : self + } + } + + /// :nodoc: + /// Returns true if given string can represent a valid tuple type name + func isValidTupleName() -> Bool { + guard hasPrefix("(") && hasSuffix(")") else { return false } + let trimmedBracketsName = dropFirstAndLast() + return trimmedBracketsName.isBracketsBalanced() && trimmedBracketsName.commaSeparated().count > 1 + } + + /// :nodoc: + func isValidArrayName() -> Bool { + if hasPrefix("Array<") { return true } + if hasPrefix("[") && hasSuffix("]") { + return dropFirstAndLast().colonSeparated().count == 1 + } + return false + } + + /// :nodoc: + func isValidDictionaryName() -> Bool { + if hasPrefix("Dictionary<") { return true } + if hasPrefix("[") && contains(":") && hasSuffix("]") { + return dropFirstAndLast().colonSeparated().count == 2 + } + return false + } + + /// :nodoc: + func isValidClosureName() -> Bool { + return components(separatedBy: "->", excludingDelimiterBetween: (["(", "<"], [")", ">"])).count > 1 + } + + /// :nodoc: + /// Returns true if all opening brackets are balanced with closed brackets. + func isBracketsBalanced() -> Bool { + var bracketsCount: Int = 0 + for char in self { + if char == "(" { bracketsCount += 1 } else if char == ")" { bracketsCount -= 1 } + if bracketsCount < 0 { return false } + } + return bracketsCount == 0 + } + + /// :nodoc: + /// Returns components separated with a comma respecting nested types + func commaSeparated() -> [String] { + return components(separatedBy: ",", excludingDelimiterBetween: ("<[({", "})]>")) + } + + /// :nodoc: + /// Returns components separated with colon respecting nested types + func colonSeparated() -> [String] { + return components(separatedBy: ":", excludingDelimiterBetween: ("<[({", "})]>")) + } + + /// :nodoc: + /// Returns components separated with semicolon respecting nested contexts + func semicolonSeparated() -> [String] { + return components(separatedBy: ";", excludingDelimiterBetween: ("{", "}")) + } + + /// :nodoc: + func components(separatedBy delimiter: String, excludingDelimiterBetween between: (open: String, close: String)) -> [String] { + return self.components(separatedBy: delimiter, excludingDelimiterBetween: (between.open.map { String($0) }, between.close.map { String($0) })) + } + + /// :nodoc: + func components(separatedBy delimiter: String, excludingDelimiterBetween between: (open: [String], close: [String])) -> [String] { + var boundingCharactersCount: Int = 0 + var quotesCount: Int = 0 + var item = "" + var items = [String]() + + var i = self.startIndex + while i < self.endIndex { + var offset = 1 + defer { + i = self.index(i, offsetBy: offset) + } + let currentlyScanned = self[i..<(self.index(i, offsetBy: delimiter.count, limitedBy: self.endIndex) ?? self.endIndex)] + if let openString = between.open.first(where: { String(self[i...]).starts(with: $0) }) { + if !(boundingCharactersCount == 0 && String(self[i]) == delimiter) { + boundingCharactersCount += 1 + } + offset = openString.count + } else if let closeString = between.close.first(where: { String(self[i...]).starts(with: $0) }) { + // do not count `->` + if !(self[i] == ">" && item.last == "-") { + boundingCharactersCount = max(0, boundingCharactersCount - 1) + } + offset = closeString.count + } + if self[i] == "\\"" { + quotesCount += 1 + } + + if currentlyScanned == delimiter && boundingCharactersCount == 0 && quotesCount % 2 == 0 { + items.append(item) + item = "" + i = self.index(i, offsetBy: delimiter.count - 1) + } else { + item += self[i.. DiffableResult { + let results = DiffableResult() + guard let castObject = object as? FileParserResult else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "path").trackDifference(actual: self.path, expected: castObject.path)) + results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) + results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) + results.append(contentsOf: DiffableResult(identifier: "functions").trackDifference(actual: self.functions, expected: castObject.functions)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + results.append(contentsOf: DiffableResult(identifier: "inlineRanges").trackDifference(actual: self.inlineRanges, expected: castObject.inlineRanges)) + results.append(contentsOf: DiffableResult(identifier: "inlineIndentations").trackDifference(actual: self.inlineIndentations, expected: castObject.inlineIndentations)) + results.append(contentsOf: DiffableResult(identifier: "modifiedDate").trackDifference(actual: self.modifiedDate, expected: castObject.modifiedDate)) + results.append(contentsOf: DiffableResult(identifier: "sourceryVersion").trackDifference(actual: self.sourceryVersion, expected: castObject.sourceryVersion)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.path) + hasher.combine(self.module) + hasher.combine(self.types) + hasher.combine(self.functions) + hasher.combine(self.typealiases) + hasher.combine(self.inlineRanges) + hasher.combine(self.inlineIndentations) + hasher.combine(self.modifiedDate) + hasher.combine(self.sourceryVersion) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? FileParserResult else { return false } + if self.path != rhs.path { return false } + if self.module != rhs.module { return false } + if self.types != rhs.types { return false } + if self.functions != rhs.functions { return false } + if self.typealiases != rhs.typealiases { return false } + if self.inlineRanges != rhs.inlineRanges { return false } + if self.inlineIndentations != rhs.inlineIndentations { return false } + if self.modifiedDate != rhs.modifiedDate { return false } + if self.sourceryVersion != rhs.sourceryVersion { return false } + return true + } + +// sourcery:inline:FileParserResult.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.path = aDecoder.decode(forKey: "path") + self.module = aDecoder.decode(forKey: "module") + guard let types: [Type] = aDecoder.decode(forKey: "types") else { + withVaList(["types"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.types = types + guard let functions: [SourceryMethod] = aDecoder.decode(forKey: "functions") else { + withVaList(["functions"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.functions = functions + guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases + guard let inlineRanges: [String: NSRange] = aDecoder.decode(forKey: "inlineRanges") else { + withVaList(["inlineRanges"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inlineRanges = inlineRanges + guard let inlineIndentations: [String: String] = aDecoder.decode(forKey: "inlineIndentations") else { + withVaList(["inlineIndentations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inlineIndentations = inlineIndentations + guard let modifiedDate: Date = aDecoder.decode(forKey: "modifiedDate") else { + withVaList(["modifiedDate"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiedDate = modifiedDate + guard let sourceryVersion: String = aDecoder.decode(forKey: "sourceryVersion") else { + withVaList(["sourceryVersion"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.sourceryVersion = sourceryVersion + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.path, forKey: "path") + aCoder.encode(self.module, forKey: "module") + aCoder.encode(self.types, forKey: "types") + aCoder.encode(self.functions, forKey: "functions") + aCoder.encode(self.typealiases, forKey: "typealiases") + aCoder.encode(self.inlineRanges, forKey: "inlineRanges") + aCoder.encode(self.inlineIndentations, forKey: "inlineIndentations") + aCoder.encode(self.modifiedDate, forKey: "modifiedDate") + aCoder.encode(self.sourceryVersion, forKey: "sourceryVersion") + } +// sourcery:end +} + +"""), + .init(name: "Generic.swift", content: +""" +import Foundation + +/// Descibes Swift generic type +public final class GenericType: NSObject, SourceryModelWithoutDescription, Diffable { + /// The name of the base type, i.e. `Array` for `Array` + public var name: String + + /// This generic type parameters + public let typeParameters: [GenericTypeParameter] + + /// :nodoc: + public init(name: String, typeParameters: [GenericTypeParameter] = []) { + self.name = name + self.typeParameters = typeParameters + } + + public var asSource: String { + let arguments = typeParameters + .map({ $0.typeName.asSource }) + .joined(separator: ", ") + return "\\(name)<\\(arguments)>" + } + + public override var description: String { + asSource + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? GenericType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeParameters").trackDifference(actual: self.typeParameters, expected: castObject.typeParameters)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeParameters) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? GenericType else { return false } + if self.name != rhs.name { return false } + if self.typeParameters != rhs.typeParameters { return false } + return true + } + +// sourcery:inline:GenericType.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeParameters: [GenericTypeParameter] = aDecoder.decode(forKey: "typeParameters") else { + withVaList(["typeParameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeParameters = typeParameters + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeParameters, forKey: "typeParameters") + } + +// sourcery:end +} + +/// Descibes Swift generic type parameter +public final class GenericTypeParameter: NSObject, SourceryModel, Diffable { + + /// Generic parameter type name + public var typeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Generic parameter type, if known + public var type: Type? + + /// :nodoc: + public init(typeName: TypeName, type: Type? = nil) { + self.typeName = typeName + self.type = type + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "typeName = \\(String(describing: self.typeName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? GenericTypeParameter else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.typeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? GenericTypeParameter else { return false } + if self.typeName != rhs.typeName { return false } + return true + } + +// sourcery:inline:GenericTypeParameter.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.type = aDecoder.decode(forKey: "type") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + } + +// sourcery:end +} + +"""), + .init(name: "GenericRequirement.swift", content: +""" +import Foundation + +/// modifier can be thing like `private`, `class`, `nonmutating` +/// if a declaration has modifier like `private(set)` it's name will be `private` and detail will be `set` +public class GenericRequirement: NSObject, SourceryModel, Diffable { + + public enum Relationship: String { + case equals + case conformsTo + + var syntax: String { + switch self { + case .equals: + return "==" + case .conformsTo: + return ":" + } + } + } + + public var leftType: AssociatedType + public let rightType: GenericTypeParameter + + /// relationship name + public let relationship: String + + /// Syntax e.g. `==` or `:` + public let relationshipSyntax: String + + public init(leftType: AssociatedType, rightType: GenericTypeParameter, relationship: Relationship) { + self.leftType = leftType + self.rightType = rightType + self.relationship = relationship.rawValue + self.relationshipSyntax = relationship.syntax + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "leftType = \\(String(describing: self.leftType)), " + string += "rightType = \\(String(describing: self.rightType)), " + string += "relationship = \\(String(describing: self.relationship)), " + string += "relationshipSyntax = \\(String(describing: self.relationshipSyntax))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? GenericRequirement else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "leftType").trackDifference(actual: self.leftType, expected: castObject.leftType)) + results.append(contentsOf: DiffableResult(identifier: "rightType").trackDifference(actual: self.rightType, expected: castObject.rightType)) + results.append(contentsOf: DiffableResult(identifier: "relationship").trackDifference(actual: self.relationship, expected: castObject.relationship)) + results.append(contentsOf: DiffableResult(identifier: "relationshipSyntax").trackDifference(actual: self.relationshipSyntax, expected: castObject.relationshipSyntax)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.leftType) + hasher.combine(self.rightType) + hasher.combine(self.relationship) + hasher.combine(self.relationshipSyntax) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? GenericRequirement else { return false } + if self.leftType != rhs.leftType { return false } + if self.rightType != rhs.rightType { return false } + if self.relationship != rhs.relationship { return false } + if self.relationshipSyntax != rhs.relationshipSyntax { return false } + return true + } + + // sourcery:inline:GenericRequirement.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let leftType: AssociatedType = aDecoder.decode(forKey: "leftType") else { + withVaList(["leftType"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.leftType = leftType + guard let rightType: GenericTypeParameter = aDecoder.decode(forKey: "rightType") else { + withVaList(["rightType"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rightType = rightType + guard let relationship: String = aDecoder.decode(forKey: "relationship") else { + withVaList(["relationship"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.relationship = relationship + guard let relationshipSyntax: String = aDecoder.decode(forKey: "relationshipSyntax") else { + withVaList(["relationshipSyntax"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.relationshipSyntax = relationshipSyntax + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.leftType, forKey: "leftType") + aCoder.encode(self.rightType, forKey: "rightType") + aCoder.encode(self.relationship, forKey: "relationship") + aCoder.encode(self.relationshipSyntax, forKey: "relationshipSyntax") + } + // sourcery:end +} + +"""), + .init(name: "Import.swift", content: +""" +import Foundation + +/// Defines import type +public class Import: NSObject, SourceryModelWithoutDescription, Diffable { + /// Import kind, e.g. class, struct in `import class Module.ClassName` + public var kind: String? + + /// Import path + public var path: String + + /// :nodoc: + public init(path: String, kind: String? = nil) { + self.path = path + self.kind = kind + } + + /// Full import value e.g. `import struct Module.StructName` + public override var description: String { + if let kind = kind { + return "\\(kind) \\(path)" + } + + return path + } + + /// Returns module name from a import, e.g. if you had `import struct Module.Submodule.Struct` it will return `Module.Submodule` + public var moduleName: String { + if kind != nil { + if let idx = path.lastIndex(of: ".") { + return String(path[.. DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Import else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "kind").trackDifference(actual: self.kind, expected: castObject.kind)) + results.append(contentsOf: DiffableResult(identifier: "path").trackDifference(actual: self.path, expected: castObject.path)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.kind) + hasher.combine(self.path) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Import else { return false } + if self.kind != rhs.kind { return false } + if self.path != rhs.path { return false } + return true + } + +// sourcery:inline:Import.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.kind = aDecoder.decode(forKey: "kind") + guard let path: String = aDecoder.decode(forKey: "path") else { + withVaList(["path"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.path = path + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.kind, forKey: "kind") + aCoder.encode(self.path, forKey: "path") + } + +// sourcery:end +} + +"""), + .init(name: "Log.swift", content: +""" +import Foundation + +/// :nodoc: +public enum Log { + + public enum Level: Int { + case errors + case warnings + case info + case verbose + } + + public static var level: Level = .warnings + public static var logBenchmarks: Bool = false + public static var logAST: Bool = false + + public static var stackMessages: Bool = false + public private(set) static var messagesStack = [String]() + + public static func error(_ message: Any) { + log(level: .errors, "error: \\(message)") + // to return error when running swift templates which is done in a different process + if ProcessInfo.processInfo.processName != "Sourcery" { + fputs("\\(message)", stderr) + } + } + + public static func warning(_ message: Any) { + log(level: .warnings, "warning: \\(message)") + } + + public static func astWarning(_ message: Any) { + guard logAST else { return } + log(level: .warnings, "ast warning: \\(message)") + } + + public static func astError(_ message: Any) { + guard logAST else { return } + log(level: .errors, "ast error: \\(message)") + } + + public static func verbose(_ message: Any) { + log(level: .verbose, message) + } + + public static func info(_ message: Any) { + log(level: .info, message) + } + + public static func benchmark(_ message: Any) { + guard logBenchmarks else { return } + if stackMessages { + messagesStack.append("\\(message)") + } else { + print(message) + } + } + + private static func log(level logLevel: Level, _ message: Any) { + guard logLevel.rawValue <= Log.level.rawValue else { return } + if stackMessages { + messagesStack.append("\\(message)") + } else { + print(message) + } + } + + public static func output(_ message: String) { + print(message) + } +} + +extension String: Error {} + +"""), + .init(name: "MethodParameter.swift", content: +""" +import Foundation + +/// Describes method parameter +public class MethodParameter: NSObject, SourceryModel, Typed, Annotated, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "argumentLabel": + return argumentLabel + case "name": + return name + case "typeName": + return typeName + case "isClosure": + return isClosure + case "typeAttributes": + return typeAttributes + default: + fatalError("unable to lookup: \\(member) in \\(self)") + } + } + /// Parameter external name + public var argumentLabel: String? + + // Note: although method parameter can have no name, this property is not optional, + // this is so to maintain compatibility with existing templates. + /// Parameter internal name + public let name: String + + /// Parameter type name + public let typeName: TypeName + + /// Parameter flag whether it's inout or not + public let `inout`: Bool + + /// Is this variadic parameter? + public let isVariadic: Bool + + // sourcery: skipEquality, skipDescription + /// Parameter type, if known + public var type: Type? + + /// Parameter type attributes, i.e. `@escaping` + public var typeAttributes: AttributeList { + return typeName.attributes + } + + /// Method parameter default value expression + public var defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + + /// :nodoc: + public init(argumentLabel: String?, name: String = "", typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false, isVariadic: Bool = false) { + self.typeName = typeName + self.argumentLabel = argumentLabel + self.name = name + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + self.`inout` = isInout + self.isVariadic = isVariadic + } + + /// :nodoc: + public init(name: String = "", typeName: TypeName, type: Type? = nil, defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false, isVariadic: Bool = false) { + self.typeName = typeName + self.argumentLabel = name + self.name = name + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + self.`inout` = isInout + self.isVariadic = isVariadic + } + + public var asSource: String { + let typeSuffix = ": \\(`inout` ? "inout " : "")\\(typeName.asSource)\\(defaultValue.map { " = \\($0)" } ?? "")" + (isVariadic ? "..." : "") + guard argumentLabel != name else { + return name + typeSuffix + } + + let labels = [argumentLabel ?? "_", name.nilIfEmpty] + .compactMap { $0 } + .joined(separator: " ") + + return (labels.nilIfEmpty ?? "_") + typeSuffix + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "argumentLabel = \\(String(describing: self.argumentLabel)), " + string += "name = \\(String(describing: self.name)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "`inout` = \\(String(describing: self.`inout`)), " + string += "isVariadic = \\(String(describing: self.isVariadic)), " + string += "typeAttributes = \\(String(describing: self.typeAttributes)), " + string += "defaultValue = \\(String(describing: self.defaultValue)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? MethodParameter else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "argumentLabel").trackDifference(actual: self.argumentLabel, expected: castObject.argumentLabel)) + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "`inout`").trackDifference(actual: self.`inout`, expected: castObject.`inout`)) + results.append(contentsOf: DiffableResult(identifier: "isVariadic").trackDifference(actual: self.isVariadic, expected: castObject.isVariadic)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.argumentLabel) + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.`inout`) + hasher.combine(self.isVariadic) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? MethodParameter else { return false } + if self.argumentLabel != rhs.argumentLabel { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.`inout` != rhs.`inout` { return false } + if self.isVariadic != rhs.isVariadic { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true + } + +// sourcery:inline:MethodParameter.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.argumentLabel = aDecoder.decode(forKey: "argumentLabel") + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.`inout` = aDecoder.decode(forKey: "`inout`") + self.isVariadic = aDecoder.decode(forKey: "isVariadic") + self.type = aDecoder.decode(forKey: "type") + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.argumentLabel, forKey: "argumentLabel") + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.`inout`, forKey: "`inout`") + aCoder.encode(self.isVariadic, forKey: "isVariadic") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + } +// sourcery:end +} + +extension Array where Element == MethodParameter { + public var asSource: String { + "(\\(map { $0.asSource }.joined(separator: ", ")))" + } +} + +"""), + .init(name: "ClosureParameter.swift", content: +""" +import Foundation + +// sourcery: skipDiffing +public final class ClosureParameter: NSObject, SourceryModel, Typed, Annotated { + /// Parameter external name + public var argumentLabel: String? + + /// Parameter internal name + public let name: String? + + /// Parameter type name + public let typeName: TypeName + + /// Parameter flag whether it's inout or not + public let `inout`: Bool + + // sourcery: skipEquality, skipDescription + /// Parameter type, if known + public var type: Type? + + /// Parameter type attributes, i.e. `@escaping` + public var typeAttributes: AttributeList { + return typeName.attributes + } + + /// Method parameter default value expression + public var defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + + /// :nodoc: + public init(argumentLabel: String? = nil, name: String? = nil, typeName: TypeName, type: Type? = nil, + defaultValue: String? = nil, annotations: [String: NSObject] = [:], isInout: Bool = false) { + self.typeName = typeName + self.argumentLabel = argumentLabel + self.name = name + self.type = type + self.defaultValue = defaultValue + self.annotations = annotations + self.`inout` = isInout + } + + public var asSource: String { + let typeInfo = "\\(`inout` ? "inout " : "")\\(typeName.asSource)" + if argumentLabel?.nilIfNotValidParameterName == nil, name?.nilIfNotValidParameterName == nil { + return typeInfo + } + + let typeSuffix = ": \\(typeInfo)" + guard argumentLabel != name else { + return name ?? "" + typeSuffix + } + + let labels = [argumentLabel ?? "_", name?.nilIfEmpty] + .compactMap { $0 } + .joined(separator: " ") + + return (labels.nilIfEmpty ?? "_") + typeSuffix + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.argumentLabel) + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.`inout`) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + return hasher.finalize() + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "argumentLabel = \\(String(describing: self.argumentLabel)), " + string += "name = \\(String(describing: self.name)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "`inout` = \\(String(describing: self.`inout`)), " + string += "typeAttributes = \\(String(describing: self.typeAttributes)), " + string += "defaultValue = \\(String(describing: self.defaultValue)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ClosureParameter else { return false } + if self.argumentLabel != rhs.argumentLabel { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.`inout` != rhs.`inout` { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + return true + } + + // sourcery:inline:ClosureParameter.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.argumentLabel = aDecoder.decode(forKey: "argumentLabel") + self.name = aDecoder.decode(forKey: "name") + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.`inout` = aDecoder.decode(forKey: "`inout`") + self.type = aDecoder.decode(forKey: "type") + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.argumentLabel, forKey: "argumentLabel") + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.`inout`, forKey: "`inout`") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + } + + // sourcery:end +} + +extension Array where Element == ClosureParameter { + public var asSource: String { + "(\\(map { $0.asSource }.joined(separator: ", ")))" + } +} + +"""), + .init(name: "Method.swift", content: +""" +import Foundation + +/// :nodoc: +public typealias SourceryMethod = Method + +/// Describes method +public final class Method: NSObject, SourceryModel, Annotated, Documented, Definition, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "definedInType": + return definedInType + case "shortName": + return shortName + case "name": + return name + case "selectorName": + return selectorName + case "callName": + return callName + case "parameters": + return parameters + case "throws": + return `throws` + case "isInitializer": + return isInitializer + case "accessLevel": + return accessLevel + case "isStatic": + return isStatic + case "returnTypeName": + return returnTypeName + case "isAsync": + return isAsync + case "attributes": + return attributes + case "isOptionalReturnType": + return isOptionalReturnType + default: + fatalError("unable to lookup: \\(member) in \\(self)") + } + } + + /// Full method name, including generic constraints, i.e. `foo(bar: T)` + public let name: String + + /// Method name including arguments names, i.e. `foo(bar:)` + public var selectorName: String + + // sourcery: skipEquality, skipDescription + /// Method name without arguments names and parenthesis, i.e. `foo` + public var shortName: String { + return name.range(of: "(").map({ String(name[..<$0.lowerBound]) }) ?? name + } + + // sourcery: skipEquality, skipDescription + /// Method name without arguments names, parenthesis and generic types, i.e. `foo` (can be used to generate code for method call) + public var callName: String { + return shortName.range(of: "<").map({ String(shortName[..<$0.lowerBound]) }) ?? shortName + } + + /// Method parameters + public var parameters: [MethodParameter] + + /// Return value type name used in declaration, including generic constraints, i.e. `where T: Equatable` + public var returnTypeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Actual return value type name if declaration uses typealias, otherwise just a `returnTypeName` + public var actualReturnTypeName: TypeName { + return returnTypeName.actualTypeName ?? returnTypeName + } + + // sourcery: skipEquality, skipDescription + /// Actual return value type, if known + public var returnType: Type? + + // sourcery: skipEquality, skipDescription + /// Whether return value type is optional + public var isOptionalReturnType: Bool { + return returnTypeName.isOptional || isFailableInitializer + } + + // sourcery: skipEquality, skipDescription + /// Whether return value type is implicitly unwrapped optional + public var isImplicitlyUnwrappedOptionalReturnType: Bool { + return returnTypeName.isImplicitlyUnwrappedOptional + } + + // sourcery: skipEquality, skipDescription + /// Return value type name without attributes and optional type information + public var unwrappedReturnTypeName: String { + return returnTypeName.unwrappedTypeName + } + + /// Whether method is async method + public let isAsync: Bool + + /// Whether method throws + public let `throws`: Bool + + /// Whether method rethrows + public let `rethrows`: Bool + + /// Method access level, i.e. `internal`, `private`, `fileprivate`, `public`, `open` + public let accessLevel: String + + /// Whether method is a static method + public let isStatic: Bool + + /// Whether method is a class method + public let isClass: Bool + + // sourcery: skipEquality, skipDescription + /// Whether method is an initializer + public var isInitializer: Bool { + return selectorName.hasPrefix("init(") || selectorName == "init" + } + + // sourcery: skipEquality, skipDescription + /// Whether method is an deinitializer + public var isDeinitializer: Bool { + return selectorName == "deinit" + } + + /// Whether method is a failable initializer + public let isFailableInitializer: Bool + + // sourcery: skipEquality, skipDescription + /// Whether method is a convenience initializer + public var isConvenienceInitializer: Bool { + modifiers.contains { $0.name == "convenience" } + } + + // sourcery: skipEquality, skipDescription + /// Whether method is required + public var isRequired: Bool { + modifiers.contains { $0.name == "required" } + } + + // sourcery: skipEquality, skipDescription + /// Whether method is final + public var isFinal: Bool { + modifiers.contains { $0.name == "final" } + } + + // sourcery: skipEquality, skipDescription + /// Whether method is mutating + public var isMutating: Bool { + modifiers.contains { $0.name == "mutating" } + } + + // sourcery: skipEquality, skipDescription + /// Whether method is generic + public var isGeneric: Bool { + shortName.hasSuffix(">") + } + + // sourcery: skipEquality, skipDescription + /// Whether method is optional (in an Objective-C protocol) + public var isOptional: Bool { + modifiers.contains { $0.name == "optional" } + } + + // sourcery: skipEquality, skipDescription + /// Whether method is nonisolated (this modifier only applies to actor methods) + public var isNonisolated: Bool { + modifiers.contains { $0.name == "nonisolated" } + } + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public let annotations: Annotations + + public let documentation: Documentation + + /// Reference to type name where the method is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc + public let definedInTypeName: TypeName? + + // sourcery: skipEquality, skipDescription + /// Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a `definedInTypeName` + public var actualDefinedInTypeName: TypeName? { + return definedInTypeName?.actualTypeName ?? definedInTypeName + } + + // sourcery: skipEquality, skipDescription + /// Reference to actual type where the object is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc or type is unknown + public var definedInType: Type? + + /// Method attributes, i.e. `@discardableResult` + public let attributes: AttributeList + + /// Method modifiers, i.e. `private` + public let modifiers: [SourceryModifier] + + // Underlying parser data, never to be used by anything else + // sourcery: skipEquality, skipDescription, skipCoding, skipJSExport + /// :nodoc: + public var __parserData: Any? + + /// :nodoc: + public init(name: String, + selectorName: String? = nil, + parameters: [MethodParameter] = [], + returnTypeName: TypeName = TypeName(name: "Void"), + isAsync: Bool = false, + throws: Bool = false, + rethrows: Bool = false, + accessLevel: AccessLevel = .internal, + isStatic: Bool = false, + isClass: Bool = false, + isFailableInitializer: Bool = false, + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + definedInTypeName: TypeName? = nil) { + + self.name = name + self.selectorName = selectorName ?? name + self.parameters = parameters + self.returnTypeName = returnTypeName + self.isAsync = isAsync + self.throws = `throws` + self.rethrows = `rethrows` + self.accessLevel = accessLevel.rawValue + self.isStatic = isStatic + self.isClass = isClass + self.isFailableInitializer = isFailableInitializer + self.attributes = attributes + self.modifiers = modifiers + self.annotations = annotations + self.documentation = documentation + self.definedInTypeName = definedInTypeName + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "selectorName = \\(String(describing: self.selectorName)), " + string += "parameters = \\(String(describing: self.parameters)), " + string += "returnTypeName = \\(String(describing: self.returnTypeName)), " + string += "isAsync = \\(String(describing: self.isAsync)), " + string += "`throws` = \\(String(describing: self.`throws`)), " + string += "`rethrows` = \\(String(describing: self.`rethrows`)), " + string += "accessLevel = \\(String(describing: self.accessLevel)), " + string += "isStatic = \\(String(describing: self.isStatic)), " + string += "isClass = \\(String(describing: self.isClass)), " + string += "isFailableInitializer = \\(String(describing: self.isFailableInitializer)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "documentation = \\(String(describing: self.documentation)), " + string += "definedInTypeName = \\(String(describing: self.definedInTypeName)), " + string += "attributes = \\(String(describing: self.attributes)), " + string += "modifiers = \\(String(describing: self.modifiers))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Method else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "selectorName").trackDifference(actual: self.selectorName, expected: castObject.selectorName)) + results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) + results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "`rethrows`").trackDifference(actual: self.`rethrows`, expected: castObject.`rethrows`)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) + results.append(contentsOf: DiffableResult(identifier: "isClass").trackDifference(actual: self.isClass, expected: castObject.isClass)) + results.append(contentsOf: DiffableResult(identifier: "isFailableInitializer").trackDifference(actual: self.isFailableInitializer, expected: castObject.isFailableInitializer)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.selectorName) + hasher.combine(self.parameters) + hasher.combine(self.returnTypeName) + hasher.combine(self.isAsync) + hasher.combine(self.`throws`) + hasher.combine(self.`rethrows`) + hasher.combine(self.accessLevel) + hasher.combine(self.isStatic) + hasher.combine(self.isClass) + hasher.combine(self.isFailableInitializer) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.definedInTypeName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Method else { return false } + if self.name != rhs.name { return false } + if self.selectorName != rhs.selectorName { return false } + if self.parameters != rhs.parameters { return false } + if self.returnTypeName != rhs.returnTypeName { return false } + if self.isAsync != rhs.isAsync { return false } + if self.`throws` != rhs.`throws` { return false } + if self.`rethrows` != rhs.`rethrows` { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.isStatic != rhs.isStatic { return false } + if self.isClass != rhs.isClass { return false } + if self.isFailableInitializer != rhs.isFailableInitializer { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + return true + } + +// sourcery:inline:Method.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let selectorName: String = aDecoder.decode(forKey: "selectorName") else { + withVaList(["selectorName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.selectorName = selectorName + guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { + withVaList(["parameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.parameters = parameters + guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { + withVaList(["returnTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.returnTypeName = returnTypeName + self.returnType = aDecoder.decode(forKey: "returnType") + self.isAsync = aDecoder.decode(forKey: "isAsync") + self.`throws` = aDecoder.decode(forKey: "`throws`") + self.`rethrows` = aDecoder.decode(forKey: "`rethrows`") + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel + self.isStatic = aDecoder.decode(forKey: "isStatic") + self.isClass = aDecoder.decode(forKey: "isClass") + self.isFailableInitializer = aDecoder.decode(forKey: "isFailableInitializer") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") + self.definedInType = aDecoder.decode(forKey: "definedInType") + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.selectorName, forKey: "selectorName") + aCoder.encode(self.parameters, forKey: "parameters") + aCoder.encode(self.returnTypeName, forKey: "returnTypeName") + aCoder.encode(self.returnType, forKey: "returnType") + aCoder.encode(self.isAsync, forKey: "isAsync") + aCoder.encode(self.`throws`, forKey: "`throws`") + aCoder.encode(self.`rethrows`, forKey: "`rethrows`") + aCoder.encode(self.accessLevel, forKey: "accessLevel") + aCoder.encode(self.isStatic, forKey: "isStatic") + aCoder.encode(self.isClass, forKey: "isClass") + aCoder.encode(self.isFailableInitializer, forKey: "isFailableInitializer") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.definedInTypeName, forKey: "definedInTypeName") + aCoder.encode(self.definedInType, forKey: "definedInType") + aCoder.encode(self.attributes, forKey: "attributes") + aCoder.encode(self.modifiers, forKey: "modifiers") + } +// sourcery:end +} + +"""), + .init(name: "Modifier.swift", content: +""" +import Foundation + +public typealias SourceryModifier = Modifier +/// modifier can be thing like `private`, `class`, `nonmutating` +/// if a declaration has modifier like `private(set)` it's name will be `private` and detail will be `set` +public class Modifier: NSObject, AutoCoding, AutoEquatable, AutoDiffable, AutoJSExport, Diffable { + + /// The declaration modifier name. + public let name: String + + /// The modifier detail, if any. + public let detail: String? + + public init(name: String, detail: String? = nil) { + self.name = name + self.detail = detail + } + + public var asSource: String { + if let detail = detail { + return "\\(name)(\\(detail))" + } else { + return name + } + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Modifier else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "detail").trackDifference(actual: self.detail, expected: castObject.detail)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.detail) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Modifier else { return false } + if self.name != rhs.name { return false } + if self.detail != rhs.detail { return false } + return true + } + + // sourcery:inline:Modifier.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + self.detail = aDecoder.decode(forKey: "detail") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.detail, forKey: "detail") + } + // sourcery:end +} + + +"""), + .init(name: "ParserResultsComposed.swift", content: +""" +// +// Created by Krzysztof Zablocki on 31/12/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// + +import Foundation + +internal struct ParserResultsComposed { + private(set) var typeMap = [String: Type]() + private(set) var modules = [String: [String: Type]]() + private(set) var types = [Type]() + + let parsedTypes: [Type] + let functions: [SourceryMethod] + let resolvedTypealiases: [String: Typealias] + let unresolvedTypealiases: [String: Typealias] + + init(parserResult: FileParserResult) { + // TODO: This logic should really be more complicated + // For any resolution we need to be looking at accessLevel and module boundaries + // e.g. there might be a typealias `private typealias Something = MyType` in one module and same name in another with public modifier, one could be accessed and the other could not + self.functions = parserResult.functions + let aliases = Self.typealiases(parserResult) + resolvedTypealiases = aliases.resolved + unresolvedTypealiases = aliases.unresolved + parsedTypes = parserResult.types + + // set definedInType for all methods and variables + parsedTypes + .forEach { type in + type.variables.forEach { $0.definedInType = type } + type.methods.forEach { $0.definedInType = type } + type.subscripts.forEach { $0.definedInType = type } + } + + // map all known types to their names + parsedTypes + .filter { !$0.isExtension } + .forEach { + typeMap[$0.globalName] = $0 + if let module = $0.module { + var typesByModules = modules[module, default: [:]] + typesByModules[$0.name] = $0 + modules[module] = typesByModules + } + } + + /// Resolve typealiases + let typealiases = Array(unresolvedTypealiases.values) + typealiases.forEach { alias in + alias.type = resolveType(typeName: alias.typeName, containingType: alias.parent) + } + + types = unifyTypes() + } + + private func resolveExtensionOfNestedType(_ type: Type) { + var components = type.localName.components(separatedBy: ".") + let rootName = type.module ?? components.removeFirst() // Module/parent name + if let moduleTypes = modules[rootName], let baseType = moduleTypes[components.joined(separator: ".")] ?? moduleTypes[type.localName] { + type.localName = baseType.localName + type.module = baseType.module + type.parent = baseType.parent + } else { + for _import in type.imports { + let parentKey = "\\(rootName).\\(components.joined(separator: "."))" + let parentKeyFull = "\\(_import.moduleName).\\(parentKey)" + if let moduleTypes = modules[_import.moduleName], let baseType = moduleTypes[parentKey] ?? moduleTypes[parentKeyFull] { + type.localName = baseType.localName + type.module = baseType.module + type.parent = baseType.parent + return + } + } + } + } + + private mutating func unifyTypes() -> [Type] { + /// Resolve actual names of extensions, as they could have been done on typealias and note updated child names in uniques if needed + parsedTypes + .filter { $0.isExtension } + .forEach { + let oldName = $0.globalName + + if $0.parent == nil, $0.localName.contains(".") { + resolveExtensionOfNestedType($0) + } + + if let resolved = resolveGlobalName(for: oldName, containingType: $0.parent, unique: typeMap, modules: modules, typealiases: resolvedTypealiases)?.name { + $0.localName = resolved.replacingOccurrences(of: "\\($0.module != nil ? "\\($0.module!)." : "")", with: "") + } else { + return + } + + // nothing left to do + guard oldName != $0.globalName else { + return + } + + // if it had contained types, they might have been fully defined and so their name has to be noted in uniques + func rewriteChildren(of type: Type) { + // child is never an extension so no need to check + for child in type.containedTypes { + typeMap[child.globalName] = child + rewriteChildren(of: child) + } + } + rewriteChildren(of: $0) + } + + // extend all types with their extensions + parsedTypes.forEach { type in + type.inheritedTypes = type.inheritedTypes.map { inheritedName in + resolveGlobalName(for: inheritedName, containingType: type.parent, unique: typeMap, modules: modules, typealiases: resolvedTypealiases)?.name ?? inheritedName + } + + let uniqueType = typeMap[type.globalName] ?? // this check will only fail on an extension? + typeFromComposedName(type.name, modules: modules) ?? // this can happen for an extension on unknown type, this case should probably be handled by the inferTypeNameFromModules + (inferTypeNameFromModules(from: type.localName, containedInType: type.parent, uniqueTypes: typeMap, modules: modules).flatMap { typeMap[$0] }) + + guard let current = uniqueType else { + assert(type.isExtension, "Type \\(type.globalName) should be extension") + + // for unknown types we still store their extensions but mark them as unknown + type.isUnknownExtension = true + if let existingType = typeMap[type.globalName] { + existingType.extend(type) + typeMap[type.globalName] = existingType + } else { + typeMap[type.globalName] = type + } + + let inheritanceClause = type.inheritedTypes.isEmpty ? "" : + ": \\(type.inheritedTypes.joined(separator: ", "))" + + Log.astWarning("Found \\"extension \\(type.name)\\(inheritanceClause)\\" of type for which there is no original type declaration information.") + return + } + + if current == type { return } + + current.extend(type) + typeMap[current.globalName] = current + } + + let values = typeMap.values + var processed = Set(minimumCapacity: values.count) + return typeMap.values.filter({ + let name = $0.globalName + let wasProcessed = processed.contains(name) + processed.insert(name) + return !wasProcessed + }) + } + + /// returns typealiases map to their full names, with `resolved` removing intermediate + /// typealises and `unresolved` including typealiases that reference other typealiases. + private static func typealiases(_ parserResult: FileParserResult) -> (resolved: [String: Typealias], unresolved: [String: Typealias]) { + var typealiasesByNames = [String: Typealias]() + parserResult.typealiases.forEach { typealiasesByNames[$0.name] = $0 } + parserResult.types.forEach { type in + type.typealiases.forEach({ (_, alias) in + // TODO: should I deal with the fact that alias.name depends on type name but typenames might be updated later on + // maybe just handle non extension case here and extension aliases after resolving them? + typealiasesByNames[alias.name] = alias + }) + } + + let unresolved = typealiasesByNames + + // ! if a typealias leads to another typealias, follow through and replace with final type + typealiasesByNames.forEach { _, alias in + var aliasNamesToReplace = [alias.name] + var finalAlias = alias + while let targetAlias = typealiasesByNames[finalAlias.typeName.name] { + aliasNamesToReplace.append(targetAlias.name) + finalAlias = targetAlias + } + + // ! replace all keys + aliasNamesToReplace.forEach { typealiasesByNames[$0] = finalAlias } + } + + return (resolved: typealiasesByNames, unresolved: unresolved) + } + + /// Resolves type identifier for name + func resolveGlobalName(for type: String, + containingType: Type? = nil, + unique: [String: Type]? = nil, + modules: [String: [String: Type]], + typealiases: [String: Typealias]) -> (name: String, typealias: Typealias?)? { + // if the type exists for this name and isn't an extension just return it's name + // if it's extension we need to check if there aren't other options TODO: verify + if let realType = unique?[type], realType.isExtension == false { + return (name: realType.globalName, typealias: nil) + } + + if let alias = typealiases[type] { + return (name: alias.type?.globalName ?? alias.typeName.name, typealias: alias) + } + + if let containingType = containingType { + if type == "Self" { + return (name: containingType.globalName, typealias: nil) + } + + var currentContainer: Type? = containingType + while currentContainer != nil, let parentName = currentContainer?.globalName { + /// TODO: no parent for sure? + /// manually walk the containment tree + if let name = resolveGlobalName(for: "\\(parentName).\\(type)", containingType: nil, unique: unique, modules: modules, typealiases: typealiases) { + return name + } + + currentContainer = currentContainer?.parent + } + +// if let name = resolveGlobalName(for: "\\(containingType.globalName).\\(type)", containingType: containingType.parent, unique: unique, modules: modules, typealiases: typealiases) { +// return name +// } + +// last check it's via module +// if let module = containingType.module, let name = resolveGlobalName(for: "\\(module).\\(type)", containingType: nil, unique: unique, modules: modules, typealiases: typealiases) { +// return name +// } + } + + // TODO: is this needed? + if let inferred = inferTypeNameFromModules(from: type, containedInType: containingType, uniqueTypes: unique ?? [:], modules: modules) { + return (name: inferred, typealias: nil) + } + + return typeFromComposedName(type, modules: modules).map { (name: $0.globalName, typealias: nil) } + } + + private func inferTypeNameFromModules(from typeIdentifier: String, containedInType: Type?, uniqueTypes: [String: Type], modules: [String: [String: Type]]) -> String? { + func fullName(for module: String) -> String { + "\\(module).\\(typeIdentifier)" + } + + func type(for module: String) -> Type? { + return modules[module]?[typeIdentifier] + } + + func ambiguousErrorMessage(from types: [Type]) -> String? { + Log.astWarning("Ambiguous type \\(typeIdentifier), found \\(types.map { $0.globalName }.joined(separator: ", ")). Specify module name at declaration site to disambiguate.") + return nil + } + + let explicitModulesAtDeclarationSite: [String] = [ + containedInType?.module.map { [$0] } ?? [], // main module for this typename + containedInType?.imports.map { $0.moduleName } ?? [] // imported modules + ] + .flatMap { $0 } + + let remainingModules = Set(modules.keys).subtracting(explicitModulesAtDeclarationSite) + + /// We need to check whether we can find type in one of the modules but we need to be careful to avoid amibiguity + /// First checking explicit modules available at declaration site (so source module + all imported ones) + /// If there is no ambigiuity there we can assume that module will be resolved by the compiler + /// If that's not the case we look after remaining modules in the application and if the typename has no ambigiuity we use that + /// But if there is more than 1 typename duplication across modules we have no way to resolve what is the compiler going to use so we fail + let moduleSetsToCheck: [[String]] = [ + explicitModulesAtDeclarationSite, + Array(remainingModules) + ] + + for modules in moduleSetsToCheck { + let possibleTypes = modules + .compactMap { type(for: $0) } + + if possibleTypes.count > 1 { + return ambiguousErrorMessage(from: possibleTypes) + } + + if let type = possibleTypes.first { + return type.globalName + } + } + + // as last result for unknown types / extensions + // try extracting type from unique array + if let module = containedInType?.module { + return uniqueTypes[fullName(for: module)]?.globalName + } + return nil + } + + func typeFromComposedName(_ name: String, modules: [String: [String: Type]]) -> Type? { + guard name.contains(".") else { return nil } + let nameComponents = name.components(separatedBy: ".") + let moduleName = nameComponents[0] + let typeName = nameComponents.suffix(from: 1).joined(separator: ".") + return modules[moduleName]?[typeName] + } + + func resolveType(typeName: TypeName, containingType: Type?) -> Type? { + let resolveTypeWithName = { (typeName: TypeName) -> Type? in + return self.resolveType(typeName: typeName, containingType: containingType) + } + + let unique = typeMap + + if let name = typeName.actualTypeName { + let resolvedIdentifier = name.generic?.name ?? name.unwrappedTypeName + return unique[resolvedIdentifier] + } + + let retrievedName = actualTypeName(for: typeName, containingType: containingType) + let lookupName = retrievedName ?? typeName + + if let tuple = lookupName.tuple { + var needsUpdate = false + + tuple.elements.forEach { tupleElement in + tupleElement.type = resolveTypeWithName(tupleElement.typeName) + if tupleElement.typeName.actualTypeName != nil { + needsUpdate = true + } + } + + if needsUpdate || retrievedName != nil { + let tupleCopy = TupleType(name: tuple.name, elements: tuple.elements) + tupleCopy.elements.forEach { + $0.typeName = $0.actualTypeName ?? $0.typeName + $0.typeName.actualTypeName = nil + } + tupleCopy.name = tupleCopy.elements.asTypeName + + typeName.tuple = tupleCopy // TODO: really don't like this old behaviour + typeName.actualTypeName = TypeName(name: tupleCopy.name, + isOptional: typeName.isOptional, + isImplicitlyUnwrappedOptional: typeName.isImplicitlyUnwrappedOptional, + tuple: tupleCopy, + array: lookupName.array, + dictionary: lookupName.dictionary, + closure: lookupName.closure, + generic: lookupName.generic + ) + } + return nil + } else + if let array = lookupName.array { + array.elementType = resolveTypeWithName(array.elementTypeName) + + if array.elementTypeName.actualTypeName != nil || retrievedName != nil { + let array = ArrayType(name: array.name, elementTypeName: array.elementTypeName, elementType: array.elementType) + array.elementTypeName = array.elementTypeName.actualTypeName ?? array.elementTypeName + array.elementTypeName.actualTypeName = nil + array.name = array.asSource + typeName.array = array // TODO: really don't like this old behaviour + typeName.generic = array.asGeneric // TODO: really don't like this old behaviour + + typeName.actualTypeName = TypeName(name: array.name, + isOptional: typeName.isOptional, + isImplicitlyUnwrappedOptional: typeName.isImplicitlyUnwrappedOptional, + tuple: lookupName.tuple, + array: array, + dictionary: lookupName.dictionary, + closure: lookupName.closure, + generic: typeName.generic + ) + } + } else + if let dictionary = lookupName.dictionary { + dictionary.keyType = resolveTypeWithName(dictionary.keyTypeName) + dictionary.valueType = resolveTypeWithName(dictionary.valueTypeName) + + if dictionary.keyTypeName.actualTypeName != nil || dictionary.valueTypeName.actualTypeName != nil || retrievedName != nil { + let dictionary = DictionaryType(name: dictionary.name, valueTypeName: dictionary.valueTypeName, valueType: dictionary.valueType, keyTypeName: dictionary.keyTypeName, keyType: dictionary.keyType) + dictionary.keyTypeName = dictionary.keyTypeName.actualTypeName ?? dictionary.keyTypeName + dictionary.keyTypeName.actualTypeName = nil // TODO: really don't like this old behaviour + dictionary.valueTypeName = dictionary.valueTypeName.actualTypeName ?? dictionary.valueTypeName + dictionary.valueTypeName.actualTypeName = nil // TODO: really don't like this old behaviour + + dictionary.name = dictionary.asSource + + typeName.dictionary = dictionary // TODO: really don't like this old behaviour + typeName.generic = dictionary.asGeneric // TODO: really don't like this old behaviour + + typeName.actualTypeName = TypeName(name: dictionary.asSource, + isOptional: typeName.isOptional, + isImplicitlyUnwrappedOptional: typeName.isImplicitlyUnwrappedOptional, + tuple: lookupName.tuple, + array: lookupName.array, + dictionary: dictionary, + closure: lookupName.closure, + generic: dictionary.asGeneric + ) + } + } else + if let closure = lookupName.closure { + var needsUpdate = false + + closure.returnType = resolveTypeWithName(closure.returnTypeName) + closure.parameters.forEach { parameter in + parameter.type = resolveTypeWithName(parameter.typeName) + if parameter.typeName.actualTypeName != nil { + needsUpdate = true + } + } + + if closure.returnTypeName.actualTypeName != nil || needsUpdate || retrievedName != nil { + typeName.closure = closure // TODO: really don't like this old behaviour + + typeName.actualTypeName = TypeName(name: closure.asSource, + isOptional: typeName.isOptional, + isImplicitlyUnwrappedOptional: typeName.isImplicitlyUnwrappedOptional, + tuple: lookupName.tuple, + array: lookupName.array, + dictionary: lookupName.dictionary, + closure: closure, + generic: lookupName.generic + ) + } + + return nil + } else + if let generic = lookupName.generic { + var needsUpdate = false + + generic.typeParameters.forEach { parameter in + parameter.type = resolveTypeWithName(parameter.typeName) + if parameter.typeName.actualTypeName != nil { + needsUpdate = true + } + } + + if needsUpdate || retrievedName != nil { + let generic = GenericType(name: generic.name, typeParameters: generic.typeParameters) + generic.typeParameters.forEach { + $0.typeName = $0.typeName.actualTypeName ?? $0.typeName + $0.typeName.actualTypeName = nil // TODO: really don't like this old behaviour + } + typeName.generic = generic // TODO: really don't like this old behaviour + typeName.array = lookupName.array // TODO: really don't like this old behaviour + typeName.dictionary = lookupName.dictionary // TODO: really don't like this old behaviour + + let params = generic.typeParameters.map { $0.typeName.asSource }.joined(separator: ", ") + + typeName.actualTypeName = TypeName(name: "\\(generic.name)<\\(params)>", + isOptional: typeName.isOptional, + isImplicitlyUnwrappedOptional: typeName.isImplicitlyUnwrappedOptional, + tuple: lookupName.tuple, + array: lookupName.array, // TODO: asArray + dictionary: lookupName.dictionary, // TODO: asDictionary + closure: lookupName.closure, + generic: generic + ) + } + } + + if let aliasedName = (typeName.actualTypeName ?? retrievedName), aliasedName.unwrappedTypeName != typeName.unwrappedTypeName { + typeName.actualTypeName = aliasedName + } + + let finalLookup = typeName.actualTypeName ?? typeName + let resolvedIdentifier = finalLookup.generic?.name ?? finalLookup.unwrappedTypeName + + // should we cache resolved typenames? + return unique[resolvedIdentifier] + } + + private func actualTypeName(for typeName: TypeName, + containingType: Type? = nil) -> TypeName? { + let unique = typeMap + let typealiases = resolvedTypealiases + + var unwrapped = typeName.unwrappedTypeName + if let generic = typeName.generic { + unwrapped = generic.name + } + + guard let aliased = resolveGlobalName(for: unwrapped, containingType: containingType, unique: unique, modules: modules, typealiases: typealiases) else { + return nil + } + + /// TODO: verify + let generic = typeName.generic.map { GenericType(name: $0.name, typeParameters: $0.typeParameters) } + generic?.name = aliased.name + let dictionary = typeName.dictionary.map { DictionaryType(name: $0.name, valueTypeName: $0.valueTypeName, valueType: $0.valueType, keyTypeName: $0.keyTypeName, keyType: $0.keyType) } + dictionary?.name = aliased.name + let array = typeName.array.map { ArrayType(name: $0.name, elementTypeName: $0.elementTypeName, elementType: $0.elementType) } + array?.name = aliased.name + + return TypeName(name: aliased.name, + isOptional: typeName.isOptional, + isImplicitlyUnwrappedOptional: typeName.isImplicitlyUnwrappedOptional, + tuple: aliased.typealias?.typeName.tuple ?? typeName.tuple, // TODO: verify + array: aliased.typealias?.typeName.array ?? array, + dictionary: aliased.typealias?.typeName.dictionary ?? dictionary, + closure: aliased.typealias?.typeName.closure ?? typeName.closure, + generic: aliased.typealias?.typeName.generic ?? generic + ) + } + +} + +"""), + .init(name: "PhantomProtocols.swift", content: +""" +// +// Created by Krzysztof Zablocki on 23/01/2017. +// Copyright (c) 2017 Pixle. All rights reserved. +// + +import Foundation + +/// Phantom protocol for diffing +protocol AutoDiffable {} + +/// Phantom protocol for equality +protocol AutoEquatable {} + +/// Phantom protocol for equality +protocol AutoDescription {} + +/// Phantom protocol for NSCoding +protocol AutoCoding {} + +protocol AutoJSExport {} + +/// Phantom protocol for NSCoding, Equatable and Diffable +protocol SourceryModelWithoutDescription: AutoDiffable, AutoEquatable, AutoCoding, AutoJSExport {} + +protocol SourceryModel: SourceryModelWithoutDescription, AutoDescription {} + +"""), + .init(name: "Protocol.swift", content: +""" +// +// Protocol.swift +// Sourcery +// +// Created by Krzysztof Zablocki on 09/12/2016. +// Copyright © 2016 Pixle. All rights reserved. +// + +import Foundation + +/// :nodoc: +public typealias SourceryProtocol = Protocol + +/// Describes Swift protocol +public final class Protocol: Type { + + /// Returns "protocol" + public override var kind: String { return "protocol" } + + /// list of all declared associated types with their names as keys + public var associatedTypes: [String: AssociatedType] { + didSet { + isGeneric = !associatedTypes.isEmpty || !genericRequirements.isEmpty + } + } + + /// list of generic requirements + public var genericRequirements: [GenericRequirement] { + didSet { + isGeneric = !associatedTypes.isEmpty || !genericRequirements.isEmpty + } + } + + /// :nodoc: + public init(name: String = "", + parent: Type? = nil, + accessLevel: AccessLevel = .internal, + isExtension: Bool = false, + variables: [Variable] = [], + methods: [Method] = [], + subscripts: [Subscript] = [], + inheritedTypes: [String] = [], + containedTypes: [Type] = [], + typealiases: [Typealias] = [], + associatedTypes: [String: AssociatedType] = [:], + genericRequirements: [GenericRequirement] = [], + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = []) { + self.genericRequirements = genericRequirements + self.associatedTypes = associatedTypes + super.init( + name: name, + parent: parent, + accessLevel: accessLevel, + isExtension: isExtension, + variables: variables, + methods: methods, + subscripts: subscripts, + inheritedTypes: inheritedTypes, + containedTypes: containedTypes, + typealiases: typealiases, + attributes: attributes, + modifiers: modifiers, + annotations: annotations, + documentation: documentation, + isGeneric: !associatedTypes.isEmpty || !genericRequirements.isEmpty + ) + } + + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \\(String(describing: self.kind)), " + string += "associatedTypes = \\(String(describing: self.associatedTypes)), " + string += "genericRequirements = \\(String(describing: self.genericRequirements))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Protocol else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "associatedTypes").trackDifference(actual: self.associatedTypes, expected: castObject.associatedTypes)) + results.append(contentsOf: DiffableResult(identifier: "genericRequirements").trackDifference(actual: self.genericRequirements, expected: castObject.genericRequirements)) + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.associatedTypes) + hasher.combine(self.genericRequirements) + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Protocol else { return false } + if self.associatedTypes != rhs.associatedTypes { return false } + if self.genericRequirements != rhs.genericRequirements { return false } + return super.isEqual(rhs) + } + +// sourcery:inline:Protocol.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let associatedTypes: [String: AssociatedType] = aDecoder.decode(forKey: "associatedTypes") else { + withVaList(["associatedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.associatedTypes = associatedTypes + guard let genericRequirements: [GenericRequirement] = aDecoder.decode(forKey: "genericRequirements") else { + withVaList(["genericRequirements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.genericRequirements = genericRequirements + super.init(coder: aDecoder) + } + + /// :nodoc: + override public func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + aCoder.encode(self.associatedTypes, forKey: "associatedTypes") + aCoder.encode(self.genericRequirements, forKey: "genericRequirements") + } +// sourcery:end +} + +"""), + .init(name: "ProtocolComposition.swift", content: +""" +// Created by eric_horacek on 2/12/20. +// Copyright © 2020 Airbnb Inc. All rights reserved. + +import Foundation + +// sourcery: skipJSExport +/// Describes a Swift [protocol composition](https://docs.swift.org/swift-book/ReferenceManual/Types.html#ID454). +public final class ProtocolComposition: Type { + + /// Returns "protocolComposition" + public override var kind: String { return "protocolComposition" } + + /// The names of the types composed to form this composition + public let composedTypeNames: [TypeName] + + // sourcery: skipEquality, skipDescription + /// The types composed to form this composition, if known + public var composedTypes: [Type]? + + /// :nodoc: + public init(name: String = "", + parent: Type? = nil, + accessLevel: AccessLevel = .internal, + isExtension: Bool = false, + variables: [Variable] = [], + methods: [Method] = [], + subscripts: [Subscript] = [], + inheritedTypes: [String] = [], + containedTypes: [Type] = [], + typealiases: [Typealias] = [], + attributes: AttributeList = [:], + annotations: [String: NSObject] = [:], + isGeneric: Bool = false, + composedTypeNames: [TypeName] = [], + composedTypes: [Type]? = nil) { + self.composedTypeNames = composedTypeNames + self.composedTypes = composedTypes + super.init( + name: name, + parent: parent, + accessLevel: accessLevel, + isExtension: isExtension, + variables: variables, + methods: methods, + subscripts: subscripts, + inheritedTypes: inheritedTypes, + containedTypes: containedTypes, + typealiases: typealiases, + annotations: annotations, + isGeneric: isGeneric + ) + } + + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \\(String(describing: self.kind)), " + string += "composedTypeNames = \\(String(describing: self.composedTypeNames))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? ProtocolComposition else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "composedTypeNames").trackDifference(actual: self.composedTypeNames, expected: castObject.composedTypeNames)) + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.composedTypeNames) + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? ProtocolComposition else { return false } + if self.composedTypeNames != rhs.composedTypeNames { return false } + return super.isEqual(rhs) + } + +// sourcery:inline:ProtocolComposition.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let composedTypeNames: [TypeName] = aDecoder.decode(forKey: "composedTypeNames") else { + withVaList(["composedTypeNames"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.composedTypeNames = composedTypeNames + self.composedTypes = aDecoder.decode(forKey: "composedTypes") + super.init(coder: aDecoder) + } + + /// :nodoc: + override public func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + aCoder.encode(self.composedTypeNames, forKey: "composedTypeNames") + aCoder.encode(self.composedTypes, forKey: "composedTypes") + } +// sourcery:end + +} + +"""), + .init(name: "Struct.swift", content: +""" +// +// Struct.swift +// Sourcery +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright © 2016 Pixle. All rights reserved. +// + +import Foundation + +// sourcery: skipDescription +/// Describes Swift struct +public final class Struct: Type { + + /// Returns "struct" + public override var kind: String { return "struct" } + + /// :nodoc: + public override init(name: String = "", + parent: Type? = nil, + accessLevel: AccessLevel = .internal, + isExtension: Bool = false, + variables: [Variable] = [], + methods: [Method] = [], + subscripts: [Subscript] = [], + inheritedTypes: [String] = [], + containedTypes: [Type] = [], + typealiases: [Typealias] = [], + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + isGeneric: Bool = false) { + super.init( + name: name, + parent: parent, + accessLevel: accessLevel, + isExtension: isExtension, + variables: variables, + methods: methods, + subscripts: subscripts, + inheritedTypes: inheritedTypes, + containedTypes: containedTypes, + typealiases: typealiases, + attributes: attributes, + modifiers: modifiers, + annotations: annotations, + documentation: documentation, + isGeneric: isGeneric + ) + } + + /// :nodoc: + override public var description: String { + var string = super.description + string += ", " + string += "kind = \\(String(describing: self.kind))" + return string + } + + override public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Struct else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: super.diffAgainst(castObject)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(super.hash) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Struct else { return false } + return super.isEqual(rhs) + } + +// sourcery:inline:Struct.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + /// :nodoc: + override public func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + } +// sourcery:end +} + +"""), + .init(name: "Subscript.swift", content: +""" +import Foundation + +/// Describes subscript +public final class Subscript: NSObject, SourceryModel, Annotated, Documented, Definition, Diffable { + + /// Method parameters + public var parameters: [MethodParameter] + + /// Return value type name used in declaration, including generic constraints, i.e. `where T: Equatable` + public var returnTypeName: TypeName + + /// Actual return value type name if declaration uses typealias, otherwise just a `returnTypeName` + public var actualReturnTypeName: TypeName { + return returnTypeName.actualTypeName ?? returnTypeName + } + + // sourcery: skipEquality, skipDescription + /// Actual return value type, if known + public var returnType: Type? + + // sourcery: skipEquality, skipDescription + /// Whether return value type is optional + public var isOptionalReturnType: Bool { + return returnTypeName.isOptional + } + + // sourcery: skipEquality, skipDescription + /// Whether return value type is implicitly unwrapped optional + public var isImplicitlyUnwrappedOptionalReturnType: Bool { + return returnTypeName.isImplicitlyUnwrappedOptional + } + + // sourcery: skipEquality, skipDescription + /// Return value type name without attributes and optional type information + public var unwrappedReturnTypeName: String { + return returnTypeName.unwrappedTypeName + } + + /// Whether method is final + public var isFinal: Bool { + modifiers.contains { $0.name == "final" } + } + + /// Variable read access level, i.e. `internal`, `private`, `fileprivate`, `public`, `open` + public let readAccess: String + + /// Variable write access, i.e. `internal`, `private`, `fileprivate`, `public`, `open`. + /// For immutable variables this value is empty string + public var writeAccess: String + + /// Whether variable is mutable or not + public var isMutable: Bool { + return writeAccess != AccessLevel.none.rawValue + } + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public let annotations: Annotations + + public let documentation: Documentation + + /// Reference to type name where the method is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc + public let definedInTypeName: TypeName? + + /// Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a `definedInTypeName` + public var actualDefinedInTypeName: TypeName? { + return definedInTypeName?.actualTypeName ?? definedInTypeName + } + + // sourcery: skipEquality, skipDescription + /// Reference to actual type where the object is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc or type is unknown + public var definedInType: Type? + + /// Method attributes, i.e. `@discardableResult` + public let attributes: AttributeList + + /// Method modifiers, i.e. `private` + public let modifiers: [SourceryModifier] + + // Underlying parser data, never to be used by anything else + // sourcery: skipEquality, skipDescription, skipCoding, skipJSExport + /// :nodoc: + public var __parserData: Any? + + /// :nodoc: + public init(parameters: [MethodParameter] = [], + returnTypeName: TypeName, + accessLevel: (read: AccessLevel, write: AccessLevel) = (.internal, .internal), + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + definedInTypeName: TypeName? = nil) { + + self.parameters = parameters + self.returnTypeName = returnTypeName + self.readAccess = accessLevel.read.rawValue + self.writeAccess = accessLevel.write.rawValue + self.attributes = attributes + self.modifiers = modifiers + self.annotations = annotations + self.documentation = documentation + self.definedInTypeName = definedInTypeName + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "parameters = \\(String(describing: self.parameters)), " + string += "returnTypeName = \\(String(describing: self.returnTypeName)), " + string += "actualReturnTypeName = \\(String(describing: self.actualReturnTypeName)), " + string += "isFinal = \\(String(describing: self.isFinal)), " + string += "readAccess = \\(String(describing: self.readAccess)), " + string += "writeAccess = \\(String(describing: self.writeAccess)), " + string += "isMutable = \\(String(describing: self.isMutable)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "documentation = \\(String(describing: self.documentation)), " + string += "definedInTypeName = \\(String(describing: self.definedInTypeName)), " + string += "actualDefinedInTypeName = \\(String(describing: self.actualDefinedInTypeName)), " + string += "attributes = \\(String(describing: self.attributes)), " + string += "modifiers = \\(String(describing: self.modifiers))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Subscript else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters)) + results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName)) + results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) + results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.parameters) + hasher.combine(self.returnTypeName) + hasher.combine(self.readAccess) + hasher.combine(self.writeAccess) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.definedInTypeName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Subscript else { return false } + if self.parameters != rhs.parameters { return false } + if self.returnTypeName != rhs.returnTypeName { return false } + if self.readAccess != rhs.readAccess { return false } + if self.writeAccess != rhs.writeAccess { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + return true + } + +// sourcery:inline:Subscript.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else { + withVaList(["parameters"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.parameters = parameters + guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else { + withVaList(["returnTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.returnTypeName = returnTypeName + self.returnType = aDecoder.decode(forKey: "returnType") + guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { + withVaList(["readAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.readAccess = readAccess + guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { + withVaList(["writeAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.writeAccess = writeAccess + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") + self.definedInType = aDecoder.decode(forKey: "definedInType") + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.parameters, forKey: "parameters") + aCoder.encode(self.returnTypeName, forKey: "returnTypeName") + aCoder.encode(self.returnType, forKey: "returnType") + aCoder.encode(self.readAccess, forKey: "readAccess") + aCoder.encode(self.writeAccess, forKey: "writeAccess") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.definedInTypeName, forKey: "definedInTypeName") + aCoder.encode(self.definedInType, forKey: "definedInType") + aCoder.encode(self.attributes, forKey: "attributes") + aCoder.encode(self.modifiers, forKey: "modifiers") + } +// sourcery:end + +} + +"""), + .init(name: "DynamicMemberLookup.swift", content: +""" +// +// Stencil +// Copyright © 2022 Stencil +// MIT Licence +// + +/// Marker protocol so we can know which types support `@dynamicMemberLookup`. Add this to your own types that support +/// lookup by String. +public protocol DynamicMemberLookup { + /// Get a value for a given `String` key + subscript(dynamicMember member: String) -> Any? { get } +} + +public extension DynamicMemberLookup where Self: RawRepresentable { + /// Get a value for a given `String` key + subscript(dynamicMember member: String) -> Any? { + switch member { + case "rawValue": + return rawValue + default: + return nil + } + } +} + +"""), + .init(name: "TemplateContext.swift", content: +""" +// +// Created by Krzysztof Zablocki on 31/12/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// + +import Foundation + +/// :nodoc: +// sourcery: skipCoding +public final class TemplateContext: NSObject, SourceryModel, NSCoding, Diffable { + // sourcery: skipJSExport + public let parserResult: FileParserResult? + public let functions: [SourceryMethod] + public let types: Types + public let argument: [String: NSObject] + + // sourcery: skipDescription + public var type: [String: Type] { + return types.typesByName + } + + public init(parserResult: FileParserResult?, types: Types, functions: [SourceryMethod], arguments: [String: NSObject]) { + self.parserResult = parserResult + self.types = types + self.functions = functions + self.argument = arguments + } + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let parserResult: FileParserResult = aDecoder.decode(forKey: "parserResult") else { + withVaList(["parserResult"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found. FileParserResults are required for template context that needs persisting.", arguments: arguments) + } + fatalError() + } + guard let argument: [String: NSObject] = aDecoder.decode(forKey: "argument") else { + withVaList(["argument"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + } + + // if we want to support multiple cycles of encode / decode we need deep copy because composer changes reference types + let fileParserResultCopy: FileParserResult? = nil +// fileParserResultCopy = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(NSKeyedArchiver.archivedData(withRootObject: parserResult)) as? FileParserResult + + let composed = Composer.uniqueTypesAndFunctions(parserResult) + self.types = .init(types: composed.types, typealiases: composed.typealiases) + self.functions = composed.functions + + self.parserResult = fileParserResultCopy + self.argument = argument + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.parserResult, forKey: "parserResult") + aCoder.encode(self.argument, forKey: "argument") + } + + public var stencilContext: [String: Any] { + return [ + "types": types, + "functions": functions, + "type": types.typesByName, + "argument": argument + ] + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "parserResult = \\(String(describing: self.parserResult)), " + string += "functions = \\(String(describing: self.functions)), " + string += "types = \\(String(describing: self.types)), " + string += "argument = \\(String(describing: self.argument)), " + string += "stencilContext = \\(String(describing: self.stencilContext))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TemplateContext else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "parserResult").trackDifference(actual: self.parserResult, expected: castObject.parserResult)) + results.append(contentsOf: DiffableResult(identifier: "functions").trackDifference(actual: self.functions, expected: castObject.functions)) + results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) + results.append(contentsOf: DiffableResult(identifier: "argument").trackDifference(actual: self.argument, expected: castObject.argument)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.parserResult) + hasher.combine(self.functions) + hasher.combine(self.types) + hasher.combine(self.argument) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TemplateContext else { return false } + if self.parserResult != rhs.parserResult { return false } + if self.functions != rhs.functions { return false } + if self.types != rhs.types { return false } + if self.argument != rhs.argument { return false } + return true + } + + // sourcery: skipDescription, skipEquality + public var jsContext: [String: Any] { + return [ + "types": [ + "all": types.all, + "protocols": types.protocols, + "classes": types.classes, + "structs": types.structs, + "enums": types.enums, + "extensions": types.extensions, + "based": types.based, + "inheriting": types.inheriting, + "implementing": types.implementing + ] as [String : Any], + "functions": functions, + "type": types.typesByName, + "argument": argument + ] + } + +} + +extension ProcessInfo { + /// :nodoc: + public var context: TemplateContext! { + return NSKeyedUnarchiver.unarchiveObject(withFile: arguments[1]) as? TemplateContext + } +} + +"""), + .init(name: "Types.swift", content: +""" +import Foundation + +// sourcery: skipJSExport +/// Collection of scanned types for accessing in templates +public final class Types: NSObject, SourceryModel, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "types": + return types + case "enums": + return enums + case "all": + return all + case "protocols": + return protocols + case "classes": + return classes + case "structs": + return structs + case "extensions": + return extensions + case "implementing": + return implementing + case "inheriting": + return inheriting + case "based": + return based + default: + fatalError("unable to lookup: \\(member) in \\(self)") + } + } + + /// :nodoc: + public let types: [Type] + + /// All known typealiases + public let typealiases: [Typealias] + + /// :nodoc: + public init(types: [Type], typealiases: [Typealias] = []) { + self.types = types + self.typealiases = typealiases + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "types = \\(String(describing: self.types)), " + string += "typealiases = \\(String(describing: self.typealiases))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Types else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "types").trackDifference(actual: self.types, expected: castObject.types)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.types) + hasher.combine(self.typealiases) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Types else { return false } + if self.types != rhs.types { return false } + if self.typealiases != rhs.typealiases { return false } + return true + } + +// sourcery:inline:Types.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let types: [Type] = aDecoder.decode(forKey: "types") else { + withVaList(["types"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.types = types + guard let typealiases: [Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.types, forKey: "types") + aCoder.encode(self.typealiases, forKey: "typealiases") + } +// sourcery:end + + // sourcery: skipDescription, skipEquality, skipCoding + /// :nodoc: + public lazy internal(set) var typesByName: [String: Type] = { + var typesByName = [String: Type]() + self.types.forEach { typesByName[$0.globalName] = $0 } + return typesByName + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// :nodoc: + public lazy internal(set) var typesaliasesByName: [String: Typealias] = { + var typesaliasesByName = [String: Typealias]() + self.typealiases.forEach { typesaliasesByName[$0.name] = $0 } + return typesaliasesByName + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known types, excluding protocols or protocol compositions. + public lazy internal(set) var all: [Type] = { + return self.types.filter { !($0 is Protocol || $0 is ProtocolComposition) } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known protocols + public lazy internal(set) var protocols: [Protocol] = { + return self.types.compactMap { $0 as? Protocol } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known protocol compositions + public lazy internal(set) var protocolCompositions: [ProtocolComposition] = { + return self.types.compactMap { $0 as? ProtocolComposition } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known classes + public lazy internal(set) var classes: [Class] = { + return self.all.compactMap { $0 as? Class } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known structs + public lazy internal(set) var structs: [Struct] = { + return self.all.compactMap { $0 as? Struct } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known enums + public lazy internal(set) var enums: [Enum] = { + return self.all.compactMap { $0 as? Enum } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// All known extensions + public lazy internal(set) var extensions: [Type] = { + return self.all.compactMap { $0.isExtension ? $0 : nil } + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// Types based on any other type, grouped by its name, even if they are not known. + /// `types.based.MyType` returns list of types based on `MyType` + public lazy internal(set) var based: TypesCollection = { + TypesCollection( + types: self.types, + collection: { Array($0.based.keys) } + ) + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// Classes inheriting from any known class, grouped by its name. + /// `types.inheriting.MyClass` returns list of types inheriting from `MyClass` + public lazy internal(set) var inheriting: TypesCollection = { + TypesCollection( + types: self.types, + collection: { Array($0.inherits.keys) }, + validate: { type in + guard type is Class else { + throw "\\(type.name) is not a class and should be used with `implementing` or `based`" + } + }) + }() + + // sourcery: skipDescription, skipEquality, skipCoding + /// Types implementing known protocol, grouped by its name. + /// `types.implementing.MyProtocol` returns list of types implementing `MyProtocol` + public lazy internal(set) var implementing: TypesCollection = { + TypesCollection( + types: self.types, + collection: { Array($0.implements.keys) }, + validate: { type in + guard type is Protocol else { + throw "\\(type.name) is a class and should be used with `inheriting` or `based`" + } + }) + }() +} + +"""), + .init(name: "TypesCollection.swift", content: +""" +import Foundation + +/// :nodoc: +public class TypesCollection: NSObject, AutoJSExport, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + return try? types(forKey: member) + } + + // sourcery:begin: skipJSExport + let all: [Type] + let types: [String: [Type]] + let validate: ((Type) throws -> Void)? + // sourcery:end + + init(types: [Type], collection: (Type) -> [String], validate: ((Type) throws -> Void)? = nil) { + self.all = types + var content = [String: [Type]]() + self.all.forEach { type in + collection(type).forEach { name in + var list = content[name] ?? [Type]() + list.append(type) + content[name] = list + } + } + self.types = content + self.validate = validate + } + + public func types(forKey key: String) throws -> [Type] { + // In some configurations, the types are keyed by "ModuleName.TypeName" + var longKey: String? + + if let validate = validate { + guard let type = all.first(where: { $0.name == key }) else { + throw "Unknown type \\(key), should be used with `based`" + } + + try validate(type) + + if let module = type.module { + longKey = [module, type.name].joined(separator: ".") + } + } + + // If we find the types directly, return them + if let types = types[key] { + return types + } + + // if we find a types for the longKey, return them + if let longKey = longKey, let types = types[longKey] { + return types + } + + return [] + } + + /// :nodoc: + public func value(forKey key: String) -> Any? { + do { + return try types(forKey: key) + } catch { + Log.error(error) + return nil + } + } + + /// :nodoc: + public subscript(_ key: String) -> [Type] { + do { + return try types(forKey: key) + } catch { + Log.error(error) + return [] + } + } +} + +"""), + .init(name: "Tuple.swift", content: +""" +import Foundation + +/// Describes tuple type +public final class TupleType: NSObject, SourceryModel, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "elements": + return elements + default: + fatalError("unable to lookup: \\(member) in \\(self)") + } + } + + /// Type name used in declaration + public var name: String + + /// Tuple elements + public var elements: [TupleElement] + + /// :nodoc: + public init(name: String, elements: [TupleElement]) { + self.name = name + self.elements = elements + } + + /// :nodoc: + public init(elements: [TupleElement]) { + self.name = elements.asSource + self.elements = elements + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "elements = \\(String(describing: self.elements))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TupleType else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "elements").trackDifference(actual: self.elements, expected: castObject.elements)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.elements) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TupleType else { return false } + if self.name != rhs.name { return false } + if self.elements != rhs.elements { return false } + return true + } + +// sourcery:inline:TupleType.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let elements: [TupleElement] = aDecoder.decode(forKey: "elements") else { + withVaList(["elements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.elements = elements + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.elements, forKey: "elements") + } +// sourcery:end +} + +/// Describes tuple type element +public final class TupleElement: NSObject, SourceryModel, Typed, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "name": + return name + case "typeName": + return typeName + case "type": + return type + default: + fatalError("unable to lookup: \\(member) in \\(self)") + } + } + + /// Tuple element name + public let name: String? + + /// Tuple element type name + public var typeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Tuple element type, if known + public var type: Type? + + /// :nodoc: + public init(name: String? = nil, typeName: TypeName, type: Type? = nil) { + self.name = name + self.typeName = typeName + self.type = type + } + + public var asSource: String { + // swiftlint:disable:next force_unwrapping + "\\(name != nil ? "\\(name!): " : "")\\(typeName.asSource)" + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "asSource = \\(String(describing: self.asSource))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TupleElement else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TupleElement else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + return true + } + +// sourcery:inline:TupleElement.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.name = aDecoder.decode(forKey: "name") + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.type = aDecoder.decode(forKey: "type") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + } +// sourcery:end +} + +extension Array where Element == TupleElement { + public var asSource: String { + "(\\(map { $0.asSource }.joined(separator: ", ")))" + } + + public var asTypeName: String { + "(\\(map { $0.typeName.asSource }.joined(separator: ", ")))" + } +} + +"""), + .init(name: "Type.swift", content: +""" +// +// Created by Krzysztof Zablocki on 11/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// + +import Foundation + +/// :nodoc: +public typealias AttributeList = [String: [Attribute]] + +/// Defines Swift type +public class Type: NSObject, SourceryModel, Annotated, Documented, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "implements": + return implements + case "name": + return name + case "kind": + return kind + case "based": + return based + case "supertype": + return supertype + case "accessLevel": + return accessLevel + case "storedVariables": + return storedVariables + case "variables": + return variables + case "allVariables": + return allVariables + case "allMethods": + return allMethods + case "annotations": + return annotations + case "methods": + return methods + case "containedType": + return containedType + case "computedVariables": + return computedVariables + case "inherits": + return inherits + case "inheritedTypes": + return inheritedTypes + default: + fatalError("unable to lookup: \\(member) in \\(self)") + } + } + + /// :nodoc: + public var module: String? + + /// Imports that existed in the file that contained this type declaration + public var imports: [Import] = [] + + // sourcery: skipEquality + /// Imports existed in all files containing this type and all its super classes/protocols + public var allImports: [Import] { + return self.unique({ $0.gatherAllImports() }, filter: { $0 == $1 }) + } + + private func gatherAllImports() -> [Import] { + var allImports: [Import] = Array(self.imports) + + self.basedTypes.values.forEach { (basedType) in + allImports.append(contentsOf: basedType.imports) + } + return allImports + } + + // All local typealiases + // sourcery: skipJSExport + /// :nodoc: + public var typealiases: [String: Typealias] { + didSet { + typealiases.values.forEach { $0.parent = self } + } + } + + // sourcery: skipJSExport + /// Whether declaration is an extension of some type + public var isExtension: Bool + + // sourcery: forceEquality + /// Kind of type declaration, i.e. `enum`, `struct`, `class`, `protocol` or `extension` + public var kind: String { return isExtension ? "extension" : "unknown" } + + /// Type access level, i.e. `internal`, `private`, `fileprivate`, `public`, `open` + public let accessLevel: String + + /// Type name in global scope. For inner types includes the name of its containing type, i.e. `Type.Inner` + public var name: String { + guard let parentName = parent?.name else { return localName } + return "\\(parentName).\\(localName)" + } + + // sourcery: skipCoding + /// Whether the type has been resolved as unknown extension + public var isUnknownExtension: Bool = false + + // sourcery: skipDescription + /// Global type name including module name, unless it's an extension of unknown type + public var globalName: String { + guard let module = module, !isUnknownExtension else { return name } + return "\\(module).\\(name)" + } + + /// Whether type is generic + public var isGeneric: Bool + + /// Type name in its own scope. + public var localName: String + + // sourcery: skipEquality, skipDescription + /// Variables defined in this type only, inluding variables defined in its extensions, + /// but not including variables inherited from superclasses (for classes only) and protocols + public var variables: [Variable] { + unique({ $0.rawVariables }, filter: Self.uniqueVariableFilter) + } + + /// Unfiltered (can contain duplications from extensions) variables defined in this type only, inluding variables defined in its extensions, + /// but not including variables inherited from superclasses (for classes only) and protocols + public var rawVariables: [Variable] + + // sourcery: skipEquality, skipDescription + /// All variables defined for this type, including variables defined in extensions, + /// in superclasses (for classes only) and protocols + public var allVariables: [Variable] { + return flattenAll({ + return $0.variables + }, + isExtension: { $0.definedInType?.isExtension == true }, + filter: { all, extracted in + !all.contains(where: { Self.uniqueVariableFilter($0, rhs: extracted) }) + }) + } + + private static func uniqueVariableFilter(_ lhs: Variable, rhs: Variable) -> Bool { + return lhs.name == rhs.name && lhs.isStatic == rhs.isStatic && lhs.typeName == rhs.typeName + } + + // sourcery: skipEquality, skipDescription + /// Methods defined in this type only, inluding methods defined in its extensions, + /// but not including methods inherited from superclasses (for classes only) and protocols + public var methods: [Method] { + unique({ $0.rawMethods }, filter: Self.uniqueMethodFilter) + } + + /// Unfiltered (can contain duplications from extensions) methods defined in this type only, inluding methods defined in its extensions, + /// but not including methods inherited from superclasses (for classes only) and protocols + public var rawMethods: [Method] + + // sourcery: skipEquality, skipDescription + /// All methods defined for this type, including methods defined in extensions, + /// in superclasses (for classes only) and protocols + public var allMethods: [Method] { + return flattenAll({ + $0.methods + }, + isExtension: { $0.definedInType?.isExtension == true }, + filter: { all, extracted in + !all.contains(where: { Self.uniqueMethodFilter($0, rhs: extracted) }) + }) + } + + private static func uniqueMethodFilter(_ lhs: Method, rhs: Method) -> Bool { + return lhs.name == rhs.name && lhs.isStatic == rhs.isStatic && lhs.isClass == rhs.isClass && lhs.actualReturnTypeName == rhs.actualReturnTypeName + } + + // sourcery: skipEquality, skipDescription + /// Subscripts defined in this type only, inluding subscripts defined in its extensions, + /// but not including subscripts inherited from superclasses (for classes only) and protocols + public var subscripts: [Subscript] { + unique({ $0.rawSubscripts }, filter: Self.uniqueSubscriptFilter) + } + + /// Unfiltered (can contain duplications from extensions) Subscripts defined in this type only, inluding subscripts defined in its extensions, + /// but not including subscripts inherited from superclasses (for classes only) and protocols + public var rawSubscripts: [Subscript] + + // sourcery: skipEquality, skipDescription + /// All subscripts defined for this type, including subscripts defined in extensions, + /// in superclasses (for classes only) and protocols + public var allSubscripts: [Subscript] { + return flattenAll({ $0.subscripts }, + isExtension: { $0.definedInType?.isExtension == true }, + filter: { all, extracted in + !all.contains(where: { Self.uniqueSubscriptFilter($0, rhs: extracted) }) + }) + } + + private static func uniqueSubscriptFilter(_ lhs: Subscript, rhs: Subscript) -> Bool { + return lhs.parameters == rhs.parameters && lhs.returnTypeName == rhs.returnTypeName && lhs.readAccess == rhs.readAccess && lhs.writeAccess == rhs.writeAccess + } + + // sourcery: skipEquality, skipDescription, skipJSExport + /// Bytes position of the body of this type in its declaration file if available. + public var bodyBytesRange: BytesRange? + + // sourcery: skipEquality, skipDescription, skipJSExport + /// Bytes position of the whole declaration of this type in its declaration file if available. + public var completeDeclarationRange: BytesRange? + + private func flattenAll(_ extraction: @escaping (Type) -> [T], isExtension: (T) -> Bool, filter: ([T], T) -> Bool) -> [T] { + let all = NSMutableOrderedSet() + let allObjects = extraction(self) + + /// The order of importance for properties is: + /// Base class + /// Inheritance + /// Protocol conformance + /// Extension + + var extensions = [T]() + var baseObjects = [T]() + + allObjects.forEach { + if isExtension($0) { + extensions.append($0) + } else { + baseObjects.append($0) + } + } + + all.addObjects(from: baseObjects) + + func filteredExtraction(_ target: Type) -> [T] { + // swiftlint:disable:next force_cast + let all = all.array as! [T] + let extracted = extraction(target).filter({ filter(all, $0) }) + return extracted + } + + inherits.values.sorted(by: { $0.name < $1.name }).forEach { all.addObjects(from: filteredExtraction($0)) } + implements.values.sorted(by: { $0.name < $1.name }).forEach { all.addObjects(from: filteredExtraction($0)) } + + // swiftlint:disable:next force_cast + let array = all.array as! [T] + all.addObjects(from: extensions.filter({ filter(array, $0) })) + + return all.array.compactMap { $0 as? T } + } + + private func unique(_ extraction: @escaping (Type) -> [T], filter: (T, T) -> Bool) -> [T] { + let all = NSMutableOrderedSet() + for nextItem in extraction(self) { + // swiftlint:disable:next force_cast + if !all.contains(where: { filter($0 as! T, nextItem) }) { + all.add(nextItem) + } + } + + return all.array.compactMap { $0 as? T } + } + + /// All initializers defined in this type + public var initializers: [Method] { + return methods.filter { $0.isInitializer } + } + + /// All annotations for this type + public var annotations: Annotations = [:] + + public var documentation: Documentation = [] + + /// Static variables defined in this type + public var staticVariables: [Variable] { + return variables.filter { $0.isStatic } + } + + /// Static methods defined in this type + public var staticMethods: [Method] { + return methods.filter { $0.isStatic } + } + + /// Class methods defined in this type + public var classMethods: [Method] { + return methods.filter { $0.isClass } + } + + /// Instance variables defined in this type + public var instanceVariables: [Variable] { + return variables.filter { !$0.isStatic } + } + + /// Instance methods defined in this type + public var instanceMethods: [Method] { + return methods.filter { !$0.isStatic && !$0.isClass } + } + + /// Computed instance variables defined in this type + public var computedVariables: [Variable] { + return variables.filter { $0.isComputed && !$0.isStatic } + } + + /// Stored instance variables defined in this type + public var storedVariables: [Variable] { + return variables.filter { !$0.isComputed && !$0.isStatic } + } + + /// Names of types this type inherits from (for classes only) and protocols it implements, in order of definition + public var inheritedTypes: [String] { + didSet { + based.removeAll() + inheritedTypes.forEach { name in + self.based[name] = name + } + } + } + + // sourcery: skipEquality, skipDescription + /// Names of types or protocols this type inherits from, including unknown (not scanned) types + public var based = [String: String]() + + // sourcery: skipEquality, skipDescription + /// Types this type inherits from or implements, including unknown (not scanned) types with extensions defined + public var basedTypes = [String: Type]() + + /// Types this type inherits from + public var inherits = [String: Type]() + + // sourcery: skipEquality, skipDescription + /// Protocols this type implements + public var implements = [String: Type]() + + /// Contained types + public var containedTypes: [Type] { + didSet { + containedTypes.forEach { + containedType[$0.localName] = $0 + $0.parent = self + } + } + } + + // sourcery: skipEquality, skipDescription + /// Contained types groupd by their names + public private(set) var containedType: [String: Type] = [:] + + /// Name of parent type (for contained types only) + public private(set) var parentName: String? + + // sourcery: skipEquality, skipDescription + /// Parent type, if known (for contained types only) + public var parent: Type? { + didSet { + parentName = parent?.name + } + } + + // sourcery: skipJSExport + /// :nodoc: + public var parentTypes: AnyIterator { + var next: Type? = self + return AnyIterator { + next = next?.parent + return next + } + } + + // sourcery: skipEquality, skipDescription + /// Superclass type, if known (only for classes) + public var supertype: Type? + + /// Type attributes, i.e. `@objc` + public var attributes: AttributeList + + /// Type modifiers, i.e. `private`, `final` + public var modifiers: [SourceryModifier] + + /// Path to file where the type is defined + // sourcery: skipDescription, skipEquality, skipJSExport + public var path: String? { + didSet { + if let path = path { + fileName = (path as NSString).lastPathComponent + } + } + } + + /// Directory to file where the type is defined + // sourcery: skipDescription, skipEquality, skipJSExport + public var directory: String? { + get { + return (path as? NSString)?.deletingLastPathComponent + } + } + + /// File name where the type was defined + public var fileName: String? + + /// :nodoc: + public init(name: String = "", + parent: Type? = nil, + accessLevel: AccessLevel = .internal, + isExtension: Bool = false, + variables: [Variable] = [], + methods: [Method] = [], + subscripts: [Subscript] = [], + inheritedTypes: [String] = [], + containedTypes: [Type] = [], + typealiases: [Typealias] = [], + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + isGeneric: Bool = false) { + + self.localName = name + self.accessLevel = accessLevel.rawValue + self.isExtension = isExtension + self.rawVariables = variables + self.rawMethods = methods + self.rawSubscripts = subscripts + self.inheritedTypes = inheritedTypes + self.containedTypes = containedTypes + self.typealiases = [:] + self.parent = parent + self.parentName = parent?.name + self.attributes = attributes + self.modifiers = modifiers + self.annotations = annotations + self.documentation = documentation + self.isGeneric = isGeneric + + super.init() + containedTypes.forEach { + containedType[$0.localName] = $0 + $0.parent = self + } + inheritedTypes.forEach { name in + self.based[name] = name + } + typealiases.forEach({ + $0.parent = self + self.typealiases[$0.aliasName] = $0 + }) + } + + /// :nodoc: + public func extend(_ type: Type) { + type.annotations.forEach { self.annotations[$0.key] = $0.value } + type.inherits.forEach { self.inherits[$0.key] = $0.value } + type.implements.forEach { self.implements[$0.key] = $0.value } + self.inheritedTypes += type.inheritedTypes + self.containedTypes += type.containedTypes + + self.rawVariables += type.rawVariables + self.rawMethods += type.rawMethods + self.rawSubscripts += type.rawSubscripts + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "module = \\(String(describing: self.module)), " + string += "imports = \\(String(describing: self.imports)), " + string += "allImports = \\(String(describing: self.allImports)), " + string += "typealiases = \\(String(describing: self.typealiases)), " + string += "isExtension = \\(String(describing: self.isExtension)), " + string += "kind = \\(String(describing: self.kind)), " + string += "accessLevel = \\(String(describing: self.accessLevel)), " + string += "name = \\(String(describing: self.name)), " + string += "isUnknownExtension = \\(String(describing: self.isUnknownExtension)), " + string += "isGeneric = \\(String(describing: self.isGeneric)), " + string += "localName = \\(String(describing: self.localName)), " + string += "rawVariables = \\(String(describing: self.rawVariables)), " + string += "rawMethods = \\(String(describing: self.rawMethods)), " + string += "rawSubscripts = \\(String(describing: self.rawSubscripts)), " + string += "initializers = \\(String(describing: self.initializers)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "documentation = \\(String(describing: self.documentation)), " + string += "staticVariables = \\(String(describing: self.staticVariables)), " + string += "staticMethods = \\(String(describing: self.staticMethods)), " + string += "classMethods = \\(String(describing: self.classMethods)), " + string += "instanceVariables = \\(String(describing: self.instanceVariables)), " + string += "instanceMethods = \\(String(describing: self.instanceMethods)), " + string += "computedVariables = \\(String(describing: self.computedVariables)), " + string += "storedVariables = \\(String(describing: self.storedVariables)), " + string += "inheritedTypes = \\(String(describing: self.inheritedTypes)), " + string += "inherits = \\(String(describing: self.inherits)), " + string += "containedTypes = \\(String(describing: self.containedTypes)), " + string += "parentName = \\(String(describing: self.parentName)), " + string += "parentTypes = \\(String(describing: self.parentTypes)), " + string += "attributes = \\(String(describing: self.attributes)), " + string += "modifiers = \\(String(describing: self.modifiers)), " + string += "fileName = \\(String(describing: self.fileName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Type else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) + results.append(contentsOf: DiffableResult(identifier: "imports").trackDifference(actual: self.imports, expected: castObject.imports)) + results.append(contentsOf: DiffableResult(identifier: "typealiases").trackDifference(actual: self.typealiases, expected: castObject.typealiases)) + results.append(contentsOf: DiffableResult(identifier: "isExtension").trackDifference(actual: self.isExtension, expected: castObject.isExtension)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "isUnknownExtension").trackDifference(actual: self.isUnknownExtension, expected: castObject.isUnknownExtension)) + results.append(contentsOf: DiffableResult(identifier: "isGeneric").trackDifference(actual: self.isGeneric, expected: castObject.isGeneric)) + results.append(contentsOf: DiffableResult(identifier: "localName").trackDifference(actual: self.localName, expected: castObject.localName)) + results.append(contentsOf: DiffableResult(identifier: "rawVariables").trackDifference(actual: self.rawVariables, expected: castObject.rawVariables)) + results.append(contentsOf: DiffableResult(identifier: "rawMethods").trackDifference(actual: self.rawMethods, expected: castObject.rawMethods)) + results.append(contentsOf: DiffableResult(identifier: "rawSubscripts").trackDifference(actual: self.rawSubscripts, expected: castObject.rawSubscripts)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "inheritedTypes").trackDifference(actual: self.inheritedTypes, expected: castObject.inheritedTypes)) + results.append(contentsOf: DiffableResult(identifier: "inherits").trackDifference(actual: self.inherits, expected: castObject.inherits)) + results.append(contentsOf: DiffableResult(identifier: "containedTypes").trackDifference(actual: self.containedTypes, expected: castObject.containedTypes)) + results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "fileName").trackDifference(actual: self.fileName, expected: castObject.fileName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.module) + hasher.combine(self.imports) + hasher.combine(self.typealiases) + hasher.combine(self.isExtension) + hasher.combine(self.accessLevel) + hasher.combine(self.isUnknownExtension) + hasher.combine(self.isGeneric) + hasher.combine(self.localName) + hasher.combine(self.rawVariables) + hasher.combine(self.rawMethods) + hasher.combine(self.rawSubscripts) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.inheritedTypes) + hasher.combine(self.inherits) + hasher.combine(self.containedTypes) + hasher.combine(self.parentName) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.fileName) + hasher.combine(kind) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Type else { return false } + if self.module != rhs.module { return false } + if self.imports != rhs.imports { return false } + if self.typealiases != rhs.typealiases { return false } + if self.isExtension != rhs.isExtension { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.isUnknownExtension != rhs.isUnknownExtension { return false } + if self.isGeneric != rhs.isGeneric { return false } + if self.localName != rhs.localName { return false } + if self.rawVariables != rhs.rawVariables { return false } + if self.rawMethods != rhs.rawMethods { return false } + if self.rawSubscripts != rhs.rawSubscripts { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.inheritedTypes != rhs.inheritedTypes { return false } + if self.inherits != rhs.inherits { return false } + if self.containedTypes != rhs.containedTypes { return false } + if self.parentName != rhs.parentName { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.fileName != rhs.fileName { return false } + if self.kind != rhs.kind { return false } + return true + } + +// sourcery:inline:Type.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + self.module = aDecoder.decode(forKey: "module") + guard let imports: [Import] = aDecoder.decode(forKey: "imports") else { + withVaList(["imports"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.imports = imports + guard let typealiases: [String: Typealias] = aDecoder.decode(forKey: "typealiases") else { + withVaList(["typealiases"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typealiases = typealiases + self.isExtension = aDecoder.decode(forKey: "isExtension") + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel + self.isGeneric = aDecoder.decode(forKey: "isGeneric") + guard let localName: String = aDecoder.decode(forKey: "localName") else { + withVaList(["localName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.localName = localName + guard let rawVariables: [Variable] = aDecoder.decode(forKey: "rawVariables") else { + withVaList(["rawVariables"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawVariables = rawVariables + guard let rawMethods: [Method] = aDecoder.decode(forKey: "rawMethods") else { + withVaList(["rawMethods"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawMethods = rawMethods + guard let rawSubscripts: [Subscript] = aDecoder.decode(forKey: "rawSubscripts") else { + withVaList(["rawSubscripts"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.rawSubscripts = rawSubscripts + self.bodyBytesRange = aDecoder.decode(forKey: "bodyBytesRange") + self.completeDeclarationRange = aDecoder.decode(forKey: "completeDeclarationRange") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + guard let inheritedTypes: [String] = aDecoder.decode(forKey: "inheritedTypes") else { + withVaList(["inheritedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inheritedTypes = inheritedTypes + guard let based: [String: String] = aDecoder.decode(forKey: "based") else { + withVaList(["based"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.based = based + guard let basedTypes: [String: Type] = aDecoder.decode(forKey: "basedTypes") else { + withVaList(["basedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.basedTypes = basedTypes + guard let inherits: [String: Type] = aDecoder.decode(forKey: "inherits") else { + withVaList(["inherits"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.inherits = inherits + guard let implements: [String: Type] = aDecoder.decode(forKey: "implements") else { + withVaList(["implements"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.implements = implements + guard let containedTypes: [Type] = aDecoder.decode(forKey: "containedTypes") else { + withVaList(["containedTypes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.containedTypes = containedTypes + guard let containedType: [String: Type] = aDecoder.decode(forKey: "containedType") else { + withVaList(["containedType"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.containedType = containedType + self.parentName = aDecoder.decode(forKey: "parentName") + self.parent = aDecoder.decode(forKey: "parent") + self.supertype = aDecoder.decode(forKey: "supertype") + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers + self.path = aDecoder.decode(forKey: "path") + self.fileName = aDecoder.decode(forKey: "fileName") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.module, forKey: "module") + aCoder.encode(self.imports, forKey: "imports") + aCoder.encode(self.typealiases, forKey: "typealiases") + aCoder.encode(self.isExtension, forKey: "isExtension") + aCoder.encode(self.accessLevel, forKey: "accessLevel") + aCoder.encode(self.isGeneric, forKey: "isGeneric") + aCoder.encode(self.localName, forKey: "localName") + aCoder.encode(self.rawVariables, forKey: "rawVariables") + aCoder.encode(self.rawMethods, forKey: "rawMethods") + aCoder.encode(self.rawSubscripts, forKey: "rawSubscripts") + aCoder.encode(self.bodyBytesRange, forKey: "bodyBytesRange") + aCoder.encode(self.completeDeclarationRange, forKey: "completeDeclarationRange") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.inheritedTypes, forKey: "inheritedTypes") + aCoder.encode(self.based, forKey: "based") + aCoder.encode(self.basedTypes, forKey: "basedTypes") + aCoder.encode(self.inherits, forKey: "inherits") + aCoder.encode(self.implements, forKey: "implements") + aCoder.encode(self.containedTypes, forKey: "containedTypes") + aCoder.encode(self.containedType, forKey: "containedType") + aCoder.encode(self.parentName, forKey: "parentName") + aCoder.encode(self.parent, forKey: "parent") + aCoder.encode(self.supertype, forKey: "supertype") + aCoder.encode(self.attributes, forKey: "attributes") + aCoder.encode(self.modifiers, forKey: "modifiers") + aCoder.encode(self.path, forKey: "path") + aCoder.encode(self.fileName, forKey: "fileName") + } +// sourcery:end + +} + +extension Type { + + // sourcery: skipDescription, skipJSExport + /// :nodoc: + var isClass: Bool { + let isNotClass = self is Struct || self is Enum || self is Protocol + return !isNotClass && !isExtension + } +} + +"""), + .init(name: "TypeName.swift", content: +""" +// +// Created by Krzysztof Zabłocki on 25/12/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// + +import Foundation + +/// Describes name of the type used in typed declaration (variable, method parameter or return value etc.) +public final class TypeName: NSObject, SourceryModelWithoutDescription, LosslessStringConvertible, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "tuple": + return tuple + case "name": + return name + case "isOptional": + return isOptional + case "unwrappedTypeName": + return unwrappedTypeName + case "isProtocolComposition": + return isProtocolComposition + case "isVoid": + return isVoid + case "isClosure": + return isClosure + default: + fatalError("unable to lookup: \\(member) in \\(self)") + } + } + /// :nodoc: + public init(name: String, + actualTypeName: TypeName? = nil, + unwrappedTypeName: String? = nil, + attributes: AttributeList = [:], + isOptional: Bool = false, + isImplicitlyUnwrappedOptional: Bool = false, + tuple: TupleType? = nil, + array: ArrayType? = nil, + dictionary: DictionaryType? = nil, + closure: ClosureType? = nil, + generic: GenericType? = nil, + isProtocolComposition: Bool = false) { + + let optionalSuffix: String + // TODO: TBR + if !name.hasPrefix("Optional<") && !name.contains(" where ") { + if isOptional { + optionalSuffix = "?" + } else if isImplicitlyUnwrappedOptional { + optionalSuffix = "!" + } else { + optionalSuffix = "" + } + } else { + optionalSuffix = "" + } + + self.name = name + optionalSuffix + self.actualTypeName = actualTypeName + self.unwrappedTypeName = unwrappedTypeName ?? name + self.tuple = tuple + self.array = array + self.dictionary = dictionary + self.closure = closure + self.generic = generic + self.isOptional = isOptional || isImplicitlyUnwrappedOptional + self.isImplicitlyUnwrappedOptional = isImplicitlyUnwrappedOptional + self.isProtocolComposition = isProtocolComposition + + self.attributes = attributes + self.modifiers = [] + super.init() + } + + /// Type name used in declaration + public var name: String + + /// The generics of this TypeName + public var generic: GenericType? + + /// Whether this TypeName is generic + public var isGeneric: Bool { + actualTypeName?.generic != nil || generic != nil + } + + /// Whether this TypeName is protocol composition + public var isProtocolComposition: Bool + + // sourcery: skipEquality + /// Actual type name if given type name is a typealias + public var actualTypeName: TypeName? + + /// Type name attributes, i.e. `@escaping` + public var attributes: AttributeList + + /// Modifiers, i.e. `escaping` + public var modifiers: [SourceryModifier] + + // sourcery: skipEquality + /// Whether type is optional + public let isOptional: Bool + + // sourcery: skipEquality + /// Whether type is implicitly unwrapped optional + public let isImplicitlyUnwrappedOptional: Bool + + // sourcery: skipEquality + /// Type name without attributes and optional type information + public var unwrappedTypeName: String + + // sourcery: skipEquality + /// Whether type is void (`Void` or `()`) + public var isVoid: Bool { + return name == "Void" || name == "()" || unwrappedTypeName == "Void" + } + + /// Whether type is a tuple + public var isTuple: Bool { + actualTypeName?.tuple != nil || tuple != nil + } + + /// Tuple type data + public var tuple: TupleType? + + /// Whether type is an array + public var isArray: Bool { + actualTypeName?.array != nil || array != nil + } + + /// Array type data + public var array: ArrayType? + + /// Whether type is a dictionary + public var isDictionary: Bool { + actualTypeName?.dictionary != nil || dictionary != nil + } + + /// Dictionary type data + public var dictionary: DictionaryType? + + /// Whether type is a closure + public var isClosure: Bool { + actualTypeName?.closure != nil || closure != nil + } + + /// Closure type data + public var closure: ClosureType? + + /// Prints typename as it would appear on definition + public var asSource: String { + // TODO: TBR special treatment + let specialTreatment = isOptional && name.hasPrefix("Optional<") + + var description = ( + attributes.flatMap({ $0.value }).map({ $0.asSource }).sorted() + + modifiers.map({ $0.asSource }) + + [specialTreatment ? name : unwrappedTypeName] + ).joined(separator: " ") + + if let _ = self.dictionary { // array and dictionary cases are covered by the unwrapped type name +// description.append(dictionary.asSource) + } else if let _ = self.array { +// description.append(array.asSource) + } else if let _ = self.generic { +// let arguments = generic.typeParameters +// .map({ $0.typeName.asSource }) +// .joined(separator: ", ") +// description.append("<\\(arguments)>") + } + if !specialTreatment { + if isImplicitlyUnwrappedOptional { + description.append("!") + } else if isOptional { + description.append("?") + } + } + + return description + } + + public override var description: String { + ( + attributes.flatMap({ $0.value }).map({ $0.asSource }).sorted() + + modifiers.map({ $0.asSource }) + + [name] + ).joined(separator: " ") + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? TypeName else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "generic").trackDifference(actual: self.generic, expected: castObject.generic)) + results.append(contentsOf: DiffableResult(identifier: "isProtocolComposition").trackDifference(actual: self.isProtocolComposition, expected: castObject.isProtocolComposition)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "tuple").trackDifference(actual: self.tuple, expected: castObject.tuple)) + results.append(contentsOf: DiffableResult(identifier: "array").trackDifference(actual: self.array, expected: castObject.array)) + results.append(contentsOf: DiffableResult(identifier: "dictionary").trackDifference(actual: self.dictionary, expected: castObject.dictionary)) + results.append(contentsOf: DiffableResult(identifier: "closure").trackDifference(actual: self.closure, expected: castObject.closure)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.generic) + hasher.combine(self.isProtocolComposition) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.tuple) + hasher.combine(self.array) + hasher.combine(self.dictionary) + hasher.combine(self.closure) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? TypeName else { return false } + if self.name != rhs.name { return false } + if self.generic != rhs.generic { return false } + if self.isProtocolComposition != rhs.isProtocolComposition { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.tuple != rhs.tuple { return false } + if self.array != rhs.array { return false } + if self.dictionary != rhs.dictionary { return false } + if self.closure != rhs.closure { return false } + return true + } + +// sourcery:inline:TypeName.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + self.generic = aDecoder.decode(forKey: "generic") + self.isProtocolComposition = aDecoder.decode(forKey: "isProtocolComposition") + self.actualTypeName = aDecoder.decode(forKey: "actualTypeName") + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers + self.isOptional = aDecoder.decode(forKey: "isOptional") + self.isImplicitlyUnwrappedOptional = aDecoder.decode(forKey: "isImplicitlyUnwrappedOptional") + guard let unwrappedTypeName: String = aDecoder.decode(forKey: "unwrappedTypeName") else { + withVaList(["unwrappedTypeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.unwrappedTypeName = unwrappedTypeName + self.tuple = aDecoder.decode(forKey: "tuple") + self.array = aDecoder.decode(forKey: "array") + self.dictionary = aDecoder.decode(forKey: "dictionary") + self.closure = aDecoder.decode(forKey: "closure") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.generic, forKey: "generic") + aCoder.encode(self.isProtocolComposition, forKey: "isProtocolComposition") + aCoder.encode(self.actualTypeName, forKey: "actualTypeName") + aCoder.encode(self.attributes, forKey: "attributes") + aCoder.encode(self.modifiers, forKey: "modifiers") + aCoder.encode(self.isOptional, forKey: "isOptional") + aCoder.encode(self.isImplicitlyUnwrappedOptional, forKey: "isImplicitlyUnwrappedOptional") + aCoder.encode(self.unwrappedTypeName, forKey: "unwrappedTypeName") + aCoder.encode(self.tuple, forKey: "tuple") + aCoder.encode(self.array, forKey: "array") + aCoder.encode(self.dictionary, forKey: "dictionary") + aCoder.encode(self.closure, forKey: "closure") + } +// sourcery:end + + // sourcery: skipEquality, skipDescription + /// :nodoc: + public override var debugDescription: String { + return name + } + + public convenience init(_ description: String) { + self.init(name: description, actualTypeName: nil) + } +} + +extension TypeName { + public static func unknown(description: String?, attributes: AttributeList = [:]) -> TypeName { + if let description = description { + Log.astWarning("Unknown type, please add type attribution to \\(description)") + } else { + Log.astWarning("Unknown type, please add type attribution") + } + return TypeName(name: "UnknownTypeSoAddTypeAttributionToVariable", attributes: attributes) + } +} + +"""), + .init(name: "Typealias.swift", content: +""" +import Foundation + +// sourcery: skipJSExport +/// :nodoc: +public final class Typealias: NSObject, Typed, SourceryModel, Diffable { + // New typealias name + public let aliasName: String + + // Target name + public let typeName: TypeName + + // sourcery: skipEquality, skipDescription + public var type: Type? + + /// module in which this typealias was declared + public var module: String? + + // sourcery: skipEquality, skipDescription + public var parent: Type? { + didSet { + parentName = parent?.name + } + } + + /// Type access level, i.e. `internal`, `private`, `fileprivate`, `public`, `open` + public let accessLevel: String + + var parentName: String? + + public var name: String { + if let parentName = parent?.name { + return "\\(module != nil ? "\\(module!)." : "")\\(parentName).\\(aliasName)" + } else { + return "\\(module != nil ? "\\(module!)." : "")\\(aliasName)" + } + } + + public init(aliasName: String = "", typeName: TypeName, accessLevel: AccessLevel = .internal, parent: Type? = nil, module: String? = nil) { + self.aliasName = aliasName + self.typeName = typeName + self.accessLevel = accessLevel.rawValue + self.parent = parent + self.parentName = parent?.name + self.module = module + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "aliasName = \\(String(describing: self.aliasName)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "module = \\(String(describing: self.module)), " + string += "accessLevel = \\(String(describing: self.accessLevel)), " + string += "parentName = \\(String(describing: self.parentName)), " + string += "name = \\(String(describing: self.name))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Typealias else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "aliasName").trackDifference(actual: self.aliasName, expected: castObject.aliasName)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "module").trackDifference(actual: self.module, expected: castObject.module)) + results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel)) + results.append(contentsOf: DiffableResult(identifier: "parentName").trackDifference(actual: self.parentName, expected: castObject.parentName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.aliasName) + hasher.combine(self.typeName) + hasher.combine(self.module) + hasher.combine(self.accessLevel) + hasher.combine(self.parentName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Typealias else { return false } + if self.aliasName != rhs.aliasName { return false } + if self.typeName != rhs.typeName { return false } + if self.module != rhs.module { return false } + if self.accessLevel != rhs.accessLevel { return false } + if self.parentName != rhs.parentName { return false } + return true + } + +// sourcery:inline:Typealias.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let aliasName: String = aDecoder.decode(forKey: "aliasName") else { + withVaList(["aliasName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.aliasName = aliasName + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.type = aDecoder.decode(forKey: "type") + self.module = aDecoder.decode(forKey: "module") + self.parent = aDecoder.decode(forKey: "parent") + guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else { + withVaList(["accessLevel"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.accessLevel = accessLevel + self.parentName = aDecoder.decode(forKey: "parentName") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.aliasName, forKey: "aliasName") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.module, forKey: "module") + aCoder.encode(self.parent, forKey: "parent") + aCoder.encode(self.accessLevel, forKey: "accessLevel") + aCoder.encode(self.parentName, forKey: "parentName") + } +// sourcery:end +} + +"""), + .init(name: "Typed.generated.swift", content: +""" +// Generated using Sourcery 2.0.3 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +// swiftlint:disable vertical_whitespace + + +extension AssociatedValue { + /// Whether type is optional. Shorthand for `typeName.isOptional` + public var isOptional: Bool { return typeName.isOptional } + /// Whether type is implicitly unwrapped optional. Shorthand for `typeName.isImplicitlyUnwrappedOptional` + public var isImplicitlyUnwrappedOptional: Bool { return typeName.isImplicitlyUnwrappedOptional } + /// Type name without attributes and optional type information. Shorthand for `typeName.unwrappedTypeName` + public var unwrappedTypeName: String { return typeName.unwrappedTypeName } + /// Actual type name if declaration uses typealias, otherwise just a `typeName`. Shorthand for `typeName.actualTypeName` + public var actualTypeName: TypeName? { return typeName.actualTypeName ?? typeName } + /// Whether type is a tuple. Shorthand for `typeName.isTuple` + public var isTuple: Bool { return typeName.isTuple } + /// Whether type is a closure. Shorthand for `typeName.isClosure` + public var isClosure: Bool { return typeName.isClosure } + /// Whether type is an array. Shorthand for `typeName.isArray` + public var isArray: Bool { return typeName.isArray } + /// Whether type is a dictionary. Shorthand for `typeName.isDictionary` + public var isDictionary: Bool { return typeName.isDictionary } +} +extension ClosureParameter { + /// Whether type is optional. Shorthand for `typeName.isOptional` + public var isOptional: Bool { return typeName.isOptional } + /// Whether type is implicitly unwrapped optional. Shorthand for `typeName.isImplicitlyUnwrappedOptional` + public var isImplicitlyUnwrappedOptional: Bool { return typeName.isImplicitlyUnwrappedOptional } + /// Type name without attributes and optional type information. Shorthand for `typeName.unwrappedTypeName` + public var unwrappedTypeName: String { return typeName.unwrappedTypeName } + /// Actual type name if declaration uses typealias, otherwise just a `typeName`. Shorthand for `typeName.actualTypeName` + public var actualTypeName: TypeName? { return typeName.actualTypeName ?? typeName } + /// Whether type is a tuple. Shorthand for `typeName.isTuple` + public var isTuple: Bool { return typeName.isTuple } + /// Whether type is a closure. Shorthand for `typeName.isClosure` + public var isClosure: Bool { return typeName.isClosure } + /// Whether type is an array. Shorthand for `typeName.isArray` + public var isArray: Bool { return typeName.isArray } + /// Whether type is a dictionary. Shorthand for `typeName.isDictionary` + public var isDictionary: Bool { return typeName.isDictionary } +} +extension MethodParameter { + /// Whether type is optional. Shorthand for `typeName.isOptional` + public var isOptional: Bool { return typeName.isOptional } + /// Whether type is implicitly unwrapped optional. Shorthand for `typeName.isImplicitlyUnwrappedOptional` + public var isImplicitlyUnwrappedOptional: Bool { return typeName.isImplicitlyUnwrappedOptional } + /// Type name without attributes and optional type information. Shorthand for `typeName.unwrappedTypeName` + public var unwrappedTypeName: String { return typeName.unwrappedTypeName } + /// Actual type name if declaration uses typealias, otherwise just a `typeName`. Shorthand for `typeName.actualTypeName` + public var actualTypeName: TypeName? { return typeName.actualTypeName ?? typeName } + /// Whether type is a tuple. Shorthand for `typeName.isTuple` + public var isTuple: Bool { return typeName.isTuple } + /// Whether type is a closure. Shorthand for `typeName.isClosure` + public var isClosure: Bool { return typeName.isClosure } + /// Whether type is an array. Shorthand for `typeName.isArray` + public var isArray: Bool { return typeName.isArray } + /// Whether type is a dictionary. Shorthand for `typeName.isDictionary` + public var isDictionary: Bool { return typeName.isDictionary } +} +extension TupleElement { + /// Whether type is optional. Shorthand for `typeName.isOptional` + public var isOptional: Bool { return typeName.isOptional } + /// Whether type is implicitly unwrapped optional. Shorthand for `typeName.isImplicitlyUnwrappedOptional` + public var isImplicitlyUnwrappedOptional: Bool { return typeName.isImplicitlyUnwrappedOptional } + /// Type name without attributes and optional type information. Shorthand for `typeName.unwrappedTypeName` + public var unwrappedTypeName: String { return typeName.unwrappedTypeName } + /// Actual type name if declaration uses typealias, otherwise just a `typeName`. Shorthand for `typeName.actualTypeName` + public var actualTypeName: TypeName? { return typeName.actualTypeName ?? typeName } + /// Whether type is a tuple. Shorthand for `typeName.isTuple` + public var isTuple: Bool { return typeName.isTuple } + /// Whether type is a closure. Shorthand for `typeName.isClosure` + public var isClosure: Bool { return typeName.isClosure } + /// Whether type is an array. Shorthand for `typeName.isArray` + public var isArray: Bool { return typeName.isArray } + /// Whether type is a dictionary. Shorthand for `typeName.isDictionary` + public var isDictionary: Bool { return typeName.isDictionary } +} +extension Typealias { + /// Whether type is optional. Shorthand for `typeName.isOptional` + public var isOptional: Bool { return typeName.isOptional } + /// Whether type is implicitly unwrapped optional. Shorthand for `typeName.isImplicitlyUnwrappedOptional` + public var isImplicitlyUnwrappedOptional: Bool { return typeName.isImplicitlyUnwrappedOptional } + /// Type name without attributes and optional type information. Shorthand for `typeName.unwrappedTypeName` + public var unwrappedTypeName: String { return typeName.unwrappedTypeName } + /// Actual type name if declaration uses typealias, otherwise just a `typeName`. Shorthand for `typeName.actualTypeName` + public var actualTypeName: TypeName? { return typeName.actualTypeName ?? typeName } + /// Whether type is a tuple. Shorthand for `typeName.isTuple` + public var isTuple: Bool { return typeName.isTuple } + /// Whether type is a closure. Shorthand for `typeName.isClosure` + public var isClosure: Bool { return typeName.isClosure } + /// Whether type is an array. Shorthand for `typeName.isArray` + public var isArray: Bool { return typeName.isArray } + /// Whether type is a dictionary. Shorthand for `typeName.isDictionary` + public var isDictionary: Bool { return typeName.isDictionary } +} +extension Variable { + /// Whether type is optional. Shorthand for `typeName.isOptional` + public var isOptional: Bool { return typeName.isOptional } + /// Whether type is implicitly unwrapped optional. Shorthand for `typeName.isImplicitlyUnwrappedOptional` + public var isImplicitlyUnwrappedOptional: Bool { return typeName.isImplicitlyUnwrappedOptional } + /// Type name without attributes and optional type information. Shorthand for `typeName.unwrappedTypeName` + public var unwrappedTypeName: String { return typeName.unwrappedTypeName } + /// Actual type name if declaration uses typealias, otherwise just a `typeName`. Shorthand for `typeName.actualTypeName` + public var actualTypeName: TypeName? { return typeName.actualTypeName ?? typeName } + /// Whether type is a tuple. Shorthand for `typeName.isTuple` + public var isTuple: Bool { return typeName.isTuple } + /// Whether type is a closure. Shorthand for `typeName.isClosure` + public var isClosure: Bool { return typeName.isClosure } + /// Whether type is an array. Shorthand for `typeName.isArray` + public var isArray: Bool { return typeName.isArray } + /// Whether type is a dictionary. Shorthand for `typeName.isDictionary` + public var isDictionary: Bool { return typeName.isDictionary } +} + +"""), + .init(name: "Typed.swift", content: +""" +import Foundation + +/// Descibes typed declaration, i.e. variable, method parameter, tuple element, enum case associated value +public protocol Typed { + + // sourcery: skipEquality, skipDescription + /// Type, if known + var type: Type? { get } + + // sourcery: skipEquality, skipDescription + /// Type name + var typeName: TypeName { get } + + // sourcery: skipEquality, skipDescription + /// Whether type is optional + var isOptional: Bool { get } + + // sourcery: skipEquality, skipDescription + /// Whether type is implicitly unwrapped optional + var isImplicitlyUnwrappedOptional: Bool { get } + + // sourcery: skipEquality, skipDescription + /// Type name without attributes and optional type information + var unwrappedTypeName: String { get } +} + +"""), + .init(name: "Variable.swift", content: +""" +// +// Created by Krzysztof Zablocki on 13/09/2016. +// Copyright (c) 2016 Pixle. All rights reserved. +// + +import Foundation + +/// :nodoc: +public typealias SourceryVariable = Variable + +/// Defines variable +public final class Variable: NSObject, SourceryModel, Typed, Annotated, Documented, Definition, Diffable, DynamicMemberLookup { + public subscript(dynamicMember member: String) -> Any? { + switch member { + case "readAccess": + return readAccess + case "annotations": + return annotations + case "isOptional": + return isOptional + case "name": + return name + case "typeName": + return typeName + case "type": + return type + case "definedInType": + return definedInType + case "isStatic": + return isStatic + case "isAsync": + return isAsync + case "throws": + return `throws` + case "isArray": + return isArray + case "isDictionary": + return isDictionary + default: + fatalError("unable to lookup: \\(member) in \\(self)") + } + } + + /// Variable name + public let name: String + + /// Variable type name + public let typeName: TypeName + + // sourcery: skipEquality, skipDescription + /// Variable type, if known, i.e. if the type is declared in the scanned sources. + /// For explanation, see + public var type: Type? + + /// Whether variable is computed and not stored + public let isComputed: Bool + + /// Whether variable is async + public let isAsync: Bool + + /// Whether variable throws + public let `throws`: Bool + + /// Whether variable is static + public let isStatic: Bool + + /// Variable read access level, i.e. `internal`, `private`, `fileprivate`, `public`, `open` + public let readAccess: String + + /// Variable write access, i.e. `internal`, `private`, `fileprivate`, `public`, `open`. + /// For immutable variables this value is empty string + public let writeAccess: String + + /// composed access level + /// sourcery: skipJSExport + public var accessLevel: (read: AccessLevel, write: AccessLevel) { + (read: AccessLevel(rawValue: readAccess) ?? .none, AccessLevel(rawValue: writeAccess) ?? .none) + } + + /// Whether variable is mutable or not + public var isMutable: Bool { + return writeAccess != AccessLevel.none.rawValue + } + + /// Variable default value expression + public var defaultValue: String? + + /// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2 + public var annotations: Annotations = [:] + + public var documentation: Documentation = [] + + /// Variable attributes, i.e. `@IBOutlet`, `@IBInspectable` + public var attributes: AttributeList + + /// Modifiers, i.e. `private` + public var modifiers: [SourceryModifier] + + /// Whether variable is final or not + public var isFinal: Bool { + return modifiers.contains { $0.name == "final" } + } + + /// Whether variable is lazy or not + public var isLazy: Bool { + return modifiers.contains { $0.name == "lazy" } + } + + /// Reference to type name where the variable is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc + public internal(set) var definedInTypeName: TypeName? + + /// Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a `definedInTypeName` + public var actualDefinedInTypeName: TypeName? { + return definedInTypeName?.actualTypeName ?? definedInTypeName + } + + // sourcery: skipEquality, skipDescription + /// Reference to actual type where the object is defined, + /// nil if defined outside of any `enum`, `struct`, `class` etc or type is unknown + public var definedInType: Type? + + /// :nodoc: + public init(name: String = "", + typeName: TypeName, + type: Type? = nil, + accessLevel: (read: AccessLevel, write: AccessLevel) = (.internal, .internal), + isComputed: Bool = false, + isAsync: Bool = false, + `throws`: Bool = false, + isStatic: Bool = false, + defaultValue: String? = nil, + attributes: AttributeList = [:], + modifiers: [SourceryModifier] = [], + annotations: [String: NSObject] = [:], + documentation: [String] = [], + definedInTypeName: TypeName? = nil) { + + self.name = name + self.typeName = typeName + self.type = type + self.isComputed = isComputed + self.isAsync = isAsync + self.`throws` = `throws` + self.isStatic = isStatic + self.defaultValue = defaultValue + self.readAccess = accessLevel.read.rawValue + self.writeAccess = accessLevel.write.rawValue + self.attributes = attributes + self.modifiers = modifiers + self.annotations = annotations + self.documentation = documentation + self.definedInTypeName = definedInTypeName + } + + /// :nodoc: + override public var description: String { + var string = "\\(Swift.type(of: self)): " + string += "name = \\(String(describing: self.name)), " + string += "typeName = \\(String(describing: self.typeName)), " + string += "isComputed = \\(String(describing: self.isComputed)), " + string += "isAsync = \\(String(describing: self.isAsync)), " + string += "`throws` = \\(String(describing: self.`throws`)), " + string += "isStatic = \\(String(describing: self.isStatic)), " + string += "readAccess = \\(String(describing: self.readAccess)), " + string += "writeAccess = \\(String(describing: self.writeAccess)), " + string += "accessLevel = \\(String(describing: self.accessLevel)), " + string += "isMutable = \\(String(describing: self.isMutable)), " + string += "defaultValue = \\(String(describing: self.defaultValue)), " + string += "annotations = \\(String(describing: self.annotations)), " + string += "documentation = \\(String(describing: self.documentation)), " + string += "attributes = \\(String(describing: self.attributes)), " + string += "modifiers = \\(String(describing: self.modifiers)), " + string += "isFinal = \\(String(describing: self.isFinal)), " + string += "isLazy = \\(String(describing: self.isLazy)), " + string += "definedInTypeName = \\(String(describing: self.definedInTypeName)), " + string += "actualDefinedInTypeName = \\(String(describing: self.actualDefinedInTypeName))" + return string + } + + public func diffAgainst(_ object: Any?) -> DiffableResult { + let results = DiffableResult() + guard let castObject = object as? Variable else { + results.append("Incorrect type ") + return results + } + results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name)) + results.append(contentsOf: DiffableResult(identifier: "typeName").trackDifference(actual: self.typeName, expected: castObject.typeName)) + results.append(contentsOf: DiffableResult(identifier: "isComputed").trackDifference(actual: self.isComputed, expected: castObject.isComputed)) + results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync)) + results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`)) + results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic)) + results.append(contentsOf: DiffableResult(identifier: "readAccess").trackDifference(actual: self.readAccess, expected: castObject.readAccess)) + results.append(contentsOf: DiffableResult(identifier: "writeAccess").trackDifference(actual: self.writeAccess, expected: castObject.writeAccess)) + results.append(contentsOf: DiffableResult(identifier: "defaultValue").trackDifference(actual: self.defaultValue, expected: castObject.defaultValue)) + results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations)) + results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation)) + results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes)) + results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers)) + results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName)) + return results + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.name) + hasher.combine(self.typeName) + hasher.combine(self.isComputed) + hasher.combine(self.isAsync) + hasher.combine(self.`throws`) + hasher.combine(self.isStatic) + hasher.combine(self.readAccess) + hasher.combine(self.writeAccess) + hasher.combine(self.defaultValue) + hasher.combine(self.annotations) + hasher.combine(self.documentation) + hasher.combine(self.attributes) + hasher.combine(self.modifiers) + hasher.combine(self.definedInTypeName) + return hasher.finalize() + } + + /// :nodoc: + public override func isEqual(_ object: Any?) -> Bool { + guard let rhs = object as? Variable else { return false } + if self.name != rhs.name { return false } + if self.typeName != rhs.typeName { return false } + if self.isComputed != rhs.isComputed { return false } + if self.isAsync != rhs.isAsync { return false } + if self.`throws` != rhs.`throws` { return false } + if self.isStatic != rhs.isStatic { return false } + if self.readAccess != rhs.readAccess { return false } + if self.writeAccess != rhs.writeAccess { return false } + if self.defaultValue != rhs.defaultValue { return false } + if self.annotations != rhs.annotations { return false } + if self.documentation != rhs.documentation { return false } + if self.attributes != rhs.attributes { return false } + if self.modifiers != rhs.modifiers { return false } + if self.definedInTypeName != rhs.definedInTypeName { return false } + return true + } + +// sourcery:inline:Variable.AutoCoding + + /// :nodoc: + required public init?(coder aDecoder: NSCoder) { + guard let name: String = aDecoder.decode(forKey: "name") else { + withVaList(["name"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.name = name + guard let typeName: TypeName = aDecoder.decode(forKey: "typeName") else { + withVaList(["typeName"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.typeName = typeName + self.type = aDecoder.decode(forKey: "type") + self.isComputed = aDecoder.decode(forKey: "isComputed") + self.isAsync = aDecoder.decode(forKey: "isAsync") + self.`throws` = aDecoder.decode(forKey: "`throws`") + self.isStatic = aDecoder.decode(forKey: "isStatic") + guard let readAccess: String = aDecoder.decode(forKey: "readAccess") else { + withVaList(["readAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.readAccess = readAccess + guard let writeAccess: String = aDecoder.decode(forKey: "writeAccess") else { + withVaList(["writeAccess"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.writeAccess = writeAccess + self.defaultValue = aDecoder.decode(forKey: "defaultValue") + guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else { + withVaList(["annotations"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.annotations = annotations + guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else { + withVaList(["documentation"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.documentation = documentation + guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else { + withVaList(["attributes"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.attributes = attributes + guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else { + withVaList(["modifiers"]) { arguments in + NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments) + } + fatalError() + }; self.modifiers = modifiers + self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName") + self.definedInType = aDecoder.decode(forKey: "definedInType") + } + + /// :nodoc: + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.name, forKey: "name") + aCoder.encode(self.typeName, forKey: "typeName") + aCoder.encode(self.type, forKey: "type") + aCoder.encode(self.isComputed, forKey: "isComputed") + aCoder.encode(self.isAsync, forKey: "isAsync") + aCoder.encode(self.`throws`, forKey: "`throws`") + aCoder.encode(self.isStatic, forKey: "isStatic") + aCoder.encode(self.readAccess, forKey: "readAccess") + aCoder.encode(self.writeAccess, forKey: "writeAccess") + aCoder.encode(self.defaultValue, forKey: "defaultValue") + aCoder.encode(self.annotations, forKey: "annotations") + aCoder.encode(self.documentation, forKey: "documentation") + aCoder.encode(self.attributes, forKey: "attributes") + aCoder.encode(self.modifiers, forKey: "modifiers") + aCoder.encode(self.definedInTypeName, forKey: "definedInTypeName") + aCoder.encode(self.definedInType, forKey: "definedInType") + } +// sourcery:end +} + +"""), +] +#endif diff --git a/SourcerySwift/Sources/SwiftTemplate.swift b/SourcerySwift/Sources/SwiftTemplate.swift index 4666e0ae2..bcafd0b8d 100644 --- a/SourcerySwift/Sources/SwiftTemplate.swift +++ b/SourcerySwift/Sources/SwiftTemplate.swift @@ -83,7 +83,7 @@ open class SwiftTemplate { import Foundation import SourceryRuntime - let context = ProcessInfo().context! + let context = ProcessInfo.processInfo.context! let types = context.types let functions = context.functions let type = context.types.typesByName @@ -235,7 +235,7 @@ open class SwiftTemplate { try includedFiles.forEach { includedFile in try includedFile.copy(templateFilesDir + Path(includedFile.lastComponent)) } - +#if os(macOS) let arguments = [ "xcrun", "--sdk", "macosx", @@ -245,6 +245,15 @@ open class SwiftTemplate { "-Xswiftc", "-suppress-warnings", "--disable-sandbox" ] +#else + let arguments = [ + "swift", + "build", + "-c", "release", + "-Xswiftc", "-suppress-warnings", + "--disable-sandbox" + ] +#endif let compilationResult = try Process.runCommand(path: "/usr/bin/env", arguments: arguments, currentDirectoryPath: buildDir) diff --git a/SourceryTests/Generating/JavaScriptTemplateSpecs.swift b/SourceryTests/Generating/JavaScriptTemplateSpecs.swift index a2a0be304..74eff999d 100644 --- a/SourceryTests/Generating/JavaScriptTemplateSpecs.swift +++ b/SourceryTests/Generating/JavaScriptTemplateSpecs.swift @@ -1,3 +1,5 @@ +#if !canImport(ObjectiveC) +#else import Foundation import Quick import Nimble @@ -62,7 +64,8 @@ class JavaScriptTemplateTests: QuickSpec { it("rethrows template parsing errors") { expect { - try Generator.generate(nil, types: Types(types: []), functions: [], template: JavaScriptTemplate(templateString: "<% invalid %>")) + expect(EJSTemplate.ejsPath).toNot(beNil()) + try Generator.generate(nil, types: Types(types: []), functions: [], template: JavaScriptTemplate(templateString: "<% invalid %>", ejsPath: EJSTemplate.ejsPath!)) } .to(throwError(closure: { (error) in expect("\(error)").to(equal(": ReferenceError: ejs:1\n >> 1| <% invalid %>\n\nCan\'t find variable: invalid")) @@ -71,7 +74,8 @@ class JavaScriptTemplateTests: QuickSpec { it("rethrows template runtime errors") { expect { - try Generator.generate(nil, types: Types(types: []), functions: [], template: JavaScriptTemplate(templateString: "<%_ for (type of types.implementing.Some) { -%><% } %>")) + expect(EJSTemplate.ejsPath).toNot(beNil()) + try Generator.generate(nil, types: Types(types: []), functions: [], template: JavaScriptTemplate(templateString: "<%_ for (type of types.implementing.Some) { -%><% } %>", ejsPath: EJSTemplate.ejsPath!)) } .to(throwError(closure: { (error) in expect("\(error)").to(equal(": Unknown type Some, should be used with `based`")) @@ -80,7 +84,8 @@ class JavaScriptTemplateTests: QuickSpec { it("throws unknown property exception") { expect { - try Generator.generate(nil, types: Types(types: []), functions: [], template: JavaScriptTemplate(templateString: "<%_ for (type of types.implements.Some) { -%><% } %>")) + expect(EJSTemplate.ejsPath).toNot(beNil()) + try Generator.generate(nil, types: Types(types: []), functions: [], template: JavaScriptTemplate(templateString: "<%_ for (type of types.implements.Some) { -%><% } %>", ejsPath: EJSTemplate.ejsPath!)) } .to(throwError(closure: { (error) in expect("\(error)").to(equal(": TypeError: ejs:1\n >> 1| <%_ for (type of types.implements.Some) { -%><% } %>\n\nUnknown property `implements`")) @@ -99,3 +104,4 @@ class JavaScriptTemplateTests: QuickSpec { } } } +#endif diff --git a/SourceryTests/Generating/StencilTemplateSpec.swift b/SourceryTests/Generating/StencilTemplateSpec.swift index 1dcfcea85..4a8b2eb74 100644 --- a/SourceryTests/Generating/StencilTemplateSpec.swift +++ b/SourceryTests/Generating/StencilTemplateSpec.swift @@ -70,12 +70,21 @@ class StencilTemplateSpec: QuickSpec { } describe("toArray") { + #if canImport(ObjectiveC) context("given array") { it("doesnt modify the value") { let result = generate("{% for key,value in type.MyClass.variables.2.annotations %}{{ value | toArray }}{% endfor %}") expect(result).to(equal("[Hello, beautiful, World]")) } } + #else + context("given array") { + it("doesnt modify the value") { + let result = generate("{% for key,value in type.MyClass.variables.2.annotations %}{{ value | toArray }}{% endfor %}") + expect(result).to(equal("[\"Hello\", \"beautiful\", \"World\"]")) + } + } + #endif context("given something") { it("transforms it into array") { @@ -111,29 +120,52 @@ class StencilTemplateSpec: QuickSpec { } describe("sorted") { + #if canImport(ObjectiveC) context("given array") { it("sorts it") { let result = generate("{% for key,value in type.MyClass.variables.2.annotations %}{{ value | sorted:\"description\" }}{% endfor %}") expect(result).to(equal("[beautiful, Hello, World]")) } } + #else + context("given array") { + it("sorts it") { + let result = generate("{% for key,value in type.MyClass.variables.2.annotations %}{{ value | sorted:\"description\" }}{% endfor %}") + expect(result).to(equal("[\"beautiful\", \"Hello\", \"World\"]")) + } + } + #endif } describe("sortedDescending") { context("given array") { + #if canImport(ObjectiveC) it("sorts it descending") { let result = generate("{% for key,value in type.MyClass.variables.2.annotations %}{{ value | sortedDescending:\"description\" }}{% endfor %}") expect(result).to(equal("[World, Hello, beautiful]")) } + #else + it("sorts it descending") { + let result = generate("{% for key,value in type.MyClass.variables.2.annotations %}{{ value | sortedDescending:\"description\" }}{% endfor %}") + expect(result).to(equal("[\"World\", \"Hello\", \"beautiful\"]")) + } + #endif } } describe("reversed") { context("given array") { + #if canImport(ObjectiveC) it("reverses it") { let result = generate("{% for key,value in type.MyClass.variables.2.annotations %}{{ value | reversed }}{% endfor %}") expect(result).to(equal("[World, beautiful, Hello]")) } + #else + it("reverses it") { + let result = generate("{% for key,value in type.MyClass.variables.2.annotations %}{{ value | reversed }}{% endfor %}") + expect(result).to(equal("[\"World\", \"beautiful\", \"Hello\"]")) + } + #endif } } diff --git a/SourceryTests/Generating/SwiftTemplateSpecs.swift b/SourceryTests/Generating/SwiftTemplateSpecs.swift index f224702a8..b864f3756 100644 --- a/SourceryTests/Generating/SwiftTemplateSpecs.swift +++ b/SourceryTests/Generating/SwiftTemplateSpecs.swift @@ -30,7 +30,7 @@ class SwiftTemplateTests: QuickSpec { let templatePath = Stubs.swiftTemplates + Path("Equality.swifttemplate") let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) - +#if canImport(ObjectiveC) it("creates persistable data") { func templateContextData(_ code: String) -> TemplateContext? { guard let parserResult = try? makeParser(for: code).parse() else { fail(); return nil } @@ -60,6 +60,7 @@ class SwiftTemplateTests: QuickSpec { expect(context.types).to(equal(unarchived?.types)) } +#endif it("generates correct output") { expect { try Sourcery(cacheDisabled: true).processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), usingTemplates: Paths(include: [templatePath]), output: output, baseIndentation: 0) }.toNot(throwError()) @@ -88,11 +89,18 @@ class SwiftTemplateTests: QuickSpec { expect(result).to(equal(expectedResult)) } +// crashing test it("handles file includes") { let templatePath = Stubs.swiftTemplates + Path("IncludeFile.swifttemplate") let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) - expect { try Sourcery(cacheDisabled: true).processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), usingTemplates: Paths(include: [templatePath]), output: output, baseIndentation: 0) }.toNot(throwError()) + expect { try Sourcery(cacheDisabled: true) + .processFiles( + .sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [templatePath]), + output: output, + baseIndentation: 0) }.toNot(throwError() + ) let result = (try? (outputDir + Sourcery().generatedPath(for: templatePath)).read(.utf8)) expect(result).to(equal(expectedResult)) @@ -192,12 +200,13 @@ class SwiftTemplateTests: QuickSpec { } context("with existing cache") { - beforeEach { - expect { try Sourcery(cacheDisabled: false).processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), usingTemplates: Paths(include: [templatePath]), output: output, baseIndentation: 0) }.toNot(throwError()) - expect((try? (outputDir + Sourcery().generatedPath(for: templatePath)).read(.utf8))).to(equal(expectedResult)) - } + // beforeEach { + + // } context("and missing build dir") { + expect { try Sourcery(cacheDisabled: false).processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), usingTemplates: Paths(include: [templatePath]), output: output, baseIndentation: 0) }.toNot(throwError()) + expect((try? (outputDir + Sourcery().generatedPath(for: templatePath)).read(.utf8))).to(equal(expectedResult)) guard let buildDir = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("SwiftTemplate").map({ Path($0.path) }) else { fail("Could not create buildDir path") return @@ -212,6 +221,8 @@ class SwiftTemplateTests: QuickSpec { it("generates the code") { expect { try Sourcery(cacheDisabled: false).processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), usingTemplates: Paths(include: [templatePath]), output: output, baseIndentation: 0) }.toNot(throwError()) + expect((try? (outputDir + Sourcery().generatedPath(for: templatePath)).read(.utf8))).to(equal(expectedResult)) + expect { try Sourcery(cacheDisabled: false).processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), usingTemplates: Paths(include: [templatePath]), output: output, baseIndentation: 0) }.toNot(throwError()) let result = (try? (outputDir + Sourcery().generatedPath(for: templatePath)).read(.utf8)) expect(result).to(equal(expectedResult)) diff --git a/SourceryTests/GeneratorSpec.swift b/SourceryTests/GeneratorSpec.swift index 2d6a233a8..202850aa3 100644 --- a/SourceryTests/GeneratorSpec.swift +++ b/SourceryTests/GeneratorSpec.swift @@ -256,10 +256,15 @@ class GeneratorSpec: QuickSpec { it("can access variable type information") { expect(generate("{% for variable in type.Complex.variables %}{{ variable.type.name }}{% endfor %}")).to(equal("FooBar")) } - + #if canImport(ObjectiveC) it("can render variable isOptional") { expect(generate("{{ type.Complex.variables.first.isOptional }}")).to(equal("0")) } + #else + it("can render variable isOptional") { + expect(generate("{{ type.Complex.variables.first.isOptional }}")).to(equal("false")) + } + #endif it("can render variable definedInType") { expect(generate("{% for type in types.all %}{% for variable in type.variables %}{{ variable.definedInType.name }} {% endfor %}{% endfor %}")).to(equal("Complex Complex Complex Complex Complex Complex Foo Options ")) diff --git a/SourceryTests/Models/EnumSpec.swift b/SourceryTests/Models/EnumSpec.swift index 974baec88..4411786ff 100644 --- a/SourceryTests/Models/EnumSpec.swift +++ b/SourceryTests/Models/EnumSpec.swift @@ -39,11 +39,14 @@ class EnumSpec: QuickSpec { } describe("When testing equality") { + +#if canImport(ObjectiveC) context("given same items") { it("is equal") { expect(sut).to(equal(Enum(name: "Foo", accessLevel: .internal, isExtension: false, inheritedTypes: ["String"], cases: [EnumCase(name: "CaseA"), EnumCase(name: "CaseB")]))) } } +#endif context("given different items") { it("is not equal") { diff --git a/SourceryTests/Models/TypedSpec.generated.swift b/SourceryTests/Models/TypedSpec.generated.swift index 5eecb42ba..f6ae2b658 100644 --- a/SourceryTests/Models/TypedSpec.generated.swift +++ b/SourceryTests/Models/TypedSpec.generated.swift @@ -27,7 +27,7 @@ class TypedSpec: QuickSpec { let variable = result?.types.first?.variables.first return variable?.typeName ?? TypeName(name: "") } - +#if canImport(ObjectiveC) it("can report optional via KVC") { expect(AssociatedValue(typeName: typeName("Int?")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) expect(AssociatedValue(typeName: typeName("Int!")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) @@ -63,6 +63,7 @@ class TypedSpec: QuickSpec { sut.typeName.actualTypeName = typeName("Int") expect(sut.value(forKeyPath: "actualTypeName") as? TypeName).to(equal(typeName("Int"))) } +#endif } describe("ClosureParameter") { func typeName(_ code: String) -> TypeName { @@ -78,6 +79,7 @@ class TypedSpec: QuickSpec { return variable?.typeName ?? TypeName(name: "") } +#if canImport(ObjectiveC) it("can report optional via KVC") { expect(ClosureParameter(typeName: typeName("Int?")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) expect(ClosureParameter(typeName: typeName("Int!")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) @@ -113,6 +115,7 @@ class TypedSpec: QuickSpec { sut.typeName.actualTypeName = typeName("Int") expect(sut.value(forKeyPath: "actualTypeName") as? TypeName).to(equal(typeName("Int"))) } +#endif } describe("MethodParameter") { func typeName(_ code: String) -> TypeName { @@ -127,7 +130,7 @@ class TypedSpec: QuickSpec { let variable = result?.types.first?.variables.first return variable?.typeName ?? TypeName(name: "") } - +#if canImport(ObjectiveC) it("can report optional via KVC") { expect(MethodParameter(typeName: typeName("Int?")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) expect(MethodParameter(typeName: typeName("Int!")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) @@ -163,6 +166,7 @@ class TypedSpec: QuickSpec { sut.typeName.actualTypeName = typeName("Int") expect(sut.value(forKeyPath: "actualTypeName") as? TypeName).to(equal(typeName("Int"))) } +#endif } describe("TupleElement") { func typeName(_ code: String) -> TypeName { @@ -177,7 +181,7 @@ class TypedSpec: QuickSpec { let variable = result?.types.first?.variables.first return variable?.typeName ?? TypeName(name: "") } - +#if canImport(ObjectiveC) it("can report optional via KVC") { expect(TupleElement(typeName: typeName("Int?")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) expect(TupleElement(typeName: typeName("Int!")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) @@ -213,6 +217,7 @@ class TypedSpec: QuickSpec { sut.typeName.actualTypeName = typeName("Int") expect(sut.value(forKeyPath: "actualTypeName") as? TypeName).to(equal(typeName("Int"))) } +#endif } describe("Typealias") { func typeName(_ code: String) -> TypeName { @@ -228,6 +233,7 @@ class TypedSpec: QuickSpec { return variable?.typeName ?? TypeName(name: "") } +#if canImport(ObjectiveC) it("can report optional via KVC") { expect(Typealias(typeName: typeName("Int?")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) expect(Typealias(typeName: typeName("Int!")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) @@ -263,6 +269,7 @@ class TypedSpec: QuickSpec { sut.typeName.actualTypeName = typeName("Int") expect(sut.value(forKeyPath: "actualTypeName") as? TypeName).to(equal(typeName("Int"))) } +#endif } describe("Variable") { func typeName(_ code: String) -> TypeName { @@ -277,7 +284,7 @@ class TypedSpec: QuickSpec { let variable = result?.types.first?.variables.first return variable?.typeName ?? TypeName(name: "") } - +#if canImport(ObjectiveC) it("can report optional via KVC") { expect(Variable(typeName: typeName("Int?")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) expect(Variable(typeName: typeName("Int!")).value(forKeyPath: "isOptional") as? Bool).to(equal(true)) @@ -313,6 +320,7 @@ class TypedSpec: QuickSpec { sut.typeName.actualTypeName = typeName("Int") expect(sut.value(forKeyPath: "actualTypeName") as? TypeName).to(equal(typeName("Int"))) } +#endif } } } diff --git a/SourceryTests/Output/DryOutputSpec.swift b/SourceryTests/Output/DryOutputSpec.swift index b3ac2e935..82a4d940e 100644 --- a/SourceryTests/Output/DryOutputSpec.swift +++ b/SourceryTests/Output/DryOutputSpec.swift @@ -15,6 +15,7 @@ import PathKit class DryOutputSpec: QuickSpec { override func spec() { // MARK: - DryOutput + JavaScriptTemplate +#if canImport(ObjectiveC) describe("DryOutput+JavaScriptTemplate") { let outputDir: Path = { return Stubs.cleanTemporarySourceryDir() @@ -38,23 +39,6 @@ class DryOutputSpec: QuickSpec { expect(outputInterceptor.result).to(beNil()) } - it("generates correct output, if isDryRun equal true") { - let templatePath = Stubs.jsTemplates + Path("Equality.ejs") - let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) - - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: [templatePath]), - output: output, - isDryRun: true, baseIndentation: 0) - }.toNot(throwError()) - - expect(outputInterceptor.result).to(equal(expectedResult)) - } - it("handles includes") { let templatePath = Stubs.jsTemplates + Path("Includes.ejs") let expectedResult = try? (Stubs.resultDirectory + Path("Basic+Other.swift")).read(.utf8) @@ -106,6 +90,7 @@ class DryOutputSpec: QuickSpec { expect(outputInterceptor.result).to(equal(expectedResult)) } } +#endif // MARK: - DryOutput + StencilTemplate describe("DryOutput+StencilTemplate") { @@ -200,10 +185,12 @@ guard lhs.n == rhs.n else { return false } } """)) + let templatePathResult = outputInterceptor .result(byOutputType: .init(id: "\(templatePath)", subType: .template)).value expect(templatePathResult) - .to(equal(""" + .to(equal( +""" // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT @@ -248,7 +235,10 @@ guard lhs.bar == rhs.bar else { return false } // MARK: - AutoEquatable for Enums -""")) +""" + )) + +#if canImport(ObjectiveC) expect(outputInterceptor.result(byOutputType: .init(id: "Generated/EqEnum+TemplateName.generated.swift", subType: .path)).value) .to(equal(""" // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery @@ -266,6 +256,7 @@ internal func == (lhs: EqEnum, rhs: EqEnum) -> Bool { } """)) +#endif } // supports different ways for code generation: end } @@ -279,23 +270,23 @@ internal func == (lhs: EqEnum, rhs: EqEnum) -> Bool { let templatePath = Stubs.swiftTemplates + Path("Equality.swifttemplate") let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) - it("has no stdout json output if isDryRun equal false (*also default value)") { - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) + it("has no stdout json output if isDryRun equal false (*also default value)") { + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: [templatePath]), - output: output, - isDryRun: false, - baseIndentation: 0) - }.toNot(throwError()) + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [templatePath]), + output: output, + isDryRun: false, + baseIndentation: 0) + }.toNot(throwError()) - expect(outputInterceptor.result).to(beNil()) - } + expect(outputInterceptor.result).to(beNil()) + } - it("generates correct output, if isDryRun equal true") { + it("given swifttemplate, generates correct output, if isDryRun equal true") { let sourcery = Sourcery(cacheDisabled: true) let outputInterceptor = OutputInterceptor() sourcery.dryOutput = outputInterceptor.handleOutput(_:) @@ -310,194 +301,212 @@ internal func == (lhs: EqEnum, rhs: EqEnum) -> Bool { expect(outputInterceptor.result).to(equal(expectedResult)) } - it("handles includes") { - let templatePath = Stubs.swiftTemplates + Path("Includes.swifttemplate") - let expectedResult = try? (Stubs.resultDirectory + Path("Basic+Other.swift")).read(.utf8) - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) - - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: [templatePath]), - output: output, - isDryRun: true, baseIndentation: 0) - }.toNot(throwError()) - - expect(outputInterceptor.result).to(equal(expectedResult)) - } - - it("handles file includes") { - let templatePath = Stubs.swiftTemplates + Path("IncludeFile.swifttemplate") - let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) - - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: [templatePath]), - output: output, - isDryRun: true, baseIndentation: 0) - }.toNot(throwError()) - - expect(outputInterceptor.result).to(equal(expectedResult)) - } - - it("handles includes without swifttemplate extension") { - let templatePath = Stubs.swiftTemplates + Path("IncludesNoExtension.swifttemplate") - let expectedResult = try? (Stubs.resultDirectory + Path("Basic+Other.swift")).read(.utf8) - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) - - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: [templatePath]), - output: output, - isDryRun: true, baseIndentation: 0) - }.toNot(throwError()) - - expect(outputInterceptor.result).to(equal(expectedResult)) - } - - it("handles file includes without swift extension") { - let templatePath = Stubs.swiftTemplates + Path("IncludeFileNoExtension.swifttemplate") - let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) - - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: [templatePath]), - output: output, - isDryRun: true, baseIndentation: 0) - }.toNot(throwError()) - - expect(outputInterceptor.result).to(equal(expectedResult)) - } - - it("handles includes from included files relatively") { - let templatePath = Stubs.swiftTemplates + Path("SubfolderIncludes.swifttemplate") - let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) - - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: [templatePath]), - output: output, - isDryRun: true, baseIndentation: 0) - }.toNot(throwError()) - - expect(outputInterceptor.result).to(equal(expectedResult)) - } - - it("handles file includes from included files relatively") { - let templatePath = Stubs.swiftTemplates + Path("SubfolderFileIncludes.swifttemplate") - let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) - - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: [templatePath]), - output: output, - isDryRun: true, baseIndentation: 0) - }.toNot(throwError()) - - expect(outputInterceptor.result).to(equal(expectedResult)) - } - - it("handles free functions") { - let templatePath = Stubs.swiftTemplates + Path("Function.swifttemplate") - let expectedResult = try? (Stubs.resultDirectory + Path("Function.swift")).read(.utf8) - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) - - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: [templatePath]), - output: output, - isDryRun: true, baseIndentation: 0) - }.toNot(throwError()) - - expect(outputInterceptor.result).to(equal(expectedResult)) - } - - // MARK: Multiple files check - it("return all outputs values") { - let templatePaths = ["Includes.swifttemplate", - "IncludeFile.swifttemplate", - "IncludesNoExtension.swifttemplate", - "IncludeFileNoExtension.swifttemplate", - "SubfolderIncludes.swifttemplate", - "SubfolderFileIncludes.swifttemplate", - "Function.swifttemplate"] - .map { Stubs.swiftTemplates + Path($0) } - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) - - let expectedResults = ["Basic+Other.swift", - "Basic.swift", - "Basic+Other.swift", - "Basic.swift", - "Basic.swift", - "Basic.swift", - "Function.swift"] - .compactMap { try? (Stubs.resultDirectory + Path($0)).read(.utf8) } - - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: templatePaths), - output: output, - isDryRun: true, baseIndentation: 0) - }.toNot(throwError()) - - expect(outputInterceptor.outputModel.outputs.count).to(equal(expectedResults.count)) - expect(outputInterceptor.outputModel.outputs.map { $0.value }.sorted()).to(equal(expectedResults.sorted())) - } - - it("has same templates in outputs as in inputs") { - let templatePaths = ["Includes.swifttemplate", - "IncludeFile.swifttemplate", - "IncludesNoExtension.swifttemplate", - "IncludeFileNoExtension.swifttemplate", - "SubfolderIncludes.swifttemplate", - "SubfolderFileIncludes.swifttemplate", - "Function.swifttemplate"] - .map { Stubs.swiftTemplates + Path($0) } - let sourcery = Sourcery(cacheDisabled: true) - let outputInterceptor = OutputInterceptor() - sourcery.dryOutput = outputInterceptor.handleOutput(_:) - - let expectedResults = ["Basic+Other.swift", - "Basic.swift", - "Basic+Other.swift", - "Basic.swift", - "Basic.swift", - "Basic.swift", - "Function.swift"] - .compactMap { try? (Stubs.resultDirectory + Path($0)).read(.utf8) } - - expect { - try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), - usingTemplates: Paths(include: templatePaths), - output: output, - isDryRun: true, baseIndentation: 0) - }.toNot(throwError()) - - expect( - outputInterceptor.outputModel.outputs.compactMap { $0.type.id }.map { Path($0) }.sorted() - ).to( - equal(templatePaths.sorted()) - ) - } +#if canImport(ObjectiveC) + it("given ejs template, generates correct output, if isDryRun equal true") { + let templatePath = Stubs.jsTemplates + Path("Equality.ejs") + let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) + + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [templatePath]), + output: output, + isDryRun: true, baseIndentation: 0) + }.toNot(throwError()) + + expect(outputInterceptor.result).to(equal(expectedResult)) + } +#endif + it("handles includes") { + let templatePath = Stubs.swiftTemplates + Path("Includes.swifttemplate") + let expectedResult = try? (Stubs.resultDirectory + Path("Basic+Other.swift")).read(.utf8) + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) + + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [templatePath]), + output: output, + isDryRun: true, baseIndentation: 0) + }.toNot(throwError()) + + expect(outputInterceptor.result).to(equal(expectedResult)) + } + + it("handles file includes") { + let templatePath = Stubs.swiftTemplates + Path("IncludeFile.swifttemplate") + let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) + + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [templatePath]), + output: output, + isDryRun: true, baseIndentation: 0) + }.toNot(throwError()) + + expect(outputInterceptor.result).to(equal(expectedResult)) + } + + it("handles includes without swifttemplate extension") { + let templatePath = Stubs.swiftTemplates + Path("IncludesNoExtension.swifttemplate") + let expectedResult = try? (Stubs.resultDirectory + Path("Basic+Other.swift")).read(.utf8) + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) + + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [templatePath]), + output: output, + isDryRun: true, baseIndentation: 0) + }.toNot(throwError()) + + expect(outputInterceptor.result).to(equal(expectedResult)) + } + + it("handles file includes without swift extension") { + let templatePath = Stubs.swiftTemplates + Path("IncludeFileNoExtension.swifttemplate") + let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) + + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [templatePath]), + output: output, + isDryRun: true, baseIndentation: 0) + }.toNot(throwError()) + + expect(outputInterceptor.result).to(equal(expectedResult)) + } + + it("handles includes from included files relatively") { + let templatePath = Stubs.swiftTemplates + Path("SubfolderIncludes.swifttemplate") + let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) + + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [templatePath]), + output: output, + isDryRun: true, baseIndentation: 0) + }.toNot(throwError()) + + expect(outputInterceptor.result).to(equal(expectedResult)) + } + + it("handles file includes from included files relatively") { + let templatePath = Stubs.swiftTemplates + Path("SubfolderFileIncludes.swifttemplate") + let expectedResult = try? (Stubs.resultDirectory + Path("Basic.swift")).read(.utf8) + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) + + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [templatePath]), + output: output, + isDryRun: true, baseIndentation: 0) + }.toNot(throwError()) + + expect(outputInterceptor.result).to(equal(expectedResult)) + } + + it("handles free functions") { + let templatePath = Stubs.swiftTemplates + Path("Function.swifttemplate") + let expectedResult = try? (Stubs.resultDirectory + Path("Function.swift")).read(.utf8) + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) + + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [templatePath]), + output: output, + isDryRun: true, baseIndentation: 0) + }.toNot(throwError()) + + expect(outputInterceptor.result).to(equal(expectedResult)) + } + + // MARK: Multiple files check + it("return all outputs values") { + let templatePaths = ["Includes.swifttemplate", + "IncludeFile.swifttemplate", + "IncludesNoExtension.swifttemplate", + "IncludeFileNoExtension.swifttemplate", + "SubfolderIncludes.swifttemplate", + "SubfolderFileIncludes.swifttemplate", + "Function.swifttemplate"] + .map { Stubs.swiftTemplates + Path($0) } + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) + + let expectedResults = ["Basic+Other.swift", + "Basic.swift", + "Basic+Other.swift", + "Basic.swift", + "Basic.swift", + "Basic.swift", + "Function.swift"] + .compactMap { try? (Stubs.resultDirectory + Path($0)).read(.utf8) } + + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: templatePaths), + output: output, + isDryRun: true, baseIndentation: 0) + }.toNot(throwError()) + + expect(outputInterceptor.outputModel.outputs.count).to(equal(expectedResults.count)) + expect(outputInterceptor.outputModel.outputs.map { $0.value }.sorted()).to(equal(expectedResults.sorted())) + } + + it("has same templates in outputs as in inputs") { + let templatePaths = ["Includes.swifttemplate", + "IncludeFile.swifttemplate", + "IncludesNoExtension.swifttemplate", + "IncludeFileNoExtension.swifttemplate", + "SubfolderIncludes.swifttemplate", + "SubfolderFileIncludes.swifttemplate", + "Function.swifttemplate"] + .map { Stubs.swiftTemplates + Path($0) } + let sourcery = Sourcery(cacheDisabled: true) + let outputInterceptor = OutputInterceptor() + sourcery.dryOutput = outputInterceptor.handleOutput(_:) + + let expectedResults = ["Basic+Other.swift", + "Basic.swift", + "Basic+Other.swift", + "Basic.swift", + "Basic.swift", + "Basic.swift", + "Function.swift"] + .compactMap { try? (Stubs.resultDirectory + Path($0)).read(.utf8) } + + expect { + try sourcery.processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: templatePaths), + output: output, + isDryRun: true, baseIndentation: 0) + }.toNot(throwError()) + + expect( + outputInterceptor.outputModel.outputs.compactMap { $0.type.id }.map { Path($0) }.sorted() + ).to( + equal(templatePaths.sorted()) + ) + } } } } diff --git a/SourceryTests/Parsing/ComposerSpec.swift b/SourceryTests/Parsing/ComposerSpec.swift index 346f17c20..a6c52e473 100644 --- a/SourceryTests/Parsing/ComposerSpec.swift +++ b/SourceryTests/Parsing/ComposerSpec.swift @@ -14,6 +14,7 @@ import PathKit #endif @testable import SourceryFramework @testable import SourceryRuntime +import XCTest // swiftlint:disable type_body_length file_length class ParserComposerSpec: QuickSpec { diff --git a/SourceryTests/Parsing/FileParser + AssociatedTypeSpec.swift b/SourceryTests/Parsing/FileParser_AssociatedTypeSpec.swift similarity index 99% rename from SourceryTests/Parsing/FileParser + AssociatedTypeSpec.swift rename to SourceryTests/Parsing/FileParser_AssociatedTypeSpec.swift index d9acbed6c..2cf50bf31 100644 --- a/SourceryTests/Parsing/FileParser + AssociatedTypeSpec.swift +++ b/SourceryTests/Parsing/FileParser_AssociatedTypeSpec.swift @@ -12,6 +12,7 @@ import PathKit final class FileParserAssociatedTypeSpec: QuickSpec { override func spec() { describe("Parser") { +#if canImport(ObjectiveC) describe("parse associated type") { func associatedType(_ code: String, protocolName: String? = nil) -> [AssociatedType] { guard let parserResult = try? makeParser(for: code).parse() else { fail(); return [] } @@ -98,6 +99,7 @@ final class FileParserAssociatedTypeSpec: QuickSpec { } } } +#endif } } } diff --git a/SourceryTests/Parsing/FileParser + AttributesModifierSpec.swift b/SourceryTests/Parsing/FileParser_AttributesModifierSpec.swift similarity index 100% rename from SourceryTests/Parsing/FileParser + AttributesModifierSpec.swift rename to SourceryTests/Parsing/FileParser_AttributesModifierSpec.swift diff --git a/SourceryTests/Parsing/FileParser + MethodsSpec.swift b/SourceryTests/Parsing/FileParser_MethodsSpec.swift similarity index 100% rename from SourceryTests/Parsing/FileParser + MethodsSpec.swift rename to SourceryTests/Parsing/FileParser_MethodsSpec.swift diff --git a/SourceryTests/Parsing/FileParser + ProtocolComposition.swift b/SourceryTests/Parsing/FileParser_ProtocolComposition.swift similarity index 100% rename from SourceryTests/Parsing/FileParser + ProtocolComposition.swift rename to SourceryTests/Parsing/FileParser_ProtocolComposition.swift diff --git a/SourceryTests/Parsing/FileParser + SubscriptsSpec.swift b/SourceryTests/Parsing/FileParser_SubscriptsSpec.swift similarity index 100% rename from SourceryTests/Parsing/FileParser + SubscriptsSpec.swift rename to SourceryTests/Parsing/FileParser_SubscriptsSpec.swift diff --git a/SourceryTests/Parsing/FileParser + TypeNameSpec.swift b/SourceryTests/Parsing/FileParser_TypeNameSpec.swift similarity index 100% rename from SourceryTests/Parsing/FileParser + TypeNameSpec.swift rename to SourceryTests/Parsing/FileParser_TypeNameSpec.swift diff --git a/SourceryTests/Parsing/FileParser + VariableSpec.swift b/SourceryTests/Parsing/FileParser_VariableSpec.swift similarity index 100% rename from SourceryTests/Parsing/FileParser + VariableSpec.swift rename to SourceryTests/Parsing/FileParser_VariableSpec.swift diff --git a/SourceryTests/Parsing/Helpers/TemplatesAnnotationParser+ForceParseInlineCodeSpec.swift b/SourceryTests/Parsing/Helpers/TemplatesAnnotationParser_ForceParseInlineCodeSpec.swift similarity index 100% rename from SourceryTests/Parsing/Helpers/TemplatesAnnotationParser+ForceParseInlineCodeSpec.swift rename to SourceryTests/Parsing/Helpers/TemplatesAnnotationParser_ForceParseInlineCodeSpec.swift diff --git a/SourceryTests/SourcerySpec.swift b/SourceryTests/SourcerySpec.swift index 3ff6597fa..6226325d7 100644 --- a/SourceryTests/SourcerySpec.swift +++ b/SourceryTests/SourcerySpec.swift @@ -7,6 +7,9 @@ import Foundation #else @testable import Sourcery #endif +#if !canImport(ObjectiveC) +import CDispatch +#endif @testable import SourceryRuntime import XcodeProj @@ -1121,6 +1124,7 @@ class SourcerySpecTests: QuickSpec { } } +#if canImport(ObjectiveC) context("with watcher") { var watcher: Any? let tmpTemplate = outputDir + Path("FakeTemplate.stencil") @@ -1140,14 +1144,15 @@ class SourcerySpecTests: QuickSpec { _ = watcher } } +#endif } context("given a template folder") { context("given a single file output") { let outputFile = outputDir + "Composed.swift" +#if canImport(JavaScriptCore) let expectedResult = try? (Stubs.resultDirectory + Path("Basic+Other+SourceryTemplates.swift")).read(.utf8).withoutWhitespaces - it("joins generated code into single file") { expect { try Sourcery(cacheDisabled: true) @@ -1164,6 +1169,24 @@ class SourcerySpecTests: QuickSpec { let result = try? outputFile.read(.utf8) expect(result?.withoutWhitespaces).to(equal(expectedResult?.withoutWhitespaces)) } +#else + let expectedResult = try? (Stubs.resultDirectory + Path("Basic+Other+SourceryTemplates_Linux.swift")).read(.utf8).withoutWhitespaces + it("joins generated code into single file") { + expect { + try Sourcery(cacheDisabled: true) + .processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), + usingTemplates: Paths(include: [ + Stubs.templateDirectory + "Basic.stencil", + Stubs.templateDirectory + "Other.stencil", + Stubs.templateDirectory + "SourceryTemplateStencil.sourcerytemplate" + ]), + output: Output(outputFile), baseIndentation: 0) + }.toNot(throwError()) + + let result = try? outputFile.read(.utf8) + expect(result?.withoutWhitespaces).to(equal(expectedResult?.withoutWhitespaces)) + } +#endif it("does not create generated file with empty content") { let templatePath = Stubs.templateDirectory + Path("Empty.stencil") @@ -1271,6 +1294,7 @@ class SourcerySpecTests: QuickSpec { }.toNot(throwError()) } +#if canImport(ObjectiveC) it("links generated files") { expect { try Sourcery(cacheDisabled: true, prune: true).processFiles(sources, usingTemplates: templates, output: output, baseIndentation: 0) @@ -1278,7 +1302,7 @@ class SourcerySpecTests: QuickSpec { expect(sourceFilesPaths.contains(outputDir + "Other.generated.swift")).to(beTrue()) } - +#endif it("links generated files when using per file generation") { templatePath = outputDir + "PerFileGeneration.stencil" update(code: """ diff --git a/SourceryTests/Stub/Result/Basic+Other+SourceryTemplates_Linux.swift b/SourceryTests/Stub/Result/Basic+Other+SourceryTemplates_Linux.swift new file mode 100644 index 000000000..4a5576a48 --- /dev/null +++ b/SourceryTests/Stub/Result/Basic+Other+SourceryTemplates_Linux.swift @@ -0,0 +1,32 @@ +// Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +extension Bar: Equatable {} + +// Bar has Annotations + +func == (lhs: Bar, rhs: Bar) -> Bool { + if lhs.parent != rhs.parent { return false } + if lhs.otherVariable != rhs.otherVariable { return false } + + return true +} + +extension Foo: Equatable {} + +func == (lhs: Foo, rhs: Foo) -> Bool { + if lhs.name != rhs.name { return false } + if lhs.value != rhs.value { return false } + + return true +} + +extension FooSubclass: Equatable {} + +func == (lhs: FooSubclass, rhs: FooSubclass) -> Bool { + if lhs.other != rhs.other { return false } + + return true +} + +// Found 3 types +// SourceryTemplateStencil found 3 types diff --git a/SourceryUtils/Sources/Sha.swift b/SourceryUtils/Sources/Sha.swift index 4de588370..ba1e90b09 100644 --- a/SourceryUtils/Sources/Sha.swift +++ b/SourceryUtils/Sources/Sha.swift @@ -4,15 +4,24 @@ // import Foundation +#if canImport(ObjectiveC) import CommonCrypto +#else +import Crypto +#endif extension Data { public func sha256() -> Data { +#if canImport(ObjectiveC) var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) self.withUnsafeBytes { (pointer) -> Void in _ = CC_SHA256(pointer.baseAddress, CC_LONG(pointer.count), &hash) } return Data(hash) + #else + let digest = SHA256.hash(data: self) + return Data(digest) + #endif } } diff --git a/SourceryUtils/Sources/Version.swift b/SourceryUtils/Sources/Version.swift index b0fd7bef3..8ae1e7330 100644 --- a/SourceryUtils/Sources/Version.swift +++ b/SourceryUtils/Sources/Version.swift @@ -13,4 +13,8 @@ public struct SourceryVersion { public static let current = SourceryVersion(value: inUnitTests ? "Major.Minor.Patch" : "2.0.3") } -public var inUnitTests = NSClassFromString("XCTest") != nil +#if canImport(ObjectiveC) +public let inUnitTests: Bool = NSClassFromString("XCTest") != nil +#else +public let inUnitTests: Bool = ProcessInfo.processInfo.processName.hasSuffix("xctest") +#endif \ No newline at end of file diff --git a/Templates/CodableContextTests/CodableContextTests.swift b/Templates/CodableContextTests/CodableContextTests.swift index afb6e0b85..40b93d2f8 100644 --- a/Templates/CodableContextTests/CodableContextTests.swift +++ b/Templates/CodableContextTests/CodableContextTests.swift @@ -5,7 +5,7 @@ import Nimble class CodableContextTests: QuickSpec { override func spec() { - +#if canImport(ObjectiveC) let encoder: JSONEncoder = { let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted @@ -22,13 +22,14 @@ class CodableContextTests: QuickSpec { let value = AssociatedValuesEnum.someCase(id: 0, name: "a") let encoded = try! encoder.encode(value) - expect(String(data: encoded, encoding: .utf8)).to(equal(""" - { - "type" : "someCase", - "id" : 0, - "name" : "a" - } - """ + expect(String(data: encoded, encoding: .utf8)).to(equal( +""" +{ + "type" : "someCase", + "id" : 0, + "name" : "a" +} +""" )) let decoded = try! decoder.decode(AssociatedValuesEnum.self, from: encoded) @@ -73,14 +74,15 @@ class CodableContextTests: QuickSpec { let value = AssociatedValuesEnumNoCaseKey.someCase(id: 0, name: "a") let encoded = try! encoder.encode(value) - expect(String(data: encoded, encoding: .utf8)).to(equal(""" - { - "someCase" : { - "id" : 0, - "name" : "a" - } - } - """ + expect(String(data: encoded, encoding: .utf8)).to(equal( +""" +{ + "someCase" : { + "id" : 0, + "name" : "a" + } +} +""" )) let decoded = try! decoder.decode(AssociatedValuesEnumNoCaseKey.self, from: encoded) @@ -131,5 +133,6 @@ class CodableContextTests: QuickSpec { } } } +#endif } } diff --git a/Templates/Tests/Context/AutoCodable.swift b/Templates/Tests/Context/AutoCodable.swift index a6f3dd2c3..85564dd75 100644 --- a/Templates/Tests/Context/AutoCodable.swift +++ b/Templates/Tests/Context/AutoCodable.swift @@ -6,12 +6,14 @@ // Copyright © 2018 Pixle. All rights reserved. // +#if canImport(ObjectiveC) import Foundation protocol AutoDecodable: Swift.Decodable {} protocol AutoEncodable: Swift.Encodable {} protocol AutoCodable: AutoDecodable, AutoEncodable {} + public struct CustomKeyDecodable: AutoDecodable { let stringValue: String let boolValue: Bool @@ -157,3 +159,4 @@ enum AssociatedValuesEnumNoCaseKey: AutoCodable, Equatable { case mixCase(Int, name: String) case anotherCase } +#endif diff --git a/Templates/Tests/Context_Linux/AutoCases.swift b/Templates/Tests/Context_Linux/AutoCases.swift new file mode 100644 index 000000000..cee4139c4 --- /dev/null +++ b/Templates/Tests/Context_Linux/AutoCases.swift @@ -0,0 +1,27 @@ +// +// AutoCases.swift +// Templates +// +// Created by Anton Domashnev on 03.05.17. +// Copyright © 2017 Pixle. All rights reserved. +// + +import Foundation + +protocol AutoCases {} + +enum AutoCasesEnum: AutoCases { + case north + case south + case east + case west +} + +enum AutoCasesOneValueEnum: AutoCases { + case one +} + +public enum AutoCasesHasAssociatedValuesEnum: AutoCases { + case foo(test: String) + case bar(number: Int) +} diff --git a/Templates/Tests/Context_Linux/AutoEquatable.swift b/Templates/Tests/Context_Linux/AutoEquatable.swift new file mode 100644 index 000000000..81f03bbe5 --- /dev/null +++ b/Templates/Tests/Context_Linux/AutoEquatable.swift @@ -0,0 +1,186 @@ +// +// AutoCases.swift +// Templates +// +// Created by Anton Domashnev on 03.05.17. +// Copyright © 2017 Pixle. All rights reserved. +// + +import Foundation + +protocol AutoEquatable {} + +protocol Parent { + var name: String { get } +} + +/// General protocol +protocol AutoEquatableProtocol: AutoEquatable { + var width: Double { get } + var height: Double { get} + static var name: String { get } +} + +/// General enum +enum AutoEquatableEnum: AutoEquatable { + case one + case two(first: String, second: String) + case three(bar: Int) + + func allValue() -> [AutoEquatableEnum] { + return [.one, .two(first: "a", second: "b"), .three(bar: 42)] + } +} + +/// Sourcery should not generate a default case for enum with only one case +enum AutoEquatableEnumWithOneCase: AutoEquatable { + case one +} + +/// Sourcery should generate correct code for struct +struct AutoEquatableStruct: AutoEquatable { + // Private Constants + private let laptopModel: String + + // Fileprivate Constants + fileprivate let phoneModel: String + + // Internal Constants + let firstName: String + + // Public Constans + public let lastName: String + + init(firstName: String, lastName: String, parents: [Parent], laptopModel: String, phoneModel: String) { + self.firstName = firstName + self.lastName = lastName + self.parents = parents + self.laptopModel = laptopModel + self.phoneModel = phoneModel + } + + // Arrays + // sourcery: arrayEquality + let parents: [Parent] + + // Variable + var moneyInThePocket: Double = 0 + + // Optional variable + var friends: [String]? + + /// Forced unwrapped variable + var age: Int! + + // Void method + func walk() { + print("I'm going") + } + + // Method with return value + func greeting(for name: String) -> String { + return "Hi \(name)" + } + + // Method with optional return value + func books(sharedWith name: String) -> String? { + return nil + } +} + +/// It should generate correct code for general class +class AutoEquatableClass: AutoEquatable { + // Private Constants + private let laptopModel: String + + // Fileprivate Constants + fileprivate let phoneModel: String + + // Internal Constants + let firstName: String + + // Public Constans + public let lastName: String + + init(firstName: String, lastName: String, parents: [Parent], laptopModel: String, phoneModel: String) { + self.firstName = firstName + self.lastName = lastName + self.parents = parents + self.laptopModel = laptopModel + self.phoneModel = phoneModel + } + + // Arrays + // sourcery: arrayEquality + let parents: [Parent] + + /// Forced unwrapped variable + var age: Int! + + // Variable + var moneyInThePocket: Double = 0 + + // Optional variable + var friends: [String]? + + // Void method + func walk() { + print("I'm going") + } + + // Method with return value + func greeting(for name: String) -> String { + return "Hi \(name)" + } + + // Method with optional return value + func books(sharedWith name: String) -> String? { + return nil + } +} + +/// Sourcery doesn't support inheritance for AutoEqualtable +class AutoEquatableClassInherited: AutoEquatableClass { + // Optional constants + let middleName: String? + + init(middleName: String?) { + self.middleName = middleName + super.init(firstName: "", lastName: "", parents: [], laptopModel: "", phoneModel: "") + } +} + +/// Should not add Equatable conformance +class AutoEquatableNSObject: NSObject, AutoEquatable { + let firstName: String + + init(firstName: String) { + self.firstName = firstName + } +} + +/// It should generate correct code for general class +/// sourcery: AutoEquatable +class AutoEquatableAnnotatedClass { + + // Variable + var moneyInThePocket: Double = 0 + +} + +// It won't be generated +class AutoEquatableAnnotatedClassInherited: AutoEquatableAnnotatedClass { + + // Variable + var middleName: String = "Poor" + +} + +// Sourcery doesn't support inheritance for AutoEqualtable so it won't be generated +/// sourcery: AutoEquatable +class AutoEquatableAnnotatedClassAnnotatedInherited: AutoEquatableAnnotatedClass { + + // Variable + var middleName: String = "Poor" + +} diff --git a/Templates/Tests/Context_Linux/AutoHashable.swift b/Templates/Tests/Context_Linux/AutoHashable.swift new file mode 100644 index 000000000..a547fe005 --- /dev/null +++ b/Templates/Tests/Context_Linux/AutoHashable.swift @@ -0,0 +1,228 @@ +import Foundation + +protocol AutoHashable {} + +/// General protocol +protocol AutoHashableProtocol: AutoHashable { + var width: Double { get } + var height: Double { get} + static var name: String { get } +} + +/// General enum +enum AutoHashableEnum: AutoHashable { + case one + case two(first: String, second: String) + case three(bar: Int) + + func allValue() -> [AutoHashableEnum] { + return [.one, .two(first: "a", second: "b"), .three(bar: 42)] + } +} + +/// Sourcery should generate correct code for struct +struct AutoHashableStruct: AutoHashable { + // Private Constants + private let laptopModel: String + + // Fileprivate Constants + fileprivate let phoneModel: String + + // Static constant + static let structName: String = "AutoHashableStruct" + + // Internal Constants + let firstName: String + + // Public Constans + public let lastName: String + + init(firstName: String, lastName: String, parents: [Parent], laptopModel: String, phoneModel: String) { + self.firstName = firstName + self.lastName = lastName + self.parents = parents + self.laptopModel = laptopModel + self.phoneModel = phoneModel + self.universityGrades = ["Math": 5, "Geometry": 3] + } + + // Arrays + let parents: [Parent] + + // Dictionary + let universityGrades: [String: Int] + + // Variable + var moneyInThePocket: Double = 0 + + // Forced unwrapped variable + var age: Int! + + // Optional variable + var friends: [String]? + + // Void method + func walk() { + print("I'm going") + } + + // Method with return value + func greeting(for name: String) -> String { + return "Hi \(name)" + } + + // Method with optional return value + func books(sharedWith name: String) -> String? { + return nil + } +} + +/// It should generate correct code for general class +class AutoHashableClass: AutoHashable { + // Private Constants + private let laptopModel: String + + // Fileprivate Constants + fileprivate let phoneModel: String + + // Static constant + static let className: String = "AutoHashableClass" + + // Internal Constants + let firstName: String + + // Public Constans + public let lastName: String + + init(firstName: String, lastName: String, parents: [Parent], laptopModel: String, phoneModel: String) { + self.firstName = firstName + self.lastName = lastName + self.parents = parents + self.laptopModel = laptopModel + self.phoneModel = phoneModel + self.universityGrades = ["Math": 5, "Geometry": 3] + } + + // Arrays + let parents: [Parent] + + // Dictionary + let universityGrades: [String: Int] + + // Variable + var moneyInThePocket: Double = 0 + + // Forced unwrapped variable + var age: Int! + + // Optional variable + var friends: [String]? + + // Void method + func walk() { + print("I'm going") + } + + // Method with return value + func greeting(for name: String) -> String { + return "Hi \(name)" + } + + // Method with optional return value + func books(sharedWith name: String) -> String? { + return nil + } +} + +class AutoHashableClassInherited: AutoHashableClass { + // Optional constants + let middleName: String? + + init(middleName: String?) { + self.middleName = middleName + super.init(firstName: "", lastName: "", parents: [], laptopModel: "", phoneModel: "") + } +} + +class AutoHashableClassInheritedInherited: AutoHashableClassInherited { + // Optional constants + let prefix: String? + + init(prefix: String?) { + self.prefix = prefix + super.init(middleName: "") + } +} + +class NonHashableClass { + let firstName: String + + init(firstName: String) { + self.firstName = firstName + } +} + +// Should not add super call +class AutoHashableClassFromNonHashableInherited: NonHashableClass, AutoHashable { + let lastName: String? + + init(lastName: String?) { + self.lastName = lastName + super.init(firstName: "") + } +} + +// Should add super call +class AutoHashableClassFromNonHashableInheritedInherited: AutoHashableClassFromNonHashableInherited { + let prefix: String? + + init(prefix: String?) { + self.prefix = prefix + super.init(lastName: "") + } +} + +class HashableClass: Hashable { + let firstName: String + + init(firstName: String) { + self.firstName = firstName + } + + static func == (lhs: HashableClass, rhs: HashableClass) -> Bool { + return lhs.firstName == rhs.firstName + } + + func hash(into hasher: inout Hasher) { + self.firstName.hash(into: &hasher) + } +} + +// Should add super +class AutoHashableFromHashableInherited: HashableClass, AutoHashable { + let lastName: String? + + init(lastName: String?) { + self.lastName = lastName + super.init(firstName: "") + } +} + +/// Should not add Hashable conformance +class AutoHashableNSObject: NSObject, AutoHashable { + let firstName: String + + init(firstName: String) { + self.firstName = firstName + } +} + +// Should add super call +class AutoHashableNSObjectInherited: AutoHashableNSObject { + let lastName: String + + init(lastName: String) { + self.lastName = lastName + super.init(firstName: "") + } +} diff --git a/Templates/Tests/Context_Linux/AutoLenses.swift b/Templates/Tests/Context_Linux/AutoLenses.swift new file mode 100644 index 000000000..755676ce3 --- /dev/null +++ b/Templates/Tests/Context_Linux/AutoLenses.swift @@ -0,0 +1,36 @@ +// +// AutoLenses.swift +// Templates +// +// Created by Anton Domashnev on 16.05.17. +// Copyright © 2017 Pixle. All rights reserved. +// + +import Foundation + +protocol AutoLenses {} + +struct House: AutoLenses { + let rooms: Room + let address: String + let size: Int +} + +struct Room: AutoLenses { + let people: [Person] + let name: String +} + +struct Person: AutoLenses { + let name: String +} + +// swiftlint:disable identifier_name +struct Rectangle: AutoLenses { + let x: Int + let y: Int + + var area: Int { + return x*y + } +} diff --git a/Templates/Tests/Context_Linux/AutoMockable.swift b/Templates/Tests/Context_Linux/AutoMockable.swift new file mode 100644 index 000000000..6e97c121d --- /dev/null +++ b/Templates/Tests/Context_Linux/AutoMockable.swift @@ -0,0 +1,184 @@ +// +// AutoMockable.swift +// Templates +// +// Created by Anton Domashnev on 17.05.17. +// Copyright © 2017 Pixle. All rights reserved. +// + +import Foundation + +protocol AutoMockable {} + +protocol BasicProtocol: AutoMockable { + func loadConfiguration() -> String? + /// Asks a Duck to quack + /// + /// - Parameter times: How many times the Duck will quack + func save(configuration: String) +} + +protocol ImplicitlyUnwrappedOptionalReturnValueProtocol: AutoMockable { + func implicitReturn() -> String! +} + +protocol InitializationProtocol: AutoMockable { + init(intParameter: Int, stringParameter: String, optionalParameter: String?) + func start() + func stop() +} + +protocol VariablesProtocol: AutoMockable { + var company: String? { get set } + var name: String { get } + var age: Int { get } + var kids: [String] { get } + var universityMarks: [String: Int] { get } +} + +protocol SameShortMethodNamesProtocol: AutoMockable { + func start(car: String, of model: String) + func start(plane: String, of model: String) +} + +protocol ExtendableProtocol: AutoMockable { + var canReport: Bool { get } + func report(message: String) +} + +protocol ReservedWordsProtocol: AutoMockable { + func `continue`(with message: String) -> String +} + +protocol ThrowableProtocol: AutoMockable { + func doOrThrow() throws -> String + func doOrThrowVoid() throws +} + +protocol CurrencyPresenter: AutoMockable { + func showSourceCurrency(_ currency: String) +} + +extension ExtendableProtocol { + var canReport: Bool { return true } + + func report(message: String = "Test") { + print(message) + } +} + +protocol ClosureProtocol: AutoMockable { + func setClosure(_ closure: @escaping () -> Void) +} + +protocol MultiClosureProtocol: AutoMockable { + func setClosure(name: String, _ closure: @escaping () -> Void) +} + +protocol NonEscapingClosureProtocol: AutoMockable { + func executeClosure(_ closure: () -> Void) +} + +protocol MultiNonEscapingClosureProtocol: AutoMockable { + func executeClosure(name: String, _ closure: () -> Void) +} + +/// sourcery: AutoMockable +protocol AnnotatedProtocol { + func sayHelloWith(name: String) +} + +protocol SingleOptionalParameterFunction: AutoMockable { + func send(message: String?) +} + +protocol FunctionWithClosureReturnType: AutoMockable { + func get() -> () -> Void + func getOptional() -> (() -> Void)? +} + +protocol FunctionWithMultilineDeclaration: AutoMockable { + func start(car: String, + of model: String) +} + +protocol ThrowingVariablesProtocol: AutoMockable { + var title: String? { get throws } + var firstName: String { get throws } +} + +protocol AsyncVariablesProtocol: AutoMockable { + var title: String? { get async } + var firstName: String { get async } +} + +protocol AsyncThrowingVariablesProtocol: AutoMockable { + var title: String? { get async throws } + var firstName: String { get async throws } +} + +protocol AsyncProtocol: AutoMockable { + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + func callAsync(parameter: Int) async -> String + func callAsyncAndThrow(parameter: Int) async throws -> String + func callAsyncVoid(parameter: Int) async -> Void + func callAsyncAndThrowVoid(parameter: Int) async throws -> Void +} + +protocol FunctionWithAttributes: AutoMockable { + @discardableResult + func callOneAttribute() -> String + + @discardableResult + @available(macOS 10.15, *) + func callTwoAttributes() -> Int + + @discardableResult + @available(iOS 13.0, *) + @available(macOS 10.15, *) + func callRepeatedAttributes() -> Bool +} + +public protocol AccessLevelProtocol: AutoMockable { + var company: String? { get set } + var name: String { get } + + func loadConfiguration() -> String? +} + +protocol StaticMethodProtocol: AutoMockable { + static func staticFunction(_: String) -> String +} + +protocol StubProtocol {} +protocol StubWithAnyNameProtocol {} + +protocol AnyProtocol: AutoMockable { + var a: any StubProtocol { get } + var b: (any StubProtocol)? { get } + var c: (any StubProtocol)! { get } + var d: (((any StubProtocol)?) -> Void) { get } + var e: [(any StubProtocol)?] { get } + func f(_ x: (any StubProtocol)?, y: (any StubProtocol)!, z: any StubProtocol) + var g: any StubProtocol { get } + var h: (any StubProtocol)? { get } + var i: (any StubProtocol)! { get } + func j(x: (any StubProtocol)?, y: (any StubProtocol)!, z: any StubProtocol) async -> String + func k(x: ((any StubProtocol)?) -> Void, y: (any StubProtocol) -> Void) + func l(x: (((any StubProtocol)?) -> Void), y: ((any StubProtocol) -> Void)) + var anyConfusingPropertyName: any StubProtocol { get } + func m(anyConfusingArgumentName: any StubProtocol) + func n(x: @escaping ((any StubProtocol)?) -> Void) + var o: any StubWithAnyNameProtocol { get } + func p(_ x: (any StubWithAnyNameProtocol)?) + func q() -> any StubProtocol + func r() -> (any StubProtocol)? + func s() -> () -> any StubProtocol + func t() -> () -> (any StubProtocol)? + func u() -> (Int, () -> (any StubProtocol)?) + func v() -> (Int, (() -> any StubProtocol)?) + func w() -> [(any StubProtocol)?] + func x() -> [String: (any StubProtocol)?] + func y() -> (any StubProtocol, (any StubProtocol)?) + func z() -> any StubProtocol & CustomStringConvertible +} diff --git a/Templates/Tests/Context_Linux/LinuxMain.swift b/Templates/Tests/Context_Linux/LinuxMain.swift new file mode 100644 index 000000000..7b869e871 --- /dev/null +++ b/Templates/Tests/Context_Linux/LinuxMain.swift @@ -0,0 +1,37 @@ +// +// LinuxMain.swift +// Templates +// +// Created by Anton Domashnev on 17.05.17. +// Copyright © 2017 Pixle. All rights reserved. +// + +import Foundation +import XCTest + +class AutoInjectionTests: XCTestCase { + func testThatItResolvesAutoInjectedDependencies() { + XCTAssertTrue(true) + } + + func testThatItDoesntResolveAutoInjectedDependencies() { + XCTAssertTrue(true) + } +} + +class AutoWiringTests: XCTestCase { + func testThatItCanResolveWithAutoWiring() { + XCTAssertTrue(true) + } + + func testThatItCanNotResolveWithAutoWiring() { + XCTAssertTrue(true) + } +} + +// sourcery: disableTests +class DisabledTests: XCTestCase { + func testThatItResolvesDisabledTestsAnnotation() { + XCTAssertTrue(true) + } +} diff --git a/Templates/Tests/Generated/AutoCodable.generated.swift b/Templates/Tests/Generated/AutoCodable.generated.swift index b8c6c935c..1b3eb3460 100644 --- a/Templates/Tests/Generated/AutoCodable.generated.swift +++ b/Templates/Tests/Generated/AutoCodable.generated.swift @@ -1,7 +1,7 @@ // Generated using Sourcery 1.3.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT - +#if canImport(ObjectiveC) extension AssociatedValuesEnum { internal init(from decoder: Decoder) throws { @@ -108,7 +108,6 @@ extension AssociatedValuesEnumNoCaseKey { } - extension CustomCodingWithNotAllDefinedKeys { internal init(from decoder: Decoder) throws { @@ -143,7 +142,6 @@ extension CustomContainerCodable { } - extension CustomMethodsCodable { enum CodingKeys: String, CodingKey { @@ -239,3 +237,4 @@ extension SkipEncodingKeys { } } +#endif diff --git a/Templates/Tests/TemplatesTests.swift b/Templates/Tests/TemplatesTests.swift index 87d8144cb..46acfd5df 100644 --- a/Templates/Tests/TemplatesTests.swift +++ b/Templates/Tests/TemplatesTests.swift @@ -6,10 +6,15 @@ import PathKit #endif class TemplatesTests: QuickSpec { - #if SWIFT_PACKAGE + #if SWIFT_PACKAGE || os(Linux) override class func setUp() { super.setUp() + generateFiles() + } + #endif + + private static func generateFiles() { print("Generating sources...", terminator: " ") let buildDir: Path @@ -32,14 +37,18 @@ class TemplatesTests: QuickSpec { print(error) } } - + #if canImport(ObjectiveC) + let contextSources = "\(resources)/Context" + #else + let contextSources = "\(resources)/Context_Linux" + #endif var output: String? buildDir.chdir { output = launch( sourceryPath: sourcery, args: [ "--sources", - "\(resources)/Context", + contextSources, "--templates", "\(resources)/Templates", "--output", @@ -56,7 +65,6 @@ class TemplatesTests: QuickSpec { print("Done!") } } - #endif override func spec() { func check(template name: String) { @@ -82,6 +90,12 @@ class TemplatesTests: QuickSpec { expect(generatedFileFilteredLines).to(equal(expectedFileFilteredLines)) } +#if !canImport(ObjectiveC) + beforeSuite { + TemplatesTests.generateFiles() + } +#endif + describe("AutoCases template") { it("generates expected code") { check(template: "AutoCases") @@ -117,12 +131,13 @@ class TemplatesTests: QuickSpec { check(template: "LinuxMain") } } - +#if canImport(ObjectiveC) describe("AutoCodable template") { it("generates expected code") { check(template: "AutoCodable") } } +#endif } private func path(forResource name: String, ofType ext: String, in dirName: String) -> String? {