Skip to content

Commit

Permalink
Merge pull request #148 from scribd/145
Browse files Browse the repository at this point in the history
Multi platform support
  • Loading branch information
trupin authored Jun 11, 2020
2 parents 12cc126 + 0fe3586 commit cd549d6
Show file tree
Hide file tree
Showing 20 changed files with 402 additions and 74 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,8 @@ Sample/fastlane/test_output

# Package
weaver-*.zip
.weaver_cache.json
.weaver_cache.json

# Tests
API
Sample/Generated
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,8 @@ var dependencyName: DependencyType

- `escaping: Bool` (default: `true` when applicable): asks Weaver to use `@escaping` when declaring a closure parameter.

- `platforms: [Platform]` (default: `[]`): List of platforms for which Weaver is allowed to use the dependency. An empty list means any platform is allowed.

#### Using protperty wrappers with parameters:

Types using parameter annotations need to take the said parameters as an input when being registered or referenced. This is particularly true when using property wrappers, because the signature of the annotation won't compile if not done correctly.
Expand Down Expand Up @@ -550,6 +552,9 @@ Options:
--tests - Activates the test helpers' generation.
--testable-imports - Modules to imports in the test helpers.
--swiftlint-disable-all - Disables all swiftlint rules.
--platform - Targeted platform.
--included-imports - Included imports.
--excluded-imports - Excluded imports.
```

### Example:
Expand All @@ -569,6 +574,10 @@ weaver swift --project-path $PROJECT_DIR/$PROJECT_NAME --main-output-path Genera
- `--recursive-off`: Deactivates recursivity for `input-path` and `ignored-path`.
- `--tests` - Activates the test helpers' generation.
- `--testable-imports` - Modules to imports in the test helpers. Variadic parameter, which means it can be set more than once.
- `--swiftlint-disable-all` - Disables all swiftlint rules in generated files.
- `--platform` - Platform for which the generated code will be compiled (iOS, watchOS, OSX, macOS or tvOS).
- `--included-imports` - Modules which can be imported in generated files.
- `--excluded-imports` - Modules which can't be imported in generated files.

### Configuration File:

Expand Down Expand Up @@ -617,7 +626,9 @@ Options:
--pretty [default: false]
--input-path - Paths to input files.
--ignored-path - Paths to ignore.
--cache-path - Cache path.
--recursive-off
--platform - Selected platform
```
For an output example, please check this [Gist](https://gist.github.com/trupin/9438713f8fae0a5a7f424eca1976f42b).
Expand Down
3 changes: 2 additions & 1 deletion Sample/API/Generated/Weaver.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import Foundation
import UIKit

/// This file is generated by Weaver 1.0.4
// swiftlint:disable all
/// This file is generated by Weaver 1.0.6
/// DO NOT EDIT!

final class MainDependencyContainer {
Expand Down
27 changes: 22 additions & 5 deletions Sample/Sample/Generated/Weaver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import API
import Foundation
import UIKit

/// This file is generated by Weaver 1.0.4
// swiftlint:disable all
/// This file is generated by Weaver 1.0.6
/// DO NOT EDIT!

@objc final class MainDependencyContainer: NSObject {
Expand Down Expand Up @@ -101,6 +102,14 @@ import UIKit
case lazy
}

enum Platform {
case OSX
case macOS
case iOS
case watchOS
case tvOS
}

enum DependencyKind {
case registration
case reference
Expand Down Expand Up @@ -366,7 +375,9 @@ struct Weaver<ConcreteType, AbstractType> {
scope: MainDependencyContainer.Scope = .container,
setter: Bool = false,
escaping: Bool = false,
builder: Optional<Any> = nil) {
builder: Optional<Any> = nil,
objc: Bool = false,
platforms: Array<MainDependencyContainer.Platform> = []) {
// no-op
}

Expand All @@ -380,7 +391,9 @@ extension Weaver where ConcreteType == Void {
scope: MainDependencyContainer.Scope = .container,
setter: Bool = false,
escaping: Bool = false,
builder: Optional<Any> = nil) {
builder: Optional<Any> = nil,
objc: Bool = false,
platforms: Array<MainDependencyContainer.Platform> = []) {
// no-op
}
}
Expand All @@ -396,7 +409,9 @@ struct WeaverP2<ConcreteType, AbstractType, P1, P2> {
scope: MainDependencyContainer.Scope = .container,
setter: Bool = false,
escaping: Bool = false,
builder: Optional<Any> = nil) {
builder: Optional<Any> = nil,
objc: Bool = false,
platforms: Array<MainDependencyContainer.Platform> = []) {
// no-op
}

Expand All @@ -410,7 +425,9 @@ extension WeaverP2 where ConcreteType == Void {
scope: MainDependencyContainer.Scope = .container,
setter: Bool = false,
escaping: Bool = false,
builder: Optional<Any> = nil) {
builder: Optional<Any> = nil,
objc: Bool = false,
platforms: Array<MainDependencyContainer.Platform> = []) {
// no-op
}
}
10 changes: 10 additions & 0 deletions Sources/WeaverCodeGen/Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ extension ConfigurationAttribute: Codable {
self = .setter(value: try container.decode(Bool.self, forKey: .value))
case .escaping:
self = .escaping(value: try container.decode(Bool.self, forKey: .value))
case .platforms:
self = .platforms(values: try container.decode([Platform].self, forKey: .value))
}
}

Expand All @@ -53,6 +55,9 @@ extension ConfigurationAttribute: Codable {
case .escaping(let value):
try container.encode(ConfigurationAttributeName.escaping, forKey: .name)
try container.encode(value, forKey: .value)
case .platforms(let value):
try container.encode(ConfigurationAttributeName.platforms, forKey: .name)
try container.encode(value, forKey: .value)
}
}
}
Expand Down Expand Up @@ -89,6 +94,7 @@ extension ConfigurationAttributeName: Codable {
case doesSupportObjc = "o"
case setter = "set"
case escaping = "e"
case platforms = "p"

init(_ value: ConfigurationAttributeName) {
switch value {
Expand All @@ -104,6 +110,8 @@ extension ConfigurationAttributeName: Codable {
self = .setter
case .escaping:
self = .escaping
case .platforms:
self = .platforms
}
}

Expand All @@ -121,6 +129,8 @@ extension ConfigurationAttributeName: Codable {
return .setter
case .escaping:
return .escaping
case .platforms:
return .platforms
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/WeaverCodeGen/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,15 @@ struct DependencyConfiguration: Configuration {

let escaping: Bool

let platforms: Set<Platform>

init(with attributes: [ConfigurationAttributeName: ConfigurationAttribute]?) {
customBuilder = attributes?[.customBuilder]?.stringValue
scope = attributes?[.scope]?.scopeValue ?? .default
doesSupportObjc = attributes?[.doesSupportObjc]?.boolValue ?? false
setter = attributes?[.setter]?.boolValue ?? false
escaping = attributes?[.escaping]?.boolValue ?? false
platforms = Set(attributes?[.platforms]?.platformValues ?? [])
}
}

Expand Down
74 changes: 62 additions & 12 deletions Sources/WeaverCodeGen/ConfigurationAttribute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public enum ConfigurationAttributeName: String {
case doesSupportObjc = "objc"
case setter
case escaping
case platforms
}

public enum ConfigurationAttribute: Hashable {
Expand All @@ -25,6 +26,7 @@ public enum ConfigurationAttribute: Hashable {
case doesSupportObjc(value: Bool)
case setter(value: Bool)
case escaping(value: Bool)
case platforms(values: [Platform])
}

// MARK: - Target
Expand Down Expand Up @@ -60,6 +62,8 @@ extension ConfigurationAttribute: CustomStringConvertible {
return "Config Attr - setter = \(value)"
case .escaping(let value):
return "Config Attr - escaping = \(value)"
case .platforms(let values):
return "Config Attr - platforms = [\(values.map { ".\($0.rawValue)" }.joined(separator: ", "))]"
}
}

Expand All @@ -77,6 +81,8 @@ extension ConfigurationAttribute: CustomStringConvertible {
return .setter
case .escaping:
return .escaping
case .platforms:
return .platforms
}
}
}
Expand Down Expand Up @@ -104,15 +110,17 @@ extension ConfigurationAnnotation {
(.scope, .dependency),
(.doesSupportObjc, .dependency),
(.setter, .dependency),
(.escaping, .dependency):
(.escaping, .dependency),
(.platforms, .dependency):
return true

case (.isIsolated, _),
(.customBuilder, _),
(.scope, _),
(.doesSupportObjc, _),
(.setter, _),
(.escaping, _):
(.escaping, _),
(.platforms, _):
return false
}
}
Expand All @@ -131,7 +139,8 @@ extension ConfigurationAnnotation {
(.customBuilder, .registration),
(.setter, .registration),
(.doesSupportObjc, .registration),
(.escaping, .parameter):
(.escaping, .parameter),
(.platforms, _):
return true
case (.isIsolated, _),
(.scope, _),
Expand All @@ -150,18 +159,20 @@ extension ConfigurationAttribute {

init(name: String, valueString: String) throws {
switch ConfigurationAttributeName(rawValue: name) {
case .isIsolated?:
case .isIsolated:
self = .isIsolated(value: try ConfigurationAttribute.boolValue(from: valueString))
case .customBuilder?:
case .customBuilder:
self = .customBuilder(value: valueString)
case .scope?:
case .scope:
self = .scope(value: try ConfigurationAttribute.scopeValue(from: valueString))
case .doesSupportObjc?:
case .doesSupportObjc:
self = .doesSupportObjc(value: try ConfigurationAttribute.boolValue(from: valueString))
case .setter?:
case .setter:
self = .setter(value: try ConfigurationAttribute.boolValue(from: valueString))
case .escaping?:
case .escaping:
self = .escaping(value: try ConfigurationAttribute.boolValue(from: valueString))
case .platforms:
self = .platforms(values: try ConfigurationAttribute.platformValues(from: valueString))
case .none:
throw TokenError.unknownConfigurationAttribute(name: name)
}
Expand All @@ -181,6 +192,27 @@ extension ConfigurationAttribute {
}
return value
}

private static func platformValues(from string: String) throws -> [Platform] {

var string = string.trimmingTrailingCharacters(in: .whitespaces)
guard string.first == "[" && string.last == "]" else {
throw TokenError.invalidConfigurationAttributeValue(value: string, expected: "Array of platforms (eg: `[.iOS, .watchOS, ...]`)")
}
string.removeFirst()
string.removeLast()

return try string
.split(separator: ",")
.map { $0.trimmingCharacters(in: .whitespaces) }
.map {
guard $0.first == ".", let platform = Platform(rawValue: $0.replacingOccurrences(of: ".", with: "")) else {
let expected = Platform.allCases.map { $0.rawValue }.joined(separator: "|")
throw TokenError.invalidConfigurationAttributeValue(value: $0, expected: expected)
}
return platform
}
}
}

extension ConfigurationAttributeTarget {
Expand Down Expand Up @@ -208,7 +240,8 @@ extension ConfigurationAttribute {
return value

case .scope,
.customBuilder:
.customBuilder,
.platforms:
return nil
}
}
Expand All @@ -222,7 +255,8 @@ extension ConfigurationAttribute {
.isIsolated,
.doesSupportObjc,
.setter,
.escaping:
.escaping,
.platforms:
return nil
}
}
Expand All @@ -236,7 +270,23 @@ extension ConfigurationAttribute {
.isIsolated,
.doesSupportObjc,
.setter,
.escaping:
.escaping,
.platforms:
return nil
}
}

var platformValues: [Platform]? {
switch self {
case .platforms(let values):
return values

case .scope,
.customBuilder,
.isIsolated,
.setter,
.escaping,
.doesSupportObjc:
return nil
}
}
Expand Down
30 changes: 30 additions & 0 deletions Sources/WeaverCodeGen/Error.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ enum LinkerError: Error {
case foundAnnotationOutsideOfType(FileLocation)
case unknownType(FileLocation?, type: CompositeType)
case dependencyNotFound(FileLocation?, dependencyName: String)
case missingTargetedPlatform
}

enum DependencyGraphError: Error {
Expand Down Expand Up @@ -161,6 +162,35 @@ extension ParserError: CustomStringConvertible {
}
}

extension LinkerError: CustomStringConvertible {

var description: String {
let location: FileLocation?
let message: String

switch self {
case .dependencyNotFound(let _location, let dependencyName):
location = _location
message = "Could not find dependency in graph: '\(dependencyName)'"
case .foundAnnotationOutsideOfType(let _location):
location = _location
message = "Found annotation outside of type"
case .missingTargetedPlatform:
location = nil
message = "Platform parameter is needed in order to process the dependency graph"
case .unknownType(let _location, let type):
location = _location
message = "Unknown type: '\(type.description)'"
}

if let location = location {
return location.xcodeLogString(.error, message)
} else {
return message
}
}
}

extension DependencyGraphError: CustomStringConvertible {

var description: String {
Expand Down
Loading

0 comments on commit cd549d6

Please sign in to comment.