Skip to content

Commit

Permalink
Fixing usage of additional APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
nerdsupremacist committed Jan 12, 2020
1 parent 7cfca8f commit 235370c
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ extension Struct where CurrentStage == Stage.Prepared {
.filter { $0.graphqlPath?.resolved.isConnection ?? true }
.map { InitializerArgument(name: $0.name, type: $0.type) }

let extraAPIArguments = additionalReferencedAPIs.filter { $0.property == nil }.map { InitializerArgument(name: $0.api.name.camelized, type: $0.api.name) }

let queryArgument = query != nil ? [InitializerArgument(name: "data", type: "Data")] : []
let fragmentArguments = fragments.map { InitializerArgument(name: $0.target.name.camelized, type: $0.target.name.upperCamelized) }

return stockArguments + queryArgument + fragmentArguments
return stockArguments + extraAPIArguments + queryArgument + fragmentArguments
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,15 @@ extension Struct where CurrentStage == Stage.Prepared {
.map { InitializerArgumentAssignmentFromQueryData(name: $0.name,
expression: $0.expression(in: self)) }

let extraAPIArguments = additionalReferencedAPIs
.filter { $0.property == nil }
.map { InitializerArgumentAssignmentFromQueryData(name: $0.api.name.camelized,
expression: $0.expression(in: self)) }

let queryArgument = query != nil ? [InitializerArgumentAssignmentFromQueryData(name: "data", expression: "data")] : []
let fragmentArguments = fragments.map { InitializerArgumentAssignmentFromQueryData(name: $0.target.name.camelized, expression: $0.target.name.camelized) }

return stockArguments + queryArgument + fragmentArguments
return stockArguments + extraAPIArguments + queryArgument + fragmentArguments
}

}
Expand All @@ -46,3 +51,12 @@ extension Property where CurrentStage == Stage.Prepared {
}

}

extension AdditionalReferencedAPI {

fileprivate func expression(in graphQlStruct: Struct<Stage.Prepared>) -> CodeTransformable {
guard api != graphQlStruct.query?.api else { return "self" }
return api.name.camelized
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extension Struct where CurrentStage == Stage.Prepared {
return properties.map { property in
switch property.graphqlPath {
case .some(let path):
let expression = path.initializerExpression() ?? property.name
let expression = path.initializerExpression(in: self) ?? property.name
return InitializerValueAssignment(name: property.name,
expression: "GraphQL(\(expression))")
case .none:
Expand All @@ -33,10 +33,11 @@ extension Struct where CurrentStage == Stage.Prepared {

extension Stage.Cleaned.Path {

func initializerExpression() -> String? {
func initializerExpression<Stage: ResolvedStage>(in parent: Struct<Stage>) -> String? {
if resolved.isMutation {
// TODO: fix naming
return ".init(api: \(resolved.validated.api.name.camelized))"
let referencedAPI = parent.additionalReferencedAPIs.first { $0.api == resolved.validated.api } ?! fatalError()
let name = referencedAPI.property?.name ?? referencedAPI.api.name.camelized
return ".init(api: \(name))"
}

if resolved.isConnection {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ struct MutationStruct: ExtraValuesSwiftCodeTransformable {

func arguments(from context: Stencil.Context, arguments: [Any?]) throws -> [String : Any] {
return [
"swiftType": mutation.returnType.swiftType(api: mutation.api.name),
"swiftUnderlyingType": mutation.returnType.swiftType(api: mutation.api.name),
"swiftType": mutation.returnType.swiftType(api: mutation.api.name, for: mutation.referencedFragment),
"queryRendererArguments": mutation.queryRendererArguments,
"queryArgumentAssignments": mutation.queryArgumentAssignments,
"expression": Stage.Cleaned.Path(resolved: mutation.path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ extension Struct where CurrentStage: ResolvedStage {
let argumentsFromStruct = properties
.compactMap { $0.directArgument }
.filter { $0.type != api }

let extraAPIArguments = additionalReferencedAPIs
.filter { $0.property == nil }
.filter { $0.api.name != api }
.map { QueryRendererArgument(name: $0.api.name.camelized, type: $0.api.name, expression: nil) }

let argumentsFromQuery = query?
.arguments
Expand All @@ -32,7 +37,7 @@ extension Struct where CurrentStage: ResolvedStage {
expression: argument.defaultValue)
} ?? []

return argumentsFromQuery + argumentsFromStruct
return argumentsFromQuery + argumentsFromStruct + extraAPIArguments
}

}
Expand Down
13 changes: 9 additions & 4 deletions Sources/Graphaello/Processing/Model/Schema/TypeReference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ extension Schema.GraphQLType.Field.TypeReference {
}
}

func swiftType(api: String?) -> String {
func swiftType(api: String?, for fragment: GraphQLFragment? = nil) -> String {
switch self {

case .concrete(let definition):
Expand All @@ -72,17 +72,22 @@ extension Schema.GraphQLType.Field.TypeReference {
return "String?"
}
}

if let fragment = fragment {
assert(fragment.target.name == definition.name)
return "Apollo\(api.upperCamelized).\(fragment.name.upperCamelized)?"
}

return "\(api).\(name.upperCamelized)?"

case .complex(let definition, let ofType):
switch definition.kind {
case .list:
return "[\(ofType.swiftType(api: api))]?"
return "[\(ofType.swiftType(api: api, for: fragment))]?"
case .nonNull:
return String(ofType.swiftType(api: api).dropLast())
return String(ofType.swiftType(api: api, for: fragment).dropLast())
case .scalar, .object, .enum, .interface, .inputObject, .union:
return ofType.swiftType(api: api)
return ofType.swiftType(api: api, for: fragment)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ extension StructResolution.FragmentName {
case let expression as ArrayExprSyntax:
guard let syntax = Array(expression.elements).single()?.expression else { throw GraphQLFragmentResolverError.invalidTypeNameForFragment(expression.description) }
try self.init(syntax: syntax)
case let expression as ArrayTypeSyntax:
try self.init(syntax: expression.elementType)
case let expression as OptionalTypeSyntax:
try self.init(syntax: expression.wrappedType)
case let expression as MemberTypeIdentifierSyntax:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,30 @@ extension Stage.Validated.Path {
var returnType: Schema.GraphQLType.Field.TypeReference {
guard let last = components.last else { fatalError() }
return components
.dropFirst()
.dropLast()
.reversed()
.reduce(last.fieldType) { returnType, component in

switch (returnType, component.fieldType) {
case (.concrete, .concrete):
return returnType
case (.complex(let definition, let ofType), .concrete) where definition.kind == .nonNull:
return ofType
case (.complex, .concrete):
return returnType
case (.complex(let lhs, _), .complex(let rhs, _)) where lhs.kind == .nonNull && rhs.kind == .nonNull:
return returnType
case (_, .complex(let definition, _)):
return .complex(definition, ofType: returnType)
}
component.fieldType.embed(returnType: returnType)
}
}

}

extension Schema.GraphQLType.Field.TypeReference {

fileprivate func embed(returnType: Schema.GraphQLType.Field.TypeReference) -> Schema.GraphQLType.Field.TypeReference {
switch (returnType, self) {
case (.concrete, .concrete):
return returnType
case (.complex(let definition, let ofType), .concrete) where definition.kind == .nonNull:
return ofType
case (.complex, .concrete):
return returnType
case (.complex(let lhs, _), .complex(let rhs, _)) where lhs.kind == .nonNull && rhs.kind == .nonNull:
return returnType
case (_, .complex(let definition, let ofType)):
return .complex(definition, ofType: ofType.embed(returnType: returnType))
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// AdditionalReferencedAPI.swift
//
//
// Created by Mathias Quintero on 12.01.20.
//

import Foundation

struct AdditionalReferencedAPI<CurrentStage: ResolvedStage>: Hashable {
let api: API
let property: Property<CurrentStage>?

static func == (lhs: AdditionalReferencedAPI<CurrentStage>, rhs: AdditionalReferencedAPI<CurrentStage>) -> Bool {
return lhs.api == rhs.api
}

func hash(into hasher: inout Hasher) {
api.hash(into: &hasher)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ extension Struct where CurrentStage: ResolvedStage {
return context[.mutations]
}

var additionalReferencedAPIs: OrderedSet<AdditionalReferencedAPI<CurrentStage>> {
let types = Dictionary(properties.filter { $0.graphqlPath == nil }.map { ($0.type, $0) }) { $1 }
return OrderedSet(mutations.map { AdditionalReferencedAPI(api: $0.api, property: types[$0.api.name]) })
}

init(code: SourceCode,
name: String,
properties: [Property<CurrentStage>],
Expand Down
4 changes: 2 additions & 2 deletions templates/swift/MutationStruct.swift.stencil
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
extension {{ structPrepared.name }} {
class {{ mutationStruct.mutation.name }}{% if mutationStruct.mutation.referencedFragment %}<V: Fragment>{% endif %}: Mutation{% if mutationStruct.mutation.referencedFragment %} where V.UnderlyingType == {{ swiftType }}{% endif %} {
class {{ mutationStruct.mutation.name }}{% if mutationStruct.mutation.referencedFragment %}<V: Fragment>{% endif %}: Mutation{% if mutationStruct.mutation.referencedFragment %} where V.UnderlyingType == {{ swiftUnderlyingType }}{% endif %} {

{% if mutationStruct.mutation.referencedFragment %}
typealias Value = V
Expand Down Expand Up @@ -32,7 +32,7 @@ extension {{ structPrepared.name }} {
}

{% if mutationStruct.mutation.referencedFragment %}
extension {{ structPrepared.name }}.{{ mutationStruct.mutation.name }} where V == Apollo{{ mutationStruct.mutation.api.name }}. {
extension {{ structPrepared.name }}.{{ mutationStruct.mutation.name }} where V == {{ swiftType }} {
{% else %}
extension {{ structPrepared.name }}.{{ mutationStruct.mutation.name }} {
{% endif %}
Expand Down

0 comments on commit 235370c

Please sign in to comment.