xdry 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,35 @@
1
+
2
+ module XDry
3
+
4
+ module EnumerableAdditions
5
+
6
+ def prefix_while
7
+ result = []
8
+ each do |item|
9
+ if yield(item)
10
+ result << item
11
+ else
12
+ break
13
+ end
14
+ end
15
+ return result
16
+ end
17
+
18
+ def suffix_while
19
+ result = []
20
+ reverse_each do |item|
21
+ if yield(item)
22
+ result << item
23
+ else
24
+ break
25
+ end
26
+ end
27
+ return result.reverse!
28
+ end
29
+
30
+ end
31
+
32
+ # tried to extend Enumerable here, but it did not work, so resorted to only extending Array
33
+ Array.send(:include, EnumerableAdditions)
34
+
35
+ end
@@ -0,0 +1,27 @@
1
+
2
+ module XDry
3
+
4
+ module StringAdditions
5
+
6
+ def blank?
7
+ self =~ /^\s*$/
8
+ end
9
+
10
+ def capitalized_identifier
11
+ case self
12
+ when 'id', 'uid' then upcase
13
+ else self[0..0].upcase + self[1..-1]
14
+ end
15
+ end
16
+
17
+ def prefixed_as_arg_name
18
+ prefix = case self when /^[aeiou]/ then 'an' else 'a' end
19
+
20
+ prefix + self.capitalized_identifier
21
+ end
22
+
23
+ end
24
+
25
+ String.send(:include, StringAdditions)
26
+
27
+ end
@@ -0,0 +1,14 @@
1
+
2
+ module XDry
3
+
4
+ module SymbolAdditions
5
+
6
+ def to_proc
7
+ proc { |obj, *args| obj.send(self, *args) }
8
+ end
9
+
10
+ end
11
+
12
+ Symbol.send(:include, SymbolAdditions)
13
+
14
+ end
data/site/_config.yml ADDED
@@ -0,0 +1,3 @@
1
+ safe: false
2
+ lsi: false
3
+ pygments: true
data/site/_example ADDED
@@ -0,0 +1,9 @@
1
+ {% example %}
2
+
3
+ {% highlight objc %}
4
+ {% endhighlight %}
5
+
6
+ {% highlight objc %}
7
+ {% endhighlight %}
8
+
9
+ {% endexample %}
@@ -0,0 +1,30 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Objective-C boilerplate generator — Extra DRY</title>
6
+ <link href='http://fonts.googleapis.com/css?family=Pacifico' rel='stylesheet' type='text/css'>
7
+ <link href='http://fonts.googleapis.com/css?family=PT+Serif' rel='stylesheet' type='text/css'>
8
+ <link href="master.css" rel="stylesheet" type="text/css" media="screen" charset="utf-8">
9
+ </head>
10
+
11
+ <body>
12
+ <a href="http://github.com/andreyvit/xdry"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
13
+
14
+ <div id="container">
15
+
16
+ {{ content }}
17
+
18
+ </div>
19
+
20
+ <script type="text/javascript">
21
+ var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
22
+ document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
23
+ </script>
24
+ <script type="text/javascript">
25
+ try {
26
+ var pageTracker = _gat._getTracker("UA-861679-14");
27
+ pageTracker._trackPageview();
28
+ } catch(err) {}</script>
29
+ </body>
30
+ </html>
@@ -0,0 +1,16 @@
1
+
2
+ module Jekyll
3
+ class HelloTag < Liquid::Block
4
+
5
+ def initialize(tag_name, text, tokens)
6
+ super
7
+ @text = text
8
+ end
9
+
10
+ def render(context)
11
+ ['<div class="example">'] + super + ['</div>']
12
+ end
13
+ end
14
+ end
15
+
16
+ Liquid::Template.register_tag('example', Jekyll::HelloTag)
@@ -0,0 +1,17 @@
1
+ class Jekyll::HighlightBlock
2
+
3
+ def render_pygments_with_unindent(context, code)
4
+ code = code.split("\n").collect do |line|
5
+ if line =~ /^ {4}/
6
+ line[4..-1]
7
+ else
8
+ line
9
+ end
10
+ end.join("\n")
11
+ render_pygments_without_unindent(context, code)
12
+ end
13
+
14
+ alias_method :render_pygments_without_unindent, :render_pygments
15
+ alias_method :render_pygments, :render_pygments_with_unindent
16
+
17
+ end
data/site/index.md ADDED
@@ -0,0 +1,417 @@
1
+ ---
2
+ title: Home
3
+ layout: default
4
+ ---
5
+
6
+ Objective-C boilerplate generator
7
+ =================================
8
+
9
+ Run Extra D.R.Y. in your Objective-C project folder to automatically add (upon your request):
10
+
11
+ * `@property`, `@synthesize`, field declarations,
12
+ * initializing constructors,
13
+ * missing release calls in dealloc,
14
+ * initWithDictionary, dictionaryRepresentation based on the chosen fields.
15
+
16
+
17
+ Installation
18
+ ------------
19
+
20
+ Install the command-line utility via RubyGems:
21
+
22
+ sudo gem install xdry
23
+
24
+
25
+ Basic Usage
26
+ -----------
27
+
28
+ Tell XD.R.Y. which changes you want done using bang-commands. For example,
29
+ add `!p` to a field declaration line to generate a property:
30
+
31
+ {% example %}
32
+
33
+ {% highlight objc %}
34
+ // Foo.h
35
+ @interface Foo {
36
+ Bar *value; !p
37
+ }
38
+
39
+ @end
40
+
41
+ // Foo.m
42
+ @implementation Foo
43
+ @end
44
+ {% endhighlight %}
45
+
46
+ {% highlight objc %}
47
+ // Foo.h
48
+ @interface Foo {
49
+ Bar *value;
50
+ }
51
+
52
+ @property(nonatomic, retain) Bar *value;
53
+
54
+ @end
55
+
56
+ // Foo.m
57
+ @implementation Foo
58
+
59
+ @synthesize value;
60
+
61
+ - (void)dealloc {
62
+ [value release], value = nil;
63
+ [super dealloc];
64
+ }
65
+
66
+ @end
67
+ {% endhighlight %}
68
+
69
+ {% endexample %}
70
+
71
+ To run XD.R.Y., open a Terminal, cd to your project folder and execute `xdry`:
72
+
73
+ cd ~/Documents/HelloWorld
74
+ xdry
75
+
76
+
77
+ Automatic Changes
78
+ -----------------
79
+
80
+ Without any instructions from your side, XD.R.Y. automatically applies the following
81
+ changes:
82
+
83
+ * Adds missing release calls to `dealloc` methods:
84
+
85
+ {% example %}
86
+
87
+ {% highlight objc %}
88
+ @interface Foo {
89
+ NSString *value;
90
+ }
91
+ @end
92
+
93
+ @implementation Foo
94
+ @end
95
+ {% endhighlight %}
96
+
97
+ {% highlight objc %}
98
+ @interface Foo {
99
+ NSString *value;
100
+ }
101
+ @end
102
+
103
+ @implementation Foo
104
+
105
+ - (void)dealloc {
106
+ [value release], value = nil;
107
+ [super dealloc];
108
+ }
109
+
110
+ @end
111
+ {% endhighlight %}
112
+
113
+ {% endexample %}
114
+
115
+ * Adds missing `@synthesize` declarations for properties with no explicit accessor methods:
116
+
117
+ {% example %}
118
+
119
+ {% highlight objc %}
120
+ @interface Foo {
121
+ NSString *value;
122
+ }
123
+
124
+ @property(nonatomic, copy) NSString *value;
125
+
126
+ @end
127
+
128
+ @implementation Foo
129
+ @end
130
+ {% endhighlight %}
131
+
132
+ {% highlight objc %}
133
+ @interface Foo {
134
+ NSString *value;
135
+ }
136
+
137
+ @property(nonatomic, copy) NSString *value;
138
+
139
+ @end
140
+
141
+ @implementation Foo
142
+
143
+ @synthesize value;
144
+
145
+ @end
146
+ {% endhighlight %}
147
+
148
+ {% endexample %}
149
+
150
+ * Adds missing fields for declared properties:
151
+
152
+ {% example %}
153
+
154
+ {% highlight objc %}
155
+ @interface Foo {
156
+ }
157
+
158
+ @property(nonatomic, copy) NSString *value;
159
+
160
+ @end
161
+ {% endhighlight %}
162
+
163
+ {% highlight objc %}
164
+ @interface Foo {
165
+ NSString *value;
166
+ }
167
+
168
+ @property(nonatomic, copy) NSString *value;
169
+
170
+ @end
171
+ {% endhighlight %}
172
+
173
+ {% endexample %}
174
+
175
+
176
+
177
+ Properties, Fields, Constructors
178
+ --------------------------------
179
+
180
+ `!p` — generate a property for the given field:
181
+
182
+ {% example %}
183
+
184
+ {% highlight objc %}
185
+ @interface Foo {
186
+ Bar *value; !p
187
+ }
188
+
189
+ @end
190
+
191
+ @implementation Foo
192
+ @end
193
+ {% endhighlight %}
194
+
195
+ {% highlight objc %}
196
+ @interface Foo {
197
+ Bar *value;
198
+ }
199
+
200
+ @property(nonatomic, retain) Bar *value;
201
+
202
+ @end
203
+
204
+ @implementation Foo
205
+
206
+ @synthesize value;
207
+
208
+ - (void)dealloc {
209
+ [value release], value = nil;
210
+ [super dealloc];
211
+ }
212
+
213
+ @end
214
+ {% endhighlight %}
215
+
216
+ {% endexample %}
217
+
218
+
219
+
220
+ `!c` — generate an initializing constructor for the given field(s):
221
+
222
+ {% example %}
223
+
224
+ {% highlight objc %}
225
+ @interface Foo {
226
+ NSString *_something; !c
227
+ }
228
+ @end
229
+
230
+ @implementation Foo
231
+ @end
232
+ {% endhighlight %}
233
+
234
+ {% highlight objc %}
235
+ @interface Foo {
236
+ NSString *_something;
237
+ }
238
+
239
+ - (id)initWithSomething:(NSString *)something;
240
+
241
+ @end
242
+
243
+ @implementation Foo
244
+
245
+ - (id)initWithSomething:(NSString *)something {
246
+ if (self = [super init]) {
247
+ _something = [something copy];
248
+ }
249
+ return self;
250
+ }
251
+
252
+ @end
253
+ {% endhighlight %}
254
+
255
+ {% endexample %}
256
+
257
+
258
+ Dictionary Coding
259
+ -----------------
260
+
261
+ XD.R.Y. can generate `initWithDictionary:(NSDictionary *)dictionary` method, useful for loading objects from a plist. Similarly, an `(NSDictionary *)dictionaryRepresentation` method is generated to produce a plist-friendly dictionary from an object.
262
+
263
+ `// persistent` marks a block of fields to read from a dictionary / serialize into a dictionary:
264
+
265
+ {% example %}
266
+
267
+ {% highlight objc %}
268
+ @interface Foo {
269
+ // persistent
270
+ NSString *_something;
271
+ }
272
+ @end
273
+
274
+ @implementation Foo
275
+ @end
276
+ {% endhighlight %}
277
+
278
+ {% highlight objc %}
279
+ @interface Foo {
280
+ // persistent
281
+ NSString *_something;
282
+ }
283
+ @end
284
+
285
+ #define SomethingKey @"Something"
286
+
287
+ @implementation Foo
288
+
289
+ - (id)initWithDictionary:(NSDictionary *)dictionary {
290
+ if (self = [super init]) {
291
+ id somethingRaw = [dictionary objectForKey:SomethingKey];
292
+ if (somethingRaw != nil) {
293
+ _something = [somethingRaw copy];
294
+ }
295
+ }
296
+ return self;
297
+ }
298
+
299
+ - (NSDictionary *)dictionaryRepresentation {
300
+ NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
301
+ [dictionary setObject:_something forKey:SomethingKey];
302
+ return dictionary;
303
+ }
304
+
305
+ @end
306
+ {% endhighlight %}
307
+
308
+ {% endexample %}
309
+
310
+ To correctly handle serialization and deserialization of arrays,
311
+ you need to hint XD.R.Y. about the item type:
312
+
313
+ {% example %}
314
+
315
+ {% highlight objc %}
316
+ @interface Foo {
317
+ // persistent
318
+ NSArray *_bars; // of Bar
319
+ }
320
+ @end
321
+
322
+ @implementation Foo
323
+ @end
324
+ {% endhighlight %}
325
+
326
+ {% highlight objc %}
327
+ @interface Foo {
328
+ // persistent
329
+ NSArray *_bars; // of Bar
330
+ }
331
+ @end
332
+
333
+ @implementation Foo
334
+ #define BarsKey @"Bars"
335
+
336
+ @implementation Foo
337
+
338
+ - (id)initWithDictionary:(NSDictionary *)dictionary {
339
+ if (self = [super init]) {
340
+ id barsRaw = [dictionary objectForKey:BarsKey];
341
+ if (barsRaw != nil) {
342
+ NSMutableArray *barsArray = [[NSMutableArray alloc] init];
343
+ for (NSDictionary *barsItemDict in (NSArray *) barsRaw) {
344
+ Bar *barsItem = [[Bar alloc] initWithDictionary:barsItemDict];
345
+ [barsArray addObject:barsItem];
346
+ [barsItem release];
347
+ }
348
+ _bars = barsArray;
349
+ }
350
+ }
351
+ return self;
352
+ }
353
+
354
+ - (NSDictionary *)dictionaryRepresentation {
355
+ NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
356
+ NSMutableArray *barsArray = [NSMutableArray array];
357
+ for (Bar *barsItem in _bars) {
358
+ [barsArray addObject:[barsItem dictionaryRepresentation]];
359
+ }
360
+ [dictionary setObject:barsArray forKey:BarsKey];
361
+ return dictionary;
362
+ }
363
+
364
+ - (void)dealloc {
365
+ [_bars release], _bars = nil;
366
+ [super dealloc];
367
+ }
368
+
369
+ @end
370
+ {% endhighlight %}
371
+
372
+ {% endexample %}
373
+
374
+
375
+
376
+ License and Authors
377
+ -------------------
378
+
379
+ Copyright 2010–2011, Andrey Tarantsov.
380
+
381
+ Distributed under the MIT license, see LICENSE file for details.
382
+
383
+
384
+ Contributing
385
+ ------------
386
+
387
+ Fork the source on GitHub: [http://github.com/andreyvit/xdry](http://github.com/andreyvit/xdry).
388
+
389
+ Add a test, make a change, verify that all tests pass, update the docs in site/index.md, send me a pull request.
390
+
391
+ Testing prerequisites:
392
+
393
+ sudo gem install rake rspec diff-lcs
394
+
395
+ The simplest way to run the tests:
396
+
397
+ rake
398
+
399
+ Get a nice colorful table with test results:
400
+
401
+ rspec -b -c -fd .
402
+
403
+ When something goes wrong, you want a verbose output:
404
+
405
+ VERBOSE=1 rake
406
+
407
+ Site (documentation) prerequisites:
408
+
409
+ sudo gem install jekyll
410
+ sudo easy_install Pygments
411
+
412
+ Regenerate the site using:
413
+
414
+ rake site:build
415
+
416
+ (open site/_site/index.html to view the results).
417
+ Don't bother with gh-pages branch.