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
data/site/master.css ADDED
@@ -0,0 +1,94 @@
1
+ /* @override file:///Users/andreyvit/Dropbox/projects/active/xdry/site/_site/master.css */
2
+
3
+ * { margin: 0px; padding: 0px; }
4
+
5
+ #container { margin: 0 auto; width: 900px; }
6
+
7
+ body { margin: 50px 20px; font: 16px 'PT Serif', arial, sans-serif; line-height: 24px; background: #fff; color: #222; }
8
+
9
+ h1, h2 { font-family: 'Pacifico', arial, sans-serif; color: #333; }
10
+ h1 { font-size: 40px; margin: 0px 0px 40px; line-height: 56px; }
11
+ h2 { font-size: 24px; margin: 30px 0px 0px; line-height: 42px; }
12
+
13
+ p { margin: 10px 0px 0px; }
14
+
15
+ ul { margin: 10px 0px; }
16
+ li { list-style-position: inside; }
17
+
18
+ pre { background: #f0f0ff; border: 1px solid #000; padding: 12px 20px; font: 14px Monaco, Menlo, monospace; line-height: 15px; }
19
+ pre, .highlight { margin: 20px 0px; }
20
+ .highlight pre { margin: 0px; }
21
+
22
+ a { color: #222; }
23
+ a:visited { color: #666; }
24
+ a:hover { color: #000; }
25
+
26
+ .example { }
27
+ .example:after { content: ""; display: block; clear: both; }
28
+ .example .highlight { float: left; width: 380px; margin-right: 10px; }
29
+ .example .highlight + .highlight { width: 510px; margin-right: 0px; }
30
+ .example .highlight:before { content: "Before"; font-size: 13px; line-height: 12px; }
31
+ .example .highlight + .highlight:before { content: "After"; }
32
+ .example pre { font-size: 12px; padding: 12px 10px; }
33
+ ul + .example .highlight { margin-top: 0px; }
34
+
35
+ .highlight { background: #ffffff; }
36
+ .highlight .c { color: #999988; font-style: italic } /* Comment */
37
+ /* .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
38
+ .highlight .k { font-weight: bold } /* Keyword */
39
+ .highlight .o { font-weight: bold } /* Operator */
40
+ .highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
41
+ .highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
42
+ .highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
43
+ .highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
44
+ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
45
+ .highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
46
+ .highlight .ge { font-style: italic } /* Generic.Emph */
47
+ .highlight .gr { color: #aa0000 } /* Generic.Error */
48
+ .highlight .gh { color: #999999 } /* Generic.Heading */
49
+ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
50
+ .highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
51
+ .highlight .go { color: #888888 } /* Generic.Output */
52
+ .highlight .gp { color: #555555 } /* Generic.Prompt */
53
+ .highlight .gs { font-weight: bold } /* Generic.Strong */
54
+ .highlight .gu { color: #aaaaaa } /* Generic.Subheading */
55
+ .highlight .gt { color: #aa0000 } /* Generic.Traceback */
56
+ .highlight .kc { font-weight: bold } /* Keyword.Constant */
57
+ .highlight .kd { font-weight: bold } /* Keyword.Declaration */
58
+ .highlight .kp { font-weight: bold } /* Keyword.Pseudo */
59
+ .highlight .kr { font-weight: bold } /* Keyword.Reserved */
60
+ .highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
61
+ .highlight .m { color: #009999 } /* Literal.Number */
62
+ .highlight .s { color: #d14 } /* Literal.String */
63
+ .highlight .na { color: #008080 } /* Name.Attribute */
64
+ .highlight .nb { color: #0086B3 } /* Name.Builtin */
65
+ .highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
66
+ .highlight .no { color: #008080 } /* Name.Constant */
67
+ .highlight .ni { color: #800080 } /* Name.Entity */
68
+ .highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
69
+ .highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
70
+ .highlight .nn { color: #555555 } /* Name.Namespace */
71
+ .highlight .nt { color: #000080 } /* Name.Tag */
72
+ .highlight .nv { color: #008080 } /* Name.Variable */
73
+ .highlight .ow { font-weight: bold } /* Operator.Word */
74
+ .highlight .w { color: #bbbbbb } /* Text.Whitespace */
75
+ .highlight .mf { color: #009999 } /* Literal.Number.Float */
76
+ .highlight .mh { color: #009999 } /* Literal.Number.Hex */
77
+ .highlight .mi { color: #009999 } /* Literal.Number.Integer */
78
+ .highlight .mo { color: #009999 } /* Literal.Number.Oct */
79
+ .highlight .sb { color: #d14 } /* Literal.String.Backtick */
80
+ .highlight .sc { color: #d14 } /* Literal.String.Char */
81
+ .highlight .sd { color: #d14 } /* Literal.String.Doc */
82
+ .highlight .s2 { color: #d14 } /* Literal.String.Double */
83
+ .highlight .se { color: #d14 } /* Literal.String.Escape */
84
+ .highlight .sh { color: #d14 } /* Literal.String.Heredoc */
85
+ .highlight .si { color: #d14 } /* Literal.String.Interpol */
86
+ .highlight .sx { color: #d14 } /* Literal.String.Other */
87
+ .highlight .sr { color: #009926 } /* Literal.String.Regex */
88
+ .highlight .s1 { color: #d14 } /* Literal.String.Single */
89
+ .highlight .ss { color: #990073 } /* Literal.String.Symbol */
90
+ .highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
91
+ .highlight .vc { color: #008080 } /* Name.Variable.Class */
92
+ .highlight .vg { color: #008080 } /* Name.Variable.Global */
93
+ .highlight .vi { color: #008080 } /* Name.Variable.Instance */
94
+ .highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
@@ -0,0 +1,80 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "boxing support" do
4
+
5
+ def box expected
6
+ expected = remove_common_indent(expected)
7
+ unless expected.lines.first.strip =~ %r,^- \(id\)box:\(([^)]+)\)(\w+) \{$,
8
+ raise StandardError, "Invalid first line: #{expected.lines.first}"
9
+ end
10
+ type_string, var_name = $1.strip, $2.strip
11
+ type = XDry::VarType.parse(type_string)
12
+ raise "Invalid variable type '#{type_string}'" if type.nil?
13
+ boxer = XDry::Boxing.converter_for(type)
14
+ raise "No boxer available for variable type '#{type_string}'" if boxer.nil?
15
+ lines = XDry::Emitter.capture do |o|
16
+ o.block "- (id)box:(#{type.to_s})#{var_name}" do
17
+ o << "return " + boxer.box(o, var_name, "#{var_name}fix") + ";"
18
+ end
19
+ end
20
+ result = lines.join("\n").gsub("\t", " ")
21
+ result.strip.should == expected.strip
22
+ end
23
+
24
+ it "should box NSString verbatim" do
25
+ box <<-END
26
+ - (id)box:(NSString *)foo {
27
+ return foo;
28
+ }
29
+ END
30
+ end
31
+
32
+ it "should box int via NSNumber" do
33
+ box <<-END
34
+ - (id)box:(int)foo {
35
+ return [NSNumber numberWithInt:foo];
36
+ }
37
+ END
38
+ end
39
+
40
+ it "should box NSInteger via NSNumber" do
41
+ box <<-END
42
+ - (id)box:(NSInteger)foo {
43
+ return [NSNumber numberWithInteger:foo];
44
+ }
45
+ END
46
+ end
47
+
48
+ it "should box float via NSNumber" do
49
+ box <<-END
50
+ - (id)box:(float)foo {
51
+ return [NSNumber numberWithFloat:foo];
52
+ }
53
+ END
54
+ end
55
+
56
+ it "should box double via NSNumber" do
57
+ box <<-END
58
+ - (id)box:(double)foo {
59
+ return [NSNumber numberWithDouble:foo];
60
+ }
61
+ END
62
+ end
63
+
64
+ it "should box NSTimeInterval as double via NSNumber" do
65
+ box <<-END
66
+ - (id)box:(NSTimeInterval)foo {
67
+ return [NSNumber numberWithDouble:foo];
68
+ }
69
+ END
70
+ end
71
+
72
+ it "should box CGFloat as float via NSNumber" do
73
+ box <<-END
74
+ - (id)box:(CGFloat)foo {
75
+ return [NSNumber numberWithFloat:foo];
76
+ }
77
+ END
78
+ end
79
+
80
+ end
@@ -0,0 +1,251 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "constructor from fields generator" do
4
+
5
+ it "should add a constructor for NSString *_something field marked with a full-line marker" do
6
+ xdry :ctor_from_field, <<-END
7
+ @interface Foo {
8
+ - !c
9
+ NSString *_something;
10
+ }
11
+
12
+ + - (id)initWithSomething:(NSString *)something;
13
+ +
14
+ @end
15
+
16
+ @implementation Foo
17
+ +
18
+ + - (id)initWithSomething:(NSString *)something {
19
+ + if (self = [super init]) {
20
+ + _something = [something copy];
21
+ + }
22
+ + return self;
23
+ + }
24
+
25
+ @end
26
+ END
27
+ end
28
+
29
+ it "should add a constructor for NSString *_something field marked with an inline marker" do
30
+ xdry :ctor_from_field, <<-END
31
+ @interface Foo {
32
+ - NSString *_something; !c
33
+ + NSString *_something;
34
+ }
35
+
36
+ + - (id)initWithSomething:(NSString *)something;
37
+ +
38
+ @end
39
+
40
+ @implementation Foo
41
+ +
42
+ + - (id)initWithSomething:(NSString *)something {
43
+ + if (self = [super init]) {
44
+ + _something = [something copy];
45
+ + }
46
+ + return self;
47
+ + }
48
+
49
+ @end
50
+ END
51
+ end
52
+
53
+ it "should do nothing when a constructor already exists" do
54
+ xdry :ctor_from_field, <<-END
55
+ @interface Foo {
56
+ - NSString *_something; !c
57
+ + NSString *_something;
58
+ }
59
+
60
+ - (id)initWithSomething:(NSString *)something;
61
+
62
+ @end
63
+
64
+ @implementation Foo
65
+
66
+ - (id)initWithSomething:(NSString *)something {
67
+ if (self = [super init]) {
68
+ _something = [something copy];
69
+ }
70
+ return self;
71
+ }
72
+
73
+ @end
74
+ END
75
+ end
76
+
77
+ it "should add a missing interface declaration when an implementation already exists" do
78
+ xdry :ctor_from_field, <<-END
79
+ @interface Foo {
80
+ - NSString *_something; !c
81
+ + NSString *_something;
82
+ }
83
+ +
84
+ + - (id)initWithSomething:(NSString *)something;
85
+
86
+ @end
87
+
88
+ @implementation Foo
89
+
90
+ - (id)initWithSomething:(NSString *)something {
91
+ if (self = [super init]) {
92
+ _something = [something copy];
93
+ }
94
+ return self;
95
+ }
96
+
97
+ @end
98
+ END
99
+ end
100
+
101
+ it "should add a missing implementation when an interface declaration already exists" do
102
+ xdry :ctor_from_field, <<-END
103
+ @interface Foo {
104
+ - NSString *_something; !c
105
+ + NSString *_something;
106
+ }
107
+
108
+ - (id)initWithSomething:(NSString *)something;
109
+
110
+ @end
111
+
112
+ @implementation Foo
113
+ +
114
+ + - (id)initWithSomething:(NSString *)something {
115
+ + if (self = [super init]) {
116
+ + _something = [something copy];
117
+ + }
118
+ + return self;
119
+ + }
120
+
121
+ @end
122
+ END
123
+ end
124
+
125
+ it "should use aSomething as arg name if a field is not prefixed" do
126
+ xdry :ctor_from_field, <<-END
127
+ @interface Foo {
128
+ - NSString *something; !c
129
+ + NSString *something;
130
+ }
131
+
132
+ + - (id)initWithSomething:(NSString *)something;
133
+ +
134
+ @end
135
+
136
+ @implementation Foo
137
+ +
138
+ + - (id)initWithSomething:(NSString *)aSomething {
139
+ + if (self = [super init]) {
140
+ + something = [aSomething copy];
141
+ + }
142
+ + return self;
143
+ + }
144
+
145
+ @end
146
+ END
147
+ end
148
+
149
+ it "should use 'an' prefix if an unprefixed field name starts with a vowel" do
150
+ xdry :ctor_from_field, <<-END
151
+ @interface Foo {
152
+ - NSString *apple; !c
153
+ + NSString *apple;
154
+ }
155
+
156
+ + - (id)initWithApple:(NSString *)apple;
157
+ +
158
+ @end
159
+
160
+ @implementation Foo
161
+ +
162
+ + - (id)initWithApple:(NSString *)anApple {
163
+ + if (self = [super init]) {
164
+ + apple = [anApple copy];
165
+ + }
166
+ + return self;
167
+ + }
168
+
169
+ @end
170
+ END
171
+ end
172
+
173
+ it "should add a missing assignment to an already defined implementation" do
174
+ xdry :ctor_from_field, <<-END
175
+ @interface Foo {
176
+ - NSString *something; !c
177
+ + NSString *something;
178
+ }
179
+
180
+ - (id)initWithSomething:(NSString *)something;
181
+
182
+ @end
183
+
184
+ @implementation Foo
185
+
186
+ - (id)initWithSomething:(NSString *)aSomething {
187
+ if (self = [super init]) {
188
+ + something = [aSomething copy];
189
+ }
190
+ return self;
191
+ }
192
+
193
+ @end
194
+ END
195
+ end
196
+
197
+ it "should use self->something if the arg name == field name in an already defined implementation" do
198
+ xdry :ctor_from_field, <<-END
199
+ @interface Foo {
200
+ - NSString *something; !c
201
+ + NSString *something;
202
+ }
203
+
204
+ - (id)initWithSomething:(NSString *)something;
205
+
206
+ @end
207
+
208
+ @implementation Foo
209
+
210
+ - (id)initWithSomething:(NSString *)something {
211
+ if (self = [super init]) {
212
+ + self->something = [something copy];
213
+ }
214
+ return self;
215
+ }
216
+
217
+ @end
218
+ END
219
+ end
220
+
221
+ it "should add a constructor for several fields" do
222
+ xdry :ctor_from_field, <<-END
223
+ @interface Foo {
224
+ - NSString *_foo; !c
225
+ - NSInteger _bar; !c
226
+ - Boz *_boz; !c
227
+ + NSString *_foo;
228
+ + NSInteger _bar;
229
+ + Boz *_boz;
230
+ }
231
+
232
+ + - (id)initWithFoo:(NSString *)foo bar:(NSInteger)bar boz:(Boz *)boz;
233
+ +
234
+ @end
235
+
236
+ @implementation Foo
237
+ +
238
+ + - (id)initWithFoo:(NSString *)foo bar:(NSInteger)bar boz:(Boz *)boz {
239
+ + if (self = [super init]) {
240
+ + _foo = [foo copy];
241
+ + _bar = bar;
242
+ + _boz = [boz retain];
243
+ + }
244
+ + return self;
245
+ + }
246
+
247
+ @end
248
+ END
249
+ end
250
+
251
+ end
@@ -0,0 +1,103 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "dealloc support" do
4
+
5
+ it "should add missing release calls to dealloc" do
6
+ xdry :dealloc, <<-END
7
+ @interface Foo {
8
+ NSString *something;
9
+ }
10
+ @end
11
+
12
+ @implementation Foo
13
+
14
+ - (void)dealloc {
15
+ + [something release], something = nil;
16
+ [super dealloc];
17
+ }
18
+
19
+ @end
20
+ END
21
+ end
22
+
23
+ it "shouldn't add release calls that already exist" do
24
+ xdry :dealloc, <<-END
25
+ @interface Foo {
26
+ NSString *something;
27
+ NSString *somethingElse;
28
+ }
29
+ @end
30
+
31
+ @implementation Foo
32
+
33
+ - (void)dealloc {
34
+ [something release];
35
+ + [somethingElse release], somethingElse = nil;
36
+ [super dealloc];
37
+ }
38
+
39
+ @end
40
+ END
41
+ end
42
+
43
+ it "shouldn't add anything if all calls already exist" do
44
+ xdry :dealloc, <<-END
45
+ @interface Foo {
46
+ NSString *something;
47
+ NSString *somethingElse;
48
+ }
49
+ @end
50
+
51
+ @implementation Foo
52
+
53
+ - (void)dealloc {
54
+ [something release];
55
+ [somethingElse release], somethingElse = nil;
56
+ [super dealloc];
57
+ }
58
+
59
+ @end
60
+ END
61
+ end
62
+
63
+ it "should detect self.foo = nil as a release call" do
64
+ xdry :dealloc, <<-END
65
+ @interface Foo {
66
+ NSString *something;
67
+ NSString *somethingElse;
68
+ }
69
+ @end
70
+
71
+ @implementation Foo
72
+
73
+ - (void)dealloc {
74
+ self.something = nil;
75
+ + [somethingElse release], somethingElse = nil;
76
+ [super dealloc];
77
+ }
78
+
79
+ @end
80
+ END
81
+ end
82
+
83
+ it "should add dealloc if it does not exist" do
84
+ xdry :dealloc, <<-END
85
+ @interface Foo {
86
+ NSString *something;
87
+ NSString *somethingElse;
88
+ }
89
+ @end
90
+
91
+ @implementation Foo
92
+ +
93
+ + - (void)dealloc {
94
+ + [something release], something = nil;
95
+ + [somethingElse release], somethingElse = nil;
96
+ + [super dealloc];
97
+ + }
98
+ +
99
+ @end
100
+ END
101
+ end
102
+
103
+ end