objc2swift_assistant 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.idea/.name +1 -0
- data/.idea/.rakeTasks +7 -0
- data/.idea/compiler.xml +22 -0
- data/.idea/copyright/profiles_settings.xml +3 -0
- data/.idea/dictionaries/ckornher.xml +7 -0
- data/.idea/encodings.xml +4 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/objc2swift_assistant.iml +103 -0
- data/.idea/runConfigurations/Console.xml +26 -0
- data/.idea/runConfigurations/assistant.xml +28 -0
- data/.idea/runConfigurations/help_text.xml +28 -0
- data/.idea/scopes/scope_settings.xml +5 -0
- data/.idea/uiDesigner.xml +124 -0
- data/.idea/vcs.xml +6 -0
- data/.idea/workspace.xml +1484 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +83 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/objc2swift_assistant +50 -0
- data/bin/setup +7 -0
- data/lib/assistant.rb +110 -0
- data/lib/objc2swift_assistant/code_recognizer.rb +220 -0
- data/lib/objc2swift_assistant/file_hierarchical_config.rb +168 -0
- data/lib/objc2swift_assistant/file_sets.rb +577 -0
- data/lib/objc2swift_assistant/logging.rb +19 -0
- data/lib/objc2swift_assistant/objc_2_swift.rb +734 -0
- data/lib/objc2swift_assistant/objc_2_swift_block_conversion.rb +106 -0
- data/lib/objc2swift_assistant/objc_2_swift_configuration.rb +108 -0
- data/lib/objc2swift_assistant/objc_2_swift_type_mapping.rb +64 -0
- data/lib/objc2swift_assistant/objc_variable_types.rb +76 -0
- data/lib/objc2swift_assistant/processing_element.rb +32 -0
- data/lib/objc2swift_assistant/recognizers/at_sign_directives_recognizer.rb +41 -0
- data/lib/objc2swift_assistant/recognizers/category_recognizer.rb +72 -0
- data/lib/objc2swift_assistant/recognizers/enum_recognizer.rb +0 -0
- data/lib/objc2swift_assistant/recognizers/implementation_recognizer.rb +31 -0
- data/lib/objc2swift_assistant/recognizers/interface_recognizer.rb +37 -0
- data/lib/objc2swift_assistant/recognizers/method_recognizer.rb +190 -0
- data/lib/objc2swift_assistant/recognizers/pragma_mark_recognizer.rb +41 -0
- data/lib/objc2swift_assistant/recognizers/property_declaration_recognizer.rb +78 -0
- data/lib/objc2swift_assistant/recognizers/protocol_recognizer.rb +40 -0
- data/lib/objc2swift_assistant/recognizers/recognizer_keys.rb +26 -0
- data/lib/objc2swift_assistant/settings_file.rb +23 -0
- data/lib/objc2swift_assistant/swift_file_generator.rb +27 -0
- data/lib/objc2swift_assistant/version.rb +3 -0
- data/objc2swift_assistant.gemspec +31 -0
- metadata +128 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "version"
|
2
|
+
|
3
|
+
module Objc2swiftAssistantLogging
|
4
|
+
|
5
|
+
LOG_LEVEL_ERRORS = 4
|
6
|
+
LOG_LEVEL_WARNINGS = 3
|
7
|
+
LOG_LEVEL_VERBOSE = 2
|
8
|
+
LOG_LEVEL_DEBUG = 1
|
9
|
+
LOG_LEVEL_NONE = 0
|
10
|
+
|
11
|
+
LOG_LEVELS_BY_NAME = [
|
12
|
+
"error" => LOG_LEVEL_ERRORS,
|
13
|
+
"warning" => LOG_LEVEL_WARNINGS ,
|
14
|
+
"verbose" => LOG_LEVEL_VERBOSE ,
|
15
|
+
"debug" => LOG_LEVEL_DEBUG,
|
16
|
+
"none" => LOG_LEVEL_NONE
|
17
|
+
]
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,734 @@
|
|
1
|
+
require_relative 'version'
|
2
|
+
|
3
|
+
require_relative 'file_sets'
|
4
|
+
require_relative 'recognizers/recognizer_keys'
|
5
|
+
require_relative 'objc_2_swift_type_mapping'
|
6
|
+
require_relative 'objc_2_swift_block_conversion'
|
7
|
+
require_relative 'processing_element'
|
8
|
+
|
9
|
+
module Objc2swiftAssistant
|
10
|
+
|
11
|
+
def cleanup_method_body_lines( file_lines )
|
12
|
+
cleaned_up = []
|
13
|
+
file_lines.each do |line|
|
14
|
+
no_trailing = line.rstrip
|
15
|
+
next if no_trailing.strip == '@end'
|
16
|
+
cleaned_up << no_trailing if no_trailing.length > 0
|
17
|
+
end
|
18
|
+
|
19
|
+
cleaned_up
|
20
|
+
end
|
21
|
+
module_function :cleanup_method_body_lines
|
22
|
+
|
23
|
+
def prepare_class_header_lines( file_lines )
|
24
|
+
cleaned_up = []
|
25
|
+
file_lines.each do |line|
|
26
|
+
no_trailing = line.rstrip
|
27
|
+
cleaned_up << '// ' + no_trailing if no_trailing.length > 0
|
28
|
+
end
|
29
|
+
|
30
|
+
cleaned_up
|
31
|
+
end
|
32
|
+
module_function :prepare_class_header_lines
|
33
|
+
|
34
|
+
def prepare_method_body_lines( lines )
|
35
|
+
raw_body_lines = cleanup_method_body_lines( lines )
|
36
|
+
body_lines = raw_body_lines.map do |line|
|
37
|
+
'// ' + line
|
38
|
+
end
|
39
|
+
|
40
|
+
body_lines
|
41
|
+
end
|
42
|
+
module_function :prepare_method_body_lines
|
43
|
+
|
44
|
+
|
45
|
+
class ObjC2SwiftFileConverter < FailableProcessingElement
|
46
|
+
attr_accessor :objc_file_node
|
47
|
+
attr_accessor :enums
|
48
|
+
attr_accessor :classes_by_name
|
49
|
+
attr_accessor :categories_by_class_and_name
|
50
|
+
attr_accessor :protocols
|
51
|
+
attr_accessor :swift_file_node
|
52
|
+
attr_accessor :configuration
|
53
|
+
|
54
|
+
attr_accessor :access_control_state
|
55
|
+
attr_accessor :protocol_optional_state
|
56
|
+
|
57
|
+
def initialize( objc_file_node, configuration )
|
58
|
+
@objc_file_node = objc_file_node
|
59
|
+
@configuration = configuration
|
60
|
+
@enums = {}
|
61
|
+
@classes_by_name = {}
|
62
|
+
@categories_by_class_and_name = {}
|
63
|
+
@protocols = []
|
64
|
+
|
65
|
+
@access_control_state = nil
|
66
|
+
@protocol_optional_state = false
|
67
|
+
end
|
68
|
+
|
69
|
+
def prepare( )
|
70
|
+
@objc_file_node.root_matches.each do |region|
|
71
|
+
|
72
|
+
if region.region_type == CLASS_INTERFACE_KEY
|
73
|
+
class_converter = class_for_name( region.class_name )
|
74
|
+
class_converter.interface_region = region
|
75
|
+
process_interface_sub_regions( region, class_converter )
|
76
|
+
elsif region.region_type == CLASS_IMPLEMENTATION_KEY
|
77
|
+
class_converter = class_for_name( region.class_name )
|
78
|
+
class_converter.implementation_region = region
|
79
|
+
process_impl_sub_regions( region, class_converter )
|
80
|
+
elsif region.region_type == EXTENSION_DECLARARATION_KEY
|
81
|
+
class_converter = class_for_name( region.class_name )
|
82
|
+
extension_converter = ObjC2SwiftCategoryConverter.new( self, region.class_name, nil, @configuration )
|
83
|
+
extension_converter.interface_region = region
|
84
|
+
class_converter.extension_converter = extension_converter
|
85
|
+
elsif region.region_type == CATEGORY_DECLARARATION_KEY
|
86
|
+
category_converter = category_for_class_and_name( region.class_name, region.category_name )
|
87
|
+
category_converter.interface_region = region
|
88
|
+
process_interface_sub_regions( region, category_converter )
|
89
|
+
elsif region.region_type == CATEGORY_IMPLEMENTATION_KEY
|
90
|
+
category_converter = category_for_class_and_name( region.class_name, region.category_name )
|
91
|
+
category_converter.implementation_region = region
|
92
|
+
process_impl_sub_regions( region, category_converter )
|
93
|
+
elsif region.region_type == PROTOCOL_DECLARATION_KEY
|
94
|
+
protocol_converter = ObjC2SwiftProtocolConverter.new( self, region.protocol_name, @configuration )
|
95
|
+
protocol_converter.interface_region = region
|
96
|
+
@protocols << protocol_converter
|
97
|
+
process_interface_sub_regions( region, protocol_converter )
|
98
|
+
|
99
|
+
# category_converter.implementation_region = region
|
100
|
+
# process_impl_sub_regions( region, category_converter )
|
101
|
+
@configuration.log_warning( "protocols NYI")
|
102
|
+
elsif region.region_type == ENUM_DECLARATION_KEY
|
103
|
+
@configuration.log_warning( "Not Yet Implemented Region Type: #{region.region_type.to_s}")
|
104
|
+
elsif region.region_type == PRAGMA_MARK_KEY
|
105
|
+
@configuration.log_warning( "Not Yet Implemented Region Type: #{region.region_type.to_s}")
|
106
|
+
else
|
107
|
+
@configuration.log_warning( "Unexpected Root Region Type: #{region.region_type.to_s}")
|
108
|
+
end
|
109
|
+
end # Iterating over root matches
|
110
|
+
|
111
|
+
@classes_by_name.each_value do |class_converter|
|
112
|
+
class_converter.prepare
|
113
|
+
end
|
114
|
+
|
115
|
+
@categories_by_class_and_name.each do |_, category_converter|
|
116
|
+
category_converter.prepare
|
117
|
+
end
|
118
|
+
|
119
|
+
@protocols.each do | protcol_converter|
|
120
|
+
protcol_converter.prepare
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# common logic for class-like entities (classes, categories, extensions)
|
125
|
+
def process_interface_sub_regions( interface_region, class_converter )
|
126
|
+
|
127
|
+
@configuration.log_verbose( "\nprocess_interface_sub_regions") unless interface_region.sub_regions.length == 0
|
128
|
+
|
129
|
+
interface_region.sub_regions.each do |sub_region|
|
130
|
+
@configuration.log_verbose( "#{sub_region.region_type} #{sub_region.starting_line_number} #{sub_region.detection_line}" )
|
131
|
+
|
132
|
+
if sub_region.region_type == PROPERTY_DECLARATION_KEY
|
133
|
+
property = class_converter.property_for_name( sub_region.name )
|
134
|
+
property.declaration_region = sub_region
|
135
|
+
property.access_control_state = @access_control_state
|
136
|
+
property.protocol_optional_state = @protocol_optional_state
|
137
|
+
elsif sub_region.region_type == METHOD_DECLARATION_KEY
|
138
|
+
method = class_converter.method_for_signature( sub_region.objc_signature )
|
139
|
+
method.declaration_region = sub_region
|
140
|
+
method.access_control_state = @access_control_state
|
141
|
+
method.protocol_optional_state = @protocol_optional_state
|
142
|
+
elsif sub_region.region_type == AT_DIRECTIVE_KEY
|
143
|
+
process_at_directive_region( sub_region )
|
144
|
+
else
|
145
|
+
unexpected_sub_region( sub_region, interface_region )
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# common logic for class-like entities (classes, categories)
|
151
|
+
def process_impl_sub_regions( impl_region, class_converter )
|
152
|
+
impl_region.sub_regions.each do |sub_region|
|
153
|
+
if sub_region.region_type == METHOD_IMPLEMENTATION_KEY
|
154
|
+
method = class_converter.method_for_signature( sub_region.objc_signature )
|
155
|
+
method.implementation_region = sub_region
|
156
|
+
else
|
157
|
+
unexpected_sub_region( sub_region, impl_region )
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def process_at_directive_region( region )
|
163
|
+
directive = region.directive_symbol
|
164
|
+
|
165
|
+
if( directive == :required )
|
166
|
+
@protocol_optional_state = directive
|
167
|
+
elsif ( directive == :optional )
|
168
|
+
@protocol_optional_state = directive
|
169
|
+
elsif ( [:public, :private, :protected].include? directive )
|
170
|
+
@access_control_state = directive
|
171
|
+
else
|
172
|
+
add_error( "unknown '@' directive: #{directive}")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def generate( generator_defs, configuration, dry_run )
|
177
|
+
@configuration.log_verbose( "Generating #{@swift_file_node.relative_path} at #{@swift_file_node.full_path}" )
|
178
|
+
|
179
|
+
@enums.each do |enum_converter|
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
@classes_by_name.each do |key, class_converter|
|
184
|
+
class_converter.generate( generator_defs, @swift_file_node.relative_path, configuration, dry_run )
|
185
|
+
end
|
186
|
+
|
187
|
+
@categories_by_class_and_name.each do |_, category_converter|
|
188
|
+
category_converter.generate( generator_defs, @swift_file_node.relative_path, configuration, dry_run )
|
189
|
+
end
|
190
|
+
|
191
|
+
@protocols.each do | protcol_converter|
|
192
|
+
protcol_converter.generate( generator_defs, @swift_file_node.relative_path, configuration, dry_run )
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# Utility
|
197
|
+
|
198
|
+
def class_for_name( class_name )
|
199
|
+
class_converter = @classes_by_name[ class_name ]
|
200
|
+
if class_converter.nil?
|
201
|
+
class_converter = ObjC2SwiftClassConverter.new( self, class_name, @configuration )
|
202
|
+
@classes_by_name[ class_name ] = class_converter
|
203
|
+
end
|
204
|
+
|
205
|
+
class_converter
|
206
|
+
end
|
207
|
+
|
208
|
+
def category_for_class_and_name( class_name, category_name )
|
209
|
+
the_key = [class_name, category_name]
|
210
|
+
category_converter = @categories_by_class_and_name[ the_key ]
|
211
|
+
if category_converter.nil?
|
212
|
+
category_converter = ObjC2SwiftCategoryConverter.new( self, class_name, category_name, @configuration )
|
213
|
+
@categories_by_class_and_name[ [class_name, category_name] ] = category_converter
|
214
|
+
end
|
215
|
+
|
216
|
+
category_converter
|
217
|
+
end
|
218
|
+
|
219
|
+
def unexpected_sub_region( sub_region, region )
|
220
|
+
@configuration.log_warning( "Unexpected Sub Region Type: #{sub_region.region_type.to_s} of #{region.region_type.to_s}")
|
221
|
+
end
|
222
|
+
|
223
|
+
def cannonical_source_file_path
|
224
|
+
objc_file_node.cannonical_source_file_path
|
225
|
+
end
|
226
|
+
|
227
|
+
def dump( indent, tab, errors_only )
|
228
|
+
puts( "#{indent}Generating Swift file #{@swift_file_node.relative_path} at #{@swift_file_node.full_path}" )
|
229
|
+
|
230
|
+
#objc_file_node
|
231
|
+
#enums
|
232
|
+
puts( "\n#{indent}Generated Classes:" ) unless @classes_by_name.length == 0
|
233
|
+
@classes_by_name.each do | _, class_converter |
|
234
|
+
puts( "#{indent+tab}#{class_converter.class_name}" )
|
235
|
+
end
|
236
|
+
|
237
|
+
puts( "\n#{indent}Generated Categories:" ) unless @categories_by_class_and_name.length == 0
|
238
|
+
@categories_by_class_and_name.each do | _, category_converter |
|
239
|
+
category_str = category_converter.category_name.nil? ? "" : " /*#{category_converter.category_name}*/"
|
240
|
+
puts( "#{indent+tab}#{category_converter.class_name}#{category_str}" )
|
241
|
+
end
|
242
|
+
|
243
|
+
puts( "\n#{indent}Generated Prototcols:" ) unless @protocols.length == 0
|
244
|
+
@protocols.each do | protocol |
|
245
|
+
puts( "#{indent+tab}#{protocol.class_name}" )
|
246
|
+
end
|
247
|
+
|
248
|
+
#protocols
|
249
|
+
#configuration
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
class ObjC2SwiftCodeConverter < FailableProcessingElement
|
256
|
+
attr_accessor :file_converter
|
257
|
+
attr_accessor :marks
|
258
|
+
attr_accessor :configuration
|
259
|
+
|
260
|
+
def initialize( file_converter, configuration )
|
261
|
+
super()
|
262
|
+
@file_converter = file_converter
|
263
|
+
@configuration = configuration
|
264
|
+
@marks = []
|
265
|
+
end
|
266
|
+
|
267
|
+
def add_mark_region( mark_region )
|
268
|
+
@marks << mark_region
|
269
|
+
end
|
270
|
+
# Utility
|
271
|
+
|
272
|
+
def cannonical_source_file_path
|
273
|
+
file_converter.cannonical_source_file_path
|
274
|
+
end
|
275
|
+
|
276
|
+
def configuration
|
277
|
+
@file_converter.configuration
|
278
|
+
end
|
279
|
+
|
280
|
+
# Configuration
|
281
|
+
def omit_file()
|
282
|
+
configuration.omit_file( cannonical_source_file_path )
|
283
|
+
end
|
284
|
+
|
285
|
+
def company_name()
|
286
|
+
configuration.company_name( cannonical_source_file_path )
|
287
|
+
end
|
288
|
+
|
289
|
+
def emit_original_signatures()
|
290
|
+
configuration.emit_original_signatures( cannonical_source_file_path )
|
291
|
+
end
|
292
|
+
|
293
|
+
def emit_original_bodies()
|
294
|
+
configuration.emit_original_bodies( cannonical_source_file_path )
|
295
|
+
end
|
296
|
+
|
297
|
+
def emit_unconverted_content()
|
298
|
+
configuration.emit_unconverted_content( cannonical_source_file_path )
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
class ObjC2SwiftClassLikeConverter < ObjC2SwiftCodeConverter
|
303
|
+
attr_accessor :methods_by_signature
|
304
|
+
attr_accessor :properties_by_name
|
305
|
+
attr_accessor :interface_region
|
306
|
+
attr_accessor :implementation_region
|
307
|
+
|
308
|
+
def initialize( file_converter, class_name, configuration )
|
309
|
+
super( file_converter, configuration )
|
310
|
+
@class_name = class_name
|
311
|
+
@methods_by_signature = {}
|
312
|
+
@properties_by_name = {}
|
313
|
+
end
|
314
|
+
|
315
|
+
def method_for_signature( method_signature )
|
316
|
+
method_converter = @methods_by_signature[ method_signature]
|
317
|
+
if method_converter.nil?
|
318
|
+
method_converter = ObjC2SwiftMethodConverter.new( self, method_signature, @configuration )
|
319
|
+
@methods_by_signature[ method_signature ] = method_converter
|
320
|
+
end
|
321
|
+
method_converter
|
322
|
+
end
|
323
|
+
|
324
|
+
def property_for_name( property_name )
|
325
|
+
property_converter = @properties_by_name[ property_name]
|
326
|
+
if property_converter.nil?
|
327
|
+
property_converter = ObjC2SwiftPropertyConverter.new( self, property_name, @configuration )
|
328
|
+
@properties_by_name[ property_name ] = property_converter
|
329
|
+
end
|
330
|
+
property_converter
|
331
|
+
end
|
332
|
+
|
333
|
+
## Hook for subclasses
|
334
|
+
def process_new_property_converter( property_converter )
|
335
|
+
end
|
336
|
+
|
337
|
+
# Error Handling
|
338
|
+
|
339
|
+
def has_errors( or_warnings )
|
340
|
+
has_em = super.has_errors( or_warnings )
|
341
|
+
|
342
|
+
has_em |= @interface_region.has_errors( or_warnings ) unless @interface_region.nil?
|
343
|
+
has_em |= @implementation_region.has_errors( or_warnings ) unless @implementation_region.nil?
|
344
|
+
|
345
|
+
has_em |= dictionary_has_errors( @methods_by_signature, or_warnings )
|
346
|
+
has_em |= dictionary_has_errors( @properties_by_name, or_warnings )
|
347
|
+
|
348
|
+
has_em
|
349
|
+
end
|
350
|
+
|
351
|
+
end
|
352
|
+
|
353
|
+
|
354
|
+
class ObjC2SwiftClassConverter < ObjC2SwiftClassLikeConverter
|
355
|
+
attr_accessor :class_name
|
356
|
+
attr_accessor :super_class
|
357
|
+
attr_accessor :extension_converter
|
358
|
+
|
359
|
+
def initialize( file_converter, class_name, configuration )
|
360
|
+
super( file_converter, class_name, configuration )
|
361
|
+
@extension_region = nil
|
362
|
+
end
|
363
|
+
|
364
|
+
def prepare
|
365
|
+
methods = all_methods
|
366
|
+
properties = all_properties
|
367
|
+
|
368
|
+
methods.each do |method_converter|
|
369
|
+
method_converter.compute_swift_name
|
370
|
+
end
|
371
|
+
|
372
|
+
properties.each do |property_converter|
|
373
|
+
methods.each do |method_converter|
|
374
|
+
property_converter.check_method_for_association(method_converter)
|
375
|
+
end
|
376
|
+
property_converter.prepare
|
377
|
+
end
|
378
|
+
|
379
|
+
methods.each do |method_converter|
|
380
|
+
method_converter.prepare
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
def all_methods
|
385
|
+
methods = @methods_by_signature.values.clone
|
386
|
+
methods << @extension_region.methods_by_signature.all_values unless @extension_region.nil?
|
387
|
+
# Categories are handled as seperate entities
|
388
|
+
# @category_regions_by_name.inject( methods ) { |m, (k, v)| m << v.methods_by_signature; m }
|
389
|
+
methods
|
390
|
+
end
|
391
|
+
|
392
|
+
def all_properties
|
393
|
+
properties = @properties_by_name.values.clone
|
394
|
+
properties << @extension_region.properties_by_name.all_values unless @extension_region.nil?
|
395
|
+
# Categories are handled as seperate entities
|
396
|
+
# @category_regions_by_name.inject( properties ) { |p, (k, v)| p << v.properties_by_name; p }
|
397
|
+
properties
|
398
|
+
end
|
399
|
+
|
400
|
+
def generate( generator_defs, file_name, configuration, dry_run )
|
401
|
+
generated_class = make_generator_class_object( generator_defs, file_name )
|
402
|
+
generated_class.source_file.company_name = configuration.company_name( cannonical_source_file_path.to_s ) unless cannonical_source_file_path.nil?
|
403
|
+
|
404
|
+
if ! @interface_region.nil? && emit_unconverted_content()
|
405
|
+
generated_class.top_inner_comment_block = Objc2swiftAssistant::prepare_class_header_lines( @interface_region.root_header )
|
406
|
+
end
|
407
|
+
|
408
|
+
properties_by_name.each do | _, property |
|
409
|
+
property.generate( generated_class, configuration, dry_run )
|
410
|
+
end
|
411
|
+
|
412
|
+
methods_by_signature.each do | _, method |
|
413
|
+
method.generate( generated_class, configuration, dry_run )
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
def make_generator_class_object( generator_defs, file_name )
|
418
|
+
@configuration.log_verbose( "------- #{@interface_region.implements}" ) unless @interface_region.nil?
|
419
|
+
if @interface_region.nil?
|
420
|
+
implements_list =[]
|
421
|
+
else
|
422
|
+
implements_list = @interface_region.super_class.nil? ? [] : [@interface_region.super_class]
|
423
|
+
implements_list << @interface_region.implements unless @interface_region.implements.nil? || @interface_region.implements.length == 0
|
424
|
+
end
|
425
|
+
|
426
|
+
SwiftGenerator::SwiftClass.new( generator_defs, class_name, implements_list, file_name:file_name.to_s, characteristics:[] )
|
427
|
+
end
|
428
|
+
|
429
|
+
def make_modifiers( access_control:nil, optional:nil )
|
430
|
+
return [] if access_control.nil?
|
431
|
+
|
432
|
+
return [access_control.to_s]
|
433
|
+
end
|
434
|
+
|
435
|
+
end
|
436
|
+
|
437
|
+
|
438
|
+
class ObjC2SwiftCategoryConverter < ObjC2SwiftClassConverter
|
439
|
+
attr_accessor :category_name
|
440
|
+
|
441
|
+
def initialize( file_converter, class_name, category_name, configuration )
|
442
|
+
super( file_converter, class_name, configuration )
|
443
|
+
@category_name = category_name
|
444
|
+
end
|
445
|
+
|
446
|
+
def make_generator_class_object( generator_defs, file_name )
|
447
|
+
SwiftGenerator::SwiftCategory.new( generator_defs, category_name, class_name, file_name:file_name.to_s, characteristics:[] )
|
448
|
+
end
|
449
|
+
|
450
|
+
end
|
451
|
+
|
452
|
+
class ObjC2SwiftProtocolConverter < ObjC2SwiftClassConverter
|
453
|
+
|
454
|
+
def initialize( file_converter, protocol_name, configuration )
|
455
|
+
super( file_converter, protocol_name, configuration )
|
456
|
+
# super( file_converter, class_name )
|
457
|
+
# @extension_region = nil
|
458
|
+
end
|
459
|
+
|
460
|
+
def make_generator_class_object( generator_defs, file_name )
|
461
|
+
extends_list = @interface_region.extends || []
|
462
|
+
SwiftGenerator::SwiftProtocol.new( generator_defs, class_name, extends_list, file_name:file_name.to_s, characteristics:[] )
|
463
|
+
end
|
464
|
+
|
465
|
+
def prepare( )
|
466
|
+
super( )
|
467
|
+
all_properties.each do |property_converter|
|
468
|
+
|
469
|
+
if property_converter.declaration_region.modifiers.include?( 'readonly' ) #declaration_region must exist
|
470
|
+
property_converter.protocol_get_set_spec = "{ get }"
|
471
|
+
else
|
472
|
+
property_converter.protocol_get_set_spec = "{ get set }"
|
473
|
+
end
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
def make_modifiers( access_control:nil, optional:nil )
|
478
|
+
access_qualifiers = super( access_control:access_control, optional:optional )
|
479
|
+
|
480
|
+
return access_qualifiers if optional.nil?
|
481
|
+
|
482
|
+
if optional == :optional
|
483
|
+
access_qualifiers << 'optional'
|
484
|
+
end
|
485
|
+
|
486
|
+
access_qualifiers
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
class ObjC2SwiftMethodConverter < ObjC2SwiftCodeConverter
|
491
|
+
attr_accessor :class_converter
|
492
|
+
attr_accessor :objc_signature
|
493
|
+
attr_accessor :swift_name
|
494
|
+
attr_accessor :declaration_region
|
495
|
+
attr_accessor :implementation_region
|
496
|
+
attr_accessor :owning_property
|
497
|
+
attr_accessor :parameters
|
498
|
+
attr_accessor :is_initializer
|
499
|
+
|
500
|
+
attr_accessor :access_control_state
|
501
|
+
attr_accessor :protocol_optional_state
|
502
|
+
|
503
|
+
|
504
|
+
def initialize( class_converter, objc_signature, configuration )
|
505
|
+
super( class_converter.file_converter, configuration )
|
506
|
+
|
507
|
+
@class_converter = class_converter
|
508
|
+
@objc_signature = objc_signature
|
509
|
+
@is_initializer = false
|
510
|
+
@parameters = nil
|
511
|
+
@access_control_state = nil
|
512
|
+
@protocol_optional_state = nil
|
513
|
+
end
|
514
|
+
|
515
|
+
def compute_swift_name
|
516
|
+
#Copy the parameters from the method region
|
517
|
+
@parameters = Marshal.load(Marshal.dump(@declaration_region.parameters)) unless @declaration_region.nil?
|
518
|
+
@parameters= Marshal.load(Marshal.dump(@implementation_region.parameters)) if @parameters.nil? unless @implementation_region.nil?
|
519
|
+
split_first_param_name
|
520
|
+
end
|
521
|
+
|
522
|
+
def prepare
|
523
|
+
end
|
524
|
+
|
525
|
+
def split_first_param_name()
|
526
|
+
# Note parameters are instances of MethodParameter
|
527
|
+
# return if @parameters.length == 0
|
528
|
+
|
529
|
+
p1 = @parameters[ 0 ]
|
530
|
+
|
531
|
+
m = p1.param_label.match( /(initWith|init)(?<arg_name>\w*)/ )
|
532
|
+
unless m.nil?
|
533
|
+
arg_name = m[ 'arg_name' ]
|
534
|
+
if arg_name.nil?
|
535
|
+
p1.param_label = nil
|
536
|
+
elsif arg_name.length < 3
|
537
|
+
p1.param_label = arg_name.downcase
|
538
|
+
else
|
539
|
+
p1.param_label = arg_name[0, 1].downcase + arg_name[1..-1]
|
540
|
+
end
|
541
|
+
|
542
|
+
@swift_name = 'init'
|
543
|
+
@is_initializer = true
|
544
|
+
else
|
545
|
+
@swift_name = @parameters[ 0 ].param_label
|
546
|
+
# p1.param_label = nil
|
547
|
+
end
|
548
|
+
|
549
|
+
if @parameters.length == 1 && (p1.param_type.nil? || p1.param_type.length == 0)
|
550
|
+
@parameters = []
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
def generate( generated_class, configuration, dry_run )
|
555
|
+
return unless @owning_property.nil?
|
556
|
+
|
557
|
+
# type_symbol = @declaration_region.type_name.to_sym
|
558
|
+
# mutability = @declaration_region.is_pointer ? :var : :let
|
559
|
+
|
560
|
+
method_region = @declaration_region || @implementation_region
|
561
|
+
|
562
|
+
if @is_initializer
|
563
|
+
generated_method = SwiftGenerator::SwiftInitializer.new( generated_class, @swift_name, arg_list( configuration ), override: false, comment: nil )
|
564
|
+
else
|
565
|
+
returns_str = swift_type_string( configuration, method_region.return_type, method_region.return_pointer_level, method_region.return_nillable_qualifier )
|
566
|
+
# returns = configuration.type_mapper.swift_type_for_objc_type( returns_str )
|
567
|
+
# TODO: handle block returns
|
568
|
+
returns = nil if returns == 'void'
|
569
|
+
generated_method = SwiftGenerator::SwiftMethod.new( generated_class, @swift_name, arg_list( configuration ), @is_initializer ? nil : returns, override: false, comment: nil )
|
570
|
+
end
|
571
|
+
|
572
|
+
generated_method.access_control_modifiers = class_converter.make_modifiers( access_control:@access_control_state,
|
573
|
+
optional:@protocol_optional_state )
|
574
|
+
generated_method << body_lines_to_emit
|
575
|
+
|
576
|
+
unless method_region.return_type.nil?
|
577
|
+
|
578
|
+
# TODO: Dummy Return Statements
|
579
|
+
# @return_nillable_qualifier = '' # Not yet implemented
|
580
|
+
# @return_type = m[ 'return_type' ]
|
581
|
+
# @return_pointer_level = m[ 'return_pointer' ].nil? ? 0 : m[ 'return_pointer' ].length
|
582
|
+
|
583
|
+
end
|
584
|
+
end
|
585
|
+
|
586
|
+
def arg_list( configuration )
|
587
|
+
param_strings = @parameters.map do |parameter|
|
588
|
+
arg_string( parameter, configuration )
|
589
|
+
end
|
590
|
+
|
591
|
+
param_strings.join( ", " )
|
592
|
+
end
|
593
|
+
|
594
|
+
def arg_string( param, configuration )
|
595
|
+
if param.is_block_type
|
596
|
+
block_signature = configuration.block_converter.block_sig_for_method_arg( param.param_type )
|
597
|
+
type_string = block_signature.swift_declaration
|
598
|
+
else
|
599
|
+
type_string = swift_type_string( configuration, param.param_type, param.pointer_level, param.null_qualifier, param.is_weak )
|
600
|
+
end
|
601
|
+
|
602
|
+
if param.param_name.nil? || param.param_name == param.param_label
|
603
|
+
sig = param.param_label
|
604
|
+
else
|
605
|
+
sig = "#{param.param_label} #{param.param_name}"
|
606
|
+
end
|
607
|
+
|
608
|
+
sig ||= '/* Unknown */'
|
609
|
+
sig += ": #{type_string}"
|
610
|
+
sig
|
611
|
+
end
|
612
|
+
|
613
|
+
|
614
|
+
def swift_type_string( configuration, param_type, pointer_level, null_qualifier, is_weak=false )
|
615
|
+
mapped_param_type = configuration.type_mapper.swift_type_for_objc_type( param_type )
|
616
|
+
|
617
|
+
mapped_param_type = "/*__weak*/ #{mapped_param_type}" if is_weak
|
618
|
+
|
619
|
+
if( pointer_level == 2 )
|
620
|
+
if mapped_param_type == "NSError"
|
621
|
+
return 'NSErrorPointer'
|
622
|
+
else
|
623
|
+
return "AutoreleasingUnsafeMutablePointer<#{mapped_param_type}?>"
|
624
|
+
end
|
625
|
+
else
|
626
|
+
return "#{mapped_param_type}#{nullable_qualifier(null_qualifier, pointer_level)}" unless mapped_param_type.nil?
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
630
|
+
def nullable_qualifier( null_qualifier, pointer_level )
|
631
|
+
pointer_chars = ''
|
632
|
+
if( pointer_level > 1)
|
633
|
+
pointer_chars = '**********'[0..pointer_level] # Almost sure to be incorrect, but reflects original code
|
634
|
+
end
|
635
|
+
|
636
|
+
if null_qualifier == '__nonnull' && pointer_level > 0
|
637
|
+
return pointer_chars + '!'
|
638
|
+
elsif null_qualifier == '__nullable'
|
639
|
+
return pointer_chars + '?'
|
640
|
+
elsif null_qualifier == '__null_unspecified'
|
641
|
+
return pointer_chars + '!'
|
642
|
+
elsif pointer_level > 0
|
643
|
+
return pointer_chars + '!'
|
644
|
+
else
|
645
|
+
return pointer_chars
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
649
|
+
def body_lines_to_emit()
|
650
|
+
if @implementation_region.nil?
|
651
|
+
return []
|
652
|
+
end
|
653
|
+
|
654
|
+
lines = []
|
655
|
+
if emit_original_bodies
|
656
|
+
if emit_original_signatures
|
657
|
+
lines = implementation_region.all_lines
|
658
|
+
else
|
659
|
+
lines = implementation_region.unmatched_lines
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
return Objc2swiftAssistant::prepare_method_body_lines( lines )
|
664
|
+
end
|
665
|
+
|
666
|
+
end
|
667
|
+
|
668
|
+
class ObjC2SwiftPropertyConverter < ObjC2SwiftCodeConverter
|
669
|
+
attr_accessor :class_converter
|
670
|
+
attr_accessor :property_name
|
671
|
+
attr_accessor :declaration_region
|
672
|
+
attr_accessor :getter_method_converter
|
673
|
+
attr_accessor :setter_method_converter
|
674
|
+
attr_accessor :protocol_get_set_spec # Must be set if part of a protocol definition
|
675
|
+
|
676
|
+
attr_accessor :access_control_state
|
677
|
+
attr_accessor :protocol_optional_state
|
678
|
+
|
679
|
+
def initialize( class_converter, property_name, configuration )
|
680
|
+
super( class_converter.file_converter, configuration )
|
681
|
+
@class_converter = class_converter
|
682
|
+
@property_name = property_name
|
683
|
+
@protocol_get_set_spec = nil
|
684
|
+
|
685
|
+
@access_control_state = nil
|
686
|
+
@protocol_optional_state = nil
|
687
|
+
end
|
688
|
+
|
689
|
+
def prepare
|
690
|
+
end
|
691
|
+
|
692
|
+
def check_method_for_association( method_converter )
|
693
|
+
if Objc2swiftAssistant::is_getter_method_name( property_name, method_converter.swift_name )
|
694
|
+
@getter_method_converter = method_converter
|
695
|
+
method_converter.owning_property = self
|
696
|
+
elsif Objc2swiftAssistant::is_setter_method_name( property_name, method_converter.swift_name )
|
697
|
+
@setter_method_converter = method_converter
|
698
|
+
method_converter.owning_property = self
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
702
|
+
def generate( generated_class, configuration, dry_run )
|
703
|
+
if @declaration_region.is_block_property
|
704
|
+
block_signature = configuration.block_converter.block_sig_for_components( @declaration_region.block_return_type, @declaration_region.block_args )
|
705
|
+
declaration_string = block_signature.swift_declaration( true )
|
706
|
+
generated = SwiftGenerator::SwiftBlockProperty.new( generated_class, @property_name, declaration_string, :optional )
|
707
|
+
else
|
708
|
+
type_symbol = configuration.type_mapper.swift_type_for_objc_type( @declaration_region.type_name ).to_sym
|
709
|
+
mutability = @declaration_region.is_pointer ? :var : :let
|
710
|
+
# puts( "NYI: mutability" )
|
711
|
+
generated = SwiftGenerator::SwiftProperty.new( generated_class, @property_name, type_symbol, :optional )
|
712
|
+
end
|
713
|
+
|
714
|
+
generated.protocol_get_set_spec = @protocol_get_set_spec unless @protocol_get_set_spec.nil? # Used in protocol declarations
|
715
|
+
|
716
|
+
unless @getter_method_converter.nil?
|
717
|
+
generated.getter_body = Objc2swiftAssistant::prepare_method_body_lines( @getter_method_converter.implementation_region.unmatched_lines || [] )
|
718
|
+
end
|
719
|
+
|
720
|
+
unless @setter_method_converter.nil?
|
721
|
+
generated.setter_body = Objc2swiftAssistant::prepare_method_body_lines( @setter_method_converter.implementation_region.unmatched_lines || [] )
|
722
|
+
end
|
723
|
+
|
724
|
+
generated.access_control_modifiers = class_converter.make_modifiers( access_control:@access_control_state,
|
725
|
+
optional:@protocol_optional_state )
|
726
|
+
end
|
727
|
+
|
728
|
+
end
|
729
|
+
|
730
|
+
class ObjC2SwiftEnumConverter
|
731
|
+
|
732
|
+
end
|
733
|
+
|
734
|
+
end
|