Swiftpack.co - Package - krzysztofzablocki/Sourcery

CircleCI codecov docs Version License Platform

Sourcery is a code generator for Swift language, built on top of Apple's own SourceKit. It extends the language abstractions to allow you to generate boilerplate code automatically.

It's used in over 30,000 projects on both iOS and macOS and it powers some of the most popular and critically-acclaimed apps you have used. Its massive community adoption was one of the factors that pushed Apple to implement derived Equality and automatic Codable conformance. Sourcery is maintained by a growing community of contributors.

Try Sourcery for your next project or add it to an existing one -- you'll save a lot of time and be happy you did!

TL;DR

Sourcery allows you to get rid of repetitive tasks. An example might be implementing Equatable, without Sourcery you need to implement stuff like this:

extension Person: Equatable {
    static func ==(lhs: Person, rhs: Person) -> Bool {
        guard lhs.firstName == rhs.firstName else { return false }
        guard lhs.lastName == rhs.lastName else { return false }
        guard lhs.birthDate == rhs.birthDate else { return false }
        return true
    }
}

This is trivial code but imagine doing this across ten types. Across fifty. How many structs and classes are in your project?

Sourcery removes the need to write this code. And if you refactor or add properties, the equality code will be automatically updated for you, eliminating possible human errors.

Sourcery automation can be applied to many more domains, e.g.

  • Equality & Hashing
  • Enum cases & Counts
  • Lenses
  • Mocks & Stubs
  • LinuxMain
  • Decorators
  • JSON coding
  • NSCoding and Codable

It's trivial to write new templates to remove boilerplate that is specific to your projects.

How To Get Started

There are plenty of tutorials for different uses of Sourcery, and you can always ask for help in our Swift Forum Category.

Installation

  • Binary form

    Download the latest release with the prebuilt binary from release tab. Unzip the archive into the desired destination and run bin/sourcery

  • Homebrew

    brew install sourcery

  • CocoaPods

    Add pod 'Sourcery' to your Podfile and run pod update Sourcery. This will download the latest release binary and will put it in your project's CocoaPods path so you will run it with $PODS_ROOT/Sourcery/bin/sourcery

  • Mint

    Run mint run krzysztofzablocki/Sourcery.

  • Building from source

    Download the latest release source code from the release tab or clone the repository and build Sourcery manually.

    • Building with Swift Package Manager

      Run swift build -c release in the root folder. This will create a .build/release folder and will put the binary there. Move the whole .build/release folder to your desired destination and run with path_to_release_folder/sourcery

      Note: JS templates are not supported when building with SPM yet.

    • Building with Xcode

      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

Documentation

Full documentation for the latest release is available here.

Usage

Sourcery is a command line tool; you can either run it manually or in a custom build phase using the following command:

$ ./sourcery --sources <sources path> --templates <templates path> --output <output path>

Note: this command differs depending on how you installed Sourcery (see Installing)

Command line options

  • --sources - Path to a source swift files or directories. You can provide multiple paths using multiple --sources option.
  • --templates - Path to templates. File or Directory. You can provide multiple paths using multiple --templates options.
  • --force-parse - File extensions of Sourcery generated file you want to parse. You can provide multiple extension using multiple --force-parse options. (i.e. file.toparse.swift will be parsed even if generated by Sourcery if --force-parse toparse). Useful when trying to implement a multiple phases generation.
  • --output [default: current path] - Path to output. File or Directory.
  • --config [default: current path] - Path to config file. File or Directory. See Configuration file.
  • --args - Additional arguments to pass to templates. Each argument can have an explicit value or will have implicit true value. Arguments should be separated with , without spaces (i.e. --args arg1=value,arg2). Arguments are accessible in templates via argument.name
  • --watch [default: false] - Watch both code and template folders for changes and regenerate automatically.
  • --verbose [default: false] - Turn on verbose logging
  • --quiet [default: false] - Turn off any logging, only emit errors
  • --disableCache [default: false] - Turn off caching of parsed data
  • --prune [default: false] - Prune empty generated files
  • --version - Display the current version of Sourcery
  • --help - Display help information

Configuration file

Instead of CLI arguments you can use a .sourcery.yml configuration file:

sources:
  - <sources path>
  - <sources path>
templates:
  - <templates path>
  - <templates path>
force-parse:
  - <string value>
  - <string value>
output:
  <output path>
args:
  <name>: <value>

Read more about this configuration file here.

Contributing

Contributions to Sourcery are welcomed and encouraged!

It is easy to get involved. Please see the Contributing guide for more details.

A list of contributors is available through GitHub.

To clarify what is expected of our community, Sourcery has adopted the code of conduct defined by the Contributor Covenant. This document is used across many open source communities, and articulates my values well. For more, see the Code of Conduct.

License

Sourcery is available under the MIT license. See LICENSE for more information.

Attributions

This tool is powered by

Thank you! to:

  • Mariusz Ostrowski for creating the logo.
  • Artsy Eidolon team, because we use their codebase as a stub data for performance testing the parser.
  • Olivier Halligon for showing me his setup scripts for CLI tools which are powering our rakefile.

Other Libraries / Tools

If you want to generate code for asset related data like .xib, .storyboards etc. use SwiftGen. SwiftGen and Sourcery are complementary tools.

Make sure to check my other libraries and tools, especially:

  • KZPlayground - Powerful playgrounds for Swift and Objective-C
  • KZFileWatchers - Daemon for observing local and remote file changes, used for building other developer tools (Sourcery uses it)

You can follow me on Twitter for news/updates about other projects I am creating.

Github

link
Stars: 5333

Releases

0.18.0 - 2020-04-28 15:41:38

New Features

  • Added optional filter for variables
  • Added json filter to output raw JSON objects
  • Added .defaultValue to AssociatedValue
  • Added support for parsing Protocol Compositions
  • Added support for parsing free functions
  • Added support for indirect enum cases
  • Added support for accessing all typealiases via typealiases and typesaliasesByName
  • Added support for parsing global typealiases

Internal Changes

  • Improved error logging when running with --watch option
  • Updated CI to Xcode 11.4.1

Bug fixes

  • Fixed expansion of undefined environment variables (now consistent with command line behaviour, where such args are empty strings)
  • Fixed a bug in inferring extensions of Dictionary and Array types
  • Fixed a bug that was including default values as part of AssociatedValues type names
  • Fixed an issue with AutoMockable.stencil template when mocked function's return type was closure
  • Fixed missing SourceryRuntime dependency of SourceryFramework (SPM)

0.17.0 - 2019-09-03 09:37:36

Internal Changes

  • Parallelized combining phase that yields 5-10x speed improvement for New York Times codebase
  • Switched cache logic to rely on file modification date instead of content Sha256
  • Additional benchmark logs showing how long does each phase take
  • update dependencies to fix cocoapods setup when using Swift 5.0 everywhere. Update Quick to 2.1.0, SourceKitten to 0.23.1 and Yams to 2.0.0

0.16.2 - 2019-07-18 19:56:13

New Features

  • Support automatic linking of files generated by annotations to project target

Bug fixes

  • Fixes always broken sourcery cache
  • Add missing SourceryFramework library product in Package.swift

0.16.1 - 2019-04-29 14:23:34

Bug fixes

  • Fix ReceivedInvocations's type for the method which have only one parameter in AutoMockable.stencil
  • Fix missing folder error that could happen when running a Swift template with existing cache
  • Don't add indentation to empty line when using inline generated code.

Internal Changes

  • Removed dependency on SwiftTryCatch pod in order to avoid Swift Package Manager errors.

0.16.0 - 2019-03-08 22:42:32

  • Replaces environment variables inside .yml configurations (like ${PROJECT_NAME}), if a value is set.
  • Fixes warning in generated AutoMockable methods that have implicit optional return values
  • Support for optional methods in ObjC protocols
  • Support for parsing lazy vars into Variable's attributes.
  • Updated Stencil to 0.13.1 and SwiftStencilKit to 2.7.0
  • In Swift templates CLI arguments should now be accessed via argument instead of arguments, to be consistent with Stencil and JS templates.
  • Now in swift templates you can define types, extensions and use other Swift features that require file scope, without using separate files. All templates code is now placed at the top level of the template executable code, instead of being placed inside an extension of TemplateContext type.
  • Fixed missing generated code annotated with inline annotation when corresponding annotation in sources are missing. This generated code will be now present in *.generated.swift file.
  • Updated AutoHashable template to use Swift 4.2's hash(into:) method from Hashable, and enable support for inheritance.
  • Record all method invocations in the AutoMockable template.
  • Replace swiftc with the Swift Package Manager to build Swift templates
  • Swift templates can now be used when using a SPM build of Sourcery.

0.15.0 - 2018-09-23 12:26:23

New Features

  • You can now pass a json string as a command line arg or annotation and have it parsed into a Dictionary or Array to be used in the template.
  • Support for Xcode 10 and Swift 4.2
  • Updated Stencil to 0.12.1

0.14.0 - 2018-08-28 08:48:38

New Features

  • You can now include entire Swift files in Swift templates
  • You can now use AutoEquatable with annotations
  • Content from multiple file annotations will now be concatenated instead of writing only the latest generated content.

For example content generated by two following templates

// sourcery:file:Generated/Foo.swift
line one
// sourcery:end

and

// sourcery:file:Generated/Foo.swift
line two
// sourcery:end

will be written to one file:

line one

line two

Internal Changes

  • Use AnyObject for class-only protocols

Bug fixes

  • Fixed parsing associated enum cases in Xcode 10
  • Fixed AutoEquatable access level for == func
  • Fixed path of generated files when linked to Xcode project
  • Fixed extraction of inline annotations in multi line comments with documentation style
  • Fixed compile error when used AutoHashable in NSObject subclass.

0.13.1 - 2018-05-08 21:24:55

New Features

  • Added support for enums in AutoCodable template
  • You can now specify the base path for the Sourcery cache directory with a cacheBasePath key in the config file

0.13.0 - 2018-04-21 19:02:16

New Features

Bug fixes

  • Fixed parsing protocol method return type followed by declaration with attribute
  • Fixed inserting auto-inlined code on the last line of declaration body
  • AutoEquatable and AutoHashable templates should not add protocol conformances in extensions

0.12.0 - 2018-04-11 20:52:49

Internal Changes

  • Migrate to Swift 4.1 and Xcode 9.3

0.11.2 - 2018-04-10 19:40:54

!!This is the last release that will support Swift 4.0. Next release (except patches) will be built with Swift 4.1!!

Bug fixes

  • Autocases template not respecting type access level
  • Ensure SPM and CocoaPods dependencies match
  • Improve AutoMockable template to handle methods with optional return values
  • Fixed crash while compiling swift templates

0.11.1 - 2018-04-09 14:48:03

!!This is the last release that will support Swift 4.0. Next release (except patches) will be built with Swift 4.1!!

Internal changes

  • Do not fail the build if slather fails
  • Updated SourceKitten to 0.20.0

Bug fixes

  • Fixed parsing protocol methods return type (#579)

0.11.0 - 2018-04-02 22:50:17

!!This is the last release that will support Swift 4.0. Next release (except patches) will be built with Swift 4.1!!

New Features

  • Supports adding new templates files while in watcher mode
  • Supports adding new source files while in watcher mode
  • Added support for subscripts
  • Added isGeneric property for Method
  • You can now pass additional arguments one by one, i.e. --args arg1=value1 --args arg2 --args arg3=value3
  • Improved support for generic types. Now you can access basic generic type information with TypeName.generic property
  • added @objcMembers attribute
  • Moved EJS and Swift templates to separate framework targets
  • EJS templates now can be used when building Sourcery with SPM
  • Added Closures to AutoMockable
  • You can now link generated files to projects using config file
  • You can now use AutoMockable with annotations
  • Updated to latest version of Stencil (commit 9184720)
  • Added support for annotation namespaces
  • Added --exclude-sources and --exclude-templates CLI options

Breaking

  • @objc attribute now has a name argument that contains Objective-C name of attributed declaration
  • Type collections types.based, types.implementing and types.inheriting now return non-optional array. If no types found, empty array will be returned. This is a breaking change for template code like this:
<% for type in (types.implementing["SomeProtocol"] ?? []) { %>

The new correct syntax would be:

<% for type in types.implementing["SomeProtocol"] { %>

Internal changes

  • Migrate to Swift 4, SwiftPM 4 and Xcode 9.2
  • selectorName for methods without parameters now will not contain ()
  • returnTypeName for initializers will be the type name of defining type, with ? for failable initializers
  • Improved compile time of AutoHashable template
  • Updated StencilSwiftKit and Stencil to 0.10.1

Bug fixes

  • Fixes FSEvents errors reported in #465 that happen on Sierra
  • JS exceptions no more override syntax errors in JS templates
  • Accessing unknown property on types now results in a better error than undefined is not an object in JS templates
  • Fixed issue in AutoMockable, where generated non-optional variables wouldn't meet protocol's requirements. For this purpose, underlying variable was introduced
  • Fixed inline:auto not inserting code if Sourcery is run with cache enabled #467
  • Fixed parsing @objc attributes on types
  • Fixed parsing void return type in methods without spaces between method name and body open curly brace and in protocols
  • Fixed AutoMockable template generating throwing method with void return type
  • Fixed parsing throwing initializers
  • Fixed trying to process files which do not exist
  • Automockable will not generate mocks for methods defined in protocol extensions
  • Fixed parsing typealiases of generic types
  • AutoLenses template will create lenses only for stored properties
  • Fixed resolving actual type name for generics with inner types
  • Fixed parsing nested types from extensions
  • Fixed removing back ticks in types names
  • Fixed creating output folder if it does not exist
  • Fixed inferring variable types with closures and improved inferring types of enum default values
  • Fixed enum cases with empty parenthesis not having () associated value

0.10.1 - 2017-12-19 23:15:44

  • When installing Sourcery via CocoaPods, the unneeded file.zip is not kept in Pods/Sourcery/ anymore (freeing ~12MB on each install of Sourcery made via CocoaPods!).

0.10.0 - 2017-12-11 23:24:03

New Features

  • Added test for count Stencil filter
  • Added new reversed Stencil filter
  • Added new isEmpty Stencil filter
  • Added new sorted and sortedDescending Stencil filters. This can sort arrays by calling e.g. protocol.allVariables|sorted:"name"
  • Added new toArray Stencil filter
  • Added a console warning when a yaml is available but any parameter between 'sources', templates', 'forceParse', 'output' are provided

Internal changes

  • Add release to Homebrew rake task
  • Fixed Swiftlint warnings
  • Fixed per file generation if there is long (approx. 150KB) output inside sourcery:file annotation
  • Do not generate default.profraw
  • Remove filters in favor of same filters from StencilSwiftKit

0.9.0 - 2017-09-22 23:15:38

New Features

  • Added support for file paths in config parameter
  • Added isDeinitializer property for methods
  • Improved config file validation and error reporting
  • Various improvements for AutoMockable template:
    • support methods with reserved keywords name
    • support methods that throws
    • improved generated declarations names

Bug fixes

  • Fixed single file generation not skipping writing the file when there is no generated content

Internal changes

  • Updated dependencies for Swift 4
  • Update internal ruby dependencies

0.8.0 - 2017-08-12 16:48:16

New Features

  • Added support in AutoHashable for static variables, [Hashable] array and [Hashable: Hashable] dictionary
  • Added definedInType property for Method and Variable
  • Added extensions filter for stencil template
  • Added include support in Swift templates
  • Swift templates now can throw errors. You can also throw just string literals.
  • Added support for TypeName in string filters (except filters from StencilSwiftKit).

Bug fixes

  • Fixed linker issue when using Swift templates
  • Updated AutoMockable to exclude generated code collisions
  • Fixed parsing of default values for variables that also have a body (e.g. for didSet)
  • Fixed line number display when an error occur while parsing a Swift template
  • Fixed rsync issue on SourceryRuntime.framework when using Swift templates
  • Fixed auto:inline for nested types (this concerns the first time the code is inserted)

Internal changes

  • Fix link for template in docs
  • Fix running Sourcery in the example app
  • Add step to update internal boilerplate code during the release

0.7.2 - 2017-06-16 22:45:59

Internal changes

  • Add Version.swift to represent CLI tool version

0.7.1 - 2017-06-14 18:15:14

Bug fixes

  • Fixed regression in parsing templates from config file
  • Removed meaningless isMutating property for Variable

Internal changes

  • Improvements in release script
  • Updated boilerplate code to reflect latest changes

0.7.0 - 2017-06-11 13:38:41

New Features

  • Added inout flag for MethodParameter
  • Added parsing mutating and final attributes with convenience isMutating and isFinal properties
  • Added support for include Stencil tag
  • Added support for excluded paths

Bug fixes

  • Fixed inserting generated code inline automatically at wrong position
  • Fixed regression in AutoEquatable & AutoHashable template with private computed variables

Internal changes

  • Internal release procedure improvements
  • Improved TemplatesTests scheme running
  • Fixed swiftlint warnings (version 0.19.0)

0.6.1 - 2017-05-28 14:32:53

New Features

  • Paths in config file are now relative to config file path by default, absolute paths should start with /
  • Improved logging and error reporting, added --quiet CLI option, added runtime errors for using invalid types in implementing and inheriting
  • Added support for includes in EJS templates (for example: <%- include('myTemplate.js') %>)
  • Add the lowerFirst filter for Stencil templates.
  • Added isRequired property for Method
  • Improved parsing of closure types
  • Check if Current Project Version match version in podspec in release task
  • Improved swift templates performance
  • Added // sourcery:file annotation for source code

Bug fixes

  • Fixed detecting computed properties
  • Fixed typo in isConvenienceInitialiser property
  • Fixed creating cache folder when cache is disabled
  • Fixed parsing multiple enum cases annotations
  • Fixed parsing inline annotations when there is an access level or attribute
  • Fixed parsing required attribute
  • Fixed typo in guides/Writing templates.md

Internal changes

  • Improved AutoMockable.stencil to support protocols with init methods
  • Improved AutoCases.stencil to use let instead of computed var
  • Updated StencilSwiftKit to 1.0.2 which includes Stencil 0.9.0
  • Adding docset to release archive
  • Add tests for bundled stencil templates
  • Moved to CocoaPods 1.2.1
  • Made Array.parallelMap's block non-escaping

0.6.0 - 2017-04-18 18:56:39

New Features

  • Added support for inline code generation without requiring explicit // sourcery:inline comments in the source files. To use, use sourcery:inline:auto in a template: // sourcery:inline:auto:MyType.TemplateName
  • Added isMutable property for Variable
  • Added support for scanning multiple targets
  • Added access level filters and disabled filtering private declarations
  • Added support for inline comments for annotations with /* and */
  • Added annotations for enum case associated values and method parameters
  • Added isConvenienceInitializer property for Method
  • Added defaultValue for variables and method parameters
  • Added docs generated with jazzy
  • Sourcery now will not create empty files and will remove existing generated files with empty content if CLI flag prune is set to true (false by default)
  • Sourcery now will remove inline annotation comments from generated code.
  • Added rethrows property to Method
  • Allow duplicated annotations to be agregated into array
  • Added ejs-style tags to control whitespaces and new lines in swift templates
  • Added CLI option to provide path to config file

Bug Fixes

  • Inserting multiple inline code block in one file
  • Suppress warnings when compiling swift templates
  • Accessing protocols in Swift templates
  • Crash that would happen sometimes when parsing typealiases

Internal changes

  • Replaced TypeReflectionBox and GenerationContext types with common TemplateContext.

0.5.9 - 2017-03-17 09:41:50

New Features

  • Added flag to check if TypeName is dictionary
  • Added support for multiple sources and templates paths, sources, templates and output paths now should be provided with --sources, --templates and --output options
  • Added support for YAML file configuration
  • Added generation of non-swift files using sourcery:file annotation

Bug Fixes

  • Fixed observing swift and js templates
  • Fixed parsing generic array types
  • Fixed using dictionary in annotations

0.5.8 - 2017-03-01 15:19:50

New Features

  • Added parsing array types
  • Added support for JavaScript templates (using EJS)

Bug Fixes

  • Fixed escaping variables with reserved names
  • Fixed duplicated methods and variables in allMethods and allVariables
  • Fixed trimming attributes in type names

0.5.7 - 2017-02-16 20:36:12

Bug Fixes

  • Cache initial file contents, including the inline generated ranges so that they are always up to date

0.5.6 - 2017-02-16 17:07:08

New Features

  • Added per file code generation

Bug Fixes

  • Fixed parsing annotations with complex content
  • Fixed inline parser using wrong caching logic

0.5.5 - 2017-02-08 19:09:31

New Features

  • Sourcery will no longer write files if content didn't change, this improves behaviour of things depending on modification date like Xcode, Swiftlint.

Internal changes

  • Improved support for contained types

Bug Fixes

  • Fixes cache handling that got broken in 0.5.4

0.5.4 - 2017-02-04 18:01:59

New Features

  • Added inline code generation
  • Added isClosure property to TypeName to detect closure types

Bug Fixes

  • Fixed parsing of associated values separater by newlines
  • Fixed preserving order of inherited types
  • Improved support for throwing methods in protocols
  • Fixed extracting parameters of methods with closures in their bodies
  • Fixed extracting method return types of tuple types
  • Improved support for typealises as tuple elements types
  • Method parameters with _ argument label will now have nil in argumentLabel property
  • Improved support for generic methods

Internal changes

  • adjusted internal templates and updated generated code
  • moved methods parsing related tests in a separate spec

0.5.3 - 2017-01-13 19:28:37

New Features

  • Added support for method return types with throws and rethrows
  • Added a new filter replace. Usage: {{ name|replace:"substring","replacement" }} - replaces occurrences of substring with replacement in name (case sensitive)
  • Improved support for inferring types of variables with initial values
  • Sourcery is now bundling a set of example templates, you can access them in Templates folder.
  • We now use parallel parsing and cache source artifacts. This leads to massive performance improvements:
  • e.g. on big codebase of over 300 swift files:
Sourcery 0.5.2
Processing time 8.69941002130508 seconds

Sourcery 0.5.3
First time 4.69904798269272 seconds
Subsequent time: 0.882099032402039 seconds

Bug Fixes

  • Method accessLevel was not exposed as string so not accessible properly via templates, fixed that.
  • Fixes on Swift Templates

0.5.2 - 2017-01-09 20:53:18

New Features

  • Added support for ImplicitlyUnwrappedOptional
  • actualTypeName property of Method.Parameter, Variable, Enum.Case.AssociatedValue, TupleType.Element now returns typeName if type is not a type alias
  • Enum now contains type information for its raw value type. rawType now return Type object, rawTypeName returns its TypeName
  • Added annotated filter to filter by annotations
  • Added negative filters counterparts
  • Added support for attributes, i.e. @escaping
  • Experimental support for Swift Templates
<% for type in types.classes { %>
    extension <%= type.name %>: Equatable {}

    <% if type.annotations["showComment"] != nil { %> // <%= type.name %> has Annotations <% } %>

        func == (lhs: <%= type.name %>, rhs: <%= type.name %>) -> Bool {
    <% for variable in type.variables { %> if lhs.<%= variable.name %> != rhs.<%= variable.name %> { return false }
        <% } %>
        return true
    }
<% } %>