ruby-contract 0.1.1
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.
- data/COPYING +56 -0
- data/Manifest +85 -0
- data/README +32 -0
- data/TODO +83 -0
- data/doc/classes/Contract.html +599 -0
- data/doc/classes/Contract/Check.html +229 -0
- data/doc/classes/Contract/Check/All.html +172 -0
- data/doc/classes/Contract/Check/Any.html +172 -0
- data/doc/classes/Contract/Check/Block.html +172 -0
- data/doc/classes/Contract/Check/None.html +173 -0
- data/doc/classes/Contract/Check/Quack.html +172 -0
- data/doc/classes/Contract/ContractError.html +151 -0
- data/doc/classes/Contract/ContractException.html +162 -0
- data/doc/classes/Contract/ContractMismatch.html +134 -0
- data/doc/classes/Kernel.html +256 -0
- data/doc/classes/Method.html +135 -0
- data/doc/classes/MethodSignatureMixin.html +208 -0
- data/doc/classes/Module.html +526 -0
- data/doc/created.rid +1 -0
- data/doc/dot/f_0.dot +14 -0
- data/doc/dot/f_0.png +0 -0
- data/doc/dot/f_1.dot +14 -0
- data/doc/dot/f_1.png +0 -0
- data/doc/dot/f_2.dot +14 -0
- data/doc/dot/f_2.png +0 -0
- data/doc/dot/f_3.dot +112 -0
- data/doc/dot/f_3.png +0 -0
- data/doc/dot/f_4.dot +62 -0
- data/doc/dot/f_4.png +0 -0
- data/doc/dot/f_5.dot +62 -0
- data/doc/dot/f_5.png +0 -0
- data/doc/dot/f_6.dot +224 -0
- data/doc/dot/f_6.png +0 -0
- data/doc/dot/f_6_0.dot +24 -0
- data/doc/dot/f_6_0.png +0 -0
- data/doc/dot/f_6_1.dot +24 -0
- data/doc/dot/f_6_1.png +0 -0
- data/doc/dot/f_7.dot +62 -0
- data/doc/dot/f_7.png +0 -0
- data/doc/files/COPYING.html +168 -0
- data/doc/files/README.html +146 -0
- data/doc/files/TODO.html +240 -0
- data/doc/files/lib/contract/assertions_rb.html +118 -0
- data/doc/files/lib/contract/exception_rb.html +125 -0
- data/doc/files/lib/contract/integration_rb.html +130 -0
- data/doc/files/lib/contract/overrides_rb.html +118 -0
- data/doc/files/lib/contract_rb.html +127 -0
- data/doc/fr_class_index.html +40 -0
- data/doc/fr_file_index.html +34 -0
- data/doc/fr_method_index.html +45 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/contract.rb +146 -0
- data/lib/contract/assertions.rb +42 -0
- data/lib/contract/exception.rb +95 -0
- data/lib/contract/integration.rb +664 -0
- data/lib/contract/overrides.rb +41 -0
- data/setup.rb +1360 -0
- data/test/coverage/_-lib-contract-assertions_rb.html +526 -0
- data/test/coverage/_-lib-contract-exception_rb.html +632 -0
- data/test/coverage/_-lib-contract-integration_rb.html +1450 -0
- data/test/coverage/_-lib-contract-overrides_rb.html +524 -0
- data/test/coverage/_-lib-contract_rb.html +724 -0
- data/test/coverage/__-lib-contract-assertions_rb.html +484 -0
- data/test/coverage/__-lib-contract-exception_rb.html +537 -0
- data/test/coverage/__-lib-contract-integration_rb.html +946 -0
- data/test/coverage/__-lib-contract-overrides_rb.html +483 -0
- data/test/coverage/__-lib-contract_rb.html +583 -0
- data/test/coverage/index.html +93 -0
- data/test/tc_all.rb +8 -0
- data/test/tc_contract.rb +109 -0
- data/test/tc_exception.rb +43 -0
- data/test/tc_integration.rb +357 -0
- metadata +136 -0
@@ -0,0 +1,946 @@
|
|
1
|
+
<?xml version="1.0" encoding="ISO-8859-15"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
3
|
+
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
5
|
+
<head><title>../lib/contract/integration.rb - coverage</title>
|
6
|
+
<style type="text/css">body {
|
7
|
+
background-color: rgb(180, 180, 180);
|
8
|
+
}
|
9
|
+
span.marked {
|
10
|
+
background-color: rgb(185, 200, 200);
|
11
|
+
display: block;
|
12
|
+
}
|
13
|
+
span.inferred {
|
14
|
+
background-color: rgb(180, 195, 195);
|
15
|
+
display: block;
|
16
|
+
}
|
17
|
+
span.run0 {
|
18
|
+
background-color: rgb(178, 204, 255);
|
19
|
+
display: block;
|
20
|
+
}
|
21
|
+
span.run1 {
|
22
|
+
background-color: rgb(178, 206, 255);
|
23
|
+
display: block;
|
24
|
+
}
|
25
|
+
span.run2 {
|
26
|
+
background-color: rgb(178, 209, 255);
|
27
|
+
display: block;
|
28
|
+
}
|
29
|
+
span.run3 {
|
30
|
+
background-color: rgb(178, 211, 255);
|
31
|
+
display: block;
|
32
|
+
}
|
33
|
+
span.run4 {
|
34
|
+
background-color: rgb(178, 214, 255);
|
35
|
+
display: block;
|
36
|
+
}
|
37
|
+
span.run5 {
|
38
|
+
background-color: rgb(178, 218, 255);
|
39
|
+
display: block;
|
40
|
+
}
|
41
|
+
span.run6 {
|
42
|
+
background-color: rgb(178, 220, 255);
|
43
|
+
display: block;
|
44
|
+
}
|
45
|
+
span.run7 {
|
46
|
+
background-color: rgb(178, 223, 255);
|
47
|
+
display: block;
|
48
|
+
}
|
49
|
+
span.run8 {
|
50
|
+
background-color: rgb(178, 225, 255);
|
51
|
+
display: block;
|
52
|
+
}
|
53
|
+
span.run9 {
|
54
|
+
background-color: rgb(178, 228, 255);
|
55
|
+
display: block;
|
56
|
+
}
|
57
|
+
span.run10 {
|
58
|
+
background-color: rgb(178, 232, 255);
|
59
|
+
display: block;
|
60
|
+
}
|
61
|
+
span.run11 {
|
62
|
+
background-color: rgb(178, 234, 255);
|
63
|
+
display: block;
|
64
|
+
}
|
65
|
+
span.run12 {
|
66
|
+
background-color: rgb(178, 237, 255);
|
67
|
+
display: block;
|
68
|
+
}
|
69
|
+
span.run13 {
|
70
|
+
background-color: rgb(178, 239, 255);
|
71
|
+
display: block;
|
72
|
+
}
|
73
|
+
span.run14 {
|
74
|
+
background-color: rgb(178, 242, 255);
|
75
|
+
display: block;
|
76
|
+
}
|
77
|
+
span.run15 {
|
78
|
+
background-color: rgb(178, 246, 255);
|
79
|
+
display: block;
|
80
|
+
}
|
81
|
+
span.run16 {
|
82
|
+
background-color: rgb(178, 248, 255);
|
83
|
+
display: block;
|
84
|
+
}
|
85
|
+
span.run17 {
|
86
|
+
background-color: rgb(178, 251, 255);
|
87
|
+
display: block;
|
88
|
+
}
|
89
|
+
span.run18 {
|
90
|
+
background-color: rgb(178, 253, 255);
|
91
|
+
display: block;
|
92
|
+
}
|
93
|
+
span.run19 {
|
94
|
+
background-color: rgb(178, 255, 253);
|
95
|
+
display: block;
|
96
|
+
}
|
97
|
+
span.run20 {
|
98
|
+
background-color: rgb(178, 255, 249);
|
99
|
+
display: block;
|
100
|
+
}
|
101
|
+
span.run21 {
|
102
|
+
background-color: rgb(178, 255, 247);
|
103
|
+
display: block;
|
104
|
+
}
|
105
|
+
span.run22 {
|
106
|
+
background-color: rgb(178, 255, 244);
|
107
|
+
display: block;
|
108
|
+
}
|
109
|
+
span.run23 {
|
110
|
+
background-color: rgb(178, 255, 242);
|
111
|
+
display: block;
|
112
|
+
}
|
113
|
+
span.run24 {
|
114
|
+
background-color: rgb(178, 255, 239);
|
115
|
+
display: block;
|
116
|
+
}
|
117
|
+
span.run25 {
|
118
|
+
background-color: rgb(178, 255, 235);
|
119
|
+
display: block;
|
120
|
+
}
|
121
|
+
span.run26 {
|
122
|
+
background-color: rgb(178, 255, 233);
|
123
|
+
display: block;
|
124
|
+
}
|
125
|
+
span.run27 {
|
126
|
+
background-color: rgb(178, 255, 230);
|
127
|
+
display: block;
|
128
|
+
}
|
129
|
+
span.run28 {
|
130
|
+
background-color: rgb(178, 255, 228);
|
131
|
+
display: block;
|
132
|
+
}
|
133
|
+
span.run29 {
|
134
|
+
background-color: rgb(178, 255, 225);
|
135
|
+
display: block;
|
136
|
+
}
|
137
|
+
span.run30 {
|
138
|
+
background-color: rgb(178, 255, 221);
|
139
|
+
display: block;
|
140
|
+
}
|
141
|
+
span.run31 {
|
142
|
+
background-color: rgb(178, 255, 219);
|
143
|
+
display: block;
|
144
|
+
}
|
145
|
+
span.run32 {
|
146
|
+
background-color: rgb(178, 255, 216);
|
147
|
+
display: block;
|
148
|
+
}
|
149
|
+
span.run33 {
|
150
|
+
background-color: rgb(178, 255, 214);
|
151
|
+
display: block;
|
152
|
+
}
|
153
|
+
span.run34 {
|
154
|
+
background-color: rgb(178, 255, 211);
|
155
|
+
display: block;
|
156
|
+
}
|
157
|
+
span.run35 {
|
158
|
+
background-color: rgb(178, 255, 207);
|
159
|
+
display: block;
|
160
|
+
}
|
161
|
+
span.run36 {
|
162
|
+
background-color: rgb(178, 255, 205);
|
163
|
+
display: block;
|
164
|
+
}
|
165
|
+
span.run37 {
|
166
|
+
background-color: rgb(178, 255, 202);
|
167
|
+
display: block;
|
168
|
+
}
|
169
|
+
span.run38 {
|
170
|
+
background-color: rgb(178, 255, 200);
|
171
|
+
display: block;
|
172
|
+
}
|
173
|
+
span.run39 {
|
174
|
+
background-color: rgb(178, 255, 197);
|
175
|
+
display: block;
|
176
|
+
}
|
177
|
+
span.run40 {
|
178
|
+
background-color: rgb(178, 255, 193);
|
179
|
+
display: block;
|
180
|
+
}
|
181
|
+
span.run41 {
|
182
|
+
background-color: rgb(178, 255, 191);
|
183
|
+
display: block;
|
184
|
+
}
|
185
|
+
span.run42 {
|
186
|
+
background-color: rgb(178, 255, 188);
|
187
|
+
display: block;
|
188
|
+
}
|
189
|
+
span.run43 {
|
190
|
+
background-color: rgb(178, 255, 186);
|
191
|
+
display: block;
|
192
|
+
}
|
193
|
+
span.run44 {
|
194
|
+
background-color: rgb(178, 255, 183);
|
195
|
+
display: block;
|
196
|
+
}
|
197
|
+
span.run45 {
|
198
|
+
background-color: rgb(178, 255, 179);
|
199
|
+
display: block;
|
200
|
+
}
|
201
|
+
span.run46 {
|
202
|
+
background-color: rgb(179, 255, 178);
|
203
|
+
display: block;
|
204
|
+
}
|
205
|
+
span.run47 {
|
206
|
+
background-color: rgb(182, 255, 178);
|
207
|
+
display: block;
|
208
|
+
}
|
209
|
+
span.run48 {
|
210
|
+
background-color: rgb(184, 255, 178);
|
211
|
+
display: block;
|
212
|
+
}
|
213
|
+
span.run49 {
|
214
|
+
background-color: rgb(187, 255, 178);
|
215
|
+
display: block;
|
216
|
+
}
|
217
|
+
span.run50 {
|
218
|
+
background-color: rgb(191, 255, 178);
|
219
|
+
display: block;
|
220
|
+
}
|
221
|
+
span.run51 {
|
222
|
+
background-color: rgb(193, 255, 178);
|
223
|
+
display: block;
|
224
|
+
}
|
225
|
+
span.run52 {
|
226
|
+
background-color: rgb(196, 255, 178);
|
227
|
+
display: block;
|
228
|
+
}
|
229
|
+
span.run53 {
|
230
|
+
background-color: rgb(198, 255, 178);
|
231
|
+
display: block;
|
232
|
+
}
|
233
|
+
span.run54 {
|
234
|
+
background-color: rgb(201, 255, 178);
|
235
|
+
display: block;
|
236
|
+
}
|
237
|
+
span.run55 {
|
238
|
+
background-color: rgb(205, 255, 178);
|
239
|
+
display: block;
|
240
|
+
}
|
241
|
+
span.run56 {
|
242
|
+
background-color: rgb(207, 255, 178);
|
243
|
+
display: block;
|
244
|
+
}
|
245
|
+
span.run57 {
|
246
|
+
background-color: rgb(210, 255, 178);
|
247
|
+
display: block;
|
248
|
+
}
|
249
|
+
span.run58 {
|
250
|
+
background-color: rgb(212, 255, 178);
|
251
|
+
display: block;
|
252
|
+
}
|
253
|
+
span.run59 {
|
254
|
+
background-color: rgb(215, 255, 178);
|
255
|
+
display: block;
|
256
|
+
}
|
257
|
+
span.run60 {
|
258
|
+
background-color: rgb(219, 255, 178);
|
259
|
+
display: block;
|
260
|
+
}
|
261
|
+
span.run61 {
|
262
|
+
background-color: rgb(221, 255, 178);
|
263
|
+
display: block;
|
264
|
+
}
|
265
|
+
span.run62 {
|
266
|
+
background-color: rgb(224, 255, 178);
|
267
|
+
display: block;
|
268
|
+
}
|
269
|
+
span.run63 {
|
270
|
+
background-color: rgb(226, 255, 178);
|
271
|
+
display: block;
|
272
|
+
}
|
273
|
+
span.run64 {
|
274
|
+
background-color: rgb(229, 255, 178);
|
275
|
+
display: block;
|
276
|
+
}
|
277
|
+
span.run65 {
|
278
|
+
background-color: rgb(233, 255, 178);
|
279
|
+
display: block;
|
280
|
+
}
|
281
|
+
span.run66 {
|
282
|
+
background-color: rgb(235, 255, 178);
|
283
|
+
display: block;
|
284
|
+
}
|
285
|
+
span.run67 {
|
286
|
+
background-color: rgb(238, 255, 178);
|
287
|
+
display: block;
|
288
|
+
}
|
289
|
+
span.run68 {
|
290
|
+
background-color: rgb(240, 255, 178);
|
291
|
+
display: block;
|
292
|
+
}
|
293
|
+
span.run69 {
|
294
|
+
background-color: rgb(243, 255, 178);
|
295
|
+
display: block;
|
296
|
+
}
|
297
|
+
span.run70 {
|
298
|
+
background-color: rgb(247, 255, 178);
|
299
|
+
display: block;
|
300
|
+
}
|
301
|
+
span.run71 {
|
302
|
+
background-color: rgb(249, 255, 178);
|
303
|
+
display: block;
|
304
|
+
}
|
305
|
+
span.run72 {
|
306
|
+
background-color: rgb(252, 255, 178);
|
307
|
+
display: block;
|
308
|
+
}
|
309
|
+
span.run73 {
|
310
|
+
background-color: rgb(255, 255, 178);
|
311
|
+
display: block;
|
312
|
+
}
|
313
|
+
span.run74 {
|
314
|
+
background-color: rgb(255, 252, 178);
|
315
|
+
display: block;
|
316
|
+
}
|
317
|
+
span.run75 {
|
318
|
+
background-color: rgb(255, 248, 178);
|
319
|
+
display: block;
|
320
|
+
}
|
321
|
+
span.run76 {
|
322
|
+
background-color: rgb(255, 246, 178);
|
323
|
+
display: block;
|
324
|
+
}
|
325
|
+
span.run77 {
|
326
|
+
background-color: rgb(255, 243, 178);
|
327
|
+
display: block;
|
328
|
+
}
|
329
|
+
span.run78 {
|
330
|
+
background-color: rgb(255, 240, 178);
|
331
|
+
display: block;
|
332
|
+
}
|
333
|
+
span.run79 {
|
334
|
+
background-color: rgb(255, 238, 178);
|
335
|
+
display: block;
|
336
|
+
}
|
337
|
+
span.run80 {
|
338
|
+
background-color: rgb(255, 234, 178);
|
339
|
+
display: block;
|
340
|
+
}
|
341
|
+
span.run81 {
|
342
|
+
background-color: rgb(255, 232, 178);
|
343
|
+
display: block;
|
344
|
+
}
|
345
|
+
span.run82 {
|
346
|
+
background-color: rgb(255, 229, 178);
|
347
|
+
display: block;
|
348
|
+
}
|
349
|
+
span.run83 {
|
350
|
+
background-color: rgb(255, 226, 178);
|
351
|
+
display: block;
|
352
|
+
}
|
353
|
+
span.run84 {
|
354
|
+
background-color: rgb(255, 224, 178);
|
355
|
+
display: block;
|
356
|
+
}
|
357
|
+
span.run85 {
|
358
|
+
background-color: rgb(255, 220, 178);
|
359
|
+
display: block;
|
360
|
+
}
|
361
|
+
span.run86 {
|
362
|
+
background-color: rgb(255, 218, 178);
|
363
|
+
display: block;
|
364
|
+
}
|
365
|
+
span.run87 {
|
366
|
+
background-color: rgb(255, 215, 178);
|
367
|
+
display: block;
|
368
|
+
}
|
369
|
+
span.run88 {
|
370
|
+
background-color: rgb(255, 212, 178);
|
371
|
+
display: block;
|
372
|
+
}
|
373
|
+
span.run89 {
|
374
|
+
background-color: rgb(255, 210, 178);
|
375
|
+
display: block;
|
376
|
+
}
|
377
|
+
span.run90 {
|
378
|
+
background-color: rgb(255, 206, 178);
|
379
|
+
display: block;
|
380
|
+
}
|
381
|
+
span.run91 {
|
382
|
+
background-color: rgb(255, 204, 178);
|
383
|
+
display: block;
|
384
|
+
}
|
385
|
+
span.run92 {
|
386
|
+
background-color: rgb(255, 201, 178);
|
387
|
+
display: block;
|
388
|
+
}
|
389
|
+
span.run93 {
|
390
|
+
background-color: rgb(255, 198, 178);
|
391
|
+
display: block;
|
392
|
+
}
|
393
|
+
span.run94 {
|
394
|
+
background-color: rgb(255, 196, 178);
|
395
|
+
display: block;
|
396
|
+
}
|
397
|
+
span.run95 {
|
398
|
+
background-color: rgb(255, 192, 178);
|
399
|
+
display: block;
|
400
|
+
}
|
401
|
+
span.run96 {
|
402
|
+
background-color: rgb(255, 189, 178);
|
403
|
+
display: block;
|
404
|
+
}
|
405
|
+
span.run97 {
|
406
|
+
background-color: rgb(255, 187, 178);
|
407
|
+
display: block;
|
408
|
+
}
|
409
|
+
span.run98 {
|
410
|
+
background-color: rgb(255, 184, 178);
|
411
|
+
display: block;
|
412
|
+
}
|
413
|
+
span.run99 {
|
414
|
+
background-color: rgb(255, 182, 178);
|
415
|
+
display: block;
|
416
|
+
}
|
417
|
+
|
418
|
+
div.overview {
|
419
|
+
border-bottom: 8px solid black;
|
420
|
+
}
|
421
|
+
</style></head>
|
422
|
+
<body><div class="overview">
|
423
|
+
<table>
|
424
|
+
<tr><td>filename</td><td><tt>../lib/contract/integration.rb</tt></td></tr>
|
425
|
+
<tr><td>total coverage</td><td>93.3</td></tr>
|
426
|
+
<tr><td>code coverage</td><td>87.9</td></tr>
|
427
|
+
</table>
|
428
|
+
</div>
|
429
|
+
<pre><span class="inferred"> 1 # This file contains code for integrating the contract library with built-in
|
430
|
+
2 # classes and methods.
|
431
|
+
3 #
|
432
|
+
4 # See Contract::Check, Module#signature and Module#fulfills.
|
433
|
+
5
|
434
|
+
6
|
435
|
+
</span><span class="marked"> 7 class Contract < Test::Unit::TestCase
|
436
|
+
</span><span class="inferred"> 8 # Implements checks that can for example be used in Module#signature
|
437
|
+
9 # specifications. They are implemented simply by overriding the === case
|
438
|
+
10 # equality operator. They can also be nested like this:
|
439
|
+
11 # # Matches something that is an Enumerable and that responds to
|
440
|
+
12 # # either :to_ary or :to_a.
|
441
|
+
13 # signature :x, Contract::Check::All[
|
442
|
+
14 # Enumerable,
|
443
|
+
15 # Contract::Check::Any[
|
444
|
+
16 # Contract::Check::Quack[:to_a],
|
445
|
+
17 # Contract::Check::Quack[:to_ary]
|
446
|
+
18 # ]
|
447
|
+
19 # ]
|
448
|
+
</span><span class="marked"> 20 module Check
|
449
|
+
</span><span class="inferred"> 21 # An abstract Base class for Contract::Check classes.
|
450
|
+
22 # Contains logic for instantation.
|
451
|
+
</span><span class="marked"> 23 class Base # :nodoc:
|
452
|
+
24 class << self
|
453
|
+
25 alias :[] :new
|
454
|
+
</span><span class="inferred"> 26 end
|
455
|
+
27
|
456
|
+
</span><span class="marked"> 28 def initialize(*args, &block)
|
457
|
+
29 @args, @block = args, block
|
458
|
+
</span><span class="inferred"> 30 end
|
459
|
+
31 end
|
460
|
+
32
|
461
|
+
33 # Checks that the specified block matches.
|
462
|
+
34 # Example:
|
463
|
+
35 # signature :x, Contract::Check.block { |arg| arg > 0 }
|
464
|
+
</span><span class="marked"> 36 class Block < Base
|
465
|
+
37 def ===(other)
|
466
|
+
38 @block.call(other)
|
467
|
+
</span><span class="inferred"> 39 end
|
468
|
+
40 end
|
469
|
+
41 # Short-cut for creating a Contract::Check::Block.
|
470
|
+
</span><span class="marked"> 42 def self.block(&block) # :yields: arg
|
471
|
+
43 Block.new(&block)
|
472
|
+
</span><span class="inferred"> 44 end
|
473
|
+
45
|
474
|
+
46 # Checks that all the specified methods are answered.
|
475
|
+
47 # Example:
|
476
|
+
48 # signature :x, Contract::Check::Quack[:to_sym]
|
477
|
+
</span><span class="marked"> 49 class Quack < Base
|
478
|
+
50 def ===(other)
|
479
|
+
51 @args.all? { |arg| other.respond_to?(arg) }
|
480
|
+
</span><span class="inferred"> 52 end
|
481
|
+
53 end
|
482
|
+
54
|
483
|
+
55 # Checks that all the specified conditions match.
|
484
|
+
56 # Example:
|
485
|
+
57 # signature :x, Contract::Check::All[Array, Enumerable]
|
486
|
+
</span><span class="marked"> 58 class All < Base
|
487
|
+
59 def ===(other)
|
488
|
+
60 @args.all? { |arg| arg === other }
|
489
|
+
</span><span class="inferred"> 61 end
|
490
|
+
62 end
|
491
|
+
63 # Alias for Contract::Check::All
|
492
|
+
</span><span class="marked"> 64 And = All
|
493
|
+
</span><span class="inferred"> 65
|
494
|
+
66 # Checks that at least one of the specified conditions match.
|
495
|
+
67 # Example:
|
496
|
+
68 # signature :x, Contract::Check::Any[String, Symbol]
|
497
|
+
</span><span class="marked"> 69 class Any < Base
|
498
|
+
70 def ===(other)
|
499
|
+
71 @args.any? { |arg| arg === other }
|
500
|
+
</span><span class="inferred"> 72 end
|
501
|
+
73 end
|
502
|
+
74 # Alias for Contract::Check::Any
|
503
|
+
</span><span class="marked"> 75 Or = Any
|
504
|
+
</span><span class="inferred"> 76
|
505
|
+
77 # Checks that none of the specified conditions match.
|
506
|
+
78 # Example:
|
507
|
+
79 # signature :x, Contract::Check::None[Numeric, Symbol]
|
508
|
+
80 # signature :x, Contract::Check::Not[Comparable]
|
509
|
+
</span><span class="marked"> 81 class None < Base
|
510
|
+
82 def ===(other)
|
511
|
+
83 not @args.any? { |arg| arg === other }
|
512
|
+
</span><span class="inferred"> 84 end
|
513
|
+
85 end
|
514
|
+
86 # Alias for Contract::Check::None
|
515
|
+
</span><span class="marked"> 87 Not = None
|
516
|
+
</span><span class="inferred"> 88 end
|
517
|
+
89
|
518
|
+
</span><span class="marked"> 90 class << self
|
519
|
+
</span><span class="inferred"> 91 # Whether signatures should be checked. By default signatures are checked
|
520
|
+
92 # only when the application is run in $DEBUG mode. (By specifying the -d
|
521
|
+
93 # switch on the invocation of Ruby.)
|
522
|
+
94 #
|
523
|
+
95 # Note: If you want to change this you need to do so before doing any
|
524
|
+
96 # Module#signature calls or it will not be applied. It's probably best
|
525
|
+
97 # set right after requiring the contract library.
|
526
|
+
</span><span class="marked"> 98 attr_accessor :check_signatures
|
527
|
+
99 alias :check_signatures? :check_signatures
|
528
|
+
</span><span class="inferred">100
|
529
|
+
101 # Whether fulfills should be checked. This is enabled by default.
|
530
|
+
102 #
|
531
|
+
103 # Note: If you want to change this you need to do so before doing any
|
532
|
+
104 # Module#fulfills calls or it will not be applied. It's probably best
|
533
|
+
105 # set right after requiring the contract library.
|
534
|
+
</span><span class="marked">106 attr_accessor :check_fulfills
|
535
|
+
107 alias :check_fulfills? :check_fulfills
|
536
|
+
</span><span class="inferred">108
|
537
|
+
109 # All adaption routes.
|
538
|
+
</span><span class="marked">110 attr_accessor :adaptions # :nodoc:
|
539
|
+
</span><span class="inferred">111 end
|
540
|
+
</span><span class="marked">112 self.check_signatures = $DEBUG if self.check_signatures.nil?
|
541
|
+
113 self.check_fulfills = true if self.check_fulfills.nil?
|
542
|
+
114 if self.adaptions.nil? then
|
543
|
+
115 self.adaptions = Hash.new { |hash, key| hash[key] = Array.new }
|
544
|
+
</span><span class="inferred">116 end
|
545
|
+
117
|
546
|
+
118 # Tries to adapt the specified object to the specified type.
|
547
|
+
119 # Returns the old object if no suitable adaption route was found or if
|
548
|
+
120 # it already is of the specified type.
|
549
|
+
121 #
|
550
|
+
122 # This will only use adaptions where the :to part is equal to the specified
|
551
|
+
123 # type. No multi-step conversion will be performed.
|
552
|
+
</span><span class="marked">124 def self.adapt(object, type)
|
553
|
+
125 return object if type === object
|
554
|
+
</span><span class="inferred">126
|
555
|
+
</span><span class="marked">127 @adaptions[type].each do |adaption|
|
556
|
+
</span><span class="false">128 if adaption[:from] === object and
|
557
|
+
</span><span class="marked">129 (adaption[:if].nil? or adaption[:if] === object)
|
558
|
+
</span><span class="false">130 then
|
559
|
+
</span><span class="marked">131 result = adaption[:via].call(object)
|
560
|
+
132 return result if type === result
|
561
|
+
</span><span class="inferred">133 end
|
562
|
+
134 end
|
563
|
+
135
|
564
|
+
</span><span class="marked">136 return object
|
565
|
+
</span><span class="inferred">137 end
|
566
|
+
138 end
|
567
|
+
139
|
568
|
+
140
|
569
|
+
</span><span class="marked">141 class Module
|
570
|
+
</span><span class="inferred">142 # Checks that the arguments and return value of a method match the specified
|
571
|
+
143 # signature. Checks are only actually done when Contract.check_signatures is
|
572
|
+
144 # set to true or if the <code>:no_adaption</code> option is +false+. The
|
573
|
+
145 # method will return +true+ in case it actually inserted the signature check
|
574
|
+
146 # logic and +nil+ in case it didn't.
|
575
|
+
147 #
|
576
|
+
148 # You will usually specify one type specifier (<code>:any</code> which will
|
577
|
+
149 # allow anything to appear at that position of the argument list or something
|
578
|
+
150 # that implements the === case equality operator -- samples are Contracts,
|
579
|
+
151 # Ranges, Classes, Modules, Regexps, Contract::Checks and so on) per argument.
|
580
|
+
152 # You can also use objects that implement the +call+ method as type specifiers
|
581
|
+
153 # which includes Methods and Procs.
|
582
|
+
154 #
|
583
|
+
155 # If you don't use the <code>:repeated</code> or <code>:allow_trailing</code>
|
584
|
+
156 # options the method will take exactly as many arguments as there are type
|
585
|
+
157 # specifiers which means that <code>signature :a_method</code> enforces
|
586
|
+
158 # +a_method+ having exactly zero arguments.
|
587
|
+
159 #
|
588
|
+
160 # The checks are done by wrapping the type checks around the method.
|
589
|
+
161 # ArgumentError exceptions will be raised in case the signature contract is
|
590
|
+
162 # not adhered to by your caller.
|
591
|
+
163 #
|
592
|
+
164 # An ArgumentError exception will be raised in case the methods natural
|
593
|
+
165 # argument list size and the signature you specified via Module.signature are
|
594
|
+
166 # incompatible. (Note that they don't have to be completely equivalent, you
|
595
|
+
167 # can still have a method taking zero or more arguments and apply a signature
|
596
|
+
168 # that limits the actual argument count to three arguments.)
|
597
|
+
169 #
|
598
|
+
170 # This method can take quite a few options. Here's a complete list:
|
599
|
+
171 #
|
600
|
+
172 # <code>:return</code>::
|
601
|
+
173 # A return type that the method must comply to. Note that this check (if
|
602
|
+
174 # failed) will actually raise a StandardError instead of an ArgumentError
|
603
|
+
175 # because the failure likely lies in the method itself and not in what the
|
604
|
+
176 # caller did.
|
605
|
+
177 #
|
606
|
+
178 # <code>:block</code>::
|
607
|
+
179 # +true+ or +false+ -- whether the method must take a block or not. So
|
608
|
+
180 # specifying <code>:block => false</code> enforces that the method is not
|
609
|
+
181 # allowed to have a block supplied.
|
610
|
+
182 #
|
611
|
+
183 # <code>:allow_trailing</code>::
|
612
|
+
184 # +true+ or +false+ -- whether the argument list may contain trailing,
|
613
|
+
185 # unchecked arguments.
|
614
|
+
186 #
|
615
|
+
187 # <code>:repeated</code>::
|
616
|
+
188 # An Array that specifies arguments of a method that will be repeated over
|
617
|
+
189 # and over again at the end of the argument list.
|
618
|
+
190 #
|
619
|
+
191 # A good sample of this are Array#values_at which takes zero or or more
|
620
|
+
192 # Numeric arguments and Enumerable#zip which takes zero or more other
|
621
|
+
193 # Enumerable arguments.
|
622
|
+
194 #
|
623
|
+
195 # Note that the Array that was associated with the <code>:repeated</code>
|
624
|
+
196 # option must not be empty or an ArgumentError exception will be raised.
|
625
|
+
197 # If there's just one repeated type you can omit the Array and directly
|
626
|
+
198 # specify the type identifier.
|
627
|
+
199 #
|
628
|
+
200 # <code>:no_adaption</code>::
|
629
|
+
201 # +true+ or +false+ -- whether no type adaption should be performed.
|
630
|
+
202 #
|
631
|
+
203 # Usage:
|
632
|
+
204 # signature(:to_s) # no arguments
|
633
|
+
205 # signature(:+, :any) # one argument, type unchecked
|
634
|
+
206 # signature(:+, Fixnum) # one argument, type Fixnum
|
635
|
+
207 # signature(:+, NumericContract)
|
636
|
+
208 # signature(:+, 1 .. 10)
|
637
|
+
209 # signature(:sqrt, lambda { |arg| arg > 0 })
|
638
|
+
210 #
|
639
|
+
211 # signature(:each, :block => true) # has to have block
|
640
|
+
212 # signature(:to_i, :block => false) # not allowed to have block
|
641
|
+
213 # signature(:to_i, :result => Fixnum) # return value must be Fixnum
|
642
|
+
214 # signature(:zip, :allow_trailing => true) # unchecked trailing args
|
643
|
+
215 # signature(:zip, :repeated => [Enumerable]) # repeated trailing args
|
644
|
+
216 # signature(:zip, :repeated => Enumerable)
|
645
|
+
217 # # foo(3, 6, 4, 7) works; foo(5), foo(3, 2) etc. don't
|
646
|
+
218 # signature(:foo, :repeated => [1..4, 5..9])
|
647
|
+
</span><span class="marked">219 def signature(method, *args)
|
648
|
+
220 options = {}
|
649
|
+
221 signature = args.dup
|
650
|
+
222 options.update(signature.pop) if signature.last.is_a?(Hash)
|
651
|
+
</span><span class="inferred">223
|
652
|
+
</span><span class="marked">224 return if not Contract.check_signatures? and options[:no_adaption]
|
653
|
+
</span><span class="inferred">225
|
654
|
+
</span><span class="marked">226 old_method = instance_method(method)
|
655
|
+
227 remove_method(method) if instance_methods(false).include?(method.to_s)
|
656
|
+
</span><span class="inferred">228
|
657
|
+
</span><span class="marked">229 arity = old_method.arity
|
658
|
+
</span><span class="false">230 if arity != signature.size and
|
659
|
+
</span><span class="marked">231 (arity >= 0 or signature.size < ~arity) then
|
660
|
+
232 raise(ArgumentError, "signature isn't compatible with arity")
|
661
|
+
</span><span class="inferred">233 end
|
662
|
+
234
|
663
|
+
235 # Normalizes specifiers to Objects that respond to === so that the run-time
|
664
|
+
236 # checks only have to deal with that case. Also checks that a specifier is
|
665
|
+
237 # actually valid.
|
666
|
+
</span><span class="marked">238 convert_specifier = lambda do |item|
|
667
|
+
</span><span class="inferred">239 # Procs, Methods etc.
|
668
|
+
</span><span class="marked">240 if item.respond_to?(:call) then
|
669
|
+
241 Contract::Check.block { |arg| item.call(arg) }
|
670
|
+
</span><span class="inferred">242 # Already okay
|
671
|
+
</span><span class="marked">243 elsif item.respond_to?(:===) or item == :any then
|
672
|
+
244 item
|
673
|
+
</span><span class="inferred">245 # Unknown specifier
|
674
|
+
246 else
|
675
|
+
</span><span class="marked">247 raise(ArgumentError, "unsupported argument specifier #{item.inspect}")
|
676
|
+
</span><span class="inferred">248 end
|
677
|
+
249 end
|
678
|
+
250
|
679
|
+
</span><span class="marked">251 signature.map!(&convert_specifier)
|
680
|
+
</span><span class="inferred">252
|
681
|
+
</span><span class="marked">253 if options.include?(:repeated) then
|
682
|
+
254 options[:repeated] = Array(options[:repeated])
|
683
|
+
255 if options[:repeated].size == 0 then
|
684
|
+
256 raise(ArgumentError, "repeated arguments may not be an empty Array")
|
685
|
+
</span><span class="inferred">257 else
|
686
|
+
</span><span class="marked">258 options[:repeated].map!(&convert_specifier)
|
687
|
+
</span><span class="inferred">259 end
|
688
|
+
260 end
|
689
|
+
261
|
690
|
+
</span><span class="marked">262 if options.include?(:return) then
|
691
|
+
263 options[:return] = convert_specifier.call(options[:return])
|
692
|
+
</span><span class="inferred">264 end
|
693
|
+
265
|
694
|
+
266 # We need to keep around references to our arguments because we will
|
695
|
+
267 # need to access them via ObjectSpace._id2ref so that they do not
|
696
|
+
268 # get garbage collected.
|
697
|
+
</span><span class="marked">269 @signatures ||= Hash.new { |hash, key| hash[key] = Array.new }
|
698
|
+
270 @signatures[method] << [signature, options, old_method]
|
699
|
+
</span><span class="inferred">271
|
700
|
+
</span><span class="marked">272 adapted = Proc.new do |obj, type, assign_to|
|
701
|
+
273 if options[:no_adaption] then
|
702
|
+
274 obj
|
703
|
+
275 elsif assign_to then
|
704
|
+
276 %{(#{assign_to} = Contract.adapt(#{obj}, #{type}))}
|
705
|
+
</span><span class="inferred">277 else
|
706
|
+
</span><span class="marked">278 %{Contract.adapt(#{obj}, #{type})}
|
707
|
+
</span><span class="inferred">279 end
|
708
|
+
280 end
|
709
|
+
281
|
710
|
+
282 # We have to use class_eval so that signatures can be specified for
|
711
|
+
283 # methods taking blocks in Ruby 1.8. (This will be obsolete in 1.9)
|
712
|
+
284 # We also make the checks as efficient as we can.
|
713
|
+
</span><span class="marked">285 code = %{
|
714
|
+
</span><span class="inferred">286 def #{method}(*args, &block)
|
715
|
+
</span><span class="false">287 old_args = args.dup
|
716
|
+
</span><span class="inferred">288
|
717
|
+
</span><span class="marked">289 #{if options.include?(:block) then
|
718
|
+
290 if options[:block] then
|
719
|
+
291 %{raise(ArgumentError, "no block given") unless block}
|
720
|
+
</span><span class="inferred">292 else
|
721
|
+
</span><span class="marked">293 %{raise(ArgumentError, "block given") if block}
|
722
|
+
</span><span class="inferred">294 end
|
723
|
+
295 end
|
724
|
+
296 }
|
725
|
+
297
|
726
|
+
</span><span class="marked">298 #{if not(options[:allow_trailing] or options.include?(:repeated))
|
727
|
+
299 msg = "wrong number of arguments (\#{args.size} for " +
|
728
|
+
</span><span class="inferred">300 "#{signature.size})"
|
729
|
+
</span><span class="marked">301 %{if args.size != #{signature.size} then
|
730
|
+
</span><span class="inferred">302 raise(ArgumentError, "#{msg}")
|
731
|
+
303 end
|
732
|
+
304 }
|
733
|
+
</span><span class="marked">305 elsif signature.size > 0
|
734
|
+
306 msg = "wrong number of arguments (\#{args.size} for " +
|
735
|
+
</span><span class="inferred">307 "at least #{signature.size}"
|
736
|
+
</span><span class="marked">308 %{if args.size < #{signature.size} then
|
737
|
+
</span><span class="inferred">309 raise(ArgumentError, "#{msg}")
|
738
|
+
310 end
|
739
|
+
311 }
|
740
|
+
312 end
|
741
|
+
313 }
|
742
|
+
314
|
743
|
+
</span><span class="marked">315 #{index = 0
|
744
|
+
316 signature.map do |part|
|
745
|
+
317 next if part == :any
|
746
|
+
318 index += 1
|
747
|
+
319 msg = "argument #{index} (\#{arg.inspect}) does not match " +
|
748
|
+
</span><span class="inferred">320 "#{part.inspect}"
|
749
|
+
</span><span class="marked">321 %{type = ObjectSpace._id2ref(#{part.object_id})
|
750
|
+
</span><span class="inferred">322 arg = args.shift
|
751
|
+
</span><span class="false">323 unless type === #{adapted[%{arg}, %{type}, %{old_args[#{index - 1}]}]}
|
752
|
+
324 raise(ArgumentError, "#{msg}")
|
753
|
+
325 end
|
754
|
+
326 }
|
755
|
+
327 end
|
756
|
+
328 }
|
757
|
+
</span><span class="inferred">329
|
758
|
+
</span><span class="marked">330 #{if repeated = options[:repeated] then
|
759
|
+
331 msg = "argument \#{idx + #{signature.size}}" +
|
760
|
+
</span><span class="inferred">332 "(\#{arg.inspect}) does not match \#{part.inspect}"
|
761
|
+
</span><span class="marked">333 %{parts = ObjectSpace._id2ref(#{repeated.object_id})
|
762
|
+
</span><span class="inferred">334 args.each_with_index do |arg, idx|
|
763
|
+
</span><span class="false">335 part = parts[idx % #{repeated.size}]
|
764
|
+
336 if part != :any and
|
765
|
+
337 not part === (#{adapted[%{arg}, %{part}, %{old_args[idx]}]})
|
766
|
+
338 then
|
767
|
+
339 raise(ArgumentError, "#{msg}")
|
768
|
+
340 end
|
769
|
+
341 end
|
770
|
+
342 }
|
771
|
+
343 end
|
772
|
+
344 }
|
773
|
+
345
|
774
|
+
346 result = ObjectSpace._id2ref(#{old_method.object_id}).bind(self).
|
775
|
+
347 call(*old_args, &block)
|
776
|
+
</span><span class="marked">348 #{if rt = options[:return] and rt != :any then
|
777
|
+
349 msg = "return value (\#{result.inspect}) does not match #{rt.inspect}"
|
778
|
+
350 %{type = ObjectSpace._id2ref(#{rt.object_id})
|
779
|
+
</span><span class="inferred">351 unless type === #{adapted[%{result}, %{type}]}
|
780
|
+
352 raise(StandardError, "#{msg}")
|
781
|
+
353 end
|
782
|
+
354 }
|
783
|
+
355 end
|
784
|
+
356 }
|
785
|
+
357 end
|
786
|
+
358 }
|
787
|
+
</span><span class="marked">359 class_eval code, "(signature check for #{old_method.inspect[/: (.+?)>\Z/, 1]})"
|
788
|
+
</span><span class="inferred">360
|
789
|
+
</span><span class="marked">361 return true
|
790
|
+
</span><span class="inferred">362 end
|
791
|
+
363
|
792
|
+
364 # Specifies that this Module/Class fulfills one or more contracts. The contracts
|
793
|
+
365 # will automatically be verified after an instance has been successfully created.
|
794
|
+
366 # This only actually does the checks when Contract.check_fulfills is enabled.
|
795
|
+
367 # The method will return +true+ in case it actually inserted the check logic and
|
796
|
+
368 # +nil+ in case it didn't.
|
797
|
+
369 #
|
798
|
+
370 # Note that this works by overriding the #initialize method which means that you
|
799
|
+
371 # should either add the fulfills statements after your initialize method or call
|
800
|
+
372 # the previously defined initialize method from your new one.
|
801
|
+
</span><span class="marked">373 def fulfills(*contracts)
|
802
|
+
374 return unless Contract.check_fulfills?
|
803
|
+
</span><span class="inferred">375
|
804
|
+
</span><span class="marked">376 contracts.each do |contract|
|
805
|
+
377 contract.implications.each do |implication|
|
806
|
+
378 include implication
|
807
|
+
</span><span class="inferred">379 end
|
808
|
+
380 end
|
809
|
+
381
|
810
|
+
</span><span class="marked">382 old_method = instance_method(:initialize)
|
811
|
+
383 remove_method(:initialize) if instance_methods(false).include?("initialize")
|
812
|
+
</span><span class="inferred">384
|
813
|
+
385 # Keep visible references around so that the GC will not eat these up.
|
814
|
+
</span><span class="marked">386 @fulfills ||= Array.new
|
815
|
+
387 @fulfills << [contracts, old_method]
|
816
|
+
</span><span class="false">388
|
817
|
+
389 # Have to use class_eval because define_method does not allow methods to take
|
818
|
+
390 # blocks. This can be cleaned up when Ruby 1.9 has become current.
|
819
|
+
391 class_eval %{
|
820
|
+
392 def initialize(*args, &block)
|
821
|
+
393 ObjectSpace._id2ref(#{old_method.object_id}).bind(self).call(*args, &block)
|
822
|
+
394 ObjectSpace._id2ref(#{contracts.object_id}).each do |contract|
|
823
|
+
395 contract.enforce self
|
824
|
+
396 end
|
825
|
+
397 end
|
826
|
+
</span><span class="marked">398 }, "(post initialization contract check for #{self.inspect})"
|
827
|
+
</span><span class="inferred">399
|
828
|
+
</span><span class="marked">400 return true
|
829
|
+
</span><span class="inferred">401 end
|
830
|
+
402 end
|
831
|
+
403
|
832
|
+
404
|
833
|
+
</span><span class="marked">405 module Kernel
|
834
|
+
</span><span class="inferred">406 # Adds an adaption route from the specified type to the specified type.
|
835
|
+
407 # Basic usage looks like this:
|
836
|
+
408 # adaption :from => StringIO, :to => String, :via => :read
|
837
|
+
409 #
|
838
|
+
410 # This method takes various options. Here's a complete list:
|
839
|
+
411 #
|
840
|
+
412 # <code>:from</code>::
|
841
|
+
413 # The type that can be converted from. Defaults to +self+ meaning you
|
842
|
+
414 # can safely omit it in Class, Module or Contract context.
|
843
|
+
415 #
|
844
|
+
416 # <code>:to</code>::
|
845
|
+
417 # The type that can be converted to. Defaults to +self+ meaning you
|
846
|
+
418 # can safely omit it in Class, Module or Contract context.
|
847
|
+
419 #
|
848
|
+
420 # Note that you need to specify either <code>:from</code> or
|
849
|
+
421 # <code>:to</code>.
|
850
|
+
422 #
|
851
|
+
423 # <code>:via</code>::
|
852
|
+
424 # How the <code>:from</code> type will be converted to the
|
853
|
+
425 # <code>:to</code> type. If this is a Symbol the conversion will be
|
854
|
+
426 # done by invoking the method identified by that Symbol on the
|
855
|
+
427 # source object. Otherwise this should be something that responds to
|
856
|
+
428 # the +call+ method (for example Methods and Procs) which will get
|
857
|
+
429 # the source object as its argument and which should return the
|
858
|
+
430 # target object.
|
859
|
+
431 #
|
860
|
+
432 # <code>:if</code>::
|
861
|
+
433 # The conversion can only be performed if this condition is met.
|
862
|
+
434 # This can either be something that implements the === case
|
863
|
+
435 # equivalence operator or something that implements the +call+
|
864
|
+
436 # method. So Methods, Procs, Modules, Classes and Contracts all
|
865
|
+
437 # make sense in this context. You can also specify a Symbol in
|
866
|
+
438 # which case the conversion can only be performed if the source
|
867
|
+
439 # object responds to the method identified by that Symbol.
|
868
|
+
440 #
|
869
|
+
441 # Note that the <code>:if</code> option will default to the same
|
870
|
+
442 # value as the <code>:via</code> option if the <code>:via</code>
|
871
|
+
443 # option is a Symbol.
|
872
|
+
444 #
|
873
|
+
445 # If you invoke this method with a block it will be used instead of
|
874
|
+
446 # the <code>:via</code> option.
|
875
|
+
447 #
|
876
|
+
448 # See Contract.adapt for how conversion look-ups are performed.
|
877
|
+
</span><span class="marked">449 def adaption(options = {}, &block) # :yield: source_object
|
878
|
+
450 options = {
|
879
|
+
</span><span class="inferred">451 :from => self,
|
880
|
+
452 :to => self
|
881
|
+
</span><span class="false">453 }.merge(options)
|
882
|
+
</span><span class="inferred">454
|
883
|
+
</span><span class="marked">455 if block then
|
884
|
+
456 if options.include?(:via) then
|
885
|
+
457 raise(ArgumentError, "Can't use both block and :via")
|
886
|
+
</span><span class="inferred">458 else
|
887
|
+
</span><span class="marked">459 options[:via] = block
|
888
|
+
</span><span class="inferred">460 end
|
889
|
+
461 end
|
890
|
+
462
|
891
|
+
</span><span class="marked">463 if options[:via].respond_to?(:to_sym) then
|
892
|
+
464 options[:via] = options[:via].to_sym
|
893
|
+
</span><span class="inferred">465 end
|
894
|
+
466
|
895
|
+
</span><span class="marked">467 options[:if] ||= options[:via] if options[:via].is_a?(Symbol)
|
896
|
+
</span><span class="inferred">468
|
897
|
+
</span><span class="marked">469 if options[:via].is_a?(Symbol) then
|
898
|
+
470 symbol = options[:via]
|
899
|
+
471 options[:via] = lambda { |obj| obj.send(symbol) }
|
900
|
+
</span><span class="inferred">472 end
|
901
|
+
473
|
902
|
+
</span><span class="marked">474 if options[:if].respond_to?(:to_sym) then
|
903
|
+
475 options[:if] = options[:if].to_sym
|
904
|
+
</span><span class="inferred">476 end
|
905
|
+
477
|
906
|
+
</span><span class="marked">478 if options[:if].is_a?(Symbol) then
|
907
|
+
479 options[:if] = Contract::Check::Quack[options[:if]]
|
908
|
+
480 elsif options[:if].respond_to?(:call) then
|
909
|
+
481 callable = options[:if]
|
910
|
+
482 options[:if] = Contract::Check.block { |obj| callable.call(obj) }
|
911
|
+
</span><span class="inferred">483 end
|
912
|
+
484
|
913
|
+
</span><span class="marked">485 if options[:from] == self and options[:to] == self then
|
914
|
+
486 raise(ArgumentError, "Need to specify either :from or :to")
|
915
|
+
487 elsif options[:from] == options[:to] then
|
916
|
+
488 raise(ArgumentError, "Self-adaption: :from and :to both are " +
|
917
|
+
</span><span class="inferred">489 options[:to].inspect)
|
918
|
+
490 end
|
919
|
+
491
|
920
|
+
</span><span class="marked">492 unless options[:via]
|
921
|
+
493 raise(ArgumentError, "Need to specify how to adapt (use :via or block)")
|
922
|
+
</span><span class="inferred">494 end
|
923
|
+
495
|
924
|
+
</span><span class="marked">496 Contract.adaptions[options[:to]] << options
|
925
|
+
</span><span class="inferred">497 end
|
926
|
+
498
|
927
|
+
499 # Built-in adaption routes that Ruby already uses in its C code.
|
928
|
+
</span><span class="marked">500 adaption :to => Symbol, :via => :to_sym
|
929
|
+
501 adaption :to => String, :via => :to_str
|
930
|
+
502 adaption :to => Array, :via => :to_ary
|
931
|
+
503 adaption :to => Integer, :via => :to_int
|
932
|
+
</span><span class="inferred">504 end
|
933
|
+
</span></pre>
|
934
|
+
<hr />
|
935
|
+
<p>
|
936
|
+
<a href="http://validator.w3.org/check/referer">
|
937
|
+
<img src="http://www.w3.org/Icons/valid-xhtml11"
|
938
|
+
alt="Valid XHTML 1.1!" height="31" width="88" />
|
939
|
+
</a>
|
940
|
+
<a href="http://jigsaw.w3.org/css-validator/">
|
941
|
+
<img style="border:0;width:88px;height:31px"
|
942
|
+
src="http://jigsaw.w3.org/css-validator/images/vcss"
|
943
|
+
alt="Valid CSS!" />
|
944
|
+
</a>
|
945
|
+
</p>
|
946
|
+
</body></html>
|