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,31 @@
1
+ require "objc2swift_assistant/version"
2
+
3
+ require "objc2swift_assistant/code_recognizer"
4
+
5
+ module Objc2swiftAssistant
6
+
7
+ class ImplementationRecognizer < CodeRecognizer
8
+ def initialize( )
9
+ super( /^\s*@implementation/, ImplementationRegion, :implementation, true )
10
+ end
11
+ end
12
+
13
+
14
+ class ImplementationRegion < ClassRootRegion
15
+
16
+ def initialize(starting_line_number, is_root_entity )
17
+ super(starting_line_number, is_root_entity, CLASS_IMPLEMENTATION_KEY )
18
+ end
19
+
20
+ def extract_information( file_slice )
21
+ class_name_match = /^\s*(@implementation)\s+(?<class_name>\w*)/.match(file_slice[0])
22
+ unless class_name_match.nil?
23
+ @class_name = class_name_match["class_name"]
24
+ else
25
+ @configuation.log_warning( "Could not match class name in #{file_slice[0]}" )
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,37 @@
1
+ require "objc2swift_assistant/version"
2
+
3
+ require "objc2swift_assistant/code_recognizer"
4
+
5
+ module Objc2swiftAssistant
6
+
7
+ class InterfaceRecognizer < CodeRecognizer
8
+ def initialize( )
9
+ super( /^\s*@interface()/, ClassInterfaceRegion, :implementation, true, voiding_regex:/^\s*@interface\s*\w*\s*\(/)
10
+ end
11
+ end
12
+
13
+
14
+ class ClassInterfaceRegion < ClassRootRegion
15
+ attr_accessor :super_class
16
+ attr_accessor :implements
17
+
18
+ def initialize(starting_line_number, is_root_entity )
19
+ super(starting_line_number, is_root_entity, CLASS_INTERFACE_KEY )
20
+ end
21
+
22
+ def extract_information( file_slice )
23
+ m = /^\s*(@interface)\s+(?<class_name>\w*)\s*:\s*(?<super_class>\w*)?\s*(<(?<implements>.*)>)?/.match(file_slice[0])
24
+ unless m.nil?
25
+ @class_name = m["class_name"]
26
+ @super_class = m["super_class"]
27
+ implements_list = m["implements"]
28
+ @implements = implements_list.nil? ? [] : implements_list.split( /\s*,\s*/ )
29
+ @configuration.log_verbose( "class_name = #{@class_name} super_class = #{@super_class} implements = #{@implements}")
30
+ else
31
+ @configuration.log_warning( "WARNING: Could not match interface declaration in #{file_slice[0]}" )
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,190 @@
1
+ require_relative "../version"
2
+
3
+ require_relative "../code_recognizer"
4
+ require_relative "../objc_variable_types"
5
+
6
+ module Objc2swiftAssistant
7
+
8
+ class MethodRecognizer < CodeRecognizer
9
+ def initialize( )
10
+ super( /^\s*[-+]\s*\(/, MethodRegion, :implementation, false )
11
+ end
12
+ end
13
+
14
+
15
+ class MethodRegion < MigrationRegion
16
+ # ObjC methods do not have "names"
17
+ attr_accessor :objc_signature
18
+ attr_accessor :is_class_method
19
+ attr_accessor :return_type
20
+ attr_accessor :return_pointer_level
21
+ attr_accessor :return_nillable_qualifier
22
+ attr_accessor :raw_parameter_text
23
+ attr_accessor :parameters
24
+ attr_accessor :takes_arguments
25
+ attr_accessor :all_lines
26
+ attr_accessor :unmatched_lines
27
+
28
+ def initialize(starting_line_number, is_root_entity )
29
+ super(starting_line_number, is_root_entity, METHOD_INDETERMINATE_KEY )
30
+ @unmatched_lines = []
31
+ @all_lines = []
32
+ end
33
+
34
+ def extract_information( file_slice )
35
+ @all_lines = file_slice
36
+ method_text = file_slice.join( "\n" )
37
+ m = method_text.match( /^\s*(?<instance_or_class>[+-])\s*\((?<return_type>\w*)\s*(?<return_pointer>\*+)?\s*(?<nil_return_qualifier>(__nullable|__nonnull))?\s*\)(?<name_and_params>[^\{;]*)\s*(?<declaration_or_implementation>(\{|(;\s*\{)+|;))/m )
38
+ if m.nil?
39
+ @configuration.log_warning( "Could not match method (implemetation or declaration) in #{file_slice[0]}..." )
40
+ else
41
+ @is_class_method = m['instance_or_class'] == '+'
42
+ @return_nillable_qualifier = m[ 'nil_return_qualifier' ]
43
+ @return_type = m[ 'return_type' ]
44
+ @return_pointer_level = m[ 'return_pointer' ].nil? ? 0 : m[ 'return_pointer' ].length
45
+ @raw_parameter_text = m[ 'name_and_params' ]
46
+ @parameters, @takes_arguments = parse_parameters( @raw_parameter_text )
47
+ @objc_signature = make_signature
48
+ @unmatched_lines = m.post_match.lines
49
+ is_declaration = m['declaration_or_implementation'] == ';'
50
+ @region_type = is_declaration ? METHOD_DECLARATION_KEY : METHOD_IMPLEMENTATION_KEY
51
+ # log_verbose( description )
52
+ end
53
+ end
54
+
55
+ def parse_parameters( parameter_text )
56
+ takes_arguments = true
57
+ parameters = []
58
+ matches = []
59
+
60
+ # handle single mthod names
61
+ if parameter_text.include?( ':' )
62
+ # Split the arguments including (simple) block arguments
63
+ parameter_text.scan( /(?<label>\w*)\s*:\s*\((?<is_weak>__weak)?(?<value>[^:]*)\)\s*(?<arg>[^:\s]*)/ ){ matches << $~ }
64
+ if matches.length > 0
65
+ # puts( matches)
66
+ matches.each do |m|
67
+ param = ObjCMethodParameter.new()
68
+ param.param_label = m[ 'label' ].strip
69
+ param.param_name = m[ 'arg' ].strip
70
+ unless m[ 'is_weak' ].nil?
71
+ param.is_weak = true
72
+ end
73
+ value = m[ 'value' ].strip
74
+ if value.include? '^'
75
+ param.is_block_type = true # Its a block parameter
76
+ param.param_type = value
77
+ else
78
+ param.is_block_type = false
79
+ m = value.match( /(?<null_qualifier>(__nullable|__nonnull))?\s*(?<type>\w*)\s*(?<pointer>\*+)?/ )
80
+ if m.nil?
81
+ param.match_failure = "Could not match #{value} as a non-blocl parameter"
82
+ else
83
+ param.param_type = m[ 'type' ].strip
84
+ param.null_qualifier = m[ 'null_qualifier' ]
85
+ param.pointer_level = m[ 'pointer' ].nil? ? 0 : m[ 'pointer' ].length
86
+ end
87
+ end
88
+
89
+ if param.param_label.nil?
90
+ param.param_label = '/* Unknown */'
91
+ end
92
+
93
+ parameters << param
94
+ takes_arguments = true
95
+ end
96
+ end
97
+ else
98
+ param = ObjCMethodParameter.new()
99
+ param.param_label = parameter_text.strip # No arguments to method: create a parameter with only a label
100
+ parameters << param
101
+ takes_arguments = false
102
+ end
103
+
104
+ return parameters, takes_arguments
105
+ end
106
+
107
+ # def extract_information( file_slice )
108
+ # method_text = file_slice.join( "\n" )
109
+ # m = method_text.match( /^\s*(?<instance_or_class>[+-])\s*\((?<return_type>\w*)\s*(?<return_pointer>\*+)?\)(?<name_and_params>[^\{;]*)\s*(?<declaration_or_implementation>(\{|(;\s*\{)+|;))/m )
110
+ # if m.nil?
111
+ # puts( "WARNING: Could not match method (implemetation or declaration) in #{file_slice[0]}..." )
112
+ # else
113
+ # @is_class_method = m['instance_or_class'] == '+'
114
+ # @return_type = m[ 'return_type' ]
115
+ # @return_pointer_level = m[ 'return_pointer' ].nil? ? 0 : m[ 'return_pointer' ].length
116
+ # @raw_parameter_text = m[ 'name_and_params' ]
117
+ # @parameters, @takes_arguments = parse_parameters( @raw_parameter_text )
118
+ # @objc_signature = make_signature
119
+ # @unmatched_lines = m.post_match.lines
120
+ # is_declaration = m['declaration_or_implementation'] == ';'
121
+ # @region_type = is_declaration ? METHOD_DECLARATION_KEY : METHOD_IMPLEMENTATION_KEY
122
+ # puts( description )
123
+ # end
124
+ # end
125
+ #
126
+ # def parse_parameters( parameter_text )
127
+ # takes_arguments = true
128
+ # parameters = []
129
+ # matches = []
130
+ # parameter_text.scan( /(?<label>\w*)\s*:\s*\(\s*(?<null_qualifier>(__nullable|__nonnull))?\s*(?<type>\w*)\s*(?<pointer>\*+)?\s*\)\s*(?<arg>\w*)/ ){ matches << $~ }
131
+ # if matches.length > 0
132
+ # puts( matches)
133
+ # matches.each do |m|
134
+ # param = MethodParameter.new()
135
+ # param.param_label = m[ 'label' ]
136
+ # param.param_name = m[ 'arg' ]
137
+ # param.param_type = m[ 'type' ]
138
+ # param.null_qualifier = m[ 'null_qualifier' ]
139
+ # param.pointer_level = m[ 'pointer' ].nil? ? 0 : m[ 'pointer' ].length
140
+ # parameters << param
141
+ # takes_arguments = true
142
+ # end
143
+ # else
144
+ # param = MethodParameter.new()
145
+ # param.param_label = parameter_text # No arguments to method: create a parameter with only a label
146
+ # parameters << param
147
+ # takes_arguments = false
148
+ # end
149
+ #
150
+ # return parameters, takes_arguments
151
+ # end
152
+
153
+
154
+ def make_signature()
155
+ signature = ''
156
+ if @takes_arguments
157
+ self.parameters.each do |param|
158
+ signature << "#{param.param_label}:"
159
+ end
160
+ else
161
+ signature = self.parameters[0].param_label
162
+ end
163
+
164
+ return signature.strip
165
+ end
166
+
167
+ def takes_arguments
168
+ return ! @parameters[0].param_name.nil?
169
+ end
170
+
171
+ def params_descr()
172
+ 'NYI'
173
+ end
174
+
175
+ def description()
176
+ return generic_description( "#{'+' if @is_class_method} return_type:#{@return_type} name:#{@name} #{'declaration' if @is_declaration} #{"body_lines:#{@unmatched_lines.length}" if @unmatched_lines.length > 0}" )
177
+ end
178
+
179
+ def brief_description
180
+ # plus_minus = @is_class_method ? '+' : '-'
181
+ # pointerText = ""
182
+ # pointerText = " *****"[1..@pointer_level+1] unless @pointer_level.nil? || @pointer_level == 0
183
+ # return "#{plus_minus} (#{@return_type}#{pointerText}) #{@raw_parameter_text}"
184
+
185
+ return @objc_signature
186
+ end
187
+
188
+ end
189
+
190
+ end
@@ -0,0 +1,41 @@
1
+ require "objc2swift_assistant/version"
2
+
3
+ require "objc2swift_assistant/code_recognizer"
4
+
5
+ module Objc2swiftAssistant
6
+
7
+ PRAGMA_MARK_REGEX = /^\s*((#pragma mark)|(\/\/\s*MARK\s*\:))(?<mark_text>.*)/
8
+
9
+ class PragmaMarkRecognizer < CodeRecognizer
10
+ def initialize( )
11
+ super( PRAGMA_MARK_REGEX, PragmaMarkRegion, :all_source_files, false )
12
+ end
13
+ end
14
+
15
+
16
+ class PragmaMarkRegion < MigrationRegion
17
+ attr_accessor :mark_text
18
+
19
+ def initialize( starting_line_number, is_root_entity )
20
+ super( starting_line_number, is_root_entity, PRAGMA_MARK_KEY, can_occur_in_class_decl:true )
21
+ end
22
+
23
+
24
+ def extract_information( file_slice )
25
+ m = PRAGMA_MARK_REGEX.match(file_slice[0])
26
+ unless m.nil?
27
+ @mark_text = m[ 'mark_text' ]
28
+ end
29
+ end
30
+ end
31
+
32
+ def description()
33
+ if @is_block_property
34
+ return generic_description( "Block Property: prop_name=#{@prop_name} block_return_type=#{@block_return_type} block_args=#{@block_args}" )
35
+ else
36
+ return generic_description( "type_name=#{@type_name} is_pointer=#{@is_pointer} prop_name=#{@prop_name}" )
37
+ end
38
+ end
39
+
40
+
41
+ end
@@ -0,0 +1,78 @@
1
+ require "objc2swift_assistant/version"
2
+
3
+ require "objc2swift_assistant/code_recognizer"
4
+
5
+ module Objc2swiftAssistant
6
+
7
+ class PropertyDeclarationRecognizer < CodeRecognizer
8
+ def initialize( )
9
+ super( /^\s*@property/, PropertyDeclarationRegion, :all_source_files, false )
10
+ end
11
+ end
12
+
13
+
14
+ class PropertyDeclarationRegion < MigrationRegion
15
+ attr_accessor :type_name
16
+ attr_accessor :is_pointer
17
+ attr_accessor :name
18
+ attr_accessor :modifiers
19
+
20
+ attr_accessor :is_block_property
21
+ attr_accessor :block_return_type
22
+ attr_accessor :block_args
23
+
24
+ def initialize(starting_line_number, is_root_entity )
25
+ super(starting_line_number, is_root_entity, PROPERTY_DECLARATION_KEY )
26
+ end
27
+
28
+ def extract_information( file_slice )
29
+ m = /^\s*(@property)\s*\((?<modifiers>.*)\)\s*(?<type>\w*)\s*(?<pointer>\*?)\s*(?<prop_name>\w*)/.match(file_slice[0])
30
+ unless m.nil?
31
+ @type_name = m["type"]
32
+ @is_pointer = m["pointer"] == '*'
33
+ @name = m["prop_name"]
34
+
35
+ #TODO: @modifiers = capture_modifiers( m["modifiers"] )
36
+ @modifiers = split_modifiers( m["modifiers"] )
37
+ if @type_name.nil? || @type_name.length == 0
38
+ # Test for Block declaration
39
+ m = /^\s*(@property)\s*\((?<modifiers>.*)\)\s*(?<return_type>\w*)\s*\(\^(?<name>\w*)\)\s*\((?<args>.*)\)/.match(file_slice[0])
40
+ unless m.nil?
41
+ @is_block_property = true
42
+
43
+ @block_return_type = m[ 'return_type' ]
44
+ @name = m[ 'name' ]
45
+ @block_args = m[ 'args' ] # TODO: Split these
46
+
47
+ @configuration.log_verbose( "Matched: " + description )
48
+ else
49
+ @configuration.log_warning( "Could not match block property declaraion in #{file_slice[0]}" )
50
+ end
51
+ else
52
+ @configuration.log_verbose( description )
53
+ end
54
+ else
55
+ @configuration.log_warning( "Could not match property declaraion in #{file_slice[0]}" )
56
+ end
57
+ end
58
+
59
+ def split_modifiers( modifiers )
60
+ return if modifiers.nil?
61
+ @modifiers = modifiers.strip.split( /\s*,\s*/ )
62
+ end
63
+
64
+ def description()
65
+ if @is_block_property
66
+ return generic_description( "Block Property: prop_name=#{@prop_name} block_return_type=#{@block_return_type} block_args=#{@block_args}" )
67
+ else
68
+ return generic_description( "type_name=#{@type_name} is_pointer=#{@is_pointer} prop_name=#{@prop_name}" )
69
+ end
70
+ end
71
+
72
+ def brief_description
73
+ return "(#{@modifiers.join( ', ' )}) #{@type_name} #{'*' if @is_pointer} #{@name}"
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,40 @@
1
+ require "objc2swift_assistant/version"
2
+
3
+ require "objc2swift_assistant/code_recognizer"
4
+
5
+ module Objc2swiftAssistant
6
+
7
+ class ProtocolRecognizer < CodeRecognizer
8
+ def initialize( )
9
+ super( /^\s*@protocol()/, ProtocolRegion, :implementation, true, voiding_regex:/^\s*@interface\s*\w*\s*\(/)
10
+ end
11
+ end
12
+
13
+
14
+ class ProtocolRegion < MigrationRegion
15
+ attr_accessor :protocol_name
16
+ attr_accessor :extends
17
+
18
+ def initialize(starting_line_number, is_root_entity )
19
+ super(starting_line_number, is_root_entity, PROTOCOL_DECLARATION_KEY )
20
+ end
21
+
22
+ def extract_information( file_slice )
23
+ m = /^\s*(@protocol)\s+(?<protocol_name>\w*)\s*(<(?<extends>.*)>)?/.match(file_slice[0])
24
+ unless m.nil?
25
+ @protocol_name = m["protocol_name"]
26
+ extends_list = m["extends"]
27
+ @extends = extends.nil? ? [] : extends_list.split( /\s*,\s*/ )
28
+ @configuration.log_verbose( "class_name = #{@protocol_name} extends = #{@extends}")
29
+ else
30
+ @configuration.log_warning( "Could not match protocol declaration in #{file_slice[0]}" )
31
+ end
32
+ end
33
+
34
+ def description()
35
+ generic_description( "Protocol: #{@protocol_name}" )
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,26 @@
1
+ require "objc2swift_assistant/version"
2
+
3
+ module Objc2swiftAssistant
4
+
5
+ CLASS_INTERFACE_KEY = :class_interface
6
+ CLASS_IMPLEMENTATION_KEY = :class_implementation
7
+ ENUM_DECLARATION_KEY = :enum_declaration
8
+ PROPERTY_DECLARATION_KEY = :property_declaration
9
+
10
+ CAT_EXT_DECLARARATION_KEY = :category_or_extension_declaration
11
+ EXTENSION_DECLARARATION_KEY = :extension_declaration
12
+ CATEGORY_DECLARARATION_KEY = :category_declaration
13
+ CATEGORY_IMPLEMENTATION_KEY = :category_implementation
14
+
15
+ PROTOCOL_DECLARATION_KEY = :protocol_declaration
16
+
17
+ PRAGMA_MARK_KEY = :pragma_mark
18
+
19
+ AT_DIRECTIVE_KEY = :at_directive
20
+
21
+ METHOD_INDETERMINATE_KEY = :method_declatation_or_implementation
22
+ METHOD_DECLARATION_KEY = :method_declaration
23
+ METHOD_IMPLEMENTATION_KEY = :method_implementation
24
+
25
+ end
26
+