xdry 0.1.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 (52) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +11 -0
  3. data/Rakefile +76 -0
  4. data/VERSION +1 -0
  5. data/bin/xdry +4 -0
  6. data/lib/xdry.rb +18 -0
  7. data/lib/xdry/boxing.rb +212 -0
  8. data/lib/xdry/generators/ctor_from_field.rb +91 -0
  9. data/lib/xdry/generators/dealloc.rb +53 -0
  10. data/lib/xdry/generators/dictionary_coding.rb +129 -0
  11. data/lib/xdry/generators/field_from_property.rb +20 -0
  12. data/lib/xdry/generators/property-from-field.rb +22 -0
  13. data/lib/xdry/generators/storing_constructor.rb +72 -0
  14. data/lib/xdry/generators/synthesize.rb +25 -0
  15. data/lib/xdry/generators_support.rb +42 -0
  16. data/lib/xdry/parsing/driver.rb +106 -0
  17. data/lib/xdry/parsing/model.rb +272 -0
  18. data/lib/xdry/parsing/nodes.rb +260 -0
  19. data/lib/xdry/parsing/parsers.rb +166 -0
  20. data/lib/xdry/parsing/parts/selectors.rb +95 -0
  21. data/lib/xdry/parsing/parts/var_types.rb +66 -0
  22. data/lib/xdry/parsing/pos.rb +75 -0
  23. data/lib/xdry/parsing/scope_stack.rb +68 -0
  24. data/lib/xdry/parsing/scopes.rb +61 -0
  25. data/lib/xdry/parsing/scopes_support.rb +143 -0
  26. data/lib/xdry/patching/emitter.rb +60 -0
  27. data/lib/xdry/patching/insertion_points.rb +209 -0
  28. data/lib/xdry/patching/item_patchers.rb +74 -0
  29. data/lib/xdry/patching/patcher.rb +139 -0
  30. data/lib/xdry/run.rb +227 -0
  31. data/lib/xdry/support/enumerable_additions.rb +35 -0
  32. data/lib/xdry/support/string_additions.rb +27 -0
  33. data/lib/xdry/support/symbol_additions.rb +14 -0
  34. data/site/_config.yml +3 -0
  35. data/site/_example +9 -0
  36. data/site/_layouts/default.html +30 -0
  37. data/site/_plugins/example.rb +16 -0
  38. data/site/_plugins/highlight_unindent.rb +17 -0
  39. data/site/index.md +417 -0
  40. data/site/master.css +94 -0
  41. data/spec/boxing_spec.rb +80 -0
  42. data/spec/ctor_from_field_spec.rb +251 -0
  43. data/spec/dealloc_spec.rb +103 -0
  44. data/spec/dictionary_coding_spec.rb +132 -0
  45. data/spec/field_from_prop_spec.rb +72 -0
  46. data/spec/prop_from_field_spec.rb +39 -0
  47. data/spec/readme_samples_spec.rb +76 -0
  48. data/spec/spec.opts +3 -0
  49. data/spec/spec_helper.rb +53 -0
  50. data/spec/synthesize_spec.rb +94 -0
  51. data/xdry.gemspec +103 -0
  52. metadata +141 -0
@@ -0,0 +1,260 @@
1
+
2
+ module XDry
3
+
4
+ class Node
5
+ attr_accessor :pos, :indent
6
+
7
+ def initialize
8
+ @tags = Set.new
9
+ end
10
+
11
+ def tags
12
+ @tags.dup
13
+ end
14
+
15
+ def tags= new_tags
16
+ @tags = Set.new(new_tags)
17
+ end
18
+
19
+ def tagged_with? tag
20
+ @tags.include? tag
21
+ end
22
+
23
+ def tags_comment
24
+ if @tags.empty? then "" else " // " + @tags.to_a.sort.join(", ") end
25
+ end
26
+
27
+ def method_missing id, *args, &block
28
+ if id.to_s =~ /^with_(.*)$/
29
+ send("#{$1}=", *args, &block)
30
+ self
31
+ else
32
+ super(id, *args, &block)
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ class NInterfaceFieldsEnd < Node
39
+ end
40
+
41
+ class NFieldDef < Node
42
+ attr_reader :name, :type
43
+
44
+ def initialize name, type
45
+ super()
46
+ @name, @type = name, type
47
+ end
48
+
49
+ def persistent?
50
+ tagged_with? 'persistent'
51
+ end
52
+
53
+ def wants_property?
54
+ tagged_with? 'wants-property'
55
+ end
56
+
57
+ def wants_constructor?
58
+ tagged_with? 'wants-constructor'
59
+ end
60
+
61
+ def to_s
62
+ "#{@type} #{@name}#{tags_comment}"
63
+ end
64
+
65
+ def to_source
66
+ "#{@type.to_source_with_space}#{@name};"
67
+ end
68
+ end
69
+
70
+ class NPropertyDef < Node
71
+ attr_reader :name, :type
72
+
73
+ def initialize name, type
74
+ super()
75
+ raise StandardError, "type cannot be nil for prop #{name}" if type.nil?
76
+ @name, @type = name, type
77
+ end
78
+
79
+ def outlet?
80
+ tagged_with? 'outlet'
81
+ end
82
+
83
+ def to_s
84
+ "#{if outlet? then 'IBOutlet ' else '' end}#{@type} #{@name}"
85
+ end
86
+
87
+ def to_source
88
+ retainment = case @type.default_property_retainment_policy
89
+ when '' then ''
90
+ else ', ' + @type.default_property_retainment_policy
91
+ end
92
+ iboutlet = if outlet? then "IBOutlet " else '' end
93
+ "@property(nonatomic#{retainment}) #{iboutlet}#{@type.to_source_with_space}#{@name};"
94
+ end
95
+ end
96
+
97
+ class NMethodHeader < Node
98
+ attr_reader :selector_def, :ret_type
99
+
100
+ def initialize selector_def, ret_type
101
+ @selector_def, @ret_type = selector_def, ret_type
102
+ end
103
+
104
+ def selector
105
+ @selector_def.selector
106
+ end
107
+
108
+ def to_s
109
+ "- (#{@ret_type})#{selector_def}"
110
+ end
111
+
112
+ end
113
+
114
+ class NMethodStart < Node
115
+ attr_reader :selector_def, :ret_type
116
+
117
+ def initialize selector_def, ret_type
118
+ @selector_def, @ret_type = selector_def, ret_type
119
+ end
120
+
121
+ def selector
122
+ @selector_def.selector
123
+ end
124
+
125
+ def to_s
126
+ "- (#{@ret_type})#{selector_def}"
127
+ end
128
+
129
+ end
130
+
131
+ class NInterfaceStart < Node
132
+ attr_reader :class_name
133
+ def initialize class_name
134
+ @class_name = class_name
135
+ end
136
+ end
137
+
138
+ class NImplementationStart < Node
139
+ attr_reader :class_name
140
+ def initialize class_name
141
+ @class_name = class_name
142
+ end
143
+ end
144
+
145
+ class NEnd < Node
146
+ end
147
+
148
+ class SynthesizeItem
149
+
150
+ attr_reader :property_name, :field_name
151
+
152
+ def initialize property_name, field_name = nil
153
+ @property_name, @field_name = property_name, field_name
154
+ end
155
+
156
+ def has_field_name?
157
+ not @field_name.nil?
158
+ end
159
+
160
+ def to_s
161
+ if has_field_name?
162
+ "#{property_name}=#{field_name}"
163
+ else
164
+ "#{property_name}"
165
+ end
166
+ end
167
+
168
+ def self.parse string
169
+ case string
170
+ when /^(\w+)$/ then SynthesizeItem.new($1, nil)
171
+ when /^(\w+)\s*=\s*(\w+)$/ then SynthesizeItem.new($1, $2)
172
+ end
173
+ end
174
+
175
+ end
176
+
177
+ class NSynthesize < Node
178
+
179
+ attr_reader :items
180
+
181
+ def initialize items
182
+ @items = items
183
+ end
184
+
185
+ def item_for_property_named property_name
186
+ @items.find { |item| item.property_name == property_name }
187
+ end
188
+
189
+ def to_s
190
+ "@synthesize " + @items.join(", ") + ";"
191
+ end
192
+
193
+ def self.parse string
194
+ if string =~ /^@synthesize\s+(.*);$/
195
+ NSynthesize.new($1.strip.split(/\s+,\s+/).collect { |s| SynthesizeItem.parse(s) }.compact)
196
+ end
197
+ end
198
+
199
+ end
200
+
201
+ class NOpeningBrace < Node
202
+ end
203
+
204
+ class NClosingBrace < Node
205
+ end
206
+
207
+ class NMethodEnd < Node
208
+ end
209
+
210
+ class NReleaseCall < Node
211
+ attr_reader :expr
212
+
213
+ def initialize expr
214
+ @expr = expr
215
+ end
216
+ end
217
+
218
+ class NSuperCall < Node
219
+ end
220
+
221
+ class NReturn < Node
222
+ end
223
+
224
+ class NDefine < Node
225
+ attr_reader :word
226
+
227
+ def initialize word
228
+ @word = word
229
+ end
230
+ end
231
+
232
+ class NLine < Node
233
+
234
+ attr_reader :line
235
+
236
+ def initialize line
237
+ @line = line
238
+ end
239
+
240
+ end
241
+
242
+ class NMarker < Node
243
+ attr_reader :text
244
+
245
+ def initialize text
246
+ @text = text
247
+ end
248
+
249
+ def to_s
250
+ "#{self.class.name}('#{text}')"
251
+ end
252
+ end
253
+
254
+ class NPartLineMarker < NMarker
255
+ end
256
+
257
+ class NFullLineMarker < NMarker
258
+ end
259
+
260
+ end
@@ -0,0 +1,166 @@
1
+ require 'set'
2
+
3
+ module XDry
4
+
5
+ class Parser
6
+
7
+ attr_reader :scope
8
+
9
+ def initialize scope
10
+ @scope = scope
11
+ end
12
+
13
+ def to_s
14
+ "#{self.class.name}"
15
+ end
16
+
17
+ end
18
+
19
+ class PGlobal < Parser
20
+
21
+ def parse_line! line, eol_comments, indent
22
+ case line
23
+ when /^@interface\s+(\w+)\s*;/
24
+ name = $1
25
+ when /^@protocol\s+(\w+)\s*;/
26
+ name = $1
27
+
28
+ when /^@interface\s+(\w+)/ #\s*(?:[:(][\w:(),\s]*)?
29
+ name, supers, postfix = $1, $2, $'
30
+ yield NInterfaceStart.new(name)
31
+ yield NOpeningBrace.new if postfix =~ /\{$/
32
+
33
+ when /^@implementation\s+(\w+)/
34
+ name = $1
35
+ yield NImplementationStart.new(name)
36
+
37
+ when /^@protocol\s+(\w+)\s*;/
38
+ puts "PREDEF protocol #{$1}"
39
+
40
+ when /^#define\s+(\w+)/
41
+ word = $1
42
+ yield NDefine.new(word)
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ class PInterfaceFields < Parser
49
+
50
+ def initialize scope
51
+ super
52
+ @tags = Set.new
53
+ end
54
+
55
+ def parse_line! line, eol_comments, indent
56
+ @this_line_tags = Set.new
57
+ [[/!p\b/, 'wants-property'], [/!c\b/, 'wants-constructor']].each do |regexp, tag|
58
+ if line =~ regexp
59
+ marker = $&
60
+ is_full_line = line.gsub(marker, '').strip.empty?
61
+ klass = is_full_line ? NFullLineMarker : NPartLineMarker
62
+ yield klass.new(marker)
63
+ (is_full_line ? @tags : @this_line_tags) << tag
64
+ return if is_full_line
65
+ end
66
+ end
67
+ case line
68
+ when /\}/
69
+ yield NInterfaceFieldsEnd.new
70
+ when %r~^//\s*persistent$~
71
+ @tags << 'persistent'
72
+ when ''
73
+ @tags.clear
74
+ when /^(\w+)\s+(\w+)\s*;/
75
+ type_name, field_name = $1, $2
76
+ yield process_type_hint(NFieldDef.new(field_name, SimpleVarType.new(type_name)), eol_comments)
77
+ when /^(\w+)\s*\*\s*(\w+)\s*;/
78
+ type_name, field_name = $1, $2
79
+ yield process_type_hint(NFieldDef.new(field_name, PointerVarType.new(type_name)), eol_comments)
80
+ when /^id<(\w+)>\s+(\w+)\s*;/
81
+ type_name, field_name = $1, $2
82
+ yield process_type_hint(NFieldDef.new(field_name, IdVarType.new()), eol_comments)
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def process_type_hint field_def, eol_comments
89
+ field_def.tags = (@tags + @this_line_tags).to_a
90
+
91
+ case field_def.type
92
+ when PointerVarType
93
+ case field_def.type.name
94
+ when 'NSArray'
95
+ if eol_comments =~ %r`//\s*of\s+(\w+)`
96
+ field_def.type.type_hint = $1
97
+ end
98
+ end
99
+ end
100
+
101
+ field_def
102
+ end
103
+ end
104
+
105
+ class PInterfaceHeader < Parser
106
+
107
+ def parse_line! line, eol_comments, indent
108
+ case line
109
+ when /^\{$/
110
+ yield NOpeningBrace.new
111
+ when /@end/
112
+ yield NEnd.new
113
+ when /^@property(\s*\([\w\s,]*\))?\s+(IBOutlet\s+)?(\w+)\s*\*\s*(\w+)\s*;$/
114
+ property_flags, iboutlet, type_name, property_name = $1, $2, $3, $4
115
+ yield NPropertyDef.new(property_name, PointerVarType.new(type_name))
116
+ when /^@property(\s*\([\w\s,]*\))?\s+(IBOutlet\s+)?(\w+)\s+(\w+)\s*;$/
117
+ property_flags, iboutlet, type_name, property_name = $1, $2, $3, $4
118
+ yield NPropertyDef.new(property_name, SimpleVarType.new(type_name))
119
+ when /^-\s*\(([^)]+)\)\s*(\w+[\w\s():*]*);$/
120
+ ret_type_decl, selector_decl = $1, $2
121
+ selector_def = SelectorDef.parse(selector_decl)
122
+ ret_type = VarType.parse(ret_type_decl)
123
+ yield NMethodHeader.new(selector_def, ret_type)
124
+
125
+ when /^-\s*\(([^)]+)\)\s*(\w+[\w\s():*]*)\{$/
126
+ ret_type_decl, selector_decl = $1, $2
127
+ selector_def = SelectorDef.parse(selector_decl)
128
+ ret_type = VarType.parse(ret_type_decl)
129
+ yield NMethodStart.new(selector_def, ret_type)
130
+
131
+ when /^@synthesize/
132
+ yield NSynthesize.parse(line)
133
+ end
134
+ end
135
+
136
+ end
137
+
138
+ class PMethodImpl < Parser
139
+
140
+ def parse_line! line, eol_comments, indent
141
+ case line
142
+ when /^\}$/
143
+ if indent == scope.start_node.indent
144
+ yield NMethodEnd.new
145
+ else
146
+ yield NClosingBrace.new
147
+ end
148
+ when /\[\s*([\w.]+)\s+release\s*\]/
149
+ expr = $1
150
+ yield NReleaseCall.new(expr)
151
+ when /\bself\s*\.\s*(\w+)\s*=\s*nil\s*[,;]/
152
+ expr = $1
153
+ yield NReleaseCall.new(expr)
154
+ when /\b(\w+)\s*=\s*nil\s*[,;]/
155
+ expr = $1
156
+ yield NReleaseCall.new(expr)
157
+ when /\[super\s/
158
+ yield NSuperCall.new
159
+ when /^return\b/
160
+ yield NReturn.new
161
+ end
162
+ end
163
+
164
+ end
165
+
166
+ end
@@ -0,0 +1,95 @@
1
+
2
+ module XDry
3
+
4
+ class SelectorDef
5
+
6
+ def self.parse string
7
+ string = string.strip
8
+ if string =~ /^\w+$/
9
+ SimpleSelectorDef.new(string)
10
+ else
11
+ comps = string.split(/\s+(?!\*)/).collect do |component_string|
12
+ if component_string =~ /^(\w+:)\s*(?:\(([^)]+)\)\s*)?(\w*)$/
13
+ keyword, type_decl, arg_name = $1, $2, $3
14
+ type = if type_decl then VarType.parse(type_decl) else nil end
15
+ SelectorComponent.new(keyword, arg_name, type)
16
+ else
17
+ raise StandardError, "Cannot parse selector component '#{component_string}' for selector '#{string}'"
18
+ end
19
+ end
20
+ CompoundSelectorDef.new(comps)
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ class SimpleSelectorDef < SelectorDef
27
+
28
+ attr_reader :selector
29
+
30
+ def initialize selector
31
+ @selector = selector
32
+ end
33
+
34
+ def simple?; true; end
35
+
36
+ def var_name_after_keyword keyword
37
+ nil
38
+ end
39
+
40
+ def to_s
41
+ @selector
42
+ end
43
+
44
+ end
45
+
46
+ class SelectorComponent
47
+ attr_reader :keyword, :arg_name, :type
48
+
49
+ def initialize keyword, arg_name, type
50
+ raise StandardError, "keyword must end with a colon: '#{keyword}'" unless keyword[-1] == ?:
51
+ @keyword, @arg_name, @type = keyword, arg_name, type
52
+ end
53
+
54
+ def keyword_without_colon
55
+ @keyword_without_colon ||= @keyword.sub(/:$/, '')
56
+ end
57
+
58
+ def has_type?
59
+ not @type.nil?
60
+ end
61
+
62
+ def to_s
63
+ if has_type?
64
+ "#{keyword}(#{@type})#{@arg_name}"
65
+ else
66
+ "#{keyword}#{@arg_name}"
67
+ end
68
+ end
69
+ end
70
+
71
+ class CompoundSelectorDef < SelectorDef
72
+ attr_reader :components
73
+
74
+ def initialize components
75
+ @components = components.freeze
76
+ end
77
+
78
+ def selector
79
+ @selector ||= @components.collect { |comp| comp.keyword }.join("")
80
+ end
81
+
82
+ def simple?; false; end
83
+
84
+ def to_s
85
+ @components.collect { |comp| comp.to_s }.join(" ")
86
+ end
87
+
88
+ def var_name_after_keyword keyword
89
+ comp = @components.find { |comp| comp.keyword == keyword }
90
+ comp && comp.arg_name
91
+ end
92
+
93
+ end
94
+
95
+ end