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,106 @@
1
+ require_relative 'version'
2
+ require_relative 'objc_2_swift_type_mapping'
3
+ require_relative 'objc_variable_types'
4
+
5
+ module Objc2swiftAssistant
6
+
7
+ class Objc2SwiftBlockConverter
8
+ attr_accessor :type_converter
9
+
10
+ def initialize( type_converter )
11
+ @type_converter = type_converter
12
+ end
13
+
14
+ def block_sig_for_method_arg( arg_type_str )
15
+ sig = Objc2SwiftBlockSignature.new( self )
16
+ sig.from_argument_type( arg_type_str)
17
+ sig
18
+ end
19
+
20
+ def block_sig_for_property( arg_type_str )
21
+ sig = Objc2SwiftBlockSignature.new( self )
22
+ sig.from_property_type( arg_type_str)
23
+ sig
24
+ end
25
+
26
+ def block_sig_for_components( return_type_str, *arg_strings )
27
+ sig = Objc2SwiftBlockSignature.new( self )
28
+ sig.from_components( return_type_str, arg_strings )
29
+ sig
30
+ end
31
+ end
32
+
33
+ class Objc2SwiftBlockSignature
34
+ attr_accessor :block_converter
35
+ attr_accessor :return_type
36
+ attr_accessor :arguments
37
+
38
+ def initialize( block_converter )
39
+ @block_converter = block_converter
40
+ end
41
+
42
+ def from_components( return_type_str, arg_strings )
43
+ @return_type = @block_converter.type_converter.swift_type_for_objc_type( return_type_str )
44
+
45
+ @arguments = arg_strings.map do |arg_str|
46
+ arg_for_objc_str( arg_str.strip )
47
+ end
48
+ end
49
+
50
+ def from_argument_type( arg_type )
51
+ if arg_type.count('^') > 1
52
+ failure = "Cannot convert nested Block: #{arg_type}"
53
+ return "String /*#{failure}*/", failure
54
+ else
55
+ m = arg_type.match( /(?<return_type>[^\(]*)\s*\(\s*\^\s*\)\s*\((?<arg_string>.*)\)/ )
56
+ if m.nil?
57
+ failure = "Cannot match block: #{arg_type}"
58
+ return "String /*#{failure}*/", failure
59
+ else
60
+ objc_return_type = m[ 'return_type' ].strip!
61
+ @return_type = @block_converter.type_converter.swift_type_for_objc_type( objc_return_type )
62
+
63
+ arg_string = m[ 'arg_string' ]
64
+ arg_strings = arg_string.nil? ? [] : arg_string.split( ',' )
65
+
66
+ @arguments = arg_strings.map do |arg_str|
67
+ arg_for_objc_str( arg_str.strip )
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def swift_declaration( full=true )
74
+ swift_args = @arguments.map do |arg|
75
+ if arg.param_name.nil?
76
+ str = "#{arg.param_type}"
77
+ else
78
+ str = "#{arg.param_name}: #{arg.param_type}"
79
+ end
80
+ str
81
+ end
82
+
83
+ sig = "(( #{swift_args.join( ', ' )} )"
84
+ if full || !return_type.nil?
85
+ if return_type.nil?
86
+ sig += " -> ())" if return_type.nil?
87
+ else
88
+ sig += " -> #{return_type})"
89
+ end
90
+ else
91
+ sig += " -> #{return_type})" unless return_type.nil?
92
+ end
93
+ sig
94
+ end
95
+
96
+ def from_property_type( prop_type )
97
+
98
+ end
99
+
100
+ def arg_for_objc_str( arg_str )
101
+ argument = ObjCBlockParameter.new()
102
+ argument.from_declaration( arg_str )
103
+ argument
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,108 @@
1
+ require_relative "version"
2
+ require_relative "file_hierarchical_config"
3
+ require_relative "objc_2_swift_type_mapping"
4
+ require_relative "objc_2_swift_block_conversion"
5
+
6
+ module Objc2swiftAssistant
7
+
8
+ LOG_LEVEL_NONE = 0
9
+ LOG_LEVEL_ERRORS = 1
10
+ LOG_LEVEL_WARNINGS = 2
11
+ LOG_LEVEL_VERBOSE = 3
12
+ LOG_LEVEL_DEBUG = 4
13
+
14
+ LOG_LEVELS_BY_NAME = {
15
+ "error" => LOG_LEVEL_ERRORS,
16
+ "warning" => LOG_LEVEL_WARNINGS ,
17
+ "verbose" => LOG_LEVEL_VERBOSE ,
18
+ "debug" => LOG_LEVEL_DEBUG,
19
+ "none" => LOG_LEVEL_NONE
20
+ }
21
+
22
+
23
+ COMPANY_NAME_KEY = 'company_name'
24
+ OMIT_FILE_KEY = 'omit_file'
25
+ EMIT_ORIGINAL_SIGNATURES_KEY = 'emit_original_signatures'
26
+ EMIT_ORIGINAL_BODIES_KEY = 'emit_original_bodies'
27
+ EMIT_UNCONVERTED_CONTENT_KEY = 'emit_unconverted_content'
28
+
29
+ ALL_CONFIG_KEYS = [
30
+ COMPANY_NAME_KEY,
31
+ OMIT_FILE_KEY,
32
+ EMIT_ORIGINAL_SIGNATURES_KEY,
33
+ EMIT_ORIGINAL_BODIES_KEY,
34
+ EMIT_UNCONVERTED_CONTENT_KEY
35
+ ]
36
+
37
+ class ObjC2SwiftConfiguration < FileHierarchicalConfig
38
+ attr_accessor :type_mapper
39
+ attr_accessor :block_converter
40
+ attr_accessor :structure_option
41
+
42
+ attr_accessor :log_level
43
+
44
+
45
+ def initialize( config_hash, log_level_name, structure_option )
46
+ super( config_hash, ALL_CONFIG_KEYS )
47
+ @node_class = ObjC2SwiftConfigNode
48
+ @type_mapper = Objc2SwiftTypeMapper.new()
49
+ @block_converter = Objc2SwiftBlockConverter.new( @type_mapper )
50
+ @log_level = LOG_LEVELS_BY_NAME[ log_level_name ]
51
+ @structure_option = structure_option
52
+ end
53
+
54
+ def omit_file( file_path )
55
+ # val = config_value(file_path, OMIT_FILE_KEY)
56
+ # puts( "Omit File: #{file_path} #{val ? 'true' : 'false' }" ) # nil will evaluate to false
57
+ config_value( file_path, OMIT_FILE_KEY )
58
+
59
+ end
60
+
61
+ def company_name( file_path )
62
+ config_value( file_path, COMPANY_NAME_KEY )
63
+ end
64
+
65
+ def emit_original_signatures( file_path )
66
+ config_value_defaulted( file_path, EMIT_ORIGINAL_SIGNATURES_KEY, true )
67
+ end
68
+
69
+ def emit_original_bodies( file_path )
70
+ config_value_defaulted( file_path, EMIT_ORIGINAL_BODIES_KEY, true )
71
+ end
72
+
73
+ def emit_unconverted_content( file_path )
74
+ config_value_defaulted( file_path, EMIT_UNCONVERTED_CONTENT_KEY, true )
75
+ end
76
+
77
+ # Logging
78
+ def log_verbose( str )
79
+ puts( str ) if @log_level >= LOG_LEVEL_VERBOSE
80
+ end
81
+
82
+ def log_warning( str )
83
+ puts( "WARNING: " + str ) if @log_level >= LOG_LEVEL_WARNINGS
84
+ end
85
+
86
+ def dump_source
87
+ [ 'all', 'errors' ].include?( @structure_option )
88
+ end
89
+
90
+ def dump_only_errors
91
+ @structure_option == 'errors'
92
+ end
93
+
94
+ end
95
+
96
+ class ObjC2SwiftConfigNode < FileHierarchicalConfigNode
97
+
98
+ def post_process_config ()
99
+ ignore_file_paths = @configuration_hash[ "ignore" ] || []
100
+ ignore_file_hash = { OMIT_FILE_KEY => true }
101
+ ignore_file_paths.each do | path_str |
102
+ make_child_node( path_str, ignore_file_hash )
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ end
@@ -0,0 +1,64 @@
1
+ require_relative "version"
2
+
3
+ module Objc2swiftAssistant
4
+
5
+ class Objc2SwiftTypeMapper
6
+
7
+ attr_accessor :mappings_by_swift_type
8
+ attr_accessor :mappings_by_objc_type
9
+
10
+ def initialize( )
11
+ @mappings_by_swift_type = {}
12
+ @mappings_by_objc_type = {}
13
+
14
+ #initialize default mappings
15
+ map_types( :BOOL, :Bool, 'false' )
16
+ map_types( :int, :Int, '0' )
17
+ map_types( :NSUInteger, :UInt, '0')
18
+ map_types( :CGFloat, :Float, '0.0' )
19
+ map_types( :id, :AnyObject?, '0.0' )
20
+ map_types( :void, nil, nil )
21
+ end
22
+
23
+ def map_types( objc_type_symbol, swift_type_symbol, swift_default_value )
24
+ mapping = Objc2SwiftTypeMapping.new( objc_type_symbol, swift_type_symbol, swift_default_value)
25
+ set_mapping( mapping )
26
+ mapping
27
+ end
28
+
29
+ def set_mapping( mapping )
30
+ @mappings_by_swift_type[ mapping.swift_type_symbol ] = mapping
31
+ @mappings_by_objc_type[ mapping.objc_type_symbol ] = mapping
32
+ end
33
+
34
+ def mapping_for_objc_type( objc_type_string )
35
+ @mappings_by_objc_type[ objc_type_string.to_sym ]
36
+ end
37
+
38
+ def swift_type_for_objc_type( objc_type_str )
39
+ mapping = mapping_for_objc_type( objc_type_str )
40
+ mapping.nil? ? objc_type_str : mapping.swift_type_string
41
+ end
42
+ end
43
+
44
+
45
+ class Objc2SwiftTypeMapping
46
+ attr_accessor :objc_type_symbol
47
+ attr_accessor :swift_type_symbol
48
+ attr_accessor :swift_default_value
49
+
50
+ def initialize( objc_type_symbol, swift_type_symbol, swift_default_value )
51
+ @objc_type_symbol = objc_type_symbol
52
+ @swift_type_symbol = swift_type_symbol
53
+ @swift_default_value = swift_default_value
54
+ end
55
+
56
+ def swift_type_string
57
+ @swift_type_symbol.nil? ? nil : @swift_type_symbol.to_s
58
+ end
59
+
60
+ end
61
+
62
+ @@type_mapping = Objc2SwiftTypeMapper.new()
63
+
64
+ end
@@ -0,0 +1,76 @@
1
+ require_relative "version"
2
+
3
+ module Objc2swiftAssistant
4
+
5
+ class ObjCAbstractParameter
6
+ attr_accessor :param_type
7
+ attr_accessor :pointer_level # 0 -> not a pointer; 1 -> *; 2 -> **, ...
8
+ attr_accessor :is_block_type
9
+ attr_accessor :match_failure
10
+ attr_accessor :is_weak
11
+
12
+ def initialize
13
+ @pointer_level = 0
14
+ @param_type = nil
15
+ @is_weak = false
16
+ end
17
+
18
+ def match_failed
19
+ return ! @match_failure.nil?
20
+ end
21
+
22
+ def process_pointer_str( pointer_str )
23
+ if pointer_str.nil?
24
+ @pointer_level = 0
25
+ else
26
+ @pointer_level = pointer_str.length
27
+ end
28
+ end
29
+ end
30
+
31
+
32
+
33
+ class ObjCProperty < ObjCAbstractParameter
34
+ #TODO: Use this class for properties
35
+ end
36
+
37
+ class ObjCReturnType < ObjCAbstractParameter
38
+ #TODO: Use this class for return types
39
+ end
40
+
41
+
42
+ class ObjCMethodParameter < ObjCAbstractParameter
43
+ attr_accessor :param_name
44
+ attr_accessor :param_label # May be empty for 1st param
45
+ attr_accessor :null_qualifier
46
+
47
+ def initialize
48
+ super()
49
+ end
50
+
51
+ def from_declaration( declaration_str )
52
+
53
+ end
54
+
55
+ end
56
+
57
+ class ObjCBlockParameter < ObjCAbstractParameter
58
+ attr_accessor :param_name
59
+ attr_accessor :null_qualifier
60
+
61
+ def from_declaration( declaration_str )
62
+ # TODO: nillabel qulaifiers
63
+ m = declaration_str.match( /^(?<type>\w*)\s*(?<pointer_values>[\*&]*)?\s*(?<name>\w*)/ )
64
+ if m.nil?
65
+ match_failure = "Could not parse block agument: #{declaration_str }"
66
+ else
67
+ process_pointer_str( m[ 'pointer_values' ] )
68
+ @is_block_type = false
69
+ @param_type = m[ 'type' ]
70
+ @param_name = m[ 'name' ]
71
+ end
72
+ end
73
+ end
74
+
75
+ end
76
+
@@ -0,0 +1,32 @@
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
+
8
+ module Objc2swiftAssistant
9
+
10
+ class FailableProcessingElement
11
+ attr_accessor :error_messages
12
+
13
+ def initiailize
14
+ @warning_messages = []
15
+ @error_messages = []
16
+ end
17
+
18
+ def has_errors
19
+ return error_messages.length > 0
20
+ end
21
+
22
+ def add_error( error_message )
23
+ @error_messages << error_message
24
+ end
25
+
26
+ def add_warning( warning_message )
27
+ @warning_messages << warning_message
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,41 @@
1
+ require "objc2swift_assistant/version"
2
+
3
+ require "objc2swift_assistant/code_recognizer"
4
+
5
+ module Objc2swiftAssistant
6
+
7
+ DIRECTIVE_REGEX = /^\s*@(?<directive>((required)|(optional)|(public)|(private)|(protected)))/
8
+
9
+ class AtDirectiveRecognizer < CodeRecognizer
10
+ def initialize( )
11
+ super( DIRECTIVE_REGEX, AtDirectiveRegion, :all_source_files, false )
12
+ end
13
+ end
14
+
15
+
16
+ class AtDirectiveRegion < MigrationRegion
17
+ attr_accessor :directive_symbol
18
+
19
+ def initialize(starting_line_number, is_root_entity )
20
+ super(starting_line_number, is_root_entity, AT_DIRECTIVE_KEY, can_occur_in_class_decl:true )
21
+ @is_single_line = true
22
+ @directive_symbol = nil
23
+ end
24
+
25
+ def extract_information( file_slice )
26
+ m = DIRECTIVE_REGEX.match(file_slice[0])
27
+ unless m.nil?
28
+ @directive_symbol = m[ 'directive' ].to_sym
29
+ end
30
+ end
31
+
32
+ def brief_description()
33
+ return "@#{@directive_symbol.to_s}"
34
+ end
35
+
36
+ def description()
37
+ generic_description( "Objective-C directive @#{@directive_symbol.to_s}" )
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,72 @@
1
+ require "objc2swift_assistant/version"
2
+
3
+ require "objc2swift_assistant/code_recognizer"
4
+
5
+
6
+ module Objc2swiftAssistant
7
+
8
+ CATEGORY_DECLARATION_REGEX = /^\s*(@interface)\s*(?<class_name>\w*)\s*\((?<category_name>\w*)\)/
9
+ CATEGORY_IMPLEMENTATION_REGEX = /^\s*(@implementation)\s*(?<class_name>\w*)\s*\((?<category_name>\w*)\)/
10
+
11
+ class CategoryDeclarationRecognizer < CodeRecognizer
12
+
13
+ def initialize( )
14
+ super( CATEGORY_DECLARATION_REGEX, CategoryDeclarationRegion, :implementation, true )
15
+ end
16
+ end
17
+
18
+
19
+ class CategoryImplRecognizer < CodeRecognizer
20
+
21
+ def initialize( )
22
+ super( CATEGORY_IMPLEMENTATION_REGEX, CategoryImplementationRegion, :implementation, true )
23
+ end
24
+ end
25
+
26
+
27
+ class AbstractCategoryRegion < ClassRootRegion
28
+ attr_accessor :category_name
29
+
30
+ def brief_description()
31
+ "#{@class_name} (#{(@category_name || "").strip})"
32
+ end
33
+ end
34
+
35
+
36
+ class CategoryDeclarationRegion < AbstractCategoryRegion
37
+ def initialize(starting_line_number, is_root_entity )
38
+ super(starting_line_number, is_root_entity, CAT_EXT_DECLARARATION_KEY )
39
+ end
40
+
41
+ def extract_information( file_slice )
42
+ m = CATEGORY_DECLARATION_REGEX.match(file_slice[0])
43
+ if m.nil?
44
+ @configuration.log_warning( "WARNING: Could not match category info in #{file_slice[0]}" )
45
+ else
46
+ @class_name = m[ 'class_name' ]
47
+ @category_name = m[ 'category_name' ]
48
+ @region_type = @category_name.nil? || @category_name.length == 0 ? EXTENSION_DECLARARATION_KEY : CATEGORY_DECLARARATION_KEY
49
+ @configuration.log_verbose( "category_name = #{@category_name} @class_name = #{@class_name}")
50
+ end
51
+ end
52
+ end
53
+
54
+
55
+ class CategoryImplementationRegion < AbstractCategoryRegion
56
+ def initialize(starting_line_number, is_root_entity )
57
+ super(starting_line_number, is_root_entity, CATEGORY_IMPLEMENTATION_KEY )
58
+ end
59
+
60
+ def extract_information( file_slice )
61
+ m = CATEGORY_IMPLEMENTATION_REGEX.match(file_slice[0])
62
+ if m.nil?
63
+ @configuration.log_warning( "Could not match category info in #{file_slice[0]}" )
64
+ else
65
+ @class_name = m[ 'class_name' ]
66
+ @category_name = m[ 'category_name' ]
67
+ @configuration.log_verbose( "Matched category = #{@category_name} @class_name = #{@class_name}")
68
+ end
69
+ end
70
+ end
71
+
72
+ end