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
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