Skip to content

Commit 2f0141e

Browse files
committed
WIP
1 parent b387aa8 commit 2f0141e

File tree

4 files changed

+152
-39
lines changed

4 files changed

+152
-39
lines changed

codegen/lib/graphql_swift_gen.rb

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,21 @@ def deserialize_value_code(field_name, expr, type, untyped: true)
218218
raise NotImplementedError, "Unexpected #{type.kind} argument type"
219219
end
220220
end
221-
221+
222+
def child_object_return_value(fieldType)
223+
if ["OBJECT", "INTERFACE"].include?(fieldType)
224+
"return .Object"
225+
elsif fieldType == "LIST" && ["OBJECT", "INTERFACE"].include?(fieldType)
226+
"return .ObjectList"
227+
elsif fieldType == "LIST" && fieldType != "OBJECT"
228+
"return .ScalarList"
229+
else
230+
"return .Scalar"
231+
end
232+
end
233+
222234
def swift_arg_defs(field)
223-
defs = ["aliasSuffix: String? = nil"]
235+
defs = ["alias: String? = nil"]
224236
field.args.each do |arg|
225237
arg_def = "#{escape_reserved_word(arg.name)}: #{swift_input_type(arg.type)}"
226238
arg_def << " = nil" unless arg.type.non_null?
@@ -252,6 +264,66 @@ def swift_attributes(deprecatable)
252264
if deprecatable.deprecation_reason
253265
message_argument = ", message:#{deprecatable.deprecation_reason.inspect}"
254266
end
255-
"@available(*, deprecated#{message_argument})"
267+
"@available(*, deprecated#{message_argument})\n"
268+
end
269+
270+
def swift_doc(element)
271+
doc = ''
272+
273+
unless element.description.nil?
274+
description = element.description
275+
description = wrap_text(description, '/// ')
276+
description = format_swift_doc_list(description)
277+
doc << "\n\n" + description
278+
end
279+
280+
if element.respond_to?(:args)
281+
if element.args.count > 0
282+
doc << "\n"
283+
doc << "/// - parameters:\n"
284+
element.args.each do |arg|
285+
doc << '/// - ' + arg.name + ': ' + "\n"
286+
end
287+
end
288+
end
289+
290+
doc
291+
end
292+
293+
def wrap_text(text, prefix, width=80)
294+
text.gsub!( /\n+/, ' ')
295+
296+
container = ''
297+
line = prefix
298+
299+
parts = text.split(' ')
300+
parts.each do |part|
301+
if line.length + part.length < width
302+
line << part
303+
else
304+
container << line
305+
container << "\n"
306+
line = prefix
307+
end
308+
end
309+
310+
if line.length > 0
311+
container << line
312+
container << "\n"
313+
end
314+
# text.gsub!( /\n/, ' ')
315+
# text.gsub!( /(\S{#{col_width}})(?=\S)/, '\1' )
316+
# text.gsub!( /(.{1,#{col_width}})(?:\s+|$)/, "\n/// \\1" )
317+
container
318+
end
319+
320+
def format_swift_doc_list(text)
321+
parts = text.split(':')
322+
list_pattern = /\s*?-\s*?`(.+?)`\s*?/
323+
if parts.count > 1 && list_pattern.match(parts.last)
324+
parts.first + ":" + parts.last.gsub(list_pattern, "\n" + ' - \1')
325+
else
326+
text
327+
end
256328
end
257329
end

codegen/lib/graphql_swift_gen/templates/ApiSchema.swift.erb

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
1-
// Generated from <%= script_name %>
1+
//
2+
// <%= schema_name %>.swift
3+
// Buy
4+
//
5+
// Created by Shopify.
6+
// Copyright (c) 2017 Shopify Inc. All rights reserved.
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
16+
// all 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
24+
// THE SOFTWARE.
25+
//
226

327
open class <%= schema_name %> {
428
<% [['Query', schema.query_root_name], ['Mutation', schema.mutation_root_name]].each do |operation_type, root_name| %>

codegen/lib/graphql_swift_gen/templates/type.swift.erb

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,51 @@
1-
// Generated from <%= script_name %>
1+
//
2+
// <%= type.name %>.swift
3+
// Buy
4+
//
5+
// Created by Shopify.
6+
// Copyright (c) 2017 Shopify Inc. All rights reserved.
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
16+
// all 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
24+
// THE SOFTWARE.
25+
//
26+
227
import Foundation
328
<% if import_graphql_support %>
429
import GraphQLSupport
530
<% end %>
631

732
<% if type.interface? || type.union? %>
33+
<%= %>
34+
<%= swift_doc(type) %>
835
public protocol <%= type.name %> {
936
var typeName: String { get }
1037
<% type.fields(include_deprecated: true).each do |field| %>
1138
<%= swift_attributes(field) %>
1239
var <%= escape_reserved_word(field.camelize_name) %>: <%= swift_output_type(field.type) %> { get }
1340
<% end %>
1441
func childResponseObjectMap() -> [GraphQL.AbstractResponse]
15-
1642
func responseObject() -> GraphQL.AbstractResponse
1743
}
1844
<% end %>
1945

2046
extension <%= schema_name %> {
2147
<% case type.kind; when 'OBJECT', 'INTERFACE', 'UNION' %>
48+
<%= swift_doc(type) %>
2249
open class <%= type.name %>Query: GraphQL.AbstractQuery, GraphQLQuery {
2350
public typealias Response = <%= type.name %>
2451

@@ -28,8 +55,8 @@ extension <%= schema_name %> {
2855
}
2956
<% end %>
3057
<% type.fields(include_deprecated: true).each do |field| %>
31-
<%= swift_attributes(field) %>
32-
@discardableResult
58+
<%= swift_doc(field) %>
59+
<%= swift_attributes(field) %>@discardableResult
3360
open func <%= escape_reserved_word(field.camelize_name) %>(<%= swift_arg_defs(field) %>) -> <%= type.name %>Query {
3461
<% unless field.args.empty? %>
3562
var args: [String] = []
@@ -53,7 +80,7 @@ extension <%= schema_name %> {
5380
subfields(subquery)
5481
<% end %>
5582

56-
addField(field: "<%= field.name %>", aliasSuffix: aliasSuffix<% unless field.args.empty? %>, args: argsString<% end %><% if field.subfields? %>, subfields: subquery<% end %>)
83+
addField(field: "<%= field.name %>", aliasSuffix: alias<% unless field.args.empty? %>, args: argsString<% end %><% if field.subfields? %>, subfields: subquery<% end %>)
5784
return self
5885
}
5986
<% end %>
@@ -76,10 +103,11 @@ extension <%= schema_name %> {
76103

77104
<% class_name = type.object? ? type.name : "Unknown#{type.name}" %>
78105
<% protocols = type.object? ? type.interfaces.map { |iface| ", #{iface.name}" }.join : ", #{type.name}" %>
106+
<%= swift_doc(type) %>
79107
open class <%= class_name %>: GraphQL.AbstractResponse, GraphQLObject<%= protocols %> {
80108
public typealias Query = <%= type.name %>Query
81109

82-
open override func deserializeValue(fieldName: String, value: Any) throws -> Any? {
110+
internal override func deserializeValue(fieldName: String, value: Any) throws -> Any? {
83111
let fieldValue = value
84112
switch fieldName {
85113
<% type.fields(include_deprecated: true).each do |field| %>
@@ -92,7 +120,7 @@ extension <%= schema_name %> {
92120
}
93121

94122
<% if type.object? %>
95-
open var typeName: String { return "<%= type.name %>" }
123+
open let typeName = "<%= type.name %>"
96124
<% else %>
97125
open var typeName: String { return field(field: "__typename") as! String }
98126

@@ -102,8 +130,7 @@ extension <%= schema_name %> {
102130
}
103131
switch typeName {
104132
<% type.possible_types.each do |possible_type| %>
105-
case "<%= possible_type.name %>":
106-
return try <%= possible_type.name %>.init(fields: fields)
133+
case "<%= possible_type.name %>": return try <%= possible_type.name %>.init(fields: fields)
107134
<% end %>
108135
default:
109136
return try <%= class_name %>.init(fields: fields)
@@ -119,44 +146,32 @@ extension <%= schema_name %> {
119146

120147
<% unless field.args.empty? %>
121148
<%= swift_attributes(field) %>
122-
open func aliased<%= field.classify_name %>(aliasSuffix: String) -> <%= swift_output_type(field.type) %> {
123-
return internalGet<%= field.classify_name %>(aliasSuffix: aliasSuffix)
149+
open func aliased<%= field.classify_name %>(alias: String) -> <%= swift_output_type(field.type) %> {
150+
return internalGet<%= field.classify_name %>(alias: alias)
124151
}
125152
<% end %>
126153

127-
func internalGet<%= field.classify_name %>(aliasSuffix: String? = nil) -> <%= swift_output_type(field.type) %> {
128-
return field(field: "<%= field.name %>", aliasSuffix: aliasSuffix) as! <%= swift_output_type(field.type) %>
154+
func internalGet<%= field.classify_name %>(alias: String? = nil) -> <%= swift_output_type(field.type) %> {
155+
return field(field: "<%= field.name %>", aliasSuffix: alias) as! <%= swift_output_type(field.type) %>
129156
}
130157
<% end %>
131158

132-
override open func childObjectType(key: String) -> GraphQL.ChildObjectType {
159+
override internal func childObjectType(key: String) -> GraphQL.ChildObjectType {
133160
switch(key) {
134161
<% type.fields(include_deprecated: true).each do |field| %>
135-
case "<%= field.name %>":
136-
<% if ['OBJECT', 'INTERFACE'].include?(field.type.unwrap_non_null.kind) %>
137-
return .Object
138-
<% elsif field.type.unwrap_non_null.kind == 'LIST' && ['OBJECT', 'INTERFACE'].include?(field.type.unwrap.kind) %>
139-
return .ObjectList
140-
<% elsif field.type.unwrap_non_null.kind == 'LIST' && field.type.unwrap.kind != 'OBJECT' %>
141-
return .ScalarList
142-
<% else %>
143-
return .Scalar
144-
<% end %>
162+
case "<%= field.name %>": <%= child_object_return_value(field.type.unwrap_non_null.kind) %>
145163
<% end %>
146-
default:
147-
return .Scalar
164+
default: return .Scalar
148165
}
149166
}
150167

151-
override open func fetchChildObject(key: String) -> GraphQL.AbstractResponse? {
168+
override internal func fetchChildObject(key: String) -> GraphQL.AbstractResponse? {
152169
switch(key) {
153170
<% type.fields(include_deprecated: true).each do |field| %>
154171
<% if field.type.unwrap_non_null.kind == 'OBJECT' %>
155-
case "<%= field.name %>":
156-
return internalGet<%= field.classify_name %>()
172+
case "<%= field.name %>": return internalGet<%= field.classify_name %>()
157173
<% elsif field.type.unwrap_non_null.kind == 'INTERFACE' %>
158-
case "<%= field.name %>":
159-
return internalGet<%= field.classify_name %>()<%= field.type.non_null? ? '' : '?' %>.responseObject()
174+
case "<%= field.name %>": return internalGet<%= field.classify_name %>()<%= field.type.non_null? ? '' : '?' %>.responseObject()
160175
<% end %>
161176
<% end %>
162177
default:
@@ -165,7 +180,7 @@ extension <%= schema_name %> {
165180
return nil
166181
}
167182

168-
override open func fetchChildObjectList(key: String) -> [GraphQL.AbstractResponse] {
183+
override internal func fetchChildObjectList(key: String) -> [GraphQL.AbstractResponse] {
169184
switch(key) {
170185
<% type.fields(include_deprecated: true).each do |field| %>
171186
<% if field.type.unwrap_non_null.kind == 'LIST' && field.type.unwrap.kind == 'OBJECT' %>
@@ -205,6 +220,7 @@ extension <%= schema_name %> {
205220
}
206221
}
207222
<% when 'INPUT_OBJECT' %>
223+
<%= swift_doc(type) %>
208224
open class <%= type.name %> {
209225
<% type.input_fields.each do |field| %>
210226
open var <%= escape_reserved_word(field.camelize_name) %>: <%= swift_input_type(field.type) %>
@@ -238,10 +254,11 @@ extension <%= schema_name %> {
238254
}
239255
}
240256
<% when 'ENUM' %>
257+
<%= swift_doc(type) %>
241258
public enum <%= type.name %>: String {
242259
<% type.enum_values.each do |value| %>
243-
<%= swift_attributes(value) %>
244-
case <%= escape_reserved_word(value.camelize_name) %> = "<%= value.name %>"
260+
<%= swift_doc(value) %>
261+
<%= swift_attributes(value) %>case <%= escape_reserved_word(value.camelize_name) %> = "<%= value.name %>"
245262
<% end %>
246263
case unknownValue = ""
247264
}

graphql_swift_gen.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
1919

2020
spec.required_ruby_version = ">= 2.1.0"
2121

22-
spec.add_dependency "graphql_schema", "~> 0.1.1"
22+
spec.add_dependency "graphql_schema", "~> 0.1.5"
2323

2424
spec.add_development_dependency "bundler", "~> 1.13"
2525
spec.add_development_dependency "rake", "~> 12.0"

0 commit comments

Comments
 (0)