├── .bundle └── config ├── .circleci └── config.yml ├── .codecov.yml ├── .github └── workflows │ ├── bump_homebrew.yml │ ├── docker.yml │ ├── jazzy.yml │ ├── release_macOS.yml │ ├── release_ubuntu.yml │ ├── test_macOS.yml │ └── test_ubuntu.yml ├── .gitignore ├── .gitmodules ├── .jazzy.yaml ├── .pre-commit-hooks.yaml ├── .ruby-version ├── .sourcery-macOS.yml ├── .sourcery-ubuntu.yml ├── .swift-version ├── .swiftlint.yml ├── .vscode ├── launch.json └── settings.json ├── ABOUT.md ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dangerfile ├── Dockerfile ├── Funding.yml ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── LINUX.md ├── LinuxMain.swift ├── Package.resolved ├── Package.swift ├── Plugins └── SourceryCommandPlugin │ └── SourceryCommandPlugin.swift ├── README.md ├── RELEASING.md ├── Rakefile ├── Resources ├── Inside-iOS-Dev-Sourcery-Intro-To-Mocking-Video-Thumbnail.png ├── daemon.gif ├── icon-1024.png ├── icon-128.png ├── icon-16.png ├── icon-256.png ├── icon-32.png ├── icon-512.png └── icon-64.png ├── Scripts ├── SwiftLint.sh ├── bootstrap ├── package_content ├── pre-commit.sh └── update-placeholders ├── Sourcery-Example ├── CodeGenerated │ └── Basic.generated.swift ├── Podfile ├── Sourcery-Example.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── Sourcery-Example.xcworkspace │ └── contents.xcworkspacedata ├── Sourcery-Example │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift └── Templates │ └── Basic.stencil ├── Sourcery.podspec ├── Sourcery ├── Configuration.swift ├── Generating │ └── Templates │ │ ├── JavaScript │ │ └── JavaScriptTemplate.swift │ │ ├── Stencil │ │ └── StencilTemplate.swift │ │ └── Swift │ │ └── SwiftTemplate.swift ├── Sourcery.swift ├── Templates │ ├── Coding.stencil │ ├── Description.stencil │ ├── Diffable.stencil │ ├── Equality.stencil │ ├── JSExport.ejs │ ├── Typed.stencil │ └── TypedSpec.stencil └── Utils │ ├── ByteRangeConversion.swift │ ├── BytesRange + Editing.swift │ ├── DryOutputModels.swift │ ├── FolderWatcher.swift │ ├── NSRange + Editing.swift │ └── Xcode+Extensions.swift ├── SourceryExecutable ├── Info.plist └── main.swift ├── SourceryFramework.podspec ├── SourceryFramework ├── Info.plist ├── SourceryFramework.h └── Sources │ ├── Generating │ ├── Generator.swift │ ├── SourceryTemplate.swift │ └── Template.swift │ └── Parsing │ ├── FileParserType.swift │ ├── String+TypeInference.swift │ ├── SwiftSyntax │ ├── AST │ │ ├── AccessLevel+SwiftSyntax.swift │ │ ├── Actor+SwiftSyntax.swift │ │ ├── Attribute+SwiftSyntax.swift │ │ ├── Class+SwiftSyntax.swift │ │ ├── Enum+SwiftSyntax.swift │ │ ├── EnumCase+SwiftSyntax.swift │ │ ├── GenericParameter+SwiftSyntax.swift │ │ ├── GenericRequirement+SwiftSyntax.swift │ │ ├── GenericType+SwiftSyntax.swift │ │ ├── Method+SwiftSyntax.swift │ │ ├── MethodParameter+SwiftSyntax.swift │ │ ├── Modifier+SwiftSyntax.swift │ │ ├── Protocol+SwiftSyntax.swift │ │ ├── Signature.swift │ │ ├── Struct+SwiftSyntax.swift │ │ ├── Subscript+SwiftSyntax.swift │ │ ├── Type+SwiftSyntax.swift │ │ ├── TypeName+SwiftSyntax.swift │ │ └── Variable+SwiftSyntax.swift │ ├── FileParserSyntax.swift │ ├── Syntax+Extensions.swift │ └── SyntaxTreeCollector.swift │ └── Utils │ ├── AnnotationsParser.swift │ ├── Bridges.swift │ ├── InlineParser.swift │ ├── StringView.swift │ └── Verifier.swift ├── SourceryJS ├── Info.plist ├── Resources │ └── ejs.js ├── SourceryJS.h └── Sources │ ├── EJSTemplate+Tests.swift │ └── EJSTemplate.swift ├── SourceryRuntime.podspec ├── SourceryRuntime ├── Sources │ ├── Common │ │ ├── AST │ │ │ ├── AccessLevel.swift │ │ │ ├── Actor.swift │ │ │ ├── Annotations.swift │ │ │ ├── Attribute.swift │ │ │ ├── Class.swift │ │ │ ├── Definition.swift │ │ │ ├── Documentation.swift │ │ │ ├── Import.swift │ │ │ ├── Modifier.swift │ │ │ ├── PhantomProtocols.swift │ │ │ ├── Protocol.swift │ │ │ ├── ProtocolComposition.swift │ │ │ ├── Struct.swift │ │ │ ├── TypeName │ │ │ │ ├── Array.swift │ │ │ │ ├── Dictionary.swift │ │ │ │ ├── Generic.swift │ │ │ │ ├── Set.swift │ │ │ │ └── Typed.swift │ │ │ └── Typealias.swift │ │ ├── Array+Parallel.swift │ │ ├── BytesRange.swift │ │ ├── Composer │ │ │ ├── Composer.swift │ │ │ └── ParserResultsComposed.swift │ │ ├── Diffable.swift │ │ ├── Extensions.swift │ │ ├── FileParserResult.swift │ │ ├── Log.swift │ │ └── TemplateContext.swift │ ├── Generated │ │ ├── AutoHashable.generated.swift │ │ ├── Coding.generated.swift │ │ ├── JSExport.generated.swift │ │ └── Typed.generated.swift │ ├── Linux │ │ ├── AST │ │ │ ├── AssociatedType_Linux.swift │ │ │ ├── AssociatedValue_Linux.swift │ │ │ ├── ClosureParameter_Linux.swift │ │ │ ├── EnumCase_Linux.swift │ │ │ ├── Enum_Linux.swift │ │ │ ├── GenericParameter_Linux.swift │ │ │ ├── GenericRequirement_Linux.swift │ │ │ ├── MethodParameter_Linux.swift │ │ │ ├── Method_Linux.swift │ │ │ ├── Protocol_Linux.swift │ │ │ ├── Subscript_Linux.swift │ │ │ ├── TypeName │ │ │ │ ├── Closure_Linux.swift │ │ │ │ ├── GenericTypeParameter_Linux.swift │ │ │ │ ├── Tuple_Linux.swift │ │ │ │ └── TypeName_Linux.swift │ │ │ ├── Type_Linux.swift │ │ │ └── Variable_Linux.swift │ │ ├── DynamicMemberLookup_Linux.swift │ │ ├── NSException_Linux.swift │ │ ├── TypesCollection_Linux.swift │ │ └── Types_Linux.swift │ └── macOS │ │ ├── AST │ │ ├── AssociatedType.swift │ │ ├── AssociatedValue.swift │ │ ├── ClosureParameter.swift │ │ ├── Enum.swift │ │ ├── EnumCase.swift │ │ ├── GenericParameter.swift │ │ ├── GenericRequirement.swift │ │ ├── Method.swift │ │ ├── MethodParameter.swift │ │ ├── Subscript.swift │ │ ├── Type.swift │ │ ├── TypeName │ │ │ ├── Closure.swift │ │ │ ├── GenericTypeParameter.swift │ │ │ ├── Tuple.swift │ │ │ └── TypeName.swift │ │ └── Variable.swift │ │ ├── Types.swift │ │ └── TypesCollection.swift └── Supporting Files │ ├── Info.plist │ └── SourceryRuntime.h ├── SourceryStencil ├── Info.plist ├── SourceryStencil.h └── Sources │ ├── NewLineNode.swift │ ├── StencilTemplate.swift │ └── TypedNode.swift ├── SourcerySwift ├── Info.plist ├── SourcerySwift.h └── Sources │ ├── SourceryRuntime.content.generated.swift │ ├── SourceryRuntime_Linux.content.generated.swift │ └── SwiftTemplate.swift ├── SourceryTests ├── ConfigurationSpec.swift ├── Generating │ ├── JavaScriptTemplateSpecs.swift │ ├── StencilTemplateSpec.swift │ └── SwiftTemplateSpecs.swift ├── GeneratorSpec.swift ├── Helpers │ ├── Builders.swift │ ├── CustomMatchers.swift │ └── Extensions.swift ├── Info.plist ├── Models │ ├── ActorSpec.swift │ ├── ArrayTypeSpec.swift │ ├── ClassSpec.swift │ ├── DiffableSpec.swift │ ├── EnumSpec.swift │ ├── MethodSpec.swift │ ├── ProtocolSpec.swift │ ├── StructSpec.swift │ ├── TypeSpec.swift │ ├── TypealiasSpec.swift │ ├── TypedSpec.generated.swift │ └── VariableSpec.swift ├── Output │ └── DryOutputSpec.swift ├── Parsing │ ├── ComposerSpec.swift │ ├── FileParserSpec.swift │ ├── FileParser_AssociatedTypeSpec.swift │ ├── FileParser_AttributesModifierSpec.swift │ ├── FileParser_MethodsSpec.swift │ ├── FileParser_ProtocolComposition.swift │ ├── FileParser_SubscriptsSpec.swift │ ├── FileParser_TypeNameSpec.swift │ ├── FileParser_VariableSpec.swift │ └── Helpers │ │ ├── AnnotationsParserSpec.swift │ │ ├── StringViewSpec.swift │ │ ├── TemplateAnnotationsParserSpec.swift │ │ ├── TemplatesAnnotationParser_ForceParseInlineCodeSpec.swift │ │ └── VerifierSpec.swift ├── Sourcery+PerformanceSpec.swift ├── SourcerySpec.swift └── Stub │ ├── Configs │ ├── invalid.yml │ ├── multi.yml │ ├── parent.yml │ └── valid.yml │ ├── DryRun-Code │ └── Base.swift │ ├── Errors │ └── localized-error.swift │ ├── JavaScriptTemplates │ ├── AllTypealiases.ejs │ ├── Equality.ejs │ ├── Function.ejs │ ├── Includes.ejs │ ├── Other.ejs │ ├── ProtocolCompositions.ejs │ ├── SubfolderIncludes.ejs │ ├── Typealiases.ejs │ └── lib │ │ ├── One.ejs │ │ └── Two.ejs │ ├── Performance-Code │ ├── Kiosk │ │ ├── Admin │ │ │ ├── AdminCardTestingViewController.swift │ │ │ ├── AdminLogViewController.swift │ │ │ ├── AdminPanelViewController.swift │ │ │ ├── AuctionWebViewController.swift │ │ │ ├── ChooseAuctionViewController.swift │ │ │ └── PasswordAlertViewController.swift │ │ ├── App │ │ │ ├── APIPingManager.swift │ │ │ ├── AppDelegate+GlobalActions.swift │ │ │ ├── AppDelegate.swift │ │ │ ├── AppSetup.swift │ │ │ ├── AppViewController.swift │ │ │ ├── BidderDetailsRetrieval.swift │ │ │ ├── CardHandler.swift │ │ │ ├── Constants.swift │ │ │ ├── GlobalFunctions.swift │ │ │ ├── KioskDateFormatter.h │ │ │ ├── KioskDateFormatter.m │ │ │ ├── Logger.swift │ │ │ ├── MarkdownParser.swift │ │ │ ├── Models │ │ │ │ ├── Artist.swift │ │ │ │ ├── Artwork.swift │ │ │ │ ├── Bid.swift │ │ │ │ ├── Bidder.swift │ │ │ │ ├── BidderPosition.swift │ │ │ │ ├── BuyersPremium.swift │ │ │ │ ├── Card.swift │ │ │ │ ├── GenericError.swift │ │ │ │ ├── Image.swift │ │ │ │ ├── JSONAble.swift │ │ │ │ ├── Location.swift │ │ │ │ ├── Sale.swift │ │ │ │ ├── SaleArtwork.swift │ │ │ │ ├── SaleArtworkViewModel.swift │ │ │ │ ├── SystemTime.swift │ │ │ │ └── User.swift │ │ │ ├── NSErrorExtensions.swift │ │ │ ├── Networking │ │ │ │ ├── APIKeys.swift │ │ │ │ ├── ArtsyAPI.swift │ │ │ │ ├── NetworkLogger.swift │ │ │ │ ├── Networking.swift │ │ │ │ ├── UserCredentials.swift │ │ │ │ └── XAppToken.swift │ │ │ ├── OfflineViewController.swift │ │ │ ├── STPCard+Validation.h │ │ │ ├── STPCard+Validation.m │ │ │ ├── StubResponses.h │ │ │ ├── StubResponses.m │ │ │ ├── SwiftExtensions.swift │ │ │ ├── UIStoryboardSegueExtensions.swift │ │ │ ├── UIViewControllerExtensions.swift │ │ │ ├── UIViewSubclassesErrorExtensions.swift │ │ │ └── Views │ │ │ │ ├── Button Subclasses │ │ │ │ └── Button.swift │ │ │ │ ├── RegisterFlowView.swift │ │ │ │ ├── SimulatorOnlyView.swift │ │ │ │ ├── Spinner.swift │ │ │ │ ├── SwitchView.swift │ │ │ │ └── Text Fields │ │ │ │ ├── CursorView.swift │ │ │ │ └── TextField.swift │ │ ├── Auction Listings │ │ │ ├── ListingsCountdownManager.swift │ │ │ ├── ListingsViewController.swift │ │ │ ├── ListingsViewModel.swift │ │ │ ├── MasonryCollectionViewCell.swift │ │ │ ├── TableCollectionViewCell.swift │ │ │ └── WebViewController.swift │ │ ├── Bid Fulfillment │ │ │ ├── AdminCCBypassNetworkModel.swift │ │ │ ├── BidCheckingNetworkModel.swift │ │ │ ├── BidDetailsPreviewView.swift │ │ │ ├── BidderNetworkModel.swift │ │ │ ├── ConfirmYourBidArtsyLoginViewController.swift │ │ │ ├── ConfirmYourBidEnterYourEmailViewController.swift │ │ │ ├── ConfirmYourBidPINViewController.swift │ │ │ ├── ConfirmYourBidPasswordViewController.swift │ │ │ ├── ConfirmYourBidViewController.swift │ │ │ ├── FulfillmentContainerViewController.swift │ │ │ ├── FulfillmentNavigationController.swift │ │ │ ├── GenericFormValidationViewModel.swift │ │ │ ├── KeypadContainerView.swift │ │ │ ├── KeypadView.swift │ │ │ ├── KeypadViewModel.swift │ │ │ ├── KeypadViewPreviewIB.png │ │ │ ├── LoadingViewController.swift │ │ │ ├── LoadingViewModel.swift │ │ │ ├── ManualCreditCardInputViewController.swift │ │ │ ├── ManualCreditCardInputViewModel.swift │ │ │ ├── Models │ │ │ │ ├── BidDetails.swift │ │ │ │ ├── NewUser.swift │ │ │ │ └── RegistrationCoordinator.swift │ │ │ ├── PlaceBidNetworkModel.swift │ │ │ ├── PlaceBidViewController.swift │ │ │ ├── RegisterViewController.swift │ │ │ ├── RegistrationEmailViewController.swift │ │ │ ├── RegistrationMobileViewController.swift │ │ │ ├── RegistrationPasswordViewController.swift │ │ │ ├── RegistrationPasswordViewModel.swift │ │ │ ├── RegistrationPostalZipViewController.swift │ │ │ ├── StripeManager.swift │ │ │ ├── SwipeCreditCardViewController.swift │ │ │ ├── YourBiddingDetailsViewController.swift │ │ │ ├── edit_button@2x.png │ │ │ └── toolbar_close@2x.png │ │ ├── Help │ │ │ ├── HelpAnimator.swift │ │ │ └── HelpViewController.swift │ │ ├── HelperFunctions.swift │ │ ├── ListingsCollectionViewCell.swift │ │ ├── Observable+JSONAble.swift │ │ ├── Observable+Logging.swift │ │ ├── Observable+Operators.swift │ │ ├── Sale Artwork Details │ │ │ ├── ImageTiledDataSource.swift │ │ │ ├── SaleArtworkDetailsViewController.swift │ │ │ ├── SaleArtworkZoomViewController.swift │ │ │ └── WhitespaceGobbler.swift │ │ ├── UIKit+Rx.swift │ │ ├── UILabel+Fonts.swift │ │ ├── UIView+LongPressDisplayMessage.swift │ │ └── UIViewController+Bidding.swift │ └── LICENSE │ ├── Result │ ├── AllTypealiases.swift │ ├── Basic+Other+SourceryTemplates.swift │ ├── Basic+Other+SourceryTemplates_Linux.swift │ ├── Basic+Other.swift │ ├── Basic.swift │ ├── BasicFooExcluded.swift │ ├── Function.swift │ ├── Other.swift │ ├── ProtocolCompositions.swift │ └── Typealiases.swift │ ├── Source │ ├── Bar.swift │ ├── Foo.swift │ ├── FooBar.swift │ └── TestProject │ │ ├── TestProject.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── TestProject │ │ └── Info.plist │ ├── Source_Linux │ ├── Bar.swift │ ├── Foo.swift │ ├── FooBar.swift │ └── TestProject │ │ ├── TestProject.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── TestProject │ │ └── Info.plist │ ├── Stubs.swift │ ├── SwiftTemplates │ ├── Equality.swift │ ├── Equality.swifttemplate │ ├── Function.swifttemplate │ ├── IncludeCycle.swifttemplate │ ├── IncludeFile.swifttemplate │ ├── IncludeFileNoExtension.swifttemplate │ ├── Includes.swifttemplate │ ├── IncludesNoExtension.swifttemplate │ ├── Invalid.swifttemplate │ ├── InvalidTag.swifttemplate │ ├── Other.swifttemplate │ ├── Runtime.swifttemplate │ ├── SelfIncludeCycle.swifttemplate │ ├── SubfolderFileIncludes.swifttemplate │ ├── SubfolderIncludes.swifttemplate │ ├── Throws.swifttemplate │ ├── includeCycle │ │ ├── One.swifttemplate │ │ └── Two.swifttemplate │ └── lib │ │ ├── Equality.swift │ │ ├── One.swifttemplate │ │ └── Two.swifttemplate │ └── Templates │ ├── Basic.stencil │ ├── GenerationWays.stencil │ ├── Include.stencil │ ├── Other.stencil │ ├── Partial.stencil │ ├── SourceryTemplateEJS.sourcerytemplate │ └── SourceryTemplateStencil.sourcerytemplate ├── SourceryUtils.podspec ├── SourceryUtils ├── Sources │ ├── Path+Extensions.swift │ ├── Sha.swift │ ├── Time.swift │ └── Version.swift └── Supporting Files │ ├── Info.plist │ └── SourceryUtils.h ├── Templates ├── .swiftlint.yml ├── CodableContext │ ├── CodableContext.h │ └── Info.plist ├── CodableContextTests │ ├── CodableContextTests.swift │ └── Info.plist ├── Templates.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── TemplatesTests.xcscheme ├── Templates │ ├── AutoCases.stencil │ ├── AutoCodable.swifttemplate │ ├── AutoEquatable.stencil │ ├── AutoHashable.stencil │ ├── AutoLenses.stencil │ ├── AutoMockable.stencil │ ├── Decorator.swifttemplate │ └── LinuxMain.stencil ├── Tests │ ├── Context │ │ ├── AutoCases.swift │ │ ├── AutoCodable.swift │ │ ├── AutoEquatable.swift │ │ ├── AutoHashable.swift │ │ ├── AutoLenses.swift │ │ ├── AutoMockable.swift │ │ └── LinuxMain.swift │ ├── Context_Linux │ │ ├── AutoCases.swift │ │ ├── AutoEquatable.swift │ │ ├── AutoHashable.swift │ │ ├── AutoLenses.swift │ │ ├── AutoMockable.swift │ │ └── LinuxMain.swift │ ├── Expected │ │ ├── AutoCases.expected │ │ ├── AutoCodable.expected │ │ ├── AutoEquatable.expected │ │ ├── AutoHashable.expected │ │ ├── AutoLenses.expected │ │ ├── AutoMockable.expected │ │ └── LinuxMain.expected │ ├── Generated │ │ ├── AutoCases.generated.swift │ │ ├── AutoCodable.generated.swift │ │ ├── AutoEquatable.generated.swift │ │ ├── AutoHashable.generated.swift │ │ ├── AutoLenses.generated.swift │ │ ├── AutoMockable.generated.swift │ │ └── LinuxMain.generated.swift │ ├── Info.plist │ └── TemplatesTests.swift └── artifactbundle.info.json.template ├── Tests └── SourceryLibTests ├── TryCatch ├── Info.plist ├── TryCatch.m └── include │ └── TryCatch.h ├── docs ├── Classes │ ├── Actor.html │ ├── ArrayType.html │ ├── AssociatedType.html │ ├── AssociatedValue.html │ ├── Attribute.html │ ├── Class.html │ ├── ClosureParameter.html │ ├── ClosureType.html │ ├── DictionaryType.html │ ├── DiffableResult.html │ ├── Enum.html │ ├── EnumCase.html │ ├── GenericParameter.html │ ├── GenericRequirement.html │ ├── GenericRequirement │ │ └── Relationship.html │ ├── GenericType.html │ ├── GenericTypeParameter.html │ ├── Import.html │ ├── Method.html │ ├── MethodParameter.html │ ├── Modifier.html │ ├── Protocol.html │ ├── ProtocolComposition.html │ ├── SetType.html │ ├── Struct.html │ ├── Subscript.html │ ├── TupleElement.html │ ├── TupleType.html │ ├── Type.html │ ├── TypeName.html │ ├── Types.html │ └── Variable.html ├── Enums │ └── Composer.html ├── Examples.html ├── Extensions │ ├── Array.html │ ├── String.html │ ├── StringProtocol.html │ └── Typealias.html ├── Guides.html ├── Other Classes.html ├── Other Enums.html ├── Other Extensions.html ├── Other Protocols.html ├── Other Typealiases.html ├── Protocols │ ├── Annotated.html │ ├── Definition.html │ ├── Diffable.html │ ├── Documented.html │ └── Typed.html ├── Types.html ├── badge.svg ├── codable.html ├── css │ ├── highlight.css │ └── jazzy.css ├── decorator.html ├── diffable.html ├── enum-cases.html ├── equatable.html ├── hashable.html ├── img │ ├── carat.png │ ├── dash.png │ ├── gh.png │ └── spinner.gif ├── index.html ├── installing.html ├── js │ ├── jazzy.js │ ├── jazzy.search.js │ ├── jquery.min.js │ ├── lunr.min.js │ └── typeahead.jquery.js ├── lenses.html ├── linuxmain.html ├── mocks.html ├── search.json ├── usage.html └── writing-templates.html └── guides ├── Codable.md ├── Decorator.md ├── Diffable.md ├── Enum cases.md ├── Equatable.md ├── Hashable.md ├── Installing.md ├── Lenses.md ├── LinuxMain.md ├── Mocks.md ├── Usage.md └── Writing templates.md /.bundle/config: -------------------------------------------------------------------------------- 1 | --- 2 | BUNDLE_DISABLE_SHARED_GEMS: "true" 3 | BUNDLE_PATH: "Vendor/bundle" 4 | BUNDLE_WITHOUT: "test:development" 5 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | test: 5 | macos: 6 | xcode: "14.3.1" 7 | environment: 8 | BUNDLE_JOBS: 3 9 | BUNDLE_RETRY: 3 10 | BUNDLE_PATH: vendor/bundle 11 | shell: /bin/bash --login -eo pipefail 12 | steps: 13 | - checkout 14 | - run: sudo defaults write com.apple.dt.Xcode IDEPackageSupportUseBuiltinSCM YES 15 | - run: rm ~/.ssh/id_rsa || true 16 | - run: for ip in $(dig @8.8.8.8 bitbucket.org +short); do ssh-keyscan bitbucket.org,$ip; ssh-keyscan $ip; done 2>/dev/null >> ~/.ssh/known_hosts || true 17 | - run: for ip in $(dig @8.8.8.8 github.com +short); do ssh-keyscan github.com,$ip; ssh-keyscan $ip; done 2>/dev/null >> ~/.ssh/known_hosts || true 18 | - run: brew update 1> /dev/null 2> /dev/null 19 | - run: brew install sourcekitten 20 | - run: brew install coreutils 21 | - run: echo "ruby-3.0.6" > ~/.ruby-version 22 | - run: bundle install 23 | - run: bundle exec rake validate_docs 24 | - run: bundle exec danger || true 25 | - run: set -o pipefail 26 | - run: bundle exec rake build 27 | - run: bundle exec rake tests 28 | workflows: 29 | version: 2 30 | build-test: 31 | jobs: 32 | - test 33 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | ignore: 3 | - Sourcery/main.swift 4 | - Sourcery/CodeGenerated/* 5 | - Pods/* 6 | status: 7 | patch: false 8 | changes: false 9 | project: 10 | default: 11 | target: 70 12 | comment: false 13 | -------------------------------------------------------------------------------- /.github/workflows/bump_homebrew.yml: -------------------------------------------------------------------------------- 1 | name: Bump Homebrew formula 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | tag-name: 7 | description: 'The git tag name to bump the formula to' 8 | required: true 9 | 10 | jobs: 11 | homebrew: 12 | name: Bump Homebrew formula 13 | runs-on: macos-13 14 | steps: 15 | - uses: mislav/bump-homebrew-formula-action@v3 16 | with: 17 | formula-name: sourcery 18 | tag-name: ${{ github.event.inputs.tag-name }} 19 | env: 20 | COMMITTER_TOKEN: ${{ secrets.HOMEBREW_COMMITTER_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: Docker 2 | 3 | permissions: 4 | contents: read 5 | packages: write 6 | 7 | on: 8 | push: 9 | branches: 10 | - master 11 | tags: 12 | - '*' 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-22.04 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | 21 | - name: Extract DOCKER_TAG using tag name 22 | if: startsWith(github.ref, 'refs/tags/') 23 | run: | 24 | echo "DOCKER_TAG=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV 25 | 26 | - name: Use default DOCKER_TAG 27 | if: startsWith(github.ref, 'refs/tags/') != true 28 | run: | 29 | echo "DOCKER_TAG=latest" >> $GITHUB_ENV 30 | 31 | - name: Set lowercase repository name 32 | run: | 33 | echo "REPOSITORY_LC=${REPOSITORY,,}" >>${GITHUB_ENV} 34 | env: 35 | REPOSITORY: '${{ github.repository }}' 36 | 37 | - name: Set up Docker Buildx 38 | uses: docker/setup-buildx-action@v1 39 | 40 | - name: Login to GitHub registry 41 | uses: docker/login-action@v1 42 | with: 43 | username: ${{ github.actor }} 44 | password: ${{ secrets.GITHUB_TOKEN }} 45 | registry: ghcr.io 46 | 47 | - uses: docker/build-push-action@v2 48 | with: 49 | push: true 50 | tags: ghcr.io/${{ env.REPOSITORY_LC }}:${{ env.DOCKER_TAG }} 51 | -------------------------------------------------------------------------------- /.github/workflows/jazzy.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Swift project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift 3 | 4 | name: rake docs 5 | 6 | on: 7 | workflow_call: 8 | workflow_dispatch: 9 | inputs: 10 | ref: 11 | description: 'Ref to build (branch, tag or SHA)' 12 | required: false 13 | default: 'master' 14 | push: 15 | branches: [ "master" ] 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} 20 | 21 | jobs: 22 | update_docs: 23 | runs-on: macos-14 24 | steps: 25 | - name: Set Xcode 15.3.0 26 | run: sudo xcode-select -s /Applications/Xcode_15.3.0.app/Contents/Developer 27 | - name: Print Current Xcode 28 | run: xcode-select -p 29 | - uses: actions/checkout@v3 30 | - name: Update Docs 31 | run: | 32 | brew install coreutils 33 | brew install sourcekitten 34 | bundle install 35 | rake docs 36 | - uses: EndBug/add-and-commit@v9.1.3 37 | with: 38 | add: '.' 39 | message: 'Update Docs' 40 | committer_name: GitHub Actions 41 | committer_email: actions@github.com 42 | 43 | 44 | -------------------------------------------------------------------------------- /.github/workflows/test_macOS.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Swift project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift 3 | 4 | name: test macOS 5 | 6 | on: 7 | workflow_call: 8 | push: 9 | branches: [ "master" ] 10 | pull_request: 11 | branches: [ "master" ] 12 | 13 | concurrency: 14 | group: ${{ github.workflow }}-${{ github.ref }} 15 | cancel-in-progress: ${{ github.ref_type != 'tag' }} 16 | 17 | jobs: 18 | macos_build: 19 | runs-on: macos-14 20 | steps: 21 | - name: Set Xcode 15.3.0 22 | run: sudo xcode-select -s /Applications/Xcode_15.3.0.app/Contents/Developer 23 | - name: Print Current Xcode 24 | run: xcode-select -p 25 | - uses: actions/checkout@v3 26 | - name: Run tests 27 | run: swift test 28 | 29 | 30 | -------------------------------------------------------------------------------- /.github/workflows/test_ubuntu.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Swift project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift 3 | 4 | name: test ubuntu 5 | 6 | on: 7 | workflow_call: 8 | push: 9 | branches: [ "master" ] 10 | pull_request: 11 | branches: [ "master" ] 12 | 13 | concurrency: 14 | group: ${{ github.workflow }}-${{ github.ref }} 15 | cancel-in-progress: ${{ github.ref_type != 'tag' }} 16 | 17 | jobs: 18 | linux_build: 19 | runs-on: ubuntu-22.04 20 | steps: 21 | - name: Setup Swift 22 | uses: YOCKOW/Action-setup-swift@main 23 | with: 24 | swift-version: "5.10" 25 | - name: Get swift version 26 | run: swift --version 27 | - uses: actions/checkout@v3 28 | - name: Run tests 29 | run: swift test 30 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/.gitmodules -------------------------------------------------------------------------------- /.jazzy.yaml: -------------------------------------------------------------------------------- 1 | author: Krzysztof Zabłocki 2 | author_url: https://twitter.com/merowing_ 3 | module: Sourcery 4 | sourcekitten_sourcefile: docs.json 5 | github_url: https://github.com/krzysztofzablocki/Sourcery 6 | copyright: 'Copyright © 2016-2021 Pixle. All rights reserved.' 7 | readme: About.md 8 | documentation: guides/*.md 9 | exclude: ["*_Linux.swift"] 10 | 11 | custom_categories: 12 | - name: Guides 13 | children: 14 | - Installing 15 | - Usage 16 | - Writing templates 17 | 18 | - name: Examples 19 | children: 20 | - Equatable 21 | - Hashable 22 | - Enum cases 23 | - Lenses 24 | - Mocks 25 | - Codable 26 | - Diffable 27 | - LinuxMain 28 | - Decorator 29 | 30 | - name: Types 31 | children: 32 | - Types 33 | - Type 34 | - Protocol 35 | - Class 36 | - Struct 37 | - Enum 38 | - EnumCase 39 | - AssociatedValue 40 | - AssociatedType 41 | - Variable 42 | - Method 43 | - MethodParameter 44 | - Subscript 45 | - TypeName 46 | - TupleType 47 | - TupleElement 48 | - ArrayType 49 | - DictionaryType 50 | - ClosureType 51 | - GenericType 52 | - GenericTypeParameter 53 | - Attribute 54 | - ProtocolComposition 55 | -------------------------------------------------------------------------------- /.pre-commit-hooks.yaml: -------------------------------------------------------------------------------- 1 | - id: sourcery 2 | name: Sourcery 3 | description: 'Meta-programming for Swift, stop writing boilerplate code.' 4 | language: swift 5 | entry: sourcery 6 | require_serial: true 7 | pass_filenames: false 8 | always_run: true 9 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.1 -------------------------------------------------------------------------------- /.sourcery-macOS.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | - SourceryRuntime/Sources/Common 3 | - SourceryRuntime/Sources/macOS 4 | templates: 5 | - Sourcery/Templates/Coding.stencil 6 | - Sourcery/Templates/JSExport.ejs 7 | - Sourcery/Templates/Typed.stencil 8 | - Sourcery/Templates/TypedSpec.stencil 9 | output: 10 | SourceryRuntime/Sources/Generated 11 | -------------------------------------------------------------------------------- /.sourcery-ubuntu.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | - SourceryRuntime/Sources/Common 3 | - SourceryRuntime/Sources/Linux 4 | templates: 5 | - Sourcery/Templates/Coding.stencil 6 | - Sourcery/Templates/JSExport.ejs 7 | - Sourcery/Templates/Typed.stencil 8 | - Sourcery/Templates/TypedSpec.stencil 9 | output: 10 | SourceryRuntime/Sources/Generated 11 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 5.8 2 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: # rule identifiers to exclude from running 2 | - function_parameter_count 3 | - line_length 4 | - variable_name 5 | - cyclomatic_complexity 6 | - nesting 7 | - conditional_binding_cascade 8 | - large_tuple 9 | 10 | opt_in_rules: # some rules are only opt-in 11 | - force_unwrapping 12 | - force_https 13 | - empty_count 14 | - conditional_binding_cascade 15 | 16 | included: 17 | - Sourcery 18 | - SourceryRuntime 19 | - SourceryTests 20 | - Templates/Tests 21 | 22 | excluded: # paths to ignore during linting. Takes precedence over `included`. 23 | - Carthage 24 | - Pods 25 | - Packages 26 | - SourceryTests/Stub 27 | - Templates/Tests/Generated 28 | - Templates/Tests/Expected 29 | 30 | type_body_length: 31 | - 700 #warning 32 | - 1000 #error 33 | 34 | file_length: 35 | - 1000 #warning 36 | - 1200 #error 37 | 38 | function_body_length: 39 | - 125 #warning 40 | - 200 #error 41 | 42 | type_name: 43 | min_length: 3 # only warning 44 | max_length: # warning and error 45 | warning: 50 46 | error: 50 47 | 48 | custom_rules: 49 | force_https: 50 | name: "Force HTTPS over HTTP" 51 | regex: "((?i)http(?!s))" 52 | match_kinds: string 53 | message: "HTTPS should be favored over HTTP" 54 | severity: warning 55 | 56 | explicit_failure_calls: 57 | name: "Avoid asserting 'false'" 58 | regex: '((assert|precondition)\(false)' 59 | message: "Use assertionFailure() or preconditionFailure() instead." 60 | severity: warning 61 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "type": "lldb", 5 | "request": "launch", 6 | "sourceLanguages": [ 7 | "swift" 8 | ], 9 | "name": "Debug sourcery", 10 | "program": "${workspaceFolder:Sourcery}/.build/debug/sourcery", 11 | "args": [], 12 | "cwd": "${workspaceFolder:Sourcery}", 13 | "preLaunchTask": "swift: Build Debug sourcery" 14 | }, 15 | { 16 | "type": "lldb", 17 | "request": "launch", 18 | "sourceLanguages": [ 19 | "swift" 20 | ], 21 | "name": "Release sourcery", 22 | "program": "${workspaceFolder:Sourcery}/.build/release/sourcery", 23 | "args": [], 24 | "cwd": "${workspaceFolder:Sourcery}", 25 | "preLaunchTask": "swift: Build Release sourcery" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Sourcery 2 | 3 | Sourcery is an open source project started by Krzysztof Zabłocki and open to the entire Cocoa community. 4 | 5 | I really appreciate your help! 6 | 7 | ## Filing issues 8 | 9 | When filing an issue, make sure to answer these questions: 10 | 11 | 1. What version of Swift are you using (`swift --version`)? 12 | 2. What did you do? 13 | 3. What did you expect to see? 14 | 4. What did you see instead? 15 | 16 | ## Contributing code 17 | 18 | Before submitting changes, please follow these guidelines: 19 | 20 | 1. Check the open issues and pull requests for existing discussions. 21 | 2. Open an issue to discuss a new feature. 22 | 3. Write tests. 23 | 4. Make sure your changes pass existing tests. 24 | 5. Make sure the entire test suite passes locally and on Circle CI. 25 | 6. Open a Pull Request. 26 | 27 | Unless otherwise noted, the Sourcery source files are distributed under 28 | the MIT-style [LICENSE](LICENSE). 29 | 30 | [Please review our Code of Conduct](https://github.com/krzysztofzablocki/Sourcery/blob/master/CODE_OF_CONDUCT.md) 31 | -------------------------------------------------------------------------------- /Dangerfile: -------------------------------------------------------------------------------- 1 | # Sometimes it's a README fix, or something like that - which isn't relevant for 2 | # including in a project's CHANGELOG for example 3 | not_declared_trivial = !(github.pr_title.include? "#trivial") 4 | has_app_changes = !git.modified_files.grep(/(Sourcery|Templates)/).empty? 5 | 6 | # Make it more obvious that a PR is a work in progress and shouldn't be merged yet 7 | warn("PR is classed as Work in Progress") if github.pr_title.include? "[WIP]" 8 | 9 | # Warn when there is a big PR 10 | warn("Big PR") if git.lines_of_code > 500 11 | 12 | # Don't let testing shortcuts get into master by accident 13 | fail("fit left in tests") if `grep -rI "fit(" SourceryTests/`.length > 1 14 | fail("fdescribe left in tests") if `grep -rI "fdescribe(" SourceryTests/`.length > 1 15 | fail("fcontext left in tests") if `grep -rI "fcontext(" SourceryTests/`.length > 1 16 | 17 | # Changelog entries are required for changes to library files. 18 | no_changelog_entry = !git.modified_files.include?("CHANGELOG.md") 19 | if has_app_changes && no_changelog_entry && not_declared_trivial 20 | fail("Any changes to library code need a summary in the Changelog.") 21 | end 22 | 23 | # New templates must be covered with tests 24 | has_new_stencil_template = !git.added_files.grep(/Templates\/Templates.*\.stencil$/).empty? 25 | has_new_template_test = !git.added_files.grep(/Templates\/Tests\/Generated/).empty? && !git.added_files.grep(/Templates\/Tests\/Context/).empty? && !git.added_files.grep(/Templates\/Tests\/Expected/).empty? 26 | if has_new_stencil_template && !has_new_template_test 27 | fail("Any new stencil template must be covered with test.") 28 | end 29 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BUILDER_IMAGE=swift:6.0-jammy 2 | ARG RUNTIME_IMAGE=swift:6.0-jammy-slim 3 | 4 | # Builder image 5 | FROM ${BUILDER_IMAGE} AS builder 6 | RUN apt-get update && apt-get install -y \ 7 | build-essential \ 8 | libffi-dev \ 9 | libncurses5-dev \ 10 | libsqlite3-dev \ 11 | && rm -r /var/lib/apt/lists/* 12 | WORKDIR /workdir/ 13 | COPY Sourcery Sourcery/ 14 | COPY SourceryExecutable SourceryExecutable/ 15 | COPY SourceryFramework SourceryFramework/ 16 | COPY SourceryJS SourceryJS/ 17 | COPY SourceryRuntime SourceryRuntime/ 18 | COPY SourceryStencil SourceryStencil/ 19 | COPY SourcerySwift SourcerySwift/ 20 | COPY SourceryTests SourceryTests/ 21 | COPY SourceryUtils SourceryUtils/ 22 | COPY Plugins Plugins/ 23 | COPY Templates Templates/ 24 | COPY Tests Tests/ 25 | COPY Package.* ./ 26 | 27 | RUN swift package update 28 | ARG SWIFT_FLAGS="-c release" 29 | RUN swift build $SWIFT_FLAGS --product sourcery 30 | RUN mv `swift build $SWIFT_FLAGS --show-bin-path`/sourcery /usr/bin 31 | RUN sourcery --version 32 | 33 | # Runtime image 34 | FROM ${RUNTIME_IMAGE} 35 | LABEL org.opencontainers.image.source https://github.com/krzysztofzablocki/Sourcery 36 | RUN apt-get update && apt-get install -y \ 37 | libcurl4 \ 38 | libsqlite3-0 \ 39 | libxml2 \ 40 | && rm -r /var/lib/apt/lists/* 41 | COPY --from=builder /usr/bin/sourcery /usr/bin 42 | 43 | RUN sourcery --version 44 | 45 | CMD ["sourcery"] 46 | -------------------------------------------------------------------------------- /Funding.yml: -------------------------------------------------------------------------------- 1 | github: krzysztofzablocki 2 | custom: https://www.merowing.info/membership 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'cocoapods', '1.14.3' 4 | gem 'danger' 5 | gem 'rake' 6 | gem 'slather' 7 | gem 'xcpretty' 8 | gem 'ffi', '1.15.3' 9 | gem 'json', '2.5.1' 10 | gem 'jazzy', '0.14.0' 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016-2021 Krzysztof Zabłocki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Resources/Inside-iOS-Dev-Sourcery-Intro-To-Mocking-Video-Thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/Resources/Inside-iOS-Dev-Sourcery-Intro-To-Mocking-Video-Thumbnail.png -------------------------------------------------------------------------------- /Resources/daemon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/Resources/daemon.gif -------------------------------------------------------------------------------- /Resources/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/Resources/icon-1024.png -------------------------------------------------------------------------------- /Resources/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/Resources/icon-128.png -------------------------------------------------------------------------------- /Resources/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/Resources/icon-16.png -------------------------------------------------------------------------------- /Resources/icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/Resources/icon-256.png -------------------------------------------------------------------------------- /Resources/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/Resources/icon-32.png -------------------------------------------------------------------------------- /Resources/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/Resources/icon-512.png -------------------------------------------------------------------------------- /Resources/icon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/Resources/icon-64.png -------------------------------------------------------------------------------- /Scripts/SwiftLint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | if which swiftlint >/dev/null; then 4 | swiftlint autocorrect 5 | swiftlint 6 | else 7 | echo "warning: SwiftLint not installed. Install using brew update && brew install swiftlint or download from https://github.com/realm/SwiftLint." 8 | fi 9 | -------------------------------------------------------------------------------- /Scripts/bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: scripts/bootstrap 3 | # Prepares git and pods integration by providing pre-commit hook and isolated CocoaPods environment via Bundler 4 | 5 | set -eu 6 | 7 | if [ -h .git/hooks/pre-commit ]; then 8 | rm .git/hooks/pre-commit 9 | fi 10 | 11 | if [ -f .git/hooks/pre-commit ]; then 12 | echo "A git pre-commit hook already exists. Please remove it and re-run this script." 13 | fi 14 | 15 | ln -s ../../scripts/pre-commit.sh .git/hooks/pre-commit 16 | 17 | bundle install --path Vendor/bundle 18 | 19 | bundle exec pod install 20 | -------------------------------------------------------------------------------- /Scripts/pre-commit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eu 3 | 4 | failed=0 5 | 6 | test_pattern='\b(fdescribe|fit|fcontext|xdescribe|xit|xcontext)\b' 7 | if git diff-index -p -M --cached HEAD -- '*Tests.swift' '*Specs.swift' | grep '^+' | egrep "$test_pattern" >/dev/null 2>&1 8 | then 9 | echo "COMMIT REJECTED for fdescribe/fit/fcontext/xdescribe/xit/xcontext." >&2 10 | echo "Remove focused and disabled tests before committing." >&2 11 | echo '----' >&2 12 | git grep --cached -E "$test_pattern" '*Tests.swift' '*Specs.swift' >&2 13 | echo '----' >&2 14 | failed=1 15 | fi 16 | 17 | misplaced_pattern='misplaced="YES"' 18 | 19 | if git diff-index -p -M --cached HEAD -- '*.xib' '*.storyboard' | grep '^+' | egrep "$misplaced_pattern" >/dev/null 2>&1 20 | then 21 | echo "COMMIT REJECTED for misplaced views. Correct them before committing." >&2 22 | echo '----' >&2 23 | git grep --cached -E "$misplaced_pattern" '*.xib' '*.storyboard' >&2 24 | echo '----' >&2 25 | failed=1 26 | fi 27 | 28 | exit $failed 29 | -------------------------------------------------------------------------------- /Sourcery-Example/CodeGenerated/Basic.generated.swift: -------------------------------------------------------------------------------- 1 | // Found 2 Types 2 | // AppDelegate ViewController 3 | -------------------------------------------------------------------------------- /Sourcery-Example/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'Sourcery-Example' do 5 | # Uncomment the next line if you're using Swift or would like to use dynamic frameworks 6 | use_frameworks! 7 | 8 | pod 'Sourcery' 9 | end 10 | -------------------------------------------------------------------------------- /Sourcery-Example/Sourcery-Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sourcery-Example/Sourcery-Example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Sourcery-Example/Sourcery-Example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Sourcery-Example/Sourcery-Example/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sourcery-Example/Sourcery-Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Sourcery-Example/Sourcery-Example/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Sourcery-Example 4 | // 5 | // Created by Krzysztof Zablocki on 11/12/2016. 6 | // Copyright © 2016 Pixle. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Sourcery-Example/Templates/Basic.stencil: -------------------------------------------------------------------------------- 1 | // Found {{ types.all.count }} Types 2 | // {% for type in types.all %} {{ type.name }} {% endfor %} 3 | -------------------------------------------------------------------------------- /Sourcery.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "Sourcery" 4 | s.version = "2.2.7" 5 | s.summary = "A tool that brings meta-programming to Swift, allowing you to code generate Swift code." 6 | s.ios.deployment_target = '12' 7 | s.osx.deployment_target = '10.15' 8 | s.tvos.deployment_target = '12' 9 | s.watchos.deployment_target = '4' 10 | 11 | s.description = <<-DESC 12 | A tool that brings meta-programming to Swift, allowing you to code generate Swift code. 13 | * Featuring daemon mode that allows you to write templates side-by-side with generated code. 14 | * Using SourceKit so you can scan your regular code. 15 | DESC 16 | 17 | s.homepage = "https://github.com/krzysztofzablocki/Sourcery" 18 | s.license = 'MIT' 19 | s.author = { "Krzysztof Zabłocki" => "krzysztof.zablocki@pixle.pl" } 20 | s.social_media_url = "https://twitter.com/merowing_" 21 | 22 | s.source = { :http => "https://github.com/krzysztofzablocki/Sourcery/releases/download/#{s.version}/sourcery-#{s.version}.zip" } 23 | s.preserve_paths = '*' 24 | s.exclude_files = '**/file.zip' 25 | 26 | s.subspec 'CLI-Only' do |subspec| 27 | subspec.preserve_paths = "bin" 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /Sourcery/Generating/Templates/Stencil/StencilTemplate.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SourceryFramework 3 | import SourceryRuntime 4 | import SourceryStencil 5 | 6 | extension StencilTemplate: SourceryFramework.Template { 7 | public func render(_ context: TemplateContext) throws -> String { 8 | do { 9 | return try self.render(context.stencilContext) 10 | } catch { 11 | throw "\(sourcePath): \(error)" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Sourcery/Generating/Templates/Swift/SwiftTemplate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftTemplate.swift 3 | // Sourcery 4 | // 5 | // Created by Krunoslav Zaher on 12/30/16. 6 | // Copyright © 2016 Pixle. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SourceryFramework 11 | import SourceryRuntime 12 | import SourcerySwift 13 | 14 | extension SwiftTemplate: Template { 15 | 16 | public func render(_ context: TemplateContext) throws -> String { 17 | return try self.render(context as Any) 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Sourcery/Templates/Description.stencil: -------------------------------------------------------------------------------- 1 | // swiftlint:disable vertical_whitespace 2 | 3 | 4 | {% for type in types.implementing.AutoDescription|class %} {% if type.variables.count %} 5 | extension {{ type.name }} { 6 | /// :nodoc: 7 | override {{ type.accessLevel }} var description: String { 8 | var string = {% if type.inheritedTypes.first == "NSObject" %}"\(Swift.type(of: self)): "{% else %}super.description 9 | string += ", "{% endif %} 10 | {% for variable in type.variables|!annotated:"skipDescription" %}string += "{{ variable.name }} = \(String(describing: self.{{ variable.name }})){% if not forloop.last %}, {% endif %}" 11 | {% endfor %}return string 12 | } 13 | } 14 | {% endif %}{% endfor %} 15 | -------------------------------------------------------------------------------- /Sourcery/Templates/Diffable.stencil: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | {% for type in types.implementing.AutoDiffable|!protocol|!annotated:"skipDiffing" %} 4 | extension {{ type.name }}{% if not type.supertype.implements.AutoDiffable %}: Diffable{% endif %} { 5 | {% if type.based.Type %}override {% else %}@objc {% endif %}public func diffAgainst(_ object: Any?) -> DiffableResult { 6 | let results = DiffableResult() 7 | guard let castObject = object as? {{ type.name }} else { 8 | results.append("Incorrect type ") 9 | return results 10 | } 11 | {% for variable in type.storedVariables|!annotated:"skipEquality" %}results.append(contentsOf: DiffableResult(identifier: "{{ variable.name }}").trackDifference(actual: self.{{ variable.name }}, expected: castObject.{{ variable.name }})) 12 | {% endfor %} 13 | {% if type.supertype.implements.AutoDiffable %}results.append(contentsOf: super.diffAgainst(castObject)) 14 | return results{% else %}return results{% endif %} 15 | } 16 | }{% endfor %} 17 | -------------------------------------------------------------------------------- /Sourcery/Templates/Equality.stencil: -------------------------------------------------------------------------------- 1 | // swiftlint:disable vertical_whitespace 2 | 3 | 4 | {% for type in types.implementing.AutoEquatable|class %} 5 | extension {{ type.name }} { 6 | /// :nodoc: 7 | {{ type.accessLevel }} override func isEqual(_ object: Any?) -> Bool { 8 | guard let rhs = object as? {{ type.name }} else { return false } 9 | {% for variable in type.storedVariables|!annotated:"skipEquality" %}if self.{{ variable.name }} != rhs.{{ variable.name }} { return false } 10 | {% endfor %} 11 | {% for variable in type.computedVariables|annotated:"forceEquality" %}if self.{{ variable.name }} != rhs.{{ variable.name }} { return false } 12 | {% endfor %} 13 | {% if type.inheritedTypes.first == "NSObject" %}return true{% else %}return super.isEqual(rhs){% endif %} 14 | } 15 | } 16 | {% endfor %} 17 | 18 | {% for type in types.implementing.AutoEquatable|class %} 19 | // MARK: - {{ type.name }} AutoHashable 20 | extension {{ type.name }} { 21 | {{ type.accessLevel }} override var hash: Int { 22 | var hasher = Hasher() 23 | {% for variable in type.storedVariables|!annotated:"skipEquality" %}hasher.combine(self.{{ variable.name }}) 24 | {% endfor %} 25 | {% for variable in type.computedVariables|annotated:"forceEquality" %}hasher.combine({{ variable.name }}) 26 | {% endfor %} 27 | {% if not type.inheritedTypes.first == "NSObject" %}hasher.combine(super.hash){% endif %} 28 | return hasher.finalize() 29 | } 30 | } 31 | {% endfor %} 32 | -------------------------------------------------------------------------------- /Sourcery/Templates/JSExport.ejs: -------------------------------------------------------------------------------- 1 | // swiftlint:disable vertical_whitespace trailing_newline 2 | 3 | #if canImport(JavaScriptCore) 4 | import JavaScriptCore 5 | 6 | <%_ for (type of types.implementing.AutoJSExport) { -%> 7 | <%_ if (type.kind != "protocol" && !type.annotations.skipJSExport) { -%> 8 | @objc protocol <%= type.name %>AutoJSExport: JSExport { 9 | <%_ for (variable of type.allVariables) { -%> 10 | <%_ if (!variable.annotations.skipJSExport) { -%> 11 | var <%= variable.name %>: <%= variable.typeName.name %> { get } 12 | <%_ } -%> 13 | <%_ } -%> 14 | } 15 | 16 | extension <%= type.name %>: <%= type.name %>AutoJSExport {} 17 | <%_ } %> 18 | <%_ } %> 19 | #endif -------------------------------------------------------------------------------- /Sourcery/Templates/Typed.stencil: -------------------------------------------------------------------------------- 1 | // swiftlint:disable vertical_whitespace 2 | 3 | 4 | {% for type in types.implementing.Typed %} 5 | extension {{ type.name }} { 6 | /// Whether type is optional. Shorthand for `typeName.isOptional` 7 | {{ type.accessLevel }} var isOptional: Bool { return typeName.isOptional } 8 | /// Whether type is implicitly unwrapped optional. Shorthand for `typeName.isImplicitlyUnwrappedOptional` 9 | {{ type.accessLevel }} var isImplicitlyUnwrappedOptional: Bool { return typeName.isImplicitlyUnwrappedOptional } 10 | /// Type name without attributes and optional type information. Shorthand for `typeName.unwrappedTypeName` 11 | {{ type.accessLevel }} var unwrappedTypeName: String { return typeName.unwrappedTypeName } 12 | /// Actual type name if declaration uses typealias, otherwise just a `typeName`. Shorthand for `typeName.actualTypeName` 13 | {{ type.accessLevel }} var actualTypeName: TypeName? { return typeName.actualTypeName ?? typeName } 14 | /// Whether type is a tuple. Shorthand for `typeName.isTuple` 15 | {{ type.accessLevel }} var isTuple: Bool { return typeName.isTuple } 16 | /// Whether type is a closure. Shorthand for `typeName.isClosure` 17 | {{ type.accessLevel }} var isClosure: Bool { return typeName.isClosure } 18 | /// Whether type is an array. Shorthand for `typeName.isArray` 19 | {{ type.accessLevel }} var isArray: Bool { return typeName.isArray } 20 | /// Whether type is a set. Shorthand for `typeName.isSet` 21 | {{ type.accessLevel }} var isSet: Bool { return typeName.isSet } 22 | /// Whether type is a dictionary. Shorthand for `typeName.isDictionary` 23 | {{ type.accessLevel }} var isDictionary: Bool { return typeName.isDictionary } 24 | }{% endfor %} 25 | -------------------------------------------------------------------------------- /Sourcery/Utils/ByteRangeConversion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ByteRangeConversion.swift 3 | // Sourcery 4 | // 5 | // Created by Evgeniy Gubin on 16.04.2021. 6 | // Copyright © 2021 Pixle. All rights reserved. 7 | // 8 | 9 | import class SourceryRuntime.BytesRange 10 | import struct SourceryFramework.ByteRange 11 | import struct SourceryFramework.ByteCount 12 | 13 | extension ByteRange { 14 | init(bytesRange: BytesRange) { 15 | self.init(location: ByteCount(bytesRange.offset), length: ByteCount(bytesRange.length)) 16 | } 17 | } 18 | 19 | extension BytesRange { 20 | convenience init(byteRange: ByteRange) { 21 | self.init(offset: Int64(byteRange.location.value), length: Int64(byteRange.length.value)) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sourcery/Utils/BytesRange + Editing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BytesRange + Editing.swift 3 | // Sourcery 4 | // 5 | // Created by Evgeniy Gubin on 16.04.2021. 6 | // Copyright © 2021 Pixle. All rights reserved. 7 | // 8 | 9 | import class SourceryRuntime.BytesRange 10 | import struct SourceryFramework.ByteRange 11 | import struct SourceryFramework.ByteCount 12 | 13 | extension BytesRange { 14 | /* 15 | See ByteRange.changingContent(_:) 16 | */ 17 | func changingContent(_ change: ByteRange) -> BytesRange { 18 | let byteRange = ByteRange(bytesRange: self) 19 | let result = byteRange.editingContent(change) 20 | return BytesRange(byteRange: result) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sourcery/Utils/DryOutputModels.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct DryOutputType: Codable { 4 | enum SubType: String, Codable { 5 | case allTemplates 6 | case template 7 | case path 8 | case range 9 | } 10 | 11 | let id: String? 12 | let subType: SubType 13 | 14 | static var allTemplates: DryOutputType { 15 | .init(id: nil, subType: .allTemplates) 16 | } 17 | static func template(_ path: String) -> DryOutputType { 18 | .init(id: path, subType: .template) 19 | } 20 | static func path(_ path: String) -> DryOutputType { 21 | .init(id: path, subType: .path) 22 | } 23 | static func range(_ range: NSRange, in file: String) -> DryOutputType { 24 | let startIndex = range.location 25 | let endIndex = range.location + range.length 26 | 27 | if startIndex == endIndex { 28 | return .init(id: "\(file):\(startIndex)", subType: .range) 29 | } 30 | 31 | return .init(id: "\(file):\(startIndex)-\(endIndex)", subType: .range) 32 | } 33 | } 34 | 35 | struct DryOutputValue: Codable { 36 | let type: DryOutputType 37 | let outputPath: String 38 | let value: String 39 | } 40 | 41 | struct DryOutputSuccess: Codable { 42 | let outputs: [DryOutputValue] 43 | } 44 | 45 | public struct DryOutputFailure: Codable { 46 | public let error: String 47 | public let log: [String] 48 | 49 | public init(error: String, log: [String]) { 50 | self.error = error 51 | self.log = log 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sourcery/Utils/NSRange + Editing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by hemet_000 on 14.04.2021. 3 | // 4 | 5 | import Foundation 6 | import struct SourceryFramework.ByteRange 7 | import struct SourceryFramework.ByteCount 8 | 9 | extension NSRange { 10 | /* 11 | See ByteRange.changingContent(_:) 12 | */ 13 | func changingContent(_ change: NSRange) -> NSRange { 14 | let byteRange = ByteRange(location: ByteCount(location), length: ByteCount(length)) 15 | let changeByteRange = ByteRange(location: ByteCount(change.location), length: ByteCount(change.length)) 16 | let result = byteRange.editingContent(changeByteRange) 17 | return NSRange(location: result.location.value, length: result.length.value) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SourceryExecutable/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(CURRENT_PROJECT_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2016 Pixle. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /SourceryFramework.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "SourceryFramework" 4 | s.version = "2.2.7" 5 | s.summary = "A tool that brings meta-programming to Swift, allowing you to code generate Swift code." 6 | s.platform = :osx, '10.15' 7 | 8 | s.description = <<-DESC 9 | A tool that brings meta-programming to Swift, allowing you to code generate Swift code. 10 | * Featuring daemon mode that allows you to write templates side-by-side with generated code. 11 | * Using SourceKit so you can scan your regular code. 12 | DESC 13 | 14 | s.homepage = "https://github.com/krzysztofzablocki/Sourcery" 15 | s.license = 'MIT' 16 | s.author = { "Krzysztof Zabłocki" => "krzysztof.zablocki@pixle.pl" } 17 | s.social_media_url = "https://twitter.com/merowing_" 18 | s.source = { :http => "https://github.com/krzysztofzablocki/Sourcery/releases/download/#{s.version}/sourcery-#{s.version}.zip" } 19 | 20 | s.source_files = "SourceryFramework/Sources/**/*.swift" 21 | 22 | s.osx.deployment_target = '10.15' 23 | 24 | s.dependency 'SourceryUtils' 25 | s.dependency 'SourceryRuntime' 26 | end 27 | -------------------------------------------------------------------------------- /SourceryFramework/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2018 Pixle. All rights reserved. 23 | 24 | 25 | -------------------------------------------------------------------------------- /SourceryFramework/SourceryFramework.h: -------------------------------------------------------------------------------- 1 | // 2 | // SourceryFramework.h 3 | // SourceryFramework 4 | // 5 | // Created by Ilya Puchka on 24/12/2018. 6 | // Copyright © 2018 Pixle. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SourceryFramework. 12 | FOUNDATION_EXPORT double SourceryFrameworkVersionNumber; 13 | 14 | //! Project version string for SourceryFramework. 15 | FOUNDATION_EXPORT const unsigned char SourceryFrameworkVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Generating/Generator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Krzysztof Zablocki on 13/09/2016. 3 | // Copyright (c) 2016 Pixle. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | import SourceryRuntime 8 | 9 | public enum Generator { 10 | public static func generate(_ parserResult: FileParserResult?, types: Types, functions: [SourceryMethod], template: Template, arguments: [String: NSObject] = [:]) throws -> String { 11 | Log.verbose("Rendering template \(template.sourcePath)") 12 | return try template.render(TemplateContext(parserResult: parserResult, types: types, functions: functions, arguments: arguments)) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Generating/SourceryTemplate.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct SourceryTemplate: Decodable { 4 | public struct Instance: Decodable { 5 | public enum Kind: String, Codable, Equatable { 6 | case stencil 7 | case ejs 8 | } 9 | 10 | public var content: String 11 | public var kind: Kind 12 | } 13 | 14 | enum CodingKeys: CodingKey { 15 | case instance 16 | } 17 | 18 | public let instance: Instance 19 | 20 | public init(from decoder: Decoder) throws { 21 | let container = try decoder.container(keyedBy: CodingKeys.self) 22 | let data = try container.decode(Data.self, forKey: .instance) 23 | instance = try JSONDecoder().decode(Instance.self, from: data) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Generating/Template.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Krzysztof Zablocki on 31/12/2016. 3 | // Copyright (c) 2016 Pixle. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | import PathKit 8 | import SourceryRuntime 9 | 10 | /// Generic template that can be used for any of the Sourcery output variants 11 | public protocol Template { 12 | /// Path to template 13 | var sourcePath: Path { get } 14 | 15 | /// Generate 16 | /// 17 | /// - Parameter types: List of types to generate. 18 | /// - Parameter arguments: List of template arguments. 19 | /// - Returns: Generated code. 20 | /// - Throws: `Throws` template errors 21 | func render(_ context: TemplateContext) throws -> String 22 | } 23 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/FileParserType.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathKit 3 | import SourceryRuntime 4 | 5 | public protocol FileParserType { 6 | 7 | var path: String? { get } 8 | var modifiedDate: Date? { get } 9 | 10 | /// Creates parser for a given contents and path. 11 | /// - Throws: parsing errors. 12 | init(contents: String, forceParse: [String], parseDocumentation: Bool, path: Path?, module: String?) throws 13 | 14 | /// Parses given file context. 15 | /// 16 | /// - Returns: All types we could find. 17 | func parse() throws -> FileParserResult 18 | } 19 | 20 | public enum ParserEngine { 21 | case swiftSyntax 22 | } 23 | 24 | public var parserEngine: ParserEngine = .swiftSyntax 25 | 26 | public func makeParser(for contents: String, forceParse: [String] = [], parseDocumentation: Bool = false, path: Path? = nil, module: String? = nil) throws -> FileParserType { 27 | switch parserEngine { 28 | case .swiftSyntax: 29 | return try FileParserSyntax(contents: contents, forceParse: forceParse, parseDocumentation: parseDocumentation, path: path, module: module) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/AST/AccessLevel+SwiftSyntax.swift: -------------------------------------------------------------------------------- 1 | import SourceryRuntime 2 | import SwiftSyntax 3 | 4 | extension AccessLevel { 5 | init?(_ modifier: Modifier) { 6 | switch modifier.tokenKind { 7 | case .keyword(.public): 8 | self = .public 9 | case .keyword(.package): 10 | self = .package 11 | case .keyword(.private): 12 | self = .private 13 | case .keyword(.fileprivate): 14 | self = .fileprivate 15 | case .keyword(.internal): 16 | self = .internal 17 | case .keyword(.open), .identifier("open"): 18 | self = .open 19 | default: 20 | return nil 21 | } 22 | } 23 | 24 | static func `default`(for parent: Type?) -> AccessLevel { 25 | var defaultAccess = AccessLevel.internal 26 | if let type = parent, type.isExtension || type is SourceryProtocol { 27 | defaultAccess = AccessLevel(rawValue: type.accessLevel) ?? defaultAccess 28 | } 29 | 30 | return defaultAccess 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/AST/Actor+SwiftSyntax.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SourceryRuntime 3 | import SwiftSyntax 4 | 5 | extension Actor { 6 | convenience init(_ node: ActorDeclSyntax, parent: Type?, annotationsParser: AnnotationsParser) { 7 | let modifiers = node.modifiers.map(Modifier.init) 8 | 9 | self.init( 10 | name: node.name.text.trimmingCharacters(in: .whitespaces), 11 | parent: parent, 12 | accessLevel: modifiers.lazy.compactMap(AccessLevel.init).first ?? .default(for: parent), 13 | isExtension: false, 14 | variables: [], 15 | methods: [], 16 | subscripts: [], 17 | inheritedTypes: node.inheritanceClause?.inheritedTypes.map { $0.type.description.trimmed } ?? [], 18 | containedTypes: [], 19 | typealiases: [], 20 | attributes: Attribute.from(node.attributes), 21 | modifiers: modifiers.map(SourceryModifier.init), 22 | annotations: annotationsParser.annotations(from: node), 23 | documentation: annotationsParser.documentation(from: node), 24 | isGeneric: node.genericParameterClause?.parameters.isEmpty == false 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/AST/Class+SwiftSyntax.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SourceryRuntime 3 | import SwiftSyntax 4 | 5 | extension Class { 6 | convenience init(_ node: ClassDeclSyntax, parent: Type?, annotationsParser: AnnotationsParser) { 7 | let modifiers = node.modifiers.map(Modifier.init) 8 | 9 | let genericRequirements: [GenericRequirement] = node.genericWhereClause?.requirements.compactMap { requirement in 10 | if let sameType = requirement.requirement.as(SameTypeRequirementSyntax.self) { 11 | return GenericRequirement(sameType) 12 | } else if let conformanceType = requirement.requirement.as(ConformanceRequirementSyntax.self) { 13 | return GenericRequirement(conformanceType) 14 | } 15 | return nil 16 | } ?? [] 17 | 18 | self.init( 19 | name: node.name.text.trimmingCharacters(in: .whitespaces), 20 | parent: parent, 21 | accessLevel: modifiers.lazy.compactMap(AccessLevel.init).first ?? .default(for: parent), 22 | isExtension: false, 23 | variables: [], 24 | methods: [], 25 | subscripts: [], 26 | inheritedTypes: node.inheritanceClause?.inheritedTypes.map { $0.type.description.trimmed } ?? [], 27 | containedTypes: [], 28 | typealiases: [], 29 | genericRequirements: genericRequirements, 30 | attributes: Attribute.from(node.attributes), 31 | modifiers: modifiers.map(SourceryModifier.init), 32 | annotations: annotationsParser.annotations(from: node), 33 | documentation: annotationsParser.documentation(from: node), 34 | isGeneric: node.genericParameterClause?.parameters.isEmpty == false 35 | ) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/AST/Enum+SwiftSyntax.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SourceryRuntime 3 | import SwiftSyntax 4 | 5 | extension Enum { 6 | convenience init(_ node: EnumDeclSyntax, parent: Type?, annotationsParser: AnnotationsParser) { 7 | let modifiers = node.modifiers.map(Modifier.init) 8 | 9 | //let rawTypeName: String? = node.inheritanceClause?.inheritedTypeCollection.first?.typeName.description.trimmed ?? nil 10 | self.init( 11 | name: node.name.text.trimmingCharacters(in: .whitespaces), 12 | parent: parent, 13 | accessLevel: modifiers.lazy.compactMap(AccessLevel.init).first ?? .default(for: parent), 14 | isExtension: false, 15 | inheritedTypes: node.inheritanceClause?.inheritedTypes.map { $0.type.description.trimmed } ?? [], // TODO: type name? 16 | rawTypeName: nil, 17 | cases: [], 18 | variables: [], 19 | methods: [], 20 | containedTypes: [], 21 | typealiases: [], 22 | attributes: Attribute.from(node.attributes), 23 | modifiers: modifiers.map(SourceryModifier.init), 24 | annotations: annotationsParser.annotations(from: node), 25 | documentation: annotationsParser.documentation(from: node), 26 | isGeneric: node.genericParameterClause?.parameters.isEmpty == false 27 | ) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/AST/GenericParameter+SwiftSyntax.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftSyntax 3 | import SourceryRuntime 4 | 5 | extension GenericParameter { 6 | convenience init(_ node: GenericParameterSyntax) { 7 | self.init(name: node.name.description.trimmed, inheritedTypeName: node.inheritedType.flatMap(TypeName.init(_:))) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/AST/GenericRequirement+SwiftSyntax.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftSyntax 3 | import SourceryRuntime 4 | 5 | extension GenericRequirement { 6 | convenience init(_ node: SameTypeRequirementSyntax) { 7 | let leftType = node.leftType.description.trimmed 8 | let rightTypeName = TypeName(node.rightType.description.trimmed) 9 | let rightType = Type(name: rightTypeName.unwrappedTypeName, isGeneric: true) 10 | let protocolType = SourceryProtocol(name: rightTypeName.unwrappedTypeName, implements: [rightTypeName.unwrappedTypeName: rightType]) 11 | self.init(leftType: .init(name: leftType), rightType: .init(typeName: rightTypeName, type: protocolType), relationship: .equals) 12 | } 13 | 14 | convenience init(_ node: ConformanceRequirementSyntax) { 15 | let leftType = node.leftType.description.trimmed 16 | let rightTypeName = TypeName(node.rightType.description.trimmed) 17 | let rightType = Type(name: rightTypeName.unwrappedTypeName, isGeneric: true) 18 | let protocolType = SourceryProtocol(name: rightTypeName.unwrappedTypeName, implements: [rightTypeName.unwrappedTypeName: rightType]) 19 | self.init(leftType: .init(name: leftType), rightType: .init(typeName: rightTypeName, type: protocolType), relationship: .conformsTo) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/AST/GenericType+SwiftSyntax.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SourceryRuntime 3 | import SwiftSyntax 4 | 5 | extension GenericType { 6 | convenience init(name: String, node: GenericArgumentClauseSyntax) { 7 | let parameters = node.arguments.map { argument in 8 | GenericTypeParameter(typeName: TypeName(argument.argument)) 9 | } 10 | 11 | self.init(name: name, typeParameters: parameters) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/AST/Protocol+SwiftSyntax.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SourceryRuntime 3 | import SwiftSyntax 4 | 5 | extension SourceryProtocol { 6 | convenience init(_ node: ProtocolDeclSyntax, parent: Type?, annotationsParser: AnnotationsParser) { 7 | let modifiers = node.modifiers.map(Modifier.init) 8 | 9 | let genericRequirements: [GenericRequirement] = node.genericWhereClause?.requirements.compactMap { requirement in 10 | if let sameType = requirement.requirement.as(SameTypeRequirementSyntax.self) { 11 | return GenericRequirement(sameType) 12 | } else if let conformanceType = requirement.requirement.as(ConformanceRequirementSyntax.self) { 13 | return GenericRequirement(conformanceType) 14 | } 15 | return nil 16 | } ?? [] 17 | 18 | self.init( 19 | name: node.name.text.trimmingCharacters(in: .whitespaces), 20 | parent: parent, 21 | accessLevel: modifiers.lazy.compactMap(AccessLevel.init).first ?? .internal, 22 | isExtension: false, 23 | variables: [], 24 | methods: [], 25 | subscripts: [], 26 | inheritedTypes: node.inheritanceClause?.inheritedTypes.map { $0.type.description.trimmed } ?? [], 27 | containedTypes: [], 28 | typealiases: [], 29 | genericRequirements: genericRequirements, 30 | attributes: Attribute.from(node.attributes), 31 | modifiers: modifiers.map(SourceryModifier.init), 32 | annotations: annotationsParser.annotations(from: node), 33 | documentation: annotationsParser.documentation(from: node) 34 | ) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/AST/Struct+SwiftSyntax.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SourceryRuntime 3 | import SwiftSyntax 4 | 5 | extension Struct { 6 | convenience init(_ node: StructDeclSyntax, parent: Type?, annotationsParser: AnnotationsParser) { 7 | let modifiers = node.modifiers.map(Modifier.init) 8 | 9 | let genericRequirements: [GenericRequirement] = node.genericWhereClause?.requirements.compactMap { requirement in 10 | if let sameType = requirement.requirement.as(SameTypeRequirementSyntax.self) { 11 | return GenericRequirement(sameType) 12 | } else if let conformanceType = requirement.requirement.as(ConformanceRequirementSyntax.self) { 13 | return GenericRequirement(conformanceType) 14 | } 15 | return nil 16 | } ?? [] 17 | 18 | self.init( 19 | name: node.name.text.trimmed, 20 | parent: parent, 21 | accessLevel: modifiers.lazy.compactMap(AccessLevel.init).first ?? .default(for: parent), 22 | isExtension: false, 23 | variables: [], 24 | methods: [], 25 | subscripts: [], 26 | inheritedTypes: node.inheritanceClause?.inheritedTypes.map { $0.type.description.trimmed } ?? [], 27 | containedTypes: [], 28 | typealiases: [], 29 | genericRequirements: genericRequirements, 30 | attributes: Attribute.from(node.attributes), 31 | modifiers: modifiers.map(SourceryModifier.init), 32 | annotations: annotationsParser.annotations(from: node), 33 | documentation: annotationsParser.documentation(from: node), 34 | isGeneric: node.genericParameterClause?.parameters.isEmpty == false 35 | ) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/AST/Type+SwiftSyntax.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SourceryRuntime 3 | import SwiftSyntax 4 | 5 | extension Type { 6 | convenience init?(_ node: TypeSyntax) { 7 | guard let typeIdentifier = node.as(IdentifierTypeSyntax.self) else { return nil } 8 | let name = typeIdentifier.name.text.trimmed 9 | let generic = typeIdentifier.genericArgumentClause.map { GenericType(name: typeIdentifier.name.text, node: $0) } 10 | self.init(name: name, isGeneric: generic != nil) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/SwiftSyntax/Syntax+Extensions.swift: -------------------------------------------------------------------------------- 1 | import SwiftSyntax 2 | 3 | public extension TriviaPiece { 4 | /// Returns string value of a comment piece or nil otherwise 5 | var comment: String? { 6 | switch self { 7 | case .spaces, 8 | .tabs, 9 | .verticalTabs, 10 | .formfeeds, 11 | .newlines, 12 | .carriageReturns, 13 | .carriageReturnLineFeeds, 14 | .unexpectedText, 15 | .backslashes, 16 | .pounds: 17 | return nil 18 | case .lineComment(let comment), 19 | .blockComment(let comment), 20 | .docLineComment(let comment), 21 | .docBlockComment(let comment): 22 | return comment 23 | } 24 | } 25 | } 26 | 27 | protocol IdentifierSyntax: SyntaxProtocol { 28 | var identifier: TokenSyntax { get } 29 | } 30 | 31 | extension ActorDeclSyntax: IdentifierSyntax {} 32 | 33 | extension ClassDeclSyntax: IdentifierSyntax {} 34 | 35 | extension StructDeclSyntax: IdentifierSyntax {} 36 | 37 | extension EnumDeclSyntax: IdentifierSyntax {} 38 | 39 | extension ProtocolDeclSyntax: IdentifierSyntax {} 40 | 41 | extension FunctionDeclSyntax: IdentifierSyntax {} 42 | 43 | extension TypeAliasDeclSyntax: IdentifierSyntax {} 44 | 45 | extension OperatorDeclSyntax: IdentifierSyntax {} 46 | 47 | extension EnumCaseElementSyntax: IdentifierSyntax {} 48 | 49 | extension SyntaxProtocol { 50 | func withoutTrivia() -> Self { 51 | with(\.leadingTrivia, []) 52 | .with(\.trailingTrivia, []) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/Utils/Bridges.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Array { 4 | public func bridge() -> NSArray { 5 | return self as NSArray 6 | } 7 | } 8 | 9 | extension CharacterSet { 10 | public func bridge() -> NSCharacterSet { 11 | return self as NSCharacterSet 12 | } 13 | } 14 | 15 | extension Dictionary { 16 | public func bridge() -> NSDictionary { 17 | return self as NSDictionary 18 | } 19 | } 20 | 21 | extension NSString { 22 | public func bridge() -> String { 23 | return self as String 24 | } 25 | } 26 | 27 | extension String { 28 | public func bridge() -> NSString { 29 | return self as NSString 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SourceryFramework/Sources/Parsing/Utils/Verifier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Krzysztof Zablocki on 23/01/2017. 3 | // Copyright (c) 2017 Pixle. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | import PathKit 8 | import SourceryUtils 9 | 10 | public enum Verifier { 11 | 12 | // swiftlint:disable:next force_try 13 | private static let conflictRegex = try! NSRegularExpression(pattern: "^\\s+?(<<<<<|>>>>>)") 14 | 15 | public enum Result { 16 | case isCodeGenerated 17 | case containsConflictMarkers 18 | case approved 19 | } 20 | 21 | public static func canParse(content: String, 22 | path: Path, 23 | generationMarker: String, 24 | forceParse: [String] = []) -> Result { 25 | guard !content.isEmpty else { return .approved } 26 | 27 | let shouldForceParse = forceParse.contains { name in 28 | return path.hasExtension(as: name) 29 | } 30 | 31 | if content.hasPrefix(generationMarker) && shouldForceParse == false { 32 | return .isCodeGenerated 33 | } 34 | 35 | if conflictRegex.numberOfMatches(in: content, options: .anchored, range: content.bridge().entireRange) > 0 { 36 | return .containsConflictMarkers 37 | } 38 | 39 | return .approved 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SourceryJS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2018 Pixle. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SourceryJS/SourceryJS.h: -------------------------------------------------------------------------------- 1 | // 2 | // SourceryJS.h 3 | // SourceryJS 4 | // 5 | // Created by Ilya Puchka on 25/01/2018. 6 | // Copyright © 2018 Pixle. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SourceryJS. 12 | FOUNDATION_EXPORT double SourceryJSVersionNumber; 13 | 14 | //! Project version string for SourceryJS. 15 | FOUNDATION_EXPORT const unsigned char SourceryJSVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /SourceryRuntime.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "SourceryRuntime" 4 | s.version = "2.2.7" 5 | s.summary = "A tool that brings meta-programming to Swift, allowing you to code generate Swift code." 6 | s.platform = :osx, '10.15' 7 | 8 | s.description = <<-DESC 9 | A tool that brings meta-programming to Swift, allowing you to code generate Swift code. 10 | * Featuring daemon mode that allows you to write templates side-by-side with generated code. 11 | * Using SourceKit so you can scan your regular code. 12 | DESC 13 | 14 | s.homepage = "https://github.com/krzysztofzablocki/Sourcery" 15 | s.license = 'MIT' 16 | s.author = { "Krzysztof Zabłocki" => "krzysztof.zablocki@pixle.pl" } 17 | s.social_media_url = "https://twitter.com/merowing_" 18 | s.source = { :http => "https://github.com/krzysztofzablocki/Sourcery/releases/download/#{s.version}/sourcery-#{s.version}.zip" } 19 | 20 | s.source_files = "SourceryRuntime/Sources/**/*.swift" 21 | 22 | s.osx.deployment_target = '10.15' 23 | 24 | s.dependency 'SourceryUtils' 25 | end 26 | -------------------------------------------------------------------------------- /SourceryRuntime/Sources/Common/AST/AccessLevel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Krzysztof Zablocki on 13/09/2016. 3 | // Copyright (c) 2016 Pixle. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | /// :nodoc: 9 | public enum AccessLevel: String { 10 | case `package` = "package" 11 | case `internal` = "internal" 12 | case `private` = "private" 13 | case `fileprivate` = "fileprivate" 14 | case `public` = "public" 15 | case `open` = "open" 16 | case none = "" 17 | } 18 | -------------------------------------------------------------------------------- /SourceryRuntime/Sources/Common/AST/Annotations.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias Annotations = [String: NSObject] 4 | 5 | /// Describes annotated declaration, i.e. type, method, variable, enum case 6 | public protocol Annotated { 7 | /** 8 | All annotations of declaration stored by their name. Value can be `bool`, `String`, float `NSNumber` 9 | or array of those types if you use several annotations with the same name. 10 | 11 | **Example:** 12 | 13 | ``` 14 | //sourcery: booleanAnnotation 15 | //sourcery: stringAnnotation = "value" 16 | //sourcery: numericAnnotation = 0.5 17 | 18 | [ 19 | "booleanAnnotation": true, 20 | "stringAnnotation": "value", 21 | "numericAnnotation": 0.5 22 | ] 23 | ``` 24 | */ 25 | var annotations: Annotations { get } 26 | } 27 | -------------------------------------------------------------------------------- /SourceryRuntime/Sources/Common/AST/Definition.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Describes that the object is defined in a context of some `Type` 4 | public protocol Definition: AnyObject { 5 | /// Reference to type name where the object is defined, 6 | /// nil if defined outside of any `enum`, `struct`, `class` etc 7 | var definedInTypeName: TypeName? { get } 8 | 9 | /// Reference to actual type where the object is defined, 10 | /// nil if defined outside of any `enum`, `struct`, `class` etc or type is unknown 11 | var definedInType: Type? { get } 12 | 13 | // sourcery: skipJSExport 14 | /// Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a `definedInTypeName` 15 | var actualDefinedInTypeName: TypeName? { get } 16 | } 17 | -------------------------------------------------------------------------------- /SourceryRuntime/Sources/Common/AST/Documentation.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias Documentation = [String] 4 | 5 | /// Describes a declaration with documentation, i.e. type, method, variable, enum case 6 | public protocol Documented { 7 | var documentation: Documentation { get } 8 | } 9 | -------------------------------------------------------------------------------- /SourceryRuntime/Sources/Common/AST/PhantomProtocols.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Krzysztof Zablocki on 23/01/2017. 3 | // Copyright (c) 2017 Pixle. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | /// Phantom protocol for diffing 9 | protocol AutoDiffable {} 10 | 11 | /// Phantom protocol for equality 12 | protocol AutoEquatable {} 13 | 14 | /// Phantom protocol for equality 15 | protocol AutoDescription {} 16 | 17 | /// Phantom protocol for NSCoding 18 | protocol AutoCoding {} 19 | 20 | protocol AutoJSExport {} 21 | 22 | /// Phantom protocol for NSCoding, Equatable and Diffable 23 | protocol SourceryModelWithoutDescription: AutoDiffable, AutoEquatable, AutoCoding, AutoJSExport {} 24 | 25 | protocol SourceryModel: SourceryModelWithoutDescription, AutoDescription {} 26 | -------------------------------------------------------------------------------- /SourceryRuntime/Sources/Common/AST/TypeName/Typed.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Descibes typed declaration, i.e. variable, method parameter, tuple element, enum case associated value 4 | public protocol Typed { 5 | 6 | // sourcery: skipEquality, skipDescription 7 | /// Type, if known 8 | var type: Type? { get } 9 | 10 | // sourcery: skipEquality, skipDescription 11 | /// Type name 12 | var typeName: TypeName { get } 13 | 14 | // sourcery: skipEquality, skipDescription 15 | /// Whether type is optional 16 | var isOptional: Bool { get } 17 | 18 | // sourcery: skipEquality, skipDescription 19 | /// Whether type is implicitly unwrapped optional 20 | var isImplicitlyUnwrappedOptional: Bool { get } 21 | 22 | // sourcery: skipEquality, skipDescription 23 | /// Type name without attributes and optional type information 24 | var unwrappedTypeName: String { get } 25 | } 26 | -------------------------------------------------------------------------------- /SourceryRuntime/Sources/Common/Array+Parallel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Krzysztof Zablocki on 06/01/2017. 3 | // Copyright (c) 2017 Pixle. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | public extension Array { 9 | func parallelFlatMap(transform: (Element) -> [T]) -> [T] { 10 | return parallelMap(transform: transform).flatMap { $0 } 11 | } 12 | 13 | func parallelCompactMap(transform: (Element) -> T?) -> [T] { 14 | return parallelMap(transform: transform).compactMap { $0 } 15 | } 16 | 17 | func parallelMap(transform: (Element) -> T) -> [T] { 18 | var result = ContiguousArray(repeating: nil, count: count) 19 | return result.withUnsafeMutableBufferPointer { buffer in 20 | nonisolated(unsafe) let buffer = buffer 21 | DispatchQueue.concurrentPerform(iterations: buffer.count) { idx in 22 | buffer[idx] = transform(self[idx]) 23 | } 24 | return buffer.map { $0! } 25 | } 26 | } 27 | 28 | func parallelPerform(_ work: (Element) -> Void) { 29 | DispatchQueue.concurrentPerform(iterations: count) { idx in 30 | work(self[idx]) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SourceryRuntime/Sources/Generated/AutoHashable.generated.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery 1.3.1 — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | // swiftlint:disable all 4 | 5 | 6 | // MARK: - AutoHashable for classes, protocols, structs 7 | 8 | // MARK: - AutoHashable for Enums 9 | -------------------------------------------------------------------------------- /SourceryRuntime/Sources/Linux/DynamicMemberLookup_Linux.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Stencil 3 | // Copyright © 2022 Stencil 4 | // MIT Licence 5 | // 6 | 7 | #if !canImport(ObjectiveC) 8 | #if canImport(Stencil) 9 | import Stencil 10 | #else 11 | // This is not supposed to work at all, since in Stencil there is a protocol conformance check against `DynamicMemberLookup`, 12 | // and, of course, a substitute with the "same name" but in `Sourcery` will never satisfy that check. 13 | // Here, we are just mimicking `Stencil.DynamicMemberLookup` to showcase what is happening within the `Sourcery` during runtime. 14 | 15 | /// Marker protocol so we can know which types support `@dynamicMemberLookup`. Add this to your own types that support 16 | /// lookup by String. 17 | public protocol DynamicMemberLookup { 18 | /// Get a value for a given `String` key 19 | subscript(dynamicMember member: String) -> Any? { get } 20 | } 21 | 22 | public extension DynamicMemberLookup where Self: RawRepresentable { 23 | /// Get a value for a given `String` key 24 | subscript(dynamicMember member: String) -> Any? { 25 | switch member { 26 | case "rawValue": 27 | return rawValue 28 | default: 29 | return nil 30 | } 31 | } 32 | } 33 | #endif 34 | 35 | public protocol SourceryDynamicMemberLookup: DynamicMemberLookup {} 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /SourceryRuntime/Sources/Linux/NSException_Linux.swift: -------------------------------------------------------------------------------- 1 | #if !canImport(ObjectiveC) 2 | import Foundation 3 | 4 | public class NSException { 5 | static func raise(_ name: String, format: String, arguments: CVaListPointer) { 6 | fatalError ("\(name) exception: \(NSString(format: format, arguments: arguments))") 7 | } 8 | 9 | static func raise(_ name: String) { 10 | fatalError("\(name) exception") 11 | } 12 | } 13 | 14 | public extension NSExceptionName { 15 | static var parseErrorException = "parseErrorException" 16 | } 17 | #endif 18 | -------------------------------------------------------------------------------- /SourceryRuntime/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2017 Pixle. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SourceryRuntime/Supporting Files/SourceryRuntime.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | //! Project version number for SourceryRuntime. 4 | FOUNDATION_EXPORT double SourceryRuntimeVersionNumber; 5 | 6 | //! Project version string for SourceryRuntime. 7 | FOUNDATION_EXPORT const unsigned char SourceryRuntimeVersionString[]; 8 | 9 | // In this header, you should import all the public headers of your framework using statements like #import 10 | 11 | 12 | -------------------------------------------------------------------------------- /SourceryStencil/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2021 Pixle. All rights reserved. 23 | 24 | 25 | -------------------------------------------------------------------------------- /SourceryStencil/SourceryStencil.h: -------------------------------------------------------------------------------- 1 | // 2 | // SourceryStencil.h 3 | // SourceryStencil 4 | // 5 | // Created by merowing on 3/19/21. 6 | // Copyright © 2021 Pixle. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SourceryStencil. 12 | FOUNDATION_EXPORT double SourceryStencilVersionNumber; 13 | 14 | //! Project version string for SourceryStencil. 15 | FOUNDATION_EXPORT const unsigned char SourceryStencilVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /SourceryStencil/Sources/NewLineNode.swift: -------------------------------------------------------------------------------- 1 | import Stencil 2 | 3 | class NewLineNode: NodeType { 4 | static let marker = "__sourcery__newline__" 5 | enum Content { 6 | case nodes([NodeType]) 7 | case reference(resolvable: Resolvable) 8 | } 9 | 10 | let token: Token? 11 | 12 | class func parse(_ parser: TokenParser, token: Token) throws -> NodeType { 13 | let components = token.components 14 | guard components.count == 1 else { 15 | throw TemplateSyntaxError( 16 | """ 17 | 'newline' tag takes no arguments 18 | """ 19 | ) 20 | } 21 | 22 | return NewLineNode() 23 | } 24 | 25 | init(token: Token? = nil) { 26 | self.token = token 27 | } 28 | 29 | func render(_ context: Context) throws -> String { 30 | return Self.marker 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SourceryStencil/Sources/TypedNode.swift: -------------------------------------------------------------------------------- 1 | import Stencil 2 | 3 | extension Array { 4 | func chunked(into size: Int) -> [[Element]] { 5 | return stride(from: 0, to: count, by: size).map { 6 | Array(self[$0 ..< Swift.min($0 + size, count)]) 7 | } 8 | } 9 | } 10 | 11 | class TypedNode: NodeType { 12 | enum Content { 13 | case nodes([NodeType]) 14 | case reference(resolvable: Resolvable) 15 | } 16 | 17 | typealias Binding = (name: String, type: String) 18 | 19 | let token: Token? 20 | let bindings: [Binding] 21 | 22 | class func parse(_ parser: TokenParser, token: Token) throws -> NodeType { 23 | let components = token.components 24 | guard components.count > 1, (components.count - 1) % 3 == 0 else { 25 | throw TemplateSyntaxError( 26 | """ 27 | 'typed' tag takes only triple of arguments e.g. name as Type 28 | """ 29 | ) 30 | } 31 | 32 | let chunks = Array(components.dropFirst()).chunked(into: 3) 33 | let bindings: [Binding] = chunks.compactMap { binding in 34 | return (name: binding[0], type: binding[2]) 35 | } 36 | return TypedNode(bindings: bindings) 37 | } 38 | 39 | init(token: Token? = nil, bindings: [Binding]) { 40 | self.token = token 41 | self.bindings = bindings 42 | } 43 | 44 | func render(_ context: Context) throws -> String { 45 | return "" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SourcerySwift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2018 Pixle. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SourcerySwift/SourcerySwift.h: -------------------------------------------------------------------------------- 1 | // 2 | // SourcerySwift.h 3 | // SourcerySwift 4 | // 5 | // Created by Ilya Puchka on 29/01/2018. 6 | // Copyright © 2018 Pixle. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SourcerySwift. 12 | FOUNDATION_EXPORT double SourcerySwiftVersionNumber; 13 | 14 | //! Project version string for SourcerySwift. 15 | FOUNDATION_EXPORT const unsigned char SourcerySwiftVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /SourceryTests/Helpers/Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Krzysztof Zablocki on 31/12/2016. 3 | // Copyright (c) 2016 Pixle. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | #if SWIFT_PACKAGE 8 | @testable import SourceryLib 9 | #else 10 | @testable import Sourcery 11 | #endif 12 | @testable import SourceryRuntime 13 | 14 | extension String { 15 | var withoutWhitespaces: String { 16 | return components(separatedBy: .whitespacesAndNewlines).joined(separator: "") 17 | } 18 | } 19 | 20 | extension Type { 21 | public func asUnknownException() -> Self { 22 | isUnknownExtension = true 23 | return self 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SourceryTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /SourceryTests/Models/ActorSpec.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | #if SWIFT_PACKAGE 4 | @testable import SourceryLib 5 | #else 6 | @testable import Sourcery 7 | #endif 8 | @testable import SourceryRuntime 9 | 10 | class ActorSpec: QuickSpec { 11 | override func spec() { 12 | describe("Actor") { 13 | var sut: Type? 14 | 15 | beforeEach { 16 | sut = Actor(name: "Foo", variables: [], inheritedTypes: [], modifiers: [.init(name: "distributed")]) 17 | } 18 | 19 | afterEach { 20 | sut = nil 21 | } 22 | 23 | it("reports kind as actor") { 24 | expect(sut?.kind).to(equal("actor")) 25 | } 26 | 27 | it("reports is distributed as true") { 28 | expect((sut as? Actor)?.isDistributed).to(beTrue()) 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SourceryTests/Models/ArrayTypeSpec.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | #if SWIFT_PACKAGE 4 | @testable import SourceryLib 5 | #else 6 | @testable import Sourcery 7 | #endif 8 | @testable import SourceryRuntime 9 | 10 | class ArrayTypeSpec: QuickSpec { 11 | override func spec() { 12 | describe("Array") { 13 | var sut: ArrayType? 14 | 15 | beforeEach { 16 | sut = ArrayType(name: "Foo", elementTypeName: TypeName(name: "Foo"), elementType: Type(name: "Bar")) 17 | } 18 | 19 | afterEach { 20 | sut = nil 21 | } 22 | 23 | it("preserves element type for generic") { 24 | expect(sut?.asGeneric.typeParameters.first?.type).toNot(beNil()) 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SourceryTests/Models/ClassSpec.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | #if SWIFT_PACKAGE 4 | @testable import SourceryLib 5 | #else 6 | @testable import Sourcery 7 | #endif 8 | @testable import SourceryRuntime 9 | 10 | class ClassSpec: QuickSpec { 11 | override func spec() { 12 | describe("Class") { 13 | var sut: Type? 14 | 15 | beforeEach { 16 | sut = Class(name: "Foo", variables: [], inheritedTypes: []) 17 | } 18 | 19 | afterEach { 20 | sut = nil 21 | } 22 | 23 | it("reports kind as class") { 24 | expect(sut?.kind).to(equal("class")) 25 | } 26 | 27 | it("supports package access level") { 28 | expect(Class(name: "Foo", accessLevel: .package).accessLevel == AccessLevel.package.rawValue).to(beTrue()) 29 | expect(Class(name: "Foo", accessLevel: .internal).accessLevel == AccessLevel.package.rawValue).to(beFalse()) 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SourceryTests/Models/ProtocolSpec.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | #if SWIFT_PACKAGE 4 | @testable import SourceryLib 5 | #else 6 | @testable import Sourcery 7 | #endif 8 | @testable import SourceryRuntime 9 | 10 | class ProtocolSpec: QuickSpec { 11 | override func spec() { 12 | describe("Protocol") { 13 | var sut: Type? 14 | 15 | beforeEach { 16 | sut = Protocol(name: "Foo", variables: [], inheritedTypes: []) 17 | } 18 | 19 | afterEach { 20 | sut = nil 21 | } 22 | 23 | it("reports kind as protocol") { 24 | expect(sut?.kind).to(equal("protocol")) 25 | } 26 | 27 | it("supports package access level") { 28 | expect(Protocol(name: "Foo", accessLevel: .package).accessLevel == AccessLevel.package.rawValue).to(beTrue()) 29 | expect(Protocol(name: "Foo", accessLevel: .internal).accessLevel == AccessLevel.package.rawValue).to(beFalse()) 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SourceryTests/Models/StructSpec.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | #if SWIFT_PACKAGE 4 | @testable import SourceryLib 5 | #else 6 | @testable import Sourcery 7 | #endif 8 | @testable import SourceryRuntime 9 | 10 | class StructSpec: QuickSpec { 11 | override func spec() { 12 | describe("Struct") { 13 | var sut: Struct? 14 | 15 | beforeEach { 16 | sut = Struct(name: "Foo", variables: [], inheritedTypes: []) 17 | } 18 | 19 | afterEach { 20 | sut = nil 21 | } 22 | 23 | it("reports kind as struct") { 24 | expect(sut?.kind).to(equal("struct")) 25 | } 26 | 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SourceryTests/Parsing/Helpers/StringViewSpec.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Ruslan Alikhamov on 02/07/2023. 3 | // Copyright (c) 2023 Evolutions - FZCO. All rights reserved. 4 | // 5 | 6 | import Quick 7 | import Nimble 8 | import PathKit 9 | #if SWIFT_PACKAGE 10 | import Foundation 11 | @testable import SourceryLib 12 | #else 13 | @testable import Sourcery 14 | #endif 15 | @testable import SourceryFramework 16 | @testable import SourceryRuntime 17 | 18 | class StringViewSpec: QuickSpec { 19 | override func spec() { 20 | describe("StringView") { 21 | describe("init()") { 22 | func instantiate(_ content: String) -> [Line] { 23 | return StringView.init(content).lines 24 | } 25 | 26 | it("parses correct number of lines when utf8 comments are present") { 27 | let lines = instantiate("protocol AgeModel {\r\n var ageDesc: String { get } // 年龄的描述\r\n}\r\n") 28 | expect(lines.count).to(equal(4)) 29 | } 30 | 31 | it("parses correct number of lines when \r\n newline symbols are present") { 32 | let lines = instantiate("'struct S {}\r\nprotocol AP {}\r\n") 33 | expect(lines.count).to(equal(3)) 34 | } 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SourceryTests/Sourcery+PerformanceSpec.swift: -------------------------------------------------------------------------------- 1 | /* 2 | // 3 | // Sourcery+PerformanceSpec.swift 4 | // Sourcery 5 | // 6 | // Created by Krzysztof Zabłocki on 26/12/2016. 7 | // Copyright © 2016 Pixle. All rights reserved. 8 | // 9 | 10 | import XCTest 11 | import PathKit 12 | 13 | @testable 14 | import Sourcery 15 | 16 | class SourceryPerformanceSpec: XCTestCase { 17 | let outputDir: Path = { 18 | Path.cleanTemporaryDir(name: "SourceryPerformance") 19 | }() 20 | 21 | func testParsingPerformanceOnCleanRun() { 22 | let _ = try? Path.cachesDir(sourcePath: Stubs.sourceForPerformance).delete() 23 | 24 | self.measure { 25 | let _ = try? Sourcery().processFiles(Stubs.sourceForPerformance, 26 | usingTemplates: Stubs.templateDirectory + Path("Basic.stencil"), 27 | output: self.outputDir, 28 | cacheDisabled: true) 29 | } 30 | } 31 | 32 | func testParsingPerformanceOnSubsequentRun() { 33 | let _ = try? Path.cachesDir(sourcePath: Stubs.sourceForPerformance).delete() 34 | let _ = try? Sourcery().processFiles(Stubs.sourceForPerformance, 35 | usingTemplates: Stubs.templateDirectory + Path("Basic.stencil"), 36 | output: self.outputDir) 37 | 38 | self.measure { 39 | let _ = try? Sourcery().processFiles(Stubs.sourceForPerformance, 40 | usingTemplates: Stubs.templateDirectory + Path("Basic.stencil"), 41 | output: self.outputDir) 42 | } 43 | } 44 | } 45 | */ 46 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Configs/invalid.yml: -------------------------------------------------------------------------------- 1 | invalid configuration 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Configs/multi.yml: -------------------------------------------------------------------------------- 1 | configurations: 2 | - sources: 3 | - "${SOURCE_PATH}/0" 4 | templates: 5 | - "Templates/0" 6 | output: "Output/0" 7 | args: 8 | serverUrl: "${serverUrl}/0" 9 | serverPort: "${serverPort}/0" 10 | - sources: 11 | - "${SOURCE_PATH}/1" 12 | templates: 13 | - "Templates/1" 14 | output: "Output/1" 15 | args: 16 | serverUrl: "${serverUrl}/1" 17 | serverPort: "${serverPort}1" 18 | 19 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Configs/parent.yml: -------------------------------------------------------------------------------- 1 | configurations: 2 | - child: valid.yml 3 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Configs/valid.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | - "${SOURCE_PATH}" 3 | templates: 4 | - "Templates" 5 | output: "Output" 6 | args: 7 | serverUrl: ${serverUrl} 8 | serverPort: ${serverPort} 9 | -------------------------------------------------------------------------------- /SourceryTests/Stub/DryRun-Code/Base.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | protocol AutoEquatable {} 4 | 5 | struct Eq: AutoEquatable { 6 | // sourcery:inline:Eq.AutoEquatable 7 | // sourcery:end 8 | let s: Int 9 | let o: String 10 | let u: String 11 | let r: Int 12 | let c: [Int] 13 | let e: Bool 14 | } 15 | 16 | struct Eq3: AutoEquatable { 17 | let counter: Int 18 | let foo: String 19 | let bar: Set 20 | } 21 | 22 | struct Eq2: AutoEquatable { 23 | // sourcery:inline:Eq2.AutoEquatable 24 | // sourcery:end 25 | let r: Int 26 | let y: String 27 | let d: [Int: Bool] 28 | let r2: Int 29 | let y2: [Int] 30 | let r3: Bool 31 | let u: Int64 32 | let n: Double 33 | } 34 | 35 | enum EqEnum: AutoEquatable { 36 | case some(Int) 37 | case other(Bool) 38 | } 39 | -------------------------------------------------------------------------------- /SourceryTests/Stub/JavaScriptTemplates/AllTypealiases.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | for (alias of types.typealiases.filter((t) => t.annotations.AutoStruct != null)) { %> 3 | struct Any<%- alias.name %>: <%- alias.type.name %> { 4 | <%_ for (variable of alias.type.instanceVariables) { -%> 5 | var <%- variable.name %>: <%- variable.typeName.asSource %> 6 | <% } -%> 7 | } 8 | <%_ } -%> 9 | -------------------------------------------------------------------------------- /SourceryTests/Stub/JavaScriptTemplates/Equality.ejs: -------------------------------------------------------------------------------- 1 | <% for (type of types.classes) { -%> 2 | <%_ %><%# this is a comment -%> 3 | extension <%= type.name %>: Equatable {} 4 | 5 | <%_ if (type.annotations.showComment) { -%> 6 | <% _%> // <%= type.name %> has Annotations 7 | 8 | <% } -%> 9 | func == (lhs: <%= type.name %>, rhs: <%= type.name %>) -> Bool { 10 | <%_ for (variable of type.variables) { -%> 11 | if lhs.<%= variable.name %> != rhs.<%= variable.name %> { return false } 12 | <%_ } %> 13 | return true 14 | } 15 | 16 | <% } -%> 17 | -------------------------------------------------------------------------------- /SourceryTests/Stub/JavaScriptTemplates/Function.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | for (func of functions) { 3 | let functionName = String(func.name.split("(")[0]) 4 | let capitalizedName = functionName.charAt(0).toUpperCase() + functionName.slice(1) 5 | -%> 6 | func wrapped<%= capitalizedName %>(<%= 7 | func.parameters.map((param) => { 8 | return param.name + ": " + param.typeName.name 9 | }).join(", ") 10 | %>) { 11 | <%= functionName %>(<%= 12 | func.parameters.map((param) => { 13 | return param.name + ": " + param.name 14 | }).join(", ") 15 | %>) 16 | } 17 | <%_ } -%> 18 | -------------------------------------------------------------------------------- /SourceryTests/Stub/JavaScriptTemplates/Includes.ejs: -------------------------------------------------------------------------------- 1 | <%- include('Equality') -%><%- include('Other.ejs') -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/JavaScriptTemplates/Other.ejs: -------------------------------------------------------------------------------- 1 | // Found <%- types.all.length %> types 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/JavaScriptTemplates/ProtocolCompositions.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | for (composition of types.protocolCompositions.filter((t) => t.annotations.AutoStruct != null)) { %> 3 | struct Any<%- composition.name %>: <%- composition.name %> { 4 | <%_ for (type of composition.composedTypes) { -%> 5 | 6 | // MARK: <%- type.name %> properties 7 | <%_ for (variable of type.instanceVariables) { -%> 8 | var <%- variable.name %>: <%- variable.typeName.asSource %> 9 | <% } 10 | } -%> 11 | } 12 | <%_ } -%> 13 | -------------------------------------------------------------------------------- /SourceryTests/Stub/JavaScriptTemplates/SubfolderIncludes.ejs: -------------------------------------------------------------------------------- 1 | <%- include('lib/One') %><% -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/JavaScriptTemplates/Typealiases.ejs: -------------------------------------------------------------------------------- 1 | <%_ for (type of types.all) { -%> 2 | // Typealiases in <%= type.name %> 3 | <%_ for (const [aliasName, aliasValue] of Object.entries(type.typealiases)) { -%> 4 | // - name '<%= aliasName %>', type '<%= aliasValue.typeName.name %>' 5 | <% } 6 | } -%> 7 | -------------------------------------------------------------------------------- /SourceryTests/Stub/JavaScriptTemplates/lib/One.ejs: -------------------------------------------------------------------------------- 1 | <%- include('Two') %><% -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/JavaScriptTemplates/lib/Two.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../Equality') %><% -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Admin/AdminLogViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class AdminLogViewController: UIViewController { 4 | 5 | override func viewDidLoad() { 6 | super.viewDidLoad() 7 | textView.text = try? NSString(contentsOf: logPath(), encoding: String.Encoding.ascii.rawValue) as String 8 | } 9 | 10 | @IBOutlet weak var textView: UITextView! 11 | @IBAction func backButtonTapped(_ sender: AnyObject) { 12 | _ = self.navigationController?.popViewController(animated: true) 13 | } 14 | 15 | func logPath() -> URL { 16 | let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last! 17 | return docs.appendingPathComponent("logger.txt") 18 | } 19 | 20 | @IBAction func scrollTapped(_ sender: AnyObject) { 21 | textView.scrollRangeToVisible(NSMakeRange(textView.text.count - 1, 1)) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Admin/AuctionWebViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class AuctionWebViewController: WebViewController { 4 | 5 | override func viewDidLoad() { 6 | super.viewDidLoad() 7 | 8 | let flexibleSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil) 9 | 10 | let exitImage = UIImage(named: "toolbar_close") 11 | let backwardBarItem = UIBarButtonItem(image: exitImage, style: .plain, target: self, action: #selector(exit)) 12 | let allItems = self.toolbarItems! + [flexibleSpace, backwardBarItem] 13 | toolbarItems = allItems 14 | } 15 | 16 | func exit() { 17 | let passwordVC = PasswordAlertViewController.alertView { [weak self] in 18 | _ = self?.navigationController?.popViewController(animated: true) 19 | return 20 | } 21 | self.present(passwordVC, animated: true) {} 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Admin/PasswordAlertViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class PasswordAlertViewController: UIAlertController { 4 | 5 | class func alertView(completion: @escaping () -> ()) -> PasswordAlertViewController { 6 | let alertController = PasswordAlertViewController(title: "Exit Kiosk", message: nil, preferredStyle: .alert) 7 | let exitAction = UIAlertAction(title: "Exit", style: .default) { (_) in 8 | completion() 9 | return 10 | } 11 | 12 | if detectDevelopmentEnvironment() { 13 | exitAction.isEnabled = true 14 | } else { 15 | exitAction.isEnabled = false 16 | } 17 | 18 | let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in } 19 | 20 | alertController.addTextField { (textField) in 21 | textField.placeholder = "Exit Password" 22 | 23 | NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextFieldTextDidChange, object: textField, queue: OperationQueue.main) { (notification) in 24 | // compiler crashes when using weak 25 | exitAction.isEnabled = textField.text == "Genome401" 26 | } 27 | } 28 | 29 | alertController.addAction(exitAction) 30 | alertController.addAction(cancelAction) 31 | return alertController 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/APIPingManager.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Moya 3 | import RxSwift 4 | 5 | class APIPingManager { 6 | 7 | let syncInterval: TimeInterval = 2 8 | var letOnline: Observable! 9 | var provider: Networking 10 | 11 | init(provider: Networking) { 12 | self.provider = provider 13 | 14 | letOnline = Observable.interval(syncInterval, scheduler: MainScheduler.instance) 15 | .flatMap { [weak self] _ in 16 | return self?.ping() ?? .empty() 17 | } 18 | .retry() // Retry because ping may fail when disconnected and error. 19 | .startWith(true) 20 | } 21 | 22 | fileprivate func ping() -> Observable { 23 | return provider.request(ArtsyAPI.ping).map(responseIsOK) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/AppSetup.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class AppSetup { 4 | 5 | var auctionID = "los-angeles-modern-auctions-march-2015" 6 | lazy var useStaging = true 7 | lazy var showDebugButtons = false 8 | lazy var disableCardReader = false 9 | var isTesting = false 10 | 11 | class var sharedState: AppSetup { 12 | struct Static { 13 | static let instance = AppSetup() 14 | } 15 | return Static.instance 16 | } 17 | 18 | init() { 19 | let defaults = UserDefaults.standard 20 | if let auction = defaults.string(forKey: "KioskAuctionID") { 21 | auctionID = auction 22 | } 23 | 24 | useStaging = defaults.bool(forKey: "KioskUseStaging") 25 | showDebugButtons = defaults.bool(forKey: "KioskShowDebugButtons") 26 | disableCardReader = defaults.bool(forKey: "KioskDisableCardReader") 27 | 28 | if let _ = NSClassFromString("XCTest") { isTesting = true } 29 | } 30 | 31 | var needsZipCode: Bool { 32 | // If we're swiping with the card reaer, we don't need to collect a zip code. 33 | return false 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Constants.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct AnimationDuration { 4 | static let Normal: TimeInterval = 0.30 5 | static let Short: TimeInterval = 0.15 6 | } 7 | 8 | let SyncInterval: TimeInterval = 60 9 | let ButtonHeight: CGFloat = 50 10 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/KioskDateFormatter.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface KioskDateFormatter :NSObject 4 | 5 | + (NSDate * __nullable)fromString:(NSString * _Nonnull)string; 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/KioskDateFormatter.m: -------------------------------------------------------------------------------- 1 | #import "KioskDateFormatter.h" 2 | @import ISO8601DateFormatter; 3 | 4 | @implementation KioskDateFormatter 5 | 6 | + (NSDate *)fromString:(NSString *)string { 7 | ISO8601DateFormatter *formatter = [[ISO8601DateFormatter alloc] init]; 8 | return [formatter dateFromString:string]; 9 | } 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/MarkdownParser.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XNGMarkdownParser 3 | import Artsy_UIFonts 4 | 5 | class MarkdownParser: XNGMarkdownParser { 6 | 7 | override init() { 8 | super.init() 9 | 10 | paragraphFont = UIFont.serifFont(withSize: 16) 11 | linkFontName = UIFont.serifItalicFont(withSize: 16).fontName 12 | boldFontName = UIFont.serifBoldFont(withSize: 16).fontName 13 | italicFontName = UIFont.serifItalicFont(withSize: 16).fontName 14 | shouldParseLinks = false 15 | 16 | let paragraphStyle = NSMutableParagraphStyle() 17 | paragraphStyle.minimumLineHeight = 16 18 | 19 | topAttributes = [ 20 | NSParagraphStyleAttributeName: paragraphStyle, 21 | NSForegroundColorAttributeName: UIColor.black 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/Artist.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftyJSON 3 | 4 | final class Artist: NSObject, JSONAbleType { 5 | 6 | let id: String 7 | dynamic var name: String 8 | let sortableID: String? 9 | 10 | var blurb: String? 11 | 12 | init(id: String, name: String, sortableID: String?) { 13 | self.id = id 14 | self.name = name 15 | self.sortableID = sortableID 16 | } 17 | 18 | static func fromJSON(_ json: [String: Any]) -> Artist { 19 | let json = JSON(json) 20 | 21 | let id = json["id"].stringValue 22 | let name = json["name"].stringValue 23 | let sortableID = json["sortable_id"].string 24 | return Artist(id: id, name:name, sortableID:sortableID) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/Bid.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftyJSON 3 | 4 | final class Bid: NSObject, JSONAbleType { 5 | let id: String 6 | let amountCents: Int 7 | 8 | init(id: String, amountCents: Int) { 9 | self.id = id 10 | self.amountCents = amountCents 11 | } 12 | 13 | static func fromJSON(_ json: [String: Any]) -> Bid { 14 | let json = JSON(json) 15 | 16 | let id = json["id"].stringValue 17 | let amount = json["amount_cents"].int 18 | return Bid(id: id, amountCents: amount!) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/Bidder.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import SwiftyJSON 3 | 4 | final class Bidder: NSObject, JSONAbleType { 5 | let id: String 6 | let saleID: String 7 | let createdByAdmin: Bool 8 | var pin: String? 9 | 10 | init(id: String, saleID: String, createdByAdmin: Bool, pin: String?) { 11 | self.id = id 12 | self.saleID = saleID 13 | self.createdByAdmin = createdByAdmin 14 | self.pin = pin 15 | } 16 | 17 | static func fromJSON(_ json: [String: Any]) -> Bidder { 18 | let json = JSON(json) 19 | 20 | let id = json["id"].stringValue 21 | let saleID = json["sale"]["id"].stringValue 22 | let createdByAdmin = json["created_by_admin"].bool ?? false 23 | let pin = json["pin"].stringValue 24 | return Bidder(id: id, saleID: saleID, createdByAdmin: createdByAdmin, pin: pin) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/BidderPosition.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftyJSON 3 | 4 | final class BidderPosition: NSObject, JSONAbleType { 5 | let id: String 6 | let highestBid: Bid? 7 | let maxBidAmountCents: Int 8 | let processedAt: Date? 9 | 10 | init(id: String, highestBid: Bid?, maxBidAmountCents: Int, processedAt: Date?) { 11 | self.id = id 12 | self.highestBid = highestBid 13 | self.maxBidAmountCents = maxBidAmountCents 14 | self.processedAt = processedAt 15 | } 16 | 17 | static func fromJSON(_ source: [String: Any]) -> BidderPosition { 18 | let json = JSON(source) 19 | 20 | let id = json["id"].stringValue 21 | let maxBidAmount = json["max_bid_amount_cents"].intValue 22 | let processedAt = KioskDateFormatter.fromString(json["processed_at"].stringValue) 23 | 24 | var bid: Bid? 25 | if let bidDictionary = json["highest_bid"].object as? [String: AnyObject] { 26 | bid = Bid.fromJSON(bidDictionary) 27 | } 28 | 29 | return BidderPosition(id: id, highestBid: bid, maxBidAmountCents: maxBidAmount, processedAt: processedAt) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/BuyersPremium.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import SwiftyJSON 3 | 4 | final class BuyersPremium: NSObject, JSONAbleType { 5 | let id: String 6 | let name: String 7 | 8 | init(id: String, name: String) { 9 | self.id = id 10 | self.name = name 11 | } 12 | 13 | static func fromJSON(_ json: [String: Any]) -> BuyersPremium { 14 | let json = JSON(json) 15 | let id = json["id"].stringValue 16 | let name = json["name"].stringValue 17 | 18 | return BuyersPremium(id: id, name: name) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/Card.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftyJSON 3 | 4 | final class Card: NSObject, JSONAbleType { 5 | let id: String 6 | let name: String 7 | let lastDigits: String 8 | let expirationMonth: String 9 | let expirationYear: String 10 | 11 | init(id: String, name: String, lastDigits: String, expirationMonth: String, expirationYear: String) { 12 | 13 | self.id = id 14 | self.name = name 15 | self.lastDigits = lastDigits 16 | self.expirationMonth = expirationMonth 17 | self.expirationYear = expirationYear 18 | } 19 | 20 | static func fromJSON(_ json: [String: Any]) -> Card { 21 | let json = JSON(json) 22 | 23 | let id = json["id"].stringValue 24 | let name = json["name"].stringValue 25 | let lastDigits = json["last_digits"].stringValue 26 | let expirationMonth = json["expiration_month"].stringValue 27 | let expirationYear = json["expiration_year"].stringValue 28 | 29 | return Card(id: id, name: name, lastDigits: lastDigits, expirationMonth: expirationMonth, expirationYear: expirationYear) 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/GenericError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftyJSON 3 | 4 | final class GenericError: NSObject, JSONAbleType { 5 | let detail: [String:AnyObject] 6 | let message: String 7 | let type: String 8 | 9 | init(type: String, message: String, detail: [String:AnyObject]) { 10 | self.detail = detail 11 | self.message = message 12 | self.type = type 13 | } 14 | 15 | static func fromJSON(_ json: [String: Any]) -> GenericError { 16 | let json = JSON(json) 17 | 18 | let type = json["type"].stringValue 19 | let message = json["message"].stringValue 20 | var detailDictionary = json["detail"].object as? [String: AnyObject] 21 | 22 | detailDictionary = detailDictionary ?? [:] 23 | return GenericError(type: type, message: message, detail: detailDictionary!) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/JSONAble.swift: -------------------------------------------------------------------------------- 1 | protocol JSONAbleType { 2 | static func fromJSON(_: [String: Any]) -> Self 3 | } 4 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/Location.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import SwiftyJSON 3 | 4 | final class Location: NSObject, JSONAbleType { 5 | let address: String 6 | let address2: String 7 | let city: String 8 | let state: String 9 | let stateCode: String 10 | var postalCode: String 11 | 12 | init(address: String, address2: String, city: String, state: String, stateCode: String, postalCode: String) { 13 | self.address = address 14 | self.address2 = address2 15 | self.city = city 16 | self.state = state 17 | self.stateCode = stateCode 18 | self.postalCode = postalCode 19 | } 20 | 21 | static func fromJSON(_ json: [String: Any]) -> Location { 22 | let json = JSON(json) 23 | 24 | let address = json["address"].stringValue 25 | let address2 = json["address_2"].stringValue 26 | let city = json["city"].stringValue 27 | let state = json["state"].stringValue 28 | let stateCode = json["state_code"].stringValue 29 | let postalCode = json["postal_code"].stringValue 30 | 31 | return Location(address: address, address2: address2, city: city, state: state, stateCode: stateCode, postalCode: postalCode) 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/SystemTime.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import RxSwift 3 | 4 | class SystemTime { 5 | var systemTimeInterval: TimeInterval? = nil 6 | 7 | init () {} 8 | 9 | func sync(_ provider: Networking) -> Observable { 10 | let endpoint: ArtsyAPI = ArtsyAPI.systemTime 11 | 12 | return provider.request(endpoint) 13 | .filterSuccessfulStatusCodes() 14 | .mapJSON() 15 | .doOnNext { [weak self] response in 16 | guard let dictionary = response as? NSDictionary else { return } 17 | 18 | let timestamp: String = (dictionary["iso8601"] as? String) ?? "" 19 | if let artsyDate = KioskDateFormatter.fromString(timestamp) { 20 | self?.systemTimeInterval = Date().timeIntervalSince(artsyDate) 21 | } 22 | 23 | }.logError().map(void) 24 | } 25 | 26 | func inSync() -> Bool { 27 | return systemTimeInterval != nil 28 | } 29 | 30 | func date() -> Date { 31 | let now = Date() 32 | if let systemTimeInterval = systemTimeInterval { 33 | return now.addingTimeInterval(-systemTimeInterval) 34 | } else { 35 | return now 36 | } 37 | } 38 | 39 | func reset() { 40 | systemTimeInterval = nil 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Models/User.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftyJSON 3 | 4 | final class User: NSObject, JSONAbleType { 5 | 6 | dynamic let id: String 7 | dynamic let email: String 8 | dynamic let name: String 9 | dynamic let paddleNumber: String 10 | dynamic let phoneNumber: String 11 | dynamic var bidder: Bidder? 12 | dynamic var location: Location? 13 | 14 | init(id: String, email: String, name: String, paddleNumber: String, phoneNumber: String, location: Location?) { 15 | self.id = id 16 | self.name = name 17 | self.paddleNumber = paddleNumber 18 | self.email = email 19 | self.phoneNumber = phoneNumber 20 | self.location = location 21 | } 22 | 23 | static func fromJSON(_ json: [String: Any]) -> User { 24 | let json = JSON(json) 25 | 26 | let id = json["id"].stringValue 27 | let name = json["name"].stringValue 28 | let email = json["email"].stringValue 29 | let paddleNumber = json["paddle_number"].stringValue 30 | let phoneNumber = json["phone"].stringValue 31 | 32 | var location: Location? 33 | if let bidDictionary = json["location"].object as? [String: AnyObject] { 34 | location = Location.fromJSON(bidDictionary) 35 | } 36 | 37 | return User(id: id, email: email, name: name, paddleNumber: paddleNumber, phoneNumber: phoneNumber, location:location) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/NSErrorExtensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Moya 3 | 4 | extension NSError { 5 | 6 | func artsyServerError() -> NSString { 7 | if let errorJSON = userInfo["data"] as? [String: AnyObject] { 8 | let error = GenericError.fromJSON(errorJSON) 9 | return "\(error.message) - \(error.detail) + \(error.detail)" as NSString 10 | } else if let response = userInfo["data"] as? Response { 11 | let stringData = NSString(data: response.data, encoding: String.Encoding.utf8.rawValue) 12 | return "Status Code: \(response.statusCode), Data Length: \(response.data.count), String Data: \(stringData)" as NSString 13 | } 14 | 15 | return "\(userInfo)" as NSString 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Networking/APIKeys.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Keys 3 | 4 | private let minimumKeyLength = 2 5 | 6 | // Mark: - API Keys 7 | 8 | struct APIKeys { 9 | let key: String 10 | let secret: String 11 | 12 | // MARK: Shared Keys 13 | 14 | fileprivate struct SharedKeys { 15 | static var instance = APIKeys() 16 | } 17 | 18 | static var sharedKeys: APIKeys { 19 | get { 20 | return SharedKeys.instance 21 | } 22 | 23 | set (newSharedKeys) { 24 | SharedKeys.instance = newSharedKeys 25 | } 26 | } 27 | 28 | // MARK: Methods 29 | 30 | var stubResponses: Bool { 31 | return key.count < minimumKeyLength || secret.count < minimumKeyLength 32 | } 33 | 34 | // MARK: Initializers 35 | 36 | init(key: String, secret: String) { 37 | self.key = key 38 | self.secret = secret 39 | } 40 | 41 | init(keys: EidolonKeys) { 42 | self.init(key: keys.artsyAPIClientKey() ?? "", secret: keys.artsyAPIClientSecret() ?? "") 43 | } 44 | 45 | init() { 46 | let keys = EidolonKeys() 47 | self.init(keys: keys) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Networking/NetworkLogger.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Moya 3 | import Result 4 | 5 | /// Logs network activity (outgoing requests and incoming responses). 6 | class NetworkLogger: PluginType { 7 | 8 | typealias Comparison = (TargetType) -> Bool 9 | 10 | let whitelist: Comparison 11 | let blacklist: Comparison 12 | 13 | init(whitelist: @escaping Comparison = { _ -> Bool in return true }, blacklist: @escaping Comparison = { _ -> Bool in return true }) { 14 | self.whitelist = whitelist 15 | self.blacklist = blacklist 16 | } 17 | 18 | func willSendRequest(_ request: RequestType, target: TargetType) { 19 | // If the target is in the blacklist, don't log it. 20 | guard blacklist(target) == false else { return } 21 | logger.log("Sending request: \(request.request?.url?.absoluteString ?? String())") 22 | } 23 | 24 | func didReceiveResponse(_ result: Result, target: TargetType) { 25 | // If the target is in the blacklist, don't log it. 26 | guard blacklist(target) == false else { return } 27 | 28 | switch result { 29 | case .success(let response): 30 | if 200..<400 ~= (response.statusCode ) && whitelist(target) == false { 31 | // If the status code is OK, and if it's not in our whitelist, then don't worry about logging its response body. 32 | logger.log("Received response(\(response.statusCode )) from \(response.response?.url?.absoluteString ?? String()).") 33 | } 34 | case .failure(let error): 35 | // Otherwise, log everything. 36 | logger.log("Received networking error: \(error)") 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Networking/UserCredentials.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct UserCredentials { 4 | let user: User 5 | let accessToken: String 6 | 7 | init(user: User, accessToken: String) { 8 | self.user = user 9 | self.accessToken = accessToken 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Networking/XAppToken.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | private extension Date { 4 | var isInPast: Bool { 5 | let now = Date() 6 | return self.compare(now) == ComparisonResult.orderedAscending 7 | } 8 | } 9 | 10 | struct XAppToken { 11 | enum DefaultsKeys: String { 12 | case TokenKey = "TokenKey" 13 | case TokenExpiry = "TokenExpiry" 14 | } 15 | 16 | // MARK: - Initializers 17 | 18 | let defaults: UserDefaults 19 | 20 | init(defaults: UserDefaults) { 21 | self.defaults = defaults 22 | } 23 | 24 | init() { 25 | self.defaults = UserDefaults.standard 26 | } 27 | 28 | // MARK: - Properties 29 | 30 | var token: String? { 31 | get { 32 | let key = defaults.string(forKey: DefaultsKeys.TokenKey.rawValue) 33 | return key 34 | } 35 | set(newToken) { 36 | defaults.set(newToken, forKey: DefaultsKeys.TokenKey.rawValue) 37 | } 38 | } 39 | 40 | var expiry: Date? { 41 | get { 42 | return defaults.object(forKey: DefaultsKeys.TokenExpiry.rawValue) as? Date 43 | } 44 | set(newExpiry) { 45 | defaults.set(newExpiry, forKey: DefaultsKeys.TokenExpiry.rawValue) 46 | } 47 | } 48 | 49 | var expired: Bool { 50 | if let expiry = expiry { 51 | return expiry.isInPast 52 | } 53 | return true 54 | } 55 | 56 | var isValid: Bool { 57 | if let token = token { 58 | return token.isNotEmpty && !expired 59 | } 60 | 61 | return false 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/OfflineViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Artsy_UIFonts 3 | 4 | class OfflineViewController: UIViewController { 5 | @IBOutlet var offlineLabel: UILabel! 6 | @IBOutlet var subtitleLabel: UILabel! 7 | 8 | override func viewDidLoad() { 9 | super.viewDidLoad() 10 | 11 | offlineLabel.font = UIFont.serifFont(withSize: 49) 12 | subtitleLabel.font = UIFont.serifItalicFont(withSize: 32) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/STPCard+Validation.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface STPCard (Validation) 5 | 6 | + (BOOL)validateCardNumber:(NSString *)cardNumber; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/STPCard+Validation.m: -------------------------------------------------------------------------------- 1 | #import "STPCard+Validation.h" 2 | 3 | @implementation STPCard (Validation) 4 | 5 | + (BOOL)validateCardNumber:(NSString *)cardNumber { 6 | STPCard *card = [[STPCard alloc] init]; 7 | card.number = cardNumber; 8 | 9 | __autoreleasing NSString *cardNumberCopy = [cardNumber copy]; 10 | 11 | return [card validateNumber:&cardNumberCopy error:nil]; 12 | } 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/StubResponses.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface StubResponses : NSObject 4 | 5 | + (BOOL)stubResponses; 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/StubResponses.m: -------------------------------------------------------------------------------- 1 | #import "StubResponses.h" 2 | 3 | #define STUB_RESPONSES YES 4 | 5 | // We're inferring if you have access to the private Artsy fonts, then you have access to our API. 6 | #if __has_include() 7 | #undef STUB_RESPONSES 8 | #define STUB_RESPONSES NO 9 | #endif 10 | 11 | @implementation StubResponses 12 | 13 | + (BOOL)stubResponses { 14 | return STUB_RESPONSES; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/SwiftExtensions.swift: -------------------------------------------------------------------------------- 1 | extension Optional { 2 | var hasValue: Bool { 3 | switch self { 4 | case .none: 5 | return false 6 | case .some(_): 7 | return true 8 | } 9 | } 10 | } 11 | 12 | extension String { 13 | func toUInt() -> UInt? { 14 | return UInt(self) 15 | } 16 | 17 | func toUInt(withDefault defaultValue: UInt) -> UInt { 18 | return UInt(self) ?? defaultValue 19 | } 20 | } 21 | 22 | // Anything that can hold a value (strings, arrays, etc) 23 | protocol Occupiable { 24 | var isEmpty: Bool { get } 25 | var isNotEmpty: Bool { get } 26 | } 27 | 28 | // Give a default implementation of isNotEmpty, so conformance only requires one implementation 29 | extension Occupiable { 30 | var isNotEmpty: Bool { 31 | return !isEmpty 32 | } 33 | } 34 | 35 | extension String: Occupiable { } 36 | 37 | // I can't think of a way to combine these collection types. Suggestions welcome. 38 | extension Array: Occupiable { } 39 | extension Dictionary: Occupiable { } 40 | extension Set: Occupiable { } 41 | 42 | // Extend the idea of occupiability to optionals. Specifically, optionals wrapping occupiable things. 43 | extension Optional where Wrapped: Occupiable { 44 | var isNilOrEmpty: Bool { 45 | switch self { 46 | case .none: 47 | return true 48 | case .some(let value): 49 | return value.isEmpty 50 | } 51 | } 52 | 53 | var isNotNilNotEmpty: Bool { 54 | return !isNilOrEmpty 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/UIStoryboardSegueExtensions.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | extension UIStoryboardSegue { 4 | } 5 | 6 | func ==(lhs: UIStoryboardSegue, rhs: SegueIdentifier) -> Bool { 7 | return lhs.identifier == rhs.rawValue 8 | } 9 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/UIViewControllerExtensions.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | extension UIViewController { 4 | 5 | /// Short hand syntax for loading the view controller 6 | 7 | func loadViewProgrammatically() { 8 | self.beginAppearanceTransition(true, animated: false) 9 | self.endAppearanceTransition() 10 | } 11 | 12 | /// Short hand syntax for performing a segue with a known hardcoded identity 13 | 14 | func performSegue(_ identifier: SegueIdentifier) { 15 | self.performSegue(withIdentifier: identifier.rawValue, sender: self) 16 | } 17 | 18 | func fulfillmentNav() -> FulfillmentNavigationController { 19 | return (navigationController! as! FulfillmentNavigationController) 20 | } 21 | 22 | func fulfillmentContainer() -> FulfillmentContainerViewController? { 23 | return fulfillmentNav().parent as? FulfillmentContainerViewController 24 | } 25 | 26 | func findChildViewControllerOfType(_ klass: AnyClass) -> UIViewController? { 27 | for child in childViewControllers { 28 | if child.isKind(of: klass) { 29 | return child 30 | } 31 | } 32 | return nil 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/UIViewSubclassesErrorExtensions.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | extension Button { 4 | 5 | func flashError(_ message: String) { 6 | let originalTitle = self.title(for: .normal) 7 | 8 | setTitleColor(.white, for: .disabled) 9 | setBackgroundColor(.artsyRedRegular(), for: .disabled, animated: true) 10 | setBorderColor(.artsyRedRegular(), for: .disabled, animated: true) 11 | 12 | setTitle(message.uppercased(), for: .disabled) 13 | 14 | delayToMainThread(2) { 15 | self.setTitleColor(.artsyGrayMedium(), for: .disabled) 16 | self.setBackgroundColor(.white, for: .disabled, animated: true) 17 | self.setTitle(originalTitle, for: .disabled) 18 | self.setBorderColor(.artsyGrayMedium(), for: .disabled, animated: true) 19 | } 20 | } 21 | } 22 | 23 | extension TextField { 24 | 25 | func flashForError() { 26 | self.setBorderColor(.artsyRedRegular()) 27 | delayToMainThread(2) { 28 | self.setBorderColor(.artsyPurpleRegular()) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Views/SimulatorOnlyView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class DeveloperOnlyView: UIView { 4 | 5 | override func awakeFromNib() { 6 | // Show only if we're supposed to show AND we're on staging. 7 | self.isHidden = !(AppSetup.sharedState.showDebugButtons && AppSetup.sharedState.useStaging) 8 | 9 | if let _ = NSClassFromString("XCTest") { 10 | // We are running in a test. 11 | self.isHidden = true 12 | self.alpha = 0 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Views/Spinner.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class Spinner: UIView { 4 | var spinner: UIView! 5 | let rotationDuration = 0.9 6 | 7 | func createSpinner() -> UIView { 8 | let view = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 5)) 9 | view.backgroundColor = .black 10 | return view 11 | } 12 | 13 | override func awakeFromNib() { 14 | spinner = createSpinner() 15 | addSubview(spinner) 16 | backgroundColor = .clear 17 | animateN(Float.infinity) 18 | } 19 | 20 | override func layoutSubviews() { 21 | // .center uses frame 22 | spinner.center = CGPoint( x: bounds.width / 2, y: bounds.height / 2) 23 | } 24 | 25 | func animateN(_ times: Float) { 26 | let transformOffset = -1.01 * M_PI 27 | let transform = CATransform3DMakeRotation( CGFloat(transformOffset), 0, 0, 1) 28 | let rotationAnimation = CABasicAnimation(keyPath:"transform") 29 | 30 | rotationAnimation.toValue = NSValue(caTransform3D:transform) 31 | rotationAnimation.duration = rotationDuration 32 | rotationAnimation.isCumulative = true 33 | rotationAnimation.repeatCount = Float(times) 34 | layer.add(rotationAnimation, forKey:"spin") 35 | } 36 | 37 | func animate(_ animate: Bool) { 38 | let isAnimating = layer.animation(forKey: "spin") != nil 39 | if (isAnimating && !animate) { 40 | layer.removeAllAnimations() 41 | 42 | } else if (!isAnimating && animate) { 43 | self.animateN(Float.infinity) 44 | } 45 | } 46 | 47 | func stopAnimating() { 48 | layer.removeAllAnimations() 49 | animateN(1) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/App/Views/Text Fields/CursorView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class CursorView: UIView { 4 | 5 | let cursorLayer: CALayer = CALayer() 6 | 7 | override init(frame: CGRect) { 8 | super.init(frame: frame) 9 | setup() 10 | } 11 | 12 | required init?(coder aDecoder: NSCoder) { 13 | super.init(coder: aDecoder) 14 | setup() 15 | } 16 | 17 | override func awakeFromNib() { 18 | setupCursorLayer() 19 | startAnimating() 20 | } 21 | 22 | func setup() { 23 | layer.addSublayer(cursorLayer) 24 | setupCursorLayer() 25 | } 26 | 27 | func setupCursorLayer() { 28 | cursorLayer.frame = CGRect(x: layer.frame.width/2 - 1, y: 0, width: 2, height: layer.frame.height) 29 | cursorLayer.backgroundColor = UIColor.black.cgColor 30 | cursorLayer.opacity = 0.0 31 | } 32 | 33 | func startAnimating() { 34 | animate(Float.infinity) 35 | } 36 | 37 | fileprivate func animate(_ times: Float) { 38 | let fade = CABasicAnimation() 39 | fade.duration = 0.5 40 | fade.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 41 | fade.repeatCount = times 42 | fade.autoreverses = true 43 | fade.fromValue = 0.0 44 | fade.toValue = 1.0 45 | cursorLayer.add(fade, forKey: "opacity") 46 | } 47 | 48 | func stopAnimating() { 49 | cursorLayer.removeAllAnimations() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/AdminCCBypassNetworkModel.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import RxSwift 3 | import Moya 4 | 5 | enum BypassResult { 6 | case requireCC 7 | case skipCCRequirement 8 | } 9 | 10 | protocol AdminCCBypassNetworkModelType { 11 | 12 | func checkForAdminCCBypass(_ saleID: String, authorizedNetworking: AuthorizedNetworking) -> Observable 13 | } 14 | 15 | class AdminCCBypassNetworkModel: AdminCCBypassNetworkModelType { 16 | 17 | /// Returns an Observable of (Bool, AuthorizedNetworking) 18 | /// The Bool represents if the Credit Card requirement should be waived. 19 | /// THe AuthorizedNetworking is the same instance that's passed in, which is a convenience for chaining observables. 20 | func checkForAdminCCBypass(_ saleID: String, authorizedNetworking: AuthorizedNetworking) -> Observable { 21 | 22 | return authorizedNetworking 23 | .request(ArtsyAuthenticatedAPI.findMyBidderRegistration(auctionID: saleID)) 24 | .filterSuccessfulStatusCodes() 25 | .mapJSON() 26 | .mapTo(arrayOf: Bidder.self) 27 | .map { bidders in 28 | return bidders.first 29 | } 30 | .map { bidder -> BypassResult in 31 | guard let bidder = bidder else { return .requireCC } 32 | 33 | switch bidder.createdByAdmin { 34 | case true: return .skipCCRequirement 35 | case false: return .requireCC 36 | } 37 | } 38 | .logError() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/ConfirmYourBidPasswordViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Unused ATM 4 | 5 | class ConfirmYourBidPasswordViewController: UIViewController { 6 | 7 | @IBOutlet var bidDetailsPreviewView: BidDetailsPreviewView! 8 | 9 | class func instantiateFromStoryboard(_ storyboard: UIStoryboard) -> ConfirmYourBidPasswordViewController { 10 | return storyboard.viewController(withID: .ConfirmYourBid) as! ConfirmYourBidPasswordViewController 11 | } 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | bidDetailsPreviewView.bidDetails = fulfillmentNav().bidDetails 17 | } 18 | 19 | @IBAction func dev_noPhoneNumberFoundTapped(_ sender: AnyObject) { 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/GenericFormValidationViewModel.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import RxSwift 3 | import Action 4 | 5 | class GenericFormValidationViewModel { 6 | let command: CocoaAction 7 | let disposeBag = DisposeBag() 8 | 9 | init(isValid: Observable, manualInvocation: Observable, finishedSubject: PublishSubject) { 10 | 11 | command = CocoaAction(enabledIf: isValid) { _ in 12 | return Observable.create { observer in 13 | 14 | finishedSubject.onCompleted() 15 | observer.onCompleted() 16 | 17 | return Disposables.create() 18 | } 19 | } 20 | 21 | manualInvocation 22 | .subscribe(onNext: { [weak self] _ in 23 | self?.command.execute() 24 | }) 25 | .addDisposableTo(disposeBag) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/KeypadContainerView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Foundation 3 | import RxSwift 4 | import Action 5 | import FLKAutoLayout 6 | 7 | //@IBDesignable 8 | class KeypadContainerView: UIView { 9 | fileprivate var keypad: KeypadView! 10 | fileprivate let viewModel = KeypadViewModel() 11 | 12 | var stringValue: Observable! 13 | var intValue: Observable! 14 | var deleteAction: CocoaAction! 15 | var resetAction: CocoaAction! 16 | 17 | override func prepareForInterfaceBuilder() { 18 | for subview in subviews { subview.removeFromSuperview() } 19 | 20 | let bundle = Bundle(for: type(of: self)) 21 | let image = UIImage(named: "KeypadViewPreviewIB", in: bundle, compatibleWith: self.traitCollection) 22 | let imageView = UIImageView(frame: self.bounds) 23 | imageView.image = image 24 | 25 | self.addSubview(imageView) 26 | } 27 | 28 | override func awakeFromNib() { 29 | super.awakeFromNib() 30 | 31 | keypad = Bundle(for: type(of: self)).loadNibNamed("KeypadView", owner: self, options: nil)?.first as? KeypadView 32 | keypad.leftAction = viewModel.deleteAction 33 | keypad.rightAction = viewModel.clearAction 34 | keypad.keyAction = viewModel.addDigitAction 35 | 36 | intValue = viewModel.intValue.asObservable() 37 | stringValue = viewModel.stringValue.asObservable() 38 | deleteAction = viewModel.deleteAction 39 | resetAction = viewModel.clearAction 40 | 41 | self.addSubview(keypad) 42 | 43 | keypad.align(to: self) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/KeypadView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import RxSwift 3 | import Action 4 | 5 | class KeypadView: UIView { 6 | var leftAction: CocoaAction? { 7 | didSet { 8 | self.leftButton.rx.action = leftAction 9 | } 10 | } 11 | var rightAction: CocoaAction? { 12 | didSet { 13 | self.rightButton.rx.action = rightAction 14 | } 15 | } 16 | 17 | var keyAction: Action? 18 | 19 | @IBOutlet fileprivate var keys: [Button]! 20 | @IBOutlet fileprivate var leftButton: Button! 21 | @IBOutlet fileprivate var rightButton: Button! 22 | 23 | @IBAction func keypadButtonTapped(_ sender: UIButton) { 24 | keyAction?.execute(sender.tag) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/KeypadViewPreviewIB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/KeypadViewPreviewIB.png -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/Models/NewUser.swift: -------------------------------------------------------------------------------- 1 | import RxSwift 2 | 3 | class NewUser { 4 | var email = Variable(nil) 5 | var password = Variable(nil) 6 | var phoneNumber = Variable(nil) 7 | var creditCardDigit = Variable(nil) 8 | var creditCardToken = Variable(nil) 9 | var creditCardName = Variable(nil) 10 | var creditCardType = Variable(nil) 11 | var zipCode = Variable(nil) 12 | var name = Variable(nil) 13 | 14 | var hasBeenRegistered = Variable(false) 15 | 16 | var swipedCreditCard = false 17 | } 18 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/edit_button@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/edit_button@2x.png -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/toolbar_close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/SourceryTests/Stub/Performance-Code/Kiosk/Bid Fulfillment/toolbar_close@2x.png -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/HelperFunctions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // Collection of stanardised mapping funtions for Rx work 4 | 5 | func stringIsEmailAddress(_ text: String) -> Bool { 6 | let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}" 7 | let testPredicate = NSPredicate(format:"SELF MATCHES %@", emailRegex) 8 | return testPredicate.evaluate(with: text) 9 | } 10 | 11 | func centsToPresentableDollarsString(_ cents: Int) -> String { 12 | guard let dollars = NumberFormatter.currencyString(forDollarCents: cents as NSNumber!) else { 13 | return "" 14 | } 15 | 16 | return dollars 17 | } 18 | 19 | func isZeroLength(string: String) -> Bool { 20 | return string.isEmpty 21 | } 22 | 23 | func isStringLength(in range: Range) -> (String) -> Bool { 24 | return { string in 25 | return range.contains(string.count) 26 | } 27 | } 28 | 29 | func isStringOf(length: Int) -> (String) -> Bool { 30 | return { string in 31 | return string.count == length 32 | } 33 | } 34 | 35 | func isStringLengthAtLeast(length: Int) -> (String) -> Bool { 36 | return { string in 37 | return string.count >= length 38 | } 39 | } 40 | 41 | func isStringLength(oneOf lengths: [Int]) -> (String) -> Bool { 42 | return { string in 43 | return lengths.contains(string.count) 44 | } 45 | } 46 | 47 | // Useful for mapping an Observable into an Observable to hide details. 48 | func void(_: T) -> Void { 49 | return Void() 50 | } 51 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Observable+JSONAble.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Moya 3 | import RxSwift 4 | 5 | enum EidolonError: String { 6 | case couldNotParseJSON 7 | case notLoggedIn 8 | case missingData 9 | } 10 | 11 | extension EidolonError: Swift.Error { } 12 | 13 | extension Observable { 14 | 15 | typealias Dictionary = [String: AnyObject] 16 | 17 | /// Get given JSONified data, pass back objects 18 | func mapTo(object classType: B.Type) -> Observable { 19 | return self.map { json in 20 | guard let dict = json as? Dictionary else { 21 | throw EidolonError.couldNotParseJSON 22 | } 23 | 24 | return B.fromJSON(dict) 25 | } 26 | } 27 | 28 | /// Get given JSONified data, pass back objects as an array 29 | func mapTo(arrayOf classType: B.Type) -> Observable<[B]> { 30 | return self.map { json in 31 | guard let array = json as? [AnyObject] else { 32 | throw EidolonError.couldNotParseJSON 33 | } 34 | 35 | guard let dicts = array as? [Dictionary] else { 36 | throw EidolonError.couldNotParseJSON 37 | } 38 | 39 | return dicts.map { B.fromJSON($0) } 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Observable+Logging.swift: -------------------------------------------------------------------------------- 1 | import RxSwift 2 | 3 | extension Observable { 4 | func logError(prefix: String = "Error: ") -> Observable { 5 | return self.do(onError: { error in 6 | print("\(prefix)\(error)") 7 | }) 8 | } 9 | 10 | func logServerError(message: String) -> Observable { 11 | return self.do(onError: { e in 12 | let error = e as NSError 13 | logger.log(message) 14 | logger.log("Error: \(error.localizedDescription). \n \(error.artsyServerError())") 15 | }) 16 | } 17 | 18 | func logNext() -> Observable { 19 | return self.do(onNext: { element in 20 | print("\(element)") 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Sale Artwork Details/ImageTiledDataSource.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import ARTiledImageView 3 | 4 | class TiledImageDataSourceWithImage: ARWebTiledImageDataSource { 5 | let image: Image 6 | 7 | init(image: Image) { 8 | self.image = image 9 | super.init() 10 | 11 | tileFormat = "jpg" 12 | tileBaseURL = URL(string: image.baseURL) 13 | tileSize = image.tileSize 14 | maxTiledHeight = image.maxTiledHeight 15 | maxTiledWidth = image.maxTiledWidth 16 | maxTileLevel = image.maxLevel 17 | minTileLevel = 11 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Sale Artwork Details/SaleArtworkZoomViewController.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import ARTiledImageView 3 | 4 | class SaleArtworkZoomViewController: UIViewController { 5 | var dataSource: TiledImageDataSourceWithImage! 6 | var saleArtwork: SaleArtwork! 7 | var tiledImageView: ARTiledImageScrollView! 8 | 9 | override func viewDidLoad() { 10 | super.viewDidLoad() 11 | 12 | let image = saleArtwork.artwork.defaultImage! 13 | dataSource = TiledImageDataSourceWithImage(image:image) 14 | 15 | let tiledView = ARTiledImageScrollView(frame:view.bounds) 16 | tiledView.decelerationRate = UIScrollViewDecelerationRateFast 17 | tiledView.showsHorizontalScrollIndicator = false 18 | tiledView.showsVerticalScrollIndicator = false 19 | tiledView.contentMode = .scaleAspectFit 20 | tiledView.dataSource = dataSource 21 | tiledView.backgroundImageURL = image.fullsizeURL() as URL! 22 | 23 | view.insertSubview(tiledView, at:0) 24 | tiledImageView = tiledView 25 | } 26 | 27 | override func viewWillAppear(_ animated: Bool) { 28 | super.viewWillAppear(animated) 29 | 30 | tiledImageView.zoom(toFit: false) 31 | } 32 | 33 | @IBAction func backButtonTapped(_ sender: AnyObject) { 34 | _ = self.navigationController?.popViewController(animated: true) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/Sale Artwork Details/WhitespaceGobbler.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class WhitespaceGobbler: UIView { 4 | override init(frame: CGRect) { 5 | super.init(frame: frame) 6 | } 7 | 8 | required init?(coder aDecoder: NSCoder) { 9 | super.init(coder: aDecoder) 10 | } 11 | 12 | convenience init() { 13 | self.init(frame: CGRect.zero) 14 | 15 | setContentHuggingPriority(50, for: .vertical) 16 | setContentHuggingPriority(50, for: .horizontal) 17 | backgroundColor = .clear 18 | } 19 | 20 | override var intrinsicContentSize: CGSize { 21 | return CGSize.zero 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/UIKit+Rx.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import RxSwift 3 | import RxCocoa 4 | 5 | extension UIView { 6 | public var rx_hidden: AnyObserver { 7 | return AnyObserver { [weak self] event in 8 | MainScheduler.ensureExecutingOnScheduler() 9 | 10 | switch event { 11 | case .next(let value): 12 | self?.isHidden = value 13 | case .error(let error): 14 | bindingErrorToInterface(error) 15 | break 16 | case .completed: 17 | break 18 | } 19 | } 20 | } 21 | } 22 | 23 | extension UITextField { 24 | var rx_returnKey: Observable { 25 | return self.rx.controlEvent(.editingDidEndOnExit).takeUntil(rx.deallocated) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/UIView+LongPressDisplayMessage.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import RxSwift 3 | 4 | private func alertController(_ message: String, title: String) -> UIAlertController { 5 | let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) 6 | 7 | alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) 8 | 9 | return alertController 10 | } 11 | 12 | extension UIView { 13 | typealias PresentAlertClosure = (_ alertController: UIAlertController) -> Void 14 | 15 | func presentOnLongPress(_ message: String, title: String, closure: @escaping PresentAlertClosure) { 16 | let recognizer = UILongPressGestureRecognizer() 17 | 18 | recognizer 19 | .rx.event 20 | .subscribe(onNext: { _ in 21 | closure(alertController(message, title: title)) 22 | }) 23 | .addDisposableTo(rx_disposeBag) 24 | 25 | isUserInteractionEnabled = true 26 | addGestureRecognizer(recognizer) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/Kiosk/UIViewController+Bidding.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import ARAnalytics 3 | 4 | extension UIViewController { 5 | func bid(auctionID: String, saleArtwork: SaleArtwork, allowAnimations: Bool, provider: Networking) { 6 | ARAnalytics.event("Bid Button Tapped", withProperties: ["id": saleArtwork.artwork.id]) 7 | 8 | let storyboard = UIStoryboard.fulfillment() 9 | let containerController = storyboard.instantiateInitialViewController() as! FulfillmentContainerViewController 10 | containerController.allowAnimations = allowAnimations 11 | 12 | if let internalNav: FulfillmentNavigationController = containerController.internalNavigationController() { 13 | internalNav.auctionID = auctionID 14 | internalNav.bidDetails.saleArtwork = saleArtwork 15 | internalNav.provider = provider 16 | } 17 | 18 | // Present the VC, then once it's ready trigger it's own showing animations 19 | appDelegate().appViewController.present(containerController, animated: false) { 20 | containerController.viewDidAppearAnimation(containerController.allowAnimations) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Performance-Code/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Artsy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Result/AllTypealiases.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | 4 | struct AnyBarAlias: HasBar { 5 | var bar: BarBaz 6 | } 7 | 8 | struct AnyFooAlias: HasFoo { 9 | var foo: FooBarBaz 10 | } 11 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Result/Basic+Other+SourceryTemplates.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | extension BarBaz: Equatable {} 4 | 5 | // BarBaz has Annotations 6 | 7 | func == (lhs: BarBaz, rhs: BarBaz) -> Bool { 8 | if lhs.parent != rhs.parent { return false } 9 | if lhs.otherVariable != rhs.otherVariable { return false } 10 | 11 | return true 12 | } 13 | 14 | extension FooBarBaz: Equatable {} 15 | 16 | func == (lhs: FooBarBaz, rhs: FooBarBaz) -> Bool { 17 | if lhs.name != rhs.name { return false } 18 | if lhs.value != rhs.value { return false } 19 | 20 | return true 21 | } 22 | 23 | extension FooSubclass: Equatable {} 24 | 25 | func == (lhs: FooSubclass, rhs: FooSubclass) -> Bool { 26 | if lhs.other != rhs.other { return false } 27 | 28 | return true 29 | } 30 | 31 | // Found 3 types 32 | // SourceryTemplateEJS Found 3 types 33 | // SourceryTemplateStencil found 3 types 34 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Result/Basic+Other+SourceryTemplates_Linux.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | extension BarBaz: Equatable {} 4 | 5 | // BarBaz has Annotations 6 | 7 | func == (lhs: BarBaz, rhs: BarBaz) -> Bool { 8 | if lhs.parent != rhs.parent { return false } 9 | if lhs.otherVariable != rhs.otherVariable { return false } 10 | 11 | return true 12 | } 13 | 14 | extension FooBarBaz: Equatable {} 15 | 16 | func == (lhs: FooBarBaz, rhs: FooBarBaz) -> Bool { 17 | if lhs.name != rhs.name { return false } 18 | if lhs.value != rhs.value { return false } 19 | 20 | return true 21 | } 22 | 23 | extension FooSubclass: Equatable {} 24 | 25 | func == (lhs: FooSubclass, rhs: FooSubclass) -> Bool { 26 | if lhs.other != rhs.other { return false } 27 | 28 | return true 29 | } 30 | 31 | // Found 3 types 32 | // SourceryTemplateStencil found 3 types 33 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Result/Basic+Other.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | extension BarBaz: Equatable {} 4 | 5 | // BarBaz has Annotations 6 | 7 | func == (lhs: BarBaz, rhs: BarBaz) -> Bool { 8 | if lhs.parent != rhs.parent { return false } 9 | if lhs.otherVariable != rhs.otherVariable { return false } 10 | 11 | return true 12 | } 13 | 14 | extension FooBarBaz: Equatable {} 15 | 16 | func == (lhs: FooBarBaz, rhs: FooBarBaz) -> Bool { 17 | if lhs.name != rhs.name { return false } 18 | if lhs.value != rhs.value { return false } 19 | 20 | return true 21 | } 22 | 23 | extension FooSubclass: Equatable {} 24 | 25 | func == (lhs: FooSubclass, rhs: FooSubclass) -> Bool { 26 | if lhs.other != rhs.other { return false } 27 | 28 | return true 29 | } 30 | 31 | // Found 3 types 32 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Result/Basic.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | extension BarBaz: Equatable {} 4 | 5 | // BarBaz has Annotations 6 | 7 | func == (lhs: BarBaz, rhs: BarBaz) -> Bool { 8 | if lhs.parent != rhs.parent { return false } 9 | if lhs.otherVariable != rhs.otherVariable { return false } 10 | 11 | return true 12 | } 13 | 14 | extension FooBarBaz: Equatable {} 15 | 16 | func == (lhs: FooBarBaz, rhs: FooBarBaz) -> Bool { 17 | if lhs.name != rhs.name { return false } 18 | if lhs.value != rhs.value { return false } 19 | 20 | return true 21 | } 22 | 23 | extension FooSubclass: Equatable {} 24 | 25 | func == (lhs: FooSubclass, rhs: FooSubclass) -> Bool { 26 | if lhs.other != rhs.other { return false } 27 | 28 | return true 29 | } 30 | 31 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Result/BasicFooExcluded.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | extension BarBaz: Equatable {} 4 | 5 | // BarBaz has Annotations 6 | 7 | func == (lhs: BarBaz, rhs: BarBaz) -> Bool { 8 | if lhs.parent != rhs.parent { return false } 9 | if lhs.otherVariable != rhs.otherVariable { return false } 10 | 11 | return true 12 | } 13 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Result/Function.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | func wrappedPerformFoo(value: FooBarBaz) { 4 | performFoo(value: value) 5 | } 6 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Result/Other.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | // Found 3 types 4 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Result/ProtocolCompositions.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | 4 | struct AnyFooBar: FooBar { 5 | 6 | // MARK: HasFoo properties 7 | var foo: FooBarBaz 8 | 9 | // MARK: HasBar properties 10 | var bar: BarBaz 11 | } 12 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Result/Typealiases.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery Major.Minor.Patch — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | // Typealiases in BarBaz 4 | // - name 'List', type '[FooBarBaz]' 5 | // Typealiases in FooBarBaz 6 | // - name 'Name', type '[String: String]' 7 | // Typealiases in FooSubclass 8 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Source/Bar.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // sourcery: this will not appear under FooBarBaz 4 | 5 | /// Documentation for bar 6 | // sourcery: showComment 7 | /// other documentation 8 | class BarBaz: FooBarBaz, AutoEquatable { 9 | typealias List = [FooBarBaz] 10 | var parent: FooBarBaz? = nil 11 | var otherVariable: Int = 0 12 | } 13 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Source/Foo.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class FooBarBaz { 4 | typealias Name = [String: String] 5 | 6 | var name: String = "" 7 | var value: Int = 0 8 | } 9 | 10 | protocol AutoEquatable {} 11 | 12 | class FooSubclass: FooBarBaz, AutoEquatable { 13 | var other: String = "" 14 | } 15 | 16 | func performFoo(value: FooBarBaz) { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Source/FooBar.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | protocol HasFoo { 4 | var foo: FooBarBaz { get } 5 | } 6 | protocol HasBar { 7 | var bar: BarBaz { get } 8 | } 9 | 10 | // sourcery: AutoStruct 11 | typealias FooBar = HasFoo & HasBar 12 | 13 | // sourcery: AutoStruct 14 | typealias FooAlias = HasFoo 15 | 16 | // sourcery: AutoStruct 17 | typealias BarAlias = HasBar 18 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Source/TestProject/TestProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Source/TestProject/TestProject/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Source_Linux/Bar.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // sourcery: this will not appear under FooBarBaz 4 | 5 | /// Documentation for bar 6 | // sourcery: showComment 7 | /// other documentation 8 | class BarBaz: FooBarBaz, AutoEquatable { 9 | // Note: when Swift Linux doesn't bug out on [String: String], add a test back for it 10 | // See https://github.com/krzysztofzablocki/Sourcery/pull/1208#issuecomment-1752185381 11 | // typealias List = [FooBarBaz] 12 | var parent: FooBarBaz? = nil 13 | var otherVariable: Int = 0 14 | } 15 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Source_Linux/Foo.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class FooBarBaz { 4 | // Note: when Swift Linux doesn't bug out on [String: String], add a test back for it 5 | // See https://github.com/krzysztofzablocki/Sourcery/pull/1208#issuecomment-1752185381 6 | // typealias Name = String 7 | 8 | var name: String = "" 9 | var value: Int = 0 10 | } 11 | 12 | protocol AutoEquatable {} 13 | 14 | class FooSubclass: FooBarBaz, AutoEquatable { 15 | var other: String = "" 16 | } 17 | 18 | func performFoo(value: FooBarBaz) { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Source_Linux/FooBar.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | protocol HasFoo { 4 | var foo: FooBarBaz { get } 5 | } 6 | protocol HasBar { 7 | var bar: BarBaz { get } 8 | } 9 | 10 | // sourcery: AutoStruct 11 | typealias FooBar = HasFoo & HasBar 12 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Source_Linux/TestProject/TestProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Source_Linux/TestProject/TestProject/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Stubs.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Krzysztof Zablocki on 13/12/2016. 3 | // Copyright (c) 2016 Pixle. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | import PathKit 8 | import Quick 9 | 10 | #if SWIFT_PACKAGE 11 | @testable import SourceryLib 12 | #else 13 | @testable import Sourcery 14 | #endif 15 | 16 | private class Reference {} 17 | 18 | enum Stubs { 19 | #if SWIFT_PACKAGE 20 | static let bundle = Bundle.module 21 | #else 22 | static let bundle = Bundle(for: Reference.self) 23 | #endif 24 | private static let basePath = bundle.resourcePath.flatMap { Path($0) }! 25 | static let swiftTemplates = basePath + Path("SwiftTemplates/") 26 | static let jsTemplates = basePath + Path("JavaScriptTemplates/") 27 | #if canImport(ObjectiveC) 28 | static let sourceDirectory = basePath + Path("Source/") 29 | #else 30 | static let sourceDirectory = basePath + Path("Source_Linux/") 31 | #endif 32 | static let sourceForPerformance = basePath + Path("Performance-Code/") 33 | static let sourceForDryRun = basePath + Path("DryRun-Code/") 34 | static let resultDirectory = basePath + Path("Result/") 35 | static let templateDirectory = basePath + Path("Templates") 36 | static let errorsDirectory = basePath + Path("Errors/") 37 | static let configs = basePath + Path("Configs/") 38 | 39 | static func cleanTemporarySourceryDir() -> Path { 40 | return Path.cleanTemporaryDir(name: "Sourcery") 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/Equality.swift: -------------------------------------------------------------------------------- 1 | import SourceryRuntime 2 | 3 | enum EqualityGenerator { 4 | static func generate(for types: Types) -> String { 5 | return types.classes.map { $0.generateEquality() }.joined(separator: "\n") 6 | } 7 | } 8 | 9 | extension Class { 10 | func generateEquality() -> String { 11 | let propertyComparisons = variables.map { $0.generateEquality() }.joined(separator: "\n ") 12 | 13 | return """ 14 | extension \(name): Equatable {} 15 | \(hasAnnotations()) 16 | func == (lhs: \(name), rhs: \(name)) -> Bool { 17 | \(propertyComparisons) 18 | 19 | return true 20 | } 21 | 22 | """ 23 | } 24 | 25 | func hasAnnotations() -> String { 26 | guard annotations["showComment"] != nil else { 27 | return "" 28 | } 29 | return """ 30 | 31 | // \(name) has Annotations 32 | 33 | """ 34 | } 35 | } 36 | 37 | extension Variable { 38 | func generateEquality() -> String { 39 | return "if lhs.\(name) != rhs.\(name) { return false }" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/Equality.swifttemplate: -------------------------------------------------------------------------------- 1 | <% for type in types.classes { -%> 2 | <%_ %><%# this is a comment -%> 3 | extension <%= type.name %>: Equatable {} 4 | 5 | <%_ if type.annotations["showComment"] != nil { -%> 6 | <% _%> // <%= type.name %> has Annotations 7 | 8 | <% } -%> 9 | func == (lhs: <%= type.name %>, rhs: <%= type.name %>) -> Bool { 10 | <%_ for variable in type.variables { -%> 11 | if lhs.<%= variable.name %> != rhs.<%= variable.name %> { return false } 12 | <%_ } %> 13 | return true 14 | } 15 | 16 | <% } -%> 17 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/Function.swifttemplate: -------------------------------------------------------------------------------- 1 | <%_ 2 | for function in functions { 3 | let functionName = String(function.name.split(separator: "(")[0]) 4 | let capitalizedName = functionName.prefix(1).uppercased() + functionName.dropFirst() 5 | -%> 6 | func wrapped<%= capitalizedName %>(<%= function.parameters.map { "\($0.name): \($0.typeName.name)" }.joined(separator: ", ") %>) { 7 | <%= functionName %>(<%= function.parameters.map { "\($0.name): \($0.name)" }.joined(separator: ", ") %>) 8 | } 9 | <%_ 10 | } 11 | -%> 12 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/IncludeCycle.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- include("includeCycle/One.swifttemplate") -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/IncludeFile.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- includeFile("Equality.swift") -%><%= EqualityGenerator.generate(for: types) %> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/IncludeFileNoExtension.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- includeFile("Equality") -%><%= EqualityGenerator.generate(for: types) %> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/Includes.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- include("Equality.swifttemplate") -%><%- include("Other.swifttemplate") -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/IncludesNoExtension.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- include("Equality") -%><%- include("Other") -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/Invalid.swifttemplate: -------------------------------------------------------------------------------- 1 | <%= %> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/InvalidTag.swifttemplate: -------------------------------------------------------------------------------- 1 | <% for type in types.all {%> 2 | extension <%= type.name > { 3 | } 4 | <%}%> 5 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/Other.swifttemplate: -------------------------------------------------------------------------------- 1 | // Found <%= types.all.count %> types 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/Runtime.swifttemplate: -------------------------------------------------------------------------------- 1 | <%= types.implementing["Some"] %> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/SelfIncludeCycle.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- include("SelfIncludeCycle.swifttemplate") -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/SubfolderFileIncludes.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- includeFile("lib/Equality.swift") -%><%= EqualityGenerator.generate(for: types) %> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/SubfolderIncludes.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- include("lib/One.swifttemplate") -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/Throws.swifttemplate: -------------------------------------------------------------------------------- 1 | <% fatalError("Template not implemented") %> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/includeCycle/One.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- include("Two.swifttemplate") -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/includeCycle/Two.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- include("One.swifttemplate") -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/lib/Equality.swift: -------------------------------------------------------------------------------- 1 | import SourceryRuntime 2 | 3 | enum EqualityGenerator { 4 | static func generate(for types: Types) -> String { 5 | return types.classes.map { $0.generateEquality() }.joined(separator: "\n") 6 | } 7 | } 8 | 9 | extension Class { 10 | func generateEquality() -> String { 11 | let propertyComparisons = variables.map { $0.generateEquality() }.joined(separator: "\n ") 12 | 13 | return """ 14 | extension \(name): Equatable {} 15 | \(hasAnnotations()) 16 | func == (lhs: \(name), rhs: \(name)) -> Bool { 17 | \(propertyComparisons) 18 | 19 | return true 20 | } 21 | 22 | """ 23 | } 24 | 25 | func hasAnnotations() -> String { 26 | guard annotations["showComment"] != nil else { 27 | return "" 28 | } 29 | return """ 30 | 31 | // \(name) has Annotations 32 | 33 | """ 34 | } 35 | } 36 | 37 | extension Variable { 38 | func generateEquality() -> String { 39 | return "if lhs.\(name) != rhs.\(name) { return false }" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/lib/One.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- include("Two.swifttemplate") -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/SwiftTemplates/lib/Two.swifttemplate: -------------------------------------------------------------------------------- 1 | <%- include("../Equality.swifttemplate") -%> 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Templates/Basic.stencil: -------------------------------------------------------------------------------- 1 | 2 | {% for type in types.classes %} 3 | extension {{ type.name }}: Equatable {} 4 | 5 | {% if type.annotations.showComment %} // {{ type.name }} has Annotations {% endif %} 6 | 7 | func == (lhs: {{ type.name }}, rhs: {{ type.name }}) -> Bool { 8 | {% for variable in type.variables %} if lhs.{{ variable.name }} != rhs.{{ variable.name }} { return false } 9 | {% endfor %} 10 | return true 11 | } 12 | {% endfor %} 13 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Templates/Include.stencil: -------------------------------------------------------------------------------- 1 | {% include "Partial.stencil" %} 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Templates/Other.stencil: -------------------------------------------------------------------------------- 1 | // Found {{ types.all.count }} types 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Templates/Partial.stencil: -------------------------------------------------------------------------------- 1 | partial template content 2 | -------------------------------------------------------------------------------- /SourceryTests/Stub/Templates/SourceryTemplateEJS.sourcerytemplate: -------------------------------------------------------------------------------- 1 | {"version":2,"instance":"eyJpZCI6IkNFOEJDQkQyLTFBODItNDQyNy1CN0M4LTM5NzVFMDRFOEUwNCIsImRlc2NyaXB0aW9uIjoiIiwiY29udGVudCI6IlwvXC8gU291cmNlcnlUZW1wbGF0ZUVKUyBGb3VuZCA8JS0gdHlwZXMuYWxsLmxlbmd0aCAlPiB0eXBlcyIsInZlcnNpb24iOjIsImZhdm9yaXRlIjp0cnVlLCJhdXRob3IiOiIiLCJ1cmwiOiIiLCJyZWdlbmVyYXRpb25Db3VudGVyIjoxLCJmaWxlVVJMIjoiZmlsZTpcL1wvXC9Vc2Vyc1wvbWVyb3dpbmdcL3dvcmtcL3ByaXZhdGVcL1NvdXJjZXJ5XC9Tb3VyY2VyeVRlc3RzXC9TdHViXC9UZW1wbGF0ZXNcL1NvdXJjZXJ5VGVtcGxhdGVFSlMuc291cmNlcnl0ZW1wbGF0ZSIsInJ1bkNvbmZpZ3VyYXRpb24iOiJzZWxlY3Rpb24iLCJzYW1wbGVDb2RlIjoic3RydWN0IEZvbyB7XG4gICAgdmFyIG51bWJlcjogSW50ID0gMlxuICAgIHZhciBuYW1lOiBTdHJpbmcgPSBcIlwiXG59XG5jbGFzcyBCb28ge30iLCJpc0xvY2tlZCI6ZmFsc2UsImtpbmQiOiJlanMiLCJ0cmltV2hpdGVzcGFjZXMiOnRydWUsIm5hbWUiOiJJbXBvcnRlZCBTb3VyY2VyeVRlc3RFSlMgMSIsImluc2VydGlvbk1vZGUiOiJlbmRPZkZpbGUifQ=="} -------------------------------------------------------------------------------- /SourceryTests/Stub/Templates/SourceryTemplateStencil.sourcerytemplate: -------------------------------------------------------------------------------- 1 | {"version":2,"instance":"eyJpZCI6IkU2RUVGOTZBLUY5QTktNEU4NC1CNUJGLTlCNkNFRkRFNTA1RSIsImRlc2NyaXB0aW9uIjoiIiwiY29udGVudCI6IlwvXC8gU291cmNlcnlUZW1wbGF0ZVN0ZW5jaWwgZm91bmQge3sgdHlwZXMuYWxsLmNvdW50IH19IHR5cGVzIiwidmVyc2lvbiI6MiwiZmF2b3JpdGUiOnRydWUsImF1dGhvciI6IiIsInVybCI6IiIsInJlZ2VuZXJhdGlvbkNvdW50ZXIiOjAsImZpbGVVUkwiOiJmaWxlOlwvXC9cL1VzZXJzXC9tZXJvd2luZ1wvd29ya1wvcHJpdmF0ZVwvU291cmNlcnlcL1NvdXJjZXJ5VGVzdHNcL1N0dWJcL1RlbXBsYXRlc1wvU291cmNlcnlUZW1wbGF0ZVN0ZW5jaWwuc291cmNlcnl0ZW1wbGF0ZSIsInJ1bkNvbmZpZ3VyYXRpb24iOiJzZWxlY3Rpb24iLCJzYW1wbGVDb2RlIjoic3RydWN0IEZvbyB7XG4gICAgdmFyIG51bWJlcjogSW50ID0gMlxuICAgIHZhciBuYW1lOiBTdHJpbmcgPSBcIlwiXG59XG5jbGFzcyBCb28ge30iLCJpc0xvY2tlZCI6ZmFsc2UsImtpbmQiOiJzdGVuY2lsIiwidHJpbVdoaXRlc3BhY2VzIjp0cnVlLCJuYW1lIjoiSW1wb3J0ZWQgU291cmNlcnlUZXN0IDEiLCJpbnNlcnRpb25Nb2RlIjoiZW5kT2ZGaWxlIn0="} -------------------------------------------------------------------------------- /SourceryUtils.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "SourceryUtils" 4 | s.version = "2.2.7" 5 | s.summary = "A tool that brings meta-programming to Swift, allowing you to code generate Swift code." 6 | s.platform = :osx, '10.15' 7 | 8 | s.description = <<-DESC 9 | A tool that brings meta-programming to Swift, allowing you to code generate Swift code. 10 | * Featuring daemon mode that allows you to write templates side-by-side with generated code. 11 | * Using SourceKit so you can scan your regular code. 12 | DESC 13 | 14 | s.homepage = "https://github.com/krzysztofzablocki/Sourcery" 15 | s.license = 'MIT' 16 | s.author = { "Krzysztof Zabłocki" => "krzysztof.zablocki@pixle.pl" } 17 | s.social_media_url = "https://twitter.com/merowing_" 18 | s.source = { :http => "https://github.com/krzysztofzablocki/Sourcery/releases/download/#{s.version}/sourcery-#{s.version}.zip" } 19 | 20 | s.source_files = "SourceryUtils/Sources/**/*.swift" 21 | 22 | s.osx.deployment_target = '10.15' 23 | 24 | s.dependency 'PathKit' 25 | end 26 | -------------------------------------------------------------------------------- /SourceryUtils/Sources/Sha.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Krzysztof Zablocki on 10/01/2017. 3 | // Copyright (c) 2017 Pixle. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | #if canImport(ObjectiveC) 8 | import CommonCrypto 9 | #else 10 | import Crypto 11 | #endif 12 | 13 | extension Data { 14 | public func sha256() -> Data { 15 | #if canImport(ObjectiveC) 16 | var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) 17 | self.withUnsafeBytes { (pointer) -> Void in 18 | _ = CC_SHA256(pointer.baseAddress, CC_LONG(pointer.count), &hash) 19 | } 20 | return Data(hash) 21 | #else 22 | let digest = SHA256.hash(data: self) 23 | return Data(digest) 24 | #endif 25 | } 26 | } 27 | 28 | extension String { 29 | public func sha256() -> String? { 30 | guard let data = data(using: String.Encoding.utf8) else { return nil } 31 | let rc = data.sha256().base64EncodedString(options: []) 32 | return rc 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SourceryUtils/Sources/Time.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Time.swift 3 | // SourceryFramework 4 | // 5 | // Created by merowing on 03/09/2019. 6 | // Copyright © 2019 Pixle. All rights reserved. 7 | // 8 | import Foundation 9 | 10 | /// Returns current timestamp interval 11 | public func currentTimestamp() -> TimeInterval { 12 | return Date().timeIntervalSince1970 13 | } 14 | -------------------------------------------------------------------------------- /SourceryUtils/Sources/Version.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Version.swift 3 | // Sourcery 4 | // 5 | // Created by Anton Domashnev on 15.06.17. 6 | // Copyright © 2017 Pixle. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct SourceryVersion { 12 | public let value: String 13 | public static let current = SourceryVersion(value: inUnitTests ? "Major.Minor.Patch" : "2.2.7") 14 | } 15 | 16 | #if canImport(ObjectiveC) 17 | public let inUnitTests: Bool = NSClassFromString("XCTest") != nil 18 | #else 19 | public let inUnitTests: Bool = ProcessInfo.processInfo.processName.hasSuffix("xctest") 20 | #endif 21 | -------------------------------------------------------------------------------- /SourceryUtils/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2018 Pixle. All rights reserved. 23 | 24 | 25 | -------------------------------------------------------------------------------- /SourceryUtils/Supporting Files/SourceryUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2018 Pixle. All rights reserved. 3 | // 4 | 5 | #import 6 | 7 | //! Project version number for SourceryUtils. 8 | FOUNDATION_EXPORT double SourceryUtilsVersionNumber; 9 | 10 | //! Project version string for SourceryUtils. 11 | FOUNDATION_EXPORT const unsigned char SourceryUtilsVersionString[]; 12 | 13 | // In this header, you should import all the public headers of your framework using statements like #import 14 | 15 | 16 | -------------------------------------------------------------------------------- /Templates/.swiftlint.yml: -------------------------------------------------------------------------------- 1 | excluded: # paths to ignore during linting. Takes precedence over `included`. 2 | - Tests/Generated 3 | - Tests/Expected 4 | -------------------------------------------------------------------------------- /Templates/CodableContext/CodableContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // CodableContext.h 3 | // CodableContext 4 | // 5 | // Created by Ilya Puchka on 29/04/2018. 6 | // Copyright © 2018 Pixle. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for CodableContext. 12 | FOUNDATION_EXPORT double CodableContextVersionNumber; 13 | 14 | //! Project version string for CodableContext. 15 | FOUNDATION_EXPORT const unsigned char CodableContextVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Templates/CodableContext/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2018 Pixle. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Templates/CodableContextTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Templates/Templates/AutoCases.stencil: -------------------------------------------------------------------------------- 1 | {% for enum in types.implementing.AutoCases|enum %} 2 | {{ enum.accessLevel }} extension {{ enum.name }} { 3 | static let count: Int = {{ enum.cases.count }} 4 | {% if not enum.hasAssociatedValues %} 5 | static let allCases: [{{ enum.name }}] = [ 6 | {% for case in enum.cases %} .{{ case.name }}{{ ',' if not forloop.last }} 7 | {% endfor %}] 8 | {% endif %} 9 | } 10 | {% endfor %} 11 | -------------------------------------------------------------------------------- /Templates/Templates/AutoLenses.stencil: -------------------------------------------------------------------------------- 1 | // swiftlint:disable variable_name 2 | infix operator *~: MultiplicationPrecedence 3 | infix operator |>: AdditionPrecedence 4 | 5 | struct Lens { 6 | let get: (Whole) -> Part 7 | let set: (Part, Whole) -> Whole 8 | } 9 | 10 | func * (lhs: Lens, rhs: Lens) -> Lens { 11 | return Lens( 12 | get: { a in rhs.get(lhs.get(a)) }, 13 | set: { (c, a) in lhs.set(rhs.set(c, lhs.get(a)), a) } 14 | ) 15 | } 16 | 17 | func *~ (lhs: Lens, rhs: B) -> (A) -> A { 18 | return { a in lhs.set(rhs, a) } 19 | } 20 | 21 | func |> (x: A, f: (A) -> B) -> B { 22 | return f(x) 23 | } 24 | 25 | func |> (f: @escaping (A) -> B, g: @escaping (B) -> C) -> (A) -> C { 26 | return { g(f($0)) } 27 | } 28 | 29 | {% for type in types.implementing.AutoLenses|struct %} 30 | extension {{ type.name }} { 31 | {% for variable in type.storedVariables %} 32 | static let {{ variable.name }}Lens = Lens<{{type.name}}, {{variable.typeName}}>( 33 | get: { $0.{{variable.name}} }, 34 | set: { {{variable.name}}, {{type.name|lowercase}} in 35 | {{type.name}}({% for argument in type.storedVariables %}{{argument.name}}: {% if variable.name == argument.name %}{{variable.name}}{% else %}{{type.name|lowercase}}.{{argument.name}}{% endif %}{{ ', ' if not forloop.last }}{% endfor %}) 36 | } 37 | ){% endfor %} 38 | } 39 | {% endfor %} 40 | -------------------------------------------------------------------------------- /Templates/Templates/LinuxMain.stencil: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | {{ argument.testimports }} 4 | {% for type in types.classes|based:"XCTestCase" %} 5 | {% if not type.annotations.disableTests %}extension {{ type.name }} { 6 | static var allTests: [(String, ({{ type.name }}) -> () throws -> Void)] = [ 7 | {% for method in type.methods %}{% if method.parameters.count == 0 and method.shortName|hasPrefix:"test" %} ("{{ method.shortName }}", {{ method.shortName }}){{ ',' if not forloop.last }} 8 | {% endif %}{% endfor %}] 9 | } 10 | {% endif %}{% endfor %} 11 | 12 | // swiftlint:disable trailing_comma 13 | XCTMain([ 14 | {% for type in types.classes|based:"XCTestCase" %}{% if not type.annotations.disableTests %} testCase({{ type.name }}.allTests), 15 | {% endif %}{% endfor %}]) 16 | // swiftlint:enable trailing_comma 17 | 18 | -------------------------------------------------------------------------------- /Templates/Tests/Context/AutoCases.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AutoCases.swift 3 | // Templates 4 | // 5 | // Created by Anton Domashnev on 03.05.17. 6 | // Copyright © 2017 Pixle. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol AutoCases {} 12 | 13 | enum AutoCasesEnum: AutoCases { 14 | case north 15 | case south 16 | case east 17 | case west 18 | } 19 | 20 | enum AutoCasesOneValueEnum: AutoCases { 21 | case one 22 | } 23 | 24 | public enum AutoCasesHasAssociatedValuesEnum: AutoCases { 25 | case foo(test: String) 26 | case bar(number: Int) 27 | } 28 | -------------------------------------------------------------------------------- /Templates/Tests/Context/AutoLenses.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLenses.swift 3 | // Templates 4 | // 5 | // Created by Anton Domashnev on 16.05.17. 6 | // Copyright © 2017 Pixle. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol AutoLenses {} 12 | 13 | struct House: AutoLenses { 14 | let rooms: Room 15 | let address: String 16 | let size: Int 17 | } 18 | 19 | struct Room: AutoLenses { 20 | let people: [Person] 21 | let name: String 22 | } 23 | 24 | struct Person: AutoLenses { 25 | let name: String 26 | } 27 | 28 | // swiftlint:disable identifier_name 29 | struct Rectangle: AutoLenses { 30 | let x: Int 31 | let y: Int 32 | 33 | var area: Int { 34 | return x*y 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Templates/Tests/Context/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LinuxMain.swift 3 | // Templates 4 | // 5 | // Created by Anton Domashnev on 17.05.17. 6 | // Copyright © 2017 Pixle. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | 12 | class AutoInjectionTests: XCTestCase { 13 | func testThatItResolvesAutoInjectedDependencies() { 14 | XCTAssertTrue(true) 15 | } 16 | 17 | func testThatItDoesntResolveAutoInjectedDependencies() { 18 | XCTAssertTrue(true) 19 | } 20 | } 21 | 22 | class AutoWiringTests: XCTestCase { 23 | func testThatItCanResolveWithAutoWiring() { 24 | XCTAssertTrue(true) 25 | } 26 | 27 | func testThatItCanNotResolveWithAutoWiring() { 28 | XCTAssertTrue(true) 29 | } 30 | } 31 | 32 | // sourcery: disableTests 33 | class DisabledTests: XCTestCase { 34 | func testThatItResolvesDisabledTestsAnnotation() { 35 | XCTAssertTrue(true) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Templates/Tests/Context_Linux/AutoCases.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AutoCases.swift 3 | // Templates 4 | // 5 | // Created by Anton Domashnev on 03.05.17. 6 | // Copyright © 2017 Pixle. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol AutoCases {} 12 | 13 | enum AutoCasesEnum: AutoCases { 14 | case north 15 | case south 16 | case east 17 | case west 18 | } 19 | 20 | enum AutoCasesOneValueEnum: AutoCases { 21 | case one 22 | } 23 | 24 | public enum AutoCasesHasAssociatedValuesEnum: AutoCases { 25 | case foo(test: String) 26 | case bar(number: Int) 27 | } 28 | -------------------------------------------------------------------------------- /Templates/Tests/Context_Linux/AutoLenses.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLenses.swift 3 | // Templates 4 | // 5 | // Created by Anton Domashnev on 16.05.17. 6 | // Copyright © 2017 Pixle. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol AutoLenses {} 12 | 13 | struct House: AutoLenses { 14 | let rooms: Room 15 | let address: String 16 | let size: Int 17 | } 18 | 19 | struct Room: AutoLenses { 20 | let people: [Person] 21 | let name: String 22 | } 23 | 24 | struct Person: AutoLenses { 25 | let name: String 26 | } 27 | 28 | // swiftlint:disable identifier_name 29 | struct Rectangle: AutoLenses { 30 | let x: Int 31 | let y: Int 32 | 33 | var area: Int { 34 | return x*y 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Templates/Tests/Context_Linux/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LinuxMain.swift 3 | // Templates 4 | // 5 | // Created by Anton Domashnev on 17.05.17. 6 | // Copyright © 2017 Pixle. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | 12 | class AutoInjectionTests: XCTestCase { 13 | func testThatItResolvesAutoInjectedDependencies() { 14 | XCTAssertTrue(true) 15 | } 16 | 17 | func testThatItDoesntResolveAutoInjectedDependencies() { 18 | XCTAssertTrue(true) 19 | } 20 | } 21 | 22 | class AutoWiringTests: XCTestCase { 23 | func testThatItCanResolveWithAutoWiring() { 24 | XCTAssertTrue(true) 25 | } 26 | 27 | func testThatItCanNotResolveWithAutoWiring() { 28 | XCTAssertTrue(true) 29 | } 30 | } 31 | 32 | // sourcery: disableTests 33 | class DisabledTests: XCTestCase { 34 | func testThatItResolvesDisabledTestsAnnotation() { 35 | XCTAssertTrue(true) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Templates/Tests/Expected/AutoCases.expected: -------------------------------------------------------------------------------- 1 | internal extension AutoCasesEnum { 2 | static let count: Int = 4 3 | static let allCases: [AutoCasesEnum] = [ 4 | .north, 5 | .south, 6 | .east, 7 | .west 8 | ] 9 | } 10 | public extension AutoCasesHasAssociatedValuesEnum { 11 | static let count: Int = 2 12 | } 13 | internal extension AutoCasesOneValueEnum { 14 | static let count: Int = 1 15 | static let allCases: [AutoCasesOneValueEnum] = [ 16 | .one 17 | ] 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Templates/Tests/Expected/LinuxMain.expected: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | extension AutoInjectionTests { 4 | static var allTests: [(String, (AutoInjectionTests) -> () throws -> Void)] = [ 5 | ("testThatItResolvesAutoInjectedDependencies", testThatItResolvesAutoInjectedDependencies), 6 | ("testThatItDoesntResolveAutoInjectedDependencies", testThatItDoesntResolveAutoInjectedDependencies) 7 | ] 8 | } 9 | extension AutoWiringTests { 10 | static var allTests: [(String, (AutoWiringTests) -> () throws -> Void)] = [ 11 | ("testThatItCanResolveWithAutoWiring", testThatItCanResolveWithAutoWiring), 12 | ("testThatItCanNotResolveWithAutoWiring", testThatItCanNotResolveWithAutoWiring) 13 | ] 14 | } 15 | 16 | // swiftlint:disable trailing_comma 17 | XCTMain([ 18 | testCase(AutoInjectionTests.allTests), 19 | testCase(AutoWiringTests.allTests), 20 | ]) 21 | // swiftlint:enable trailing_comma 22 | -------------------------------------------------------------------------------- /Templates/Tests/Generated/AutoCases.generated.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery 1.3.0 — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | 4 | internal extension AutoCasesEnum { 5 | static let count: Int = 4 6 | static let allCases: [AutoCasesEnum] = [ 7 | .north, 8 | .south, 9 | .east, 10 | .west 11 | ] 12 | } 13 | public extension AutoCasesHasAssociatedValuesEnum { 14 | static let count: Int = 2 15 | } 16 | internal extension AutoCasesOneValueEnum { 17 | static let count: Int = 1 18 | static let allCases: [AutoCasesOneValueEnum] = [ 19 | .one 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /Templates/Tests/Generated/LinuxMain.generated.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery 1.3.0 — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | import XCTest 4 | 5 | extension AutoInjectionTests { 6 | static var allTests: [(String, (AutoInjectionTests) -> () throws -> Void)] = [ 7 | ("testThatItResolvesAutoInjectedDependencies", testThatItResolvesAutoInjectedDependencies), 8 | ("testThatItDoesntResolveAutoInjectedDependencies", testThatItDoesntResolveAutoInjectedDependencies) 9 | ] 10 | } 11 | extension AutoWiringTests { 12 | static var allTests: [(String, (AutoWiringTests) -> () throws -> Void)] = [ 13 | ("testThatItCanResolveWithAutoWiring", testThatItCanResolveWithAutoWiring), 14 | ("testThatItCanNotResolveWithAutoWiring", testThatItCanNotResolveWithAutoWiring) 15 | ] 16 | } 17 | 18 | // swiftlint:disable trailing_comma 19 | XCTMain([ 20 | testCase(AutoInjectionTests.allTests), 21 | testCase(AutoWiringTests.allTests), 22 | ]) 23 | // swiftlint:enable trailing_comma 24 | 25 | -------------------------------------------------------------------------------- /Templates/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Templates/artifactbundle.info.json.template: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": "1.0", 3 | "artifacts": { 4 | "sourcery": { 5 | "type": "executable", 6 | "version": "VERSION", 7 | "variants": [ 8 | { 9 | "path": "sourcery/bin/sourcery", 10 | "supportedTriples": ["x86_64-apple-macosx", "arm64-apple-macosx"] 11 | }, 12 | ] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Tests/SourceryLibTests: -------------------------------------------------------------------------------- 1 | ../SourceryTests -------------------------------------------------------------------------------- /TryCatch/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2019 Pixle. All rights reserved. 23 | 24 | 25 | -------------------------------------------------------------------------------- /TryCatch/include/TryCatch.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftTryCatch.h 3 | // 4 | // Created by William Falcon on 10/10/14. 5 | // Copyright (c) 2014 William Falcon. All rights reserved. 6 | // 7 | /* 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #import 28 | 29 | @interface SwiftTryCatch : NSObject 30 | 31 | /** 32 | Provides try catch functionality for swift by wrapping around Objective-C 33 | */ 34 | + (void)tryBlock:(void(^)(void))tryBlock catchBlock:(void(^)(NSException*exception))catchBlock finallyBlock:(void(^)(void))finallyBlock; 35 | + (void)throwString:(NSString*)s; 36 | + (void)throwException:(NSException*)e; 37 | @end 38 | -------------------------------------------------------------------------------- /docs/badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | documentation 17 | 18 | 19 | documentation 20 | 21 | 22 | 100% 23 | 24 | 25 | 100% 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/docs/img/carat.png -------------------------------------------------------------------------------- /docs/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/docs/img/dash.png -------------------------------------------------------------------------------- /docs/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/docs/img/gh.png -------------------------------------------------------------------------------- /docs/img/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzysztofzablocki/Sourcery/68b7bd044d06d8860e763b65f107ea8647620658/docs/img/spinner.gif -------------------------------------------------------------------------------- /guides/Diffable.md: -------------------------------------------------------------------------------- 1 | ## I want to have diffing in tests 2 | 3 | Template used to generate much better output when using equality in tests, instead of having to read wall of text it's used to generate precise property level differences. This template uses [Sourcery Diffable implementation](../SourceryRuntime/Sources/Diffable.swift) 4 | 5 | from this: 6 | before 7 | 8 | to this: 9 | after 10 | 11 | 12 | ### [Stencil Template](https://github.com/krzysztofzablocki/Sourcery/blob/master/Sourcery/Templates/Diffable.stencil) 13 | 14 | #### Available annotations: 15 | 16 | - `skipEquality` allows you to skip variable from being compared. 17 | -------------------------------------------------------------------------------- /guides/Enum cases.md: -------------------------------------------------------------------------------- 1 | ## I want to list all cases in an enum 2 | 3 | Generate `count` and `allCases` for any enumeration that is marked with `AutoCases` phantom protocol. 4 | 5 | ### [Stencil Template](https://github.com/krzysztofzablocki/Sourcery/blob/master/Templates/Templates/AutoCases.stencil) 6 | 7 | #### Example output: 8 | 9 | ```swift 10 | extension BetaSettingsGroup { 11 | static let count: Int = return 8 12 | 13 | static let allCases: [BetaSettingsGroup] = [ 14 | .featuresInDevelopment, 15 | .advertising, 16 | .analytics, 17 | .marketing, 18 | .news, 19 | .notifications, 20 | .tech, 21 | .appInformation 22 | ] 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /guides/Equatable.md: -------------------------------------------------------------------------------- 1 | ## I want to generate `Equatable` implementation 2 | 3 | 4 | Template used to generate equality for all types that either conform to the `AutoEquatable` protocol or are [annotated](Writing%20templates.md#using-source-annotations) with `AutoEquatable` annotation, allowing us to avoid writing boilerplate code. 5 | 6 | It adds `:Equatable` conformance to all types, except protocols (because it would require turning them into PAT's). 7 | For protocols it's just generating `func ==`. 8 | 9 | ### [Stencil template](https://github.com/krzysztofzablocki/Sourcery/blob/master/Templates/Templates/AutoEquatable.stencil) 10 | 11 | #### Available variable annotations: 12 | 13 | - `skipEquality` allows you to skip variable from being compared. 14 | - `arrayEquality` mark this to use array comparsion for variables that have array of items that don't implement `Equatable` but have `==` operator e.g. Protocols 15 | 16 | #### Example output: 17 | 18 | ```swift 19 | // MARK: - AdNodeViewModel AutoEquatable 20 | extension AdNodeViewModel: Equatable {} 21 | 22 | internal func == (lhs: AdNodeViewModel, rhs: AdNodeViewModel) -> Bool { 23 | guard lhs.remoteAdView == rhs.remoteAdView else { return false } 24 | guard lhs.hidesDisclaimer == rhs.hidesDisclaimer else { return false } 25 | guard lhs.type == rhs.type else { return false } 26 | guard lhs.height == rhs.height else { return false } 27 | 28 | guard lhs.attributedDisclaimer == rhs.attributedDisclaimer else { return false } 29 | 30 | return true 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /guides/Hashable.md: -------------------------------------------------------------------------------- 1 | ## I want to generate `Hashable` implementation 2 | 3 | Template used to generate hashing for all types that conform to `:AutoHashable`, allowing us to avoid writing boilerplate code. 4 | 5 | It adds `:Hashable` conformance to all types, except protocols (because it would require turning them into PAT's). 6 | For protocols it's just generating `var hashValue` comparator. 7 | 8 | ### [Stencil template](https://github.com/krzysztofzablocki/Sourcery/blob/master/Templates/Templates/AutoHashable.stencil) 9 | 10 | #### Available variable annotations: 11 | 12 | - `skipHashing` allows you to skip variable from being compared. 13 | - `includeInHashing` is only applied on enums and allows us to add some computed variable into hashing logic 14 | 15 | #### Example output: 16 | 17 | ```swift 18 | // MARK: - AdNodeViewModel AutoHashable 19 | extension AdNodeViewModel: Hashable { 20 | 21 | internal var hashValue: Int { 22 | return combineHashes(remoteAdView.hashValue, hidesDisclaimer.hashValue, type.hashValue, height.hashValue, attributedDisclaimer.hashValue, 0) 23 | } 24 | } 25 | ``` -------------------------------------------------------------------------------- /guides/Installing.md: -------------------------------------------------------------------------------- 1 | ## Installing 2 | 3 | - _Binary form_ 4 | 5 | Download latest release with prebuilt binary from [release tab](https://github.com/krzysztofzablocki/Sourcery/releases/latest). Unzip the archive into desired destination and run `bin/sourcery` 6 | 7 | - _CocoaPods_ 8 | 9 | Add pod 'Sourcery' to your Podfile and run `pod update Sourcery`. This will download latest release binary and will put it to your project's CocoaPods path so you will run it with `$PODS_ROOT/Sourcery/bin/sourcery` 10 | 11 | - _Building from source_ 12 | 13 | Download latest release source code from [release tab](https://github.com/krzysztofzablocki/Sourcery/releases/latest) or clone the repository an build Sourcery manually. 14 | 15 | - _Building with Swift Package Manager_ 16 | 17 | Run `swift build -c release` in the root folder. This will create a `.build/release` folder and will put binary there. Move the **whole `.build/release` folder** to your desired destination and run with `path_to_release_folder/sourcery` 18 | 19 | > Note: JS templates are not supported when building with SPM yet. 20 | 21 | - _Building with Xcode_ 22 | 23 | Open `Sourcery.xcworkspace` and build with `Sourcery-Release` scheme. This will create `Sourcery.app` in the Derived Data folder. You can copy it to your desired destination and run with `path_to_sourcery_app/Sourcery.app/Contents/MacOS/Sourcery` 24 | -------------------------------------------------------------------------------- /guides/Lenses.md: -------------------------------------------------------------------------------- 1 | ## I want to generate Lenses for all structs 2 | 3 | _Contributed by [@filip_zawada](http://twitter.com/filip_zawada)_ 4 | 5 | What are Lenses? Great explanation by @mbrandonw 6 | 7 | This script assumes you follow swift naming convention, e.g. structs start with an upper letter. 8 | 9 | ### [Stencil template](https://github.com/krzysztofzablocki/Sourcery/blob/master/Templates/Templates/AutoLenses.stencil) 10 | 11 | #### Example output: 12 | 13 | ```swift 14 | extension House { 15 | 16 | static let roomsLens = Lens( 17 | get: { $0.rooms }, 18 | set: { rooms, house in 19 | House(rooms: rooms, address: house.address, size: house.size) 20 | } 21 | ) 22 | static let addressLens = Lens( 23 | get: { $0.address }, 24 | set: { address, house in 25 | House(rooms: house.rooms, address: address, size: house.size) 26 | } 27 | ) 28 | ... 29 | ``` 30 | -------------------------------------------------------------------------------- /guides/LinuxMain.md: -------------------------------------------------------------------------------- 1 | ## I want to generate `LinuxMain.swift` for all my tests 2 | 3 | For all test cases generates `allTests` static variable and passes all of them as `XCTestCaseEntry` to `XCTMain`. Run with `--args testimports='import MyTests'` parameter to import test modules. 4 | 5 | ### [Stencil template](https://github.com/krzysztofzablocki/Sourcery/blob/master/Templates/Templates/LinuxMain.stencil) 6 | 7 | #### Available annotations: 8 | 9 | - `disableTests` allows you to disable the whole test case. 10 | 11 | #### Example output: 12 | 13 | ```swift 14 | import XCTest 15 | //testimports 16 | 17 | extension AutoInjectionTests { 18 | static var allTests = [ 19 | ("testThatItResolvesAutoInjectedDependencies", testThatItResolvesAutoInjectedDependencies), 20 | ... 21 | ] 22 | } 23 | 24 | extension AutoWiringTests { 25 | static var allTests = [ 26 | ("testThatItCanResolveWithAutoWiring", testThatItCanResolveWithAutoWiring), 27 | ... 28 | ] 29 | } 30 | 31 | ... 32 | 33 | XCTMain([ 34 | testCase(AutoInjectionTests.allTests), 35 | testCase(AutoWiringTests.allTests), 36 | ... 37 | ]) 38 | 39 | ``` 40 | --------------------------------------------------------------------------------