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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.idea/.name +1 -0
  4. data/.idea/.rakeTasks +7 -0
  5. data/.idea/compiler.xml +22 -0
  6. data/.idea/copyright/profiles_settings.xml +3 -0
  7. data/.idea/dictionaries/ckornher.xml +7 -0
  8. data/.idea/encodings.xml +4 -0
  9. data/.idea/misc.xml +4 -0
  10. data/.idea/modules.xml +8 -0
  11. data/.idea/objc2swift_assistant.iml +103 -0
  12. data/.idea/runConfigurations/Console.xml +26 -0
  13. data/.idea/runConfigurations/assistant.xml +28 -0
  14. data/.idea/runConfigurations/help_text.xml +28 -0
  15. data/.idea/scopes/scope_settings.xml +5 -0
  16. data/.idea/uiDesigner.xml +124 -0
  17. data/.idea/vcs.xml +6 -0
  18. data/.idea/workspace.xml +1484 -0
  19. data/.rspec +2 -0
  20. data/.travis.yml +3 -0
  21. data/CODE_OF_CONDUCT.md +13 -0
  22. data/Gemfile +8 -0
  23. data/LICENSE.txt +21 -0
  24. data/README.md +83 -0
  25. data/Rakefile +1 -0
  26. data/bin/console +14 -0
  27. data/bin/objc2swift_assistant +50 -0
  28. data/bin/setup +7 -0
  29. data/lib/assistant.rb +110 -0
  30. data/lib/objc2swift_assistant/code_recognizer.rb +220 -0
  31. data/lib/objc2swift_assistant/file_hierarchical_config.rb +168 -0
  32. data/lib/objc2swift_assistant/file_sets.rb +577 -0
  33. data/lib/objc2swift_assistant/logging.rb +19 -0
  34. data/lib/objc2swift_assistant/objc_2_swift.rb +734 -0
  35. data/lib/objc2swift_assistant/objc_2_swift_block_conversion.rb +106 -0
  36. data/lib/objc2swift_assistant/objc_2_swift_configuration.rb +108 -0
  37. data/lib/objc2swift_assistant/objc_2_swift_type_mapping.rb +64 -0
  38. data/lib/objc2swift_assistant/objc_variable_types.rb +76 -0
  39. data/lib/objc2swift_assistant/processing_element.rb +32 -0
  40. data/lib/objc2swift_assistant/recognizers/at_sign_directives_recognizer.rb +41 -0
  41. data/lib/objc2swift_assistant/recognizers/category_recognizer.rb +72 -0
  42. data/lib/objc2swift_assistant/recognizers/enum_recognizer.rb +0 -0
  43. data/lib/objc2swift_assistant/recognizers/implementation_recognizer.rb +31 -0
  44. data/lib/objc2swift_assistant/recognizers/interface_recognizer.rb +37 -0
  45. data/lib/objc2swift_assistant/recognizers/method_recognizer.rb +190 -0
  46. data/lib/objc2swift_assistant/recognizers/pragma_mark_recognizer.rb +41 -0
  47. data/lib/objc2swift_assistant/recognizers/property_declaration_recognizer.rb +78 -0
  48. data/lib/objc2swift_assistant/recognizers/protocol_recognizer.rb +40 -0
  49. data/lib/objc2swift_assistant/recognizers/recognizer_keys.rb +26 -0
  50. data/lib/objc2swift_assistant/settings_file.rb +23 -0
  51. data/lib/objc2swift_assistant/swift_file_generator.rb +27 -0
  52. data/lib/objc2swift_assistant/version.rb +3 -0
  53. data/objc2swift_assistant.gemspec +31 -0
  54. 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