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,135 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
+
<head>
|
8
|
+
<title>Class: Method</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
+
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
+
<script type="text/javascript">
|
13
|
+
// <![CDATA[
|
14
|
+
|
15
|
+
function popupCode( url ) {
|
16
|
+
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
+
}
|
18
|
+
|
19
|
+
function toggleCode( id ) {
|
20
|
+
if ( document.getElementById )
|
21
|
+
elem = document.getElementById( id );
|
22
|
+
else if ( document.all )
|
23
|
+
elem = eval( "document.all." + id );
|
24
|
+
else
|
25
|
+
return false;
|
26
|
+
|
27
|
+
elemStyle = elem.style;
|
28
|
+
|
29
|
+
if ( elemStyle.display != "block" ) {
|
30
|
+
elemStyle.display = "block"
|
31
|
+
} else {
|
32
|
+
elemStyle.display = "none"
|
33
|
+
}
|
34
|
+
|
35
|
+
return true;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Make codeblocks hidden by default
|
39
|
+
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
+
|
41
|
+
// ]]>
|
42
|
+
</script>
|
43
|
+
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
<div id="classHeader">
|
50
|
+
<table class="header-table">
|
51
|
+
<tr class="top-aligned-row">
|
52
|
+
<td><strong>Class</strong></td>
|
53
|
+
<td class="class-name-in-header">Method</td>
|
54
|
+
</tr>
|
55
|
+
<tr class="top-aligned-row">
|
56
|
+
<td><strong>In:</strong></td>
|
57
|
+
<td>
|
58
|
+
<a href="../files/lib/contract/integration_rb.html">
|
59
|
+
lib/contract/integration.rb
|
60
|
+
</a>
|
61
|
+
<br />
|
62
|
+
</td>
|
63
|
+
</tr>
|
64
|
+
|
65
|
+
<tr class="top-aligned-row">
|
66
|
+
<td><strong>Parent:</strong></td>
|
67
|
+
<td>
|
68
|
+
Object
|
69
|
+
</td>
|
70
|
+
</tr>
|
71
|
+
</table>
|
72
|
+
</div>
|
73
|
+
<!-- banner header -->
|
74
|
+
|
75
|
+
<div id="bodyContent">
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
<div id="contextContent">
|
80
|
+
<div id="diagram">
|
81
|
+
<map id="map" name="map">
|
82
|
+
<area shape="RECT" coords="33,117,105,165" href="Method.html" alt="Method" title="Method">
|
83
|
+
<area shape="RECT" coords="259,117,331,165" href="Contract.html" alt="Contract" title="Contract">
|
84
|
+
<area shape="RECT" coords="393,21,465,69" href="Module.html" alt="Module" title="Module">
|
85
|
+
<area shape="RECT" coords="515,21,621,69" href="UnboundMethod.html" alt="UnboundMethod" title="UnboundMethod">
|
86
|
+
<area shape="RECT" coords="355,117,488,165" href="Contract/Check/Any.html" alt="Contract::Check::Any" title="Contract::Check::Any">
|
87
|
+
<area shape="RECT" coords="512,117,635,165" href="Contract/Check/All.html" alt="Contract::Check::All" title="Contract::Check::All">
|
88
|
+
<area shape="RECT" coords="659,117,795,165" href="Contract/Check/None.html" alt="Contract::Check::None" title="Contract::Check::None">
|
89
|
+
<area shape="RECT" coords="819,117,957,165" href="Contract/Check/Block.html" alt="Contract::Check::Block" title="Contract::Check::Block">
|
90
|
+
<area shape="RECT" coords="659,21,795,69" href="Contract/Check/Base.html" alt="Contract::Check::Base" title="Contract::Check::Base">
|
91
|
+
<area shape="RECT" coords="981,117,1123,165" href="Contract/Check/Quack.html" alt="Contract::Check::Quack" title="Contract::Check::Quack">
|
92
|
+
<area shape="RECT" coords="7,17,132,61" href="MethodSignatureMixin.html" alt="MethodSignatureMixin" title="MethodSignatureMixin">
|
93
|
+
<area shape="RECT" coords="127,17,220,61" href="Kernel.html" alt="Kernel" title="Kernel">
|
94
|
+
</map>
|
95
|
+
<img src="../dot/f_6.png" usemap="#map" border=0 alt="lib/contract/integration.rb">
|
96
|
+
</div>
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
</div>
|
101
|
+
|
102
|
+
|
103
|
+
</div>
|
104
|
+
|
105
|
+
|
106
|
+
<!-- if includes -->
|
107
|
+
<div id="includes">
|
108
|
+
<h3 class="section-bar">Included Modules</h3>
|
109
|
+
|
110
|
+
<div id="includes-list">
|
111
|
+
<span class="include-name"><a href="MethodSignatureMixin.html">MethodSignatureMixin</a></span>
|
112
|
+
</div>
|
113
|
+
</div>
|
114
|
+
|
115
|
+
<div id="section">
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
<!-- if method_list -->
|
125
|
+
|
126
|
+
|
127
|
+
</div>
|
128
|
+
|
129
|
+
|
130
|
+
<div id="validator-badges">
|
131
|
+
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
132
|
+
</div>
|
133
|
+
|
134
|
+
</body>
|
135
|
+
</html>
|
@@ -0,0 +1,208 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
+
<head>
|
8
|
+
<title>Module: MethodSignatureMixin</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
+
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
+
<script type="text/javascript">
|
13
|
+
// <![CDATA[
|
14
|
+
|
15
|
+
function popupCode( url ) {
|
16
|
+
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
+
}
|
18
|
+
|
19
|
+
function toggleCode( id ) {
|
20
|
+
if ( document.getElementById )
|
21
|
+
elem = document.getElementById( id );
|
22
|
+
else if ( document.all )
|
23
|
+
elem = eval( "document.all." + id );
|
24
|
+
else
|
25
|
+
return false;
|
26
|
+
|
27
|
+
elemStyle = elem.style;
|
28
|
+
|
29
|
+
if ( elemStyle.display != "block" ) {
|
30
|
+
elemStyle.display = "block"
|
31
|
+
} else {
|
32
|
+
elemStyle.display = "none"
|
33
|
+
}
|
34
|
+
|
35
|
+
return true;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Make codeblocks hidden by default
|
39
|
+
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
+
|
41
|
+
// ]]>
|
42
|
+
</script>
|
43
|
+
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
<div id="classHeader">
|
50
|
+
<table class="header-table">
|
51
|
+
<tr class="top-aligned-row">
|
52
|
+
<td><strong>Module</strong></td>
|
53
|
+
<td class="class-name-in-header">MethodSignatureMixin</td>
|
54
|
+
</tr>
|
55
|
+
<tr class="top-aligned-row">
|
56
|
+
<td><strong>In:</strong></td>
|
57
|
+
<td>
|
58
|
+
<a href="../files/lib/contract/integration_rb.html">
|
59
|
+
lib/contract/integration.rb
|
60
|
+
</a>
|
61
|
+
<br />
|
62
|
+
</td>
|
63
|
+
</tr>
|
64
|
+
|
65
|
+
</table>
|
66
|
+
</div>
|
67
|
+
<!-- banner header -->
|
68
|
+
|
69
|
+
<div id="bodyContent">
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
<div id="contextContent">
|
74
|
+
<div id="diagram">
|
75
|
+
<map id="map" name="map">
|
76
|
+
<area shape="RECT" coords="33,117,105,165" href="Method.html" alt="Method" title="Method">
|
77
|
+
<area shape="RECT" coords="259,117,331,165" href="Contract.html" alt="Contract" title="Contract">
|
78
|
+
<area shape="RECT" coords="393,21,465,69" href="Module.html" alt="Module" title="Module">
|
79
|
+
<area shape="RECT" coords="515,21,621,69" href="UnboundMethod.html" alt="UnboundMethod" title="UnboundMethod">
|
80
|
+
<area shape="RECT" coords="355,117,488,165" href="Contract/Check/Any.html" alt="Contract::Check::Any" title="Contract::Check::Any">
|
81
|
+
<area shape="RECT" coords="512,117,635,165" href="Contract/Check/All.html" alt="Contract::Check::All" title="Contract::Check::All">
|
82
|
+
<area shape="RECT" coords="659,117,795,165" href="Contract/Check/None.html" alt="Contract::Check::None" title="Contract::Check::None">
|
83
|
+
<area shape="RECT" coords="819,117,957,165" href="Contract/Check/Block.html" alt="Contract::Check::Block" title="Contract::Check::Block">
|
84
|
+
<area shape="RECT" coords="659,21,795,69" href="Contract/Check/Base.html" alt="Contract::Check::Base" title="Contract::Check::Base">
|
85
|
+
<area shape="RECT" coords="981,117,1123,165" href="Contract/Check/Quack.html" alt="Contract::Check::Quack" title="Contract::Check::Quack">
|
86
|
+
<area shape="RECT" coords="7,17,132,61" href="MethodSignatureMixin.html" alt="MethodSignatureMixin" title="MethodSignatureMixin">
|
87
|
+
<area shape="RECT" coords="127,17,220,61" href="Kernel.html" alt="Kernel" title="Kernel">
|
88
|
+
</map>
|
89
|
+
<img src="../dot/f_6.png" usemap="#map" border=0 alt="lib/contract/integration.rb">
|
90
|
+
</div>
|
91
|
+
|
92
|
+
<div id="description">
|
93
|
+
<p>
|
94
|
+
Modifies <a href="Method.html">Method</a> and UnboundMethod so that
|
95
|
+
signatures set by Module.signatures can be retrieved.
|
96
|
+
</p>
|
97
|
+
<p>
|
98
|
+
Note that this can only work when the method origin and definition name are
|
99
|
+
known which is the reason for ruby-contract currently overloading all
|
100
|
+
methods that return a method.
|
101
|
+
</p>
|
102
|
+
<p>
|
103
|
+
This could be greatly simplified it <a
|
104
|
+
href="http://www.rcrchive.net/rcr/show/292">www.rcrchive.net/rcr/show/292</a>
|
105
|
+
were to be accepted. You can help the development of ruby-contract by
|
106
|
+
voting for that RCR.
|
107
|
+
</p>
|
108
|
+
|
109
|
+
</div>
|
110
|
+
|
111
|
+
|
112
|
+
</div>
|
113
|
+
|
114
|
+
<div id="method-list">
|
115
|
+
<h3 class="section-bar">Methods</h3>
|
116
|
+
|
117
|
+
<div class="name-list">
|
118
|
+
<a href="#M000018">has_signature?</a>
|
119
|
+
<a href="#M000017">signature</a>
|
120
|
+
</div>
|
121
|
+
</div>
|
122
|
+
|
123
|
+
</div>
|
124
|
+
|
125
|
+
|
126
|
+
<!-- if includes -->
|
127
|
+
|
128
|
+
<div id="section">
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
<!-- if method_list -->
|
138
|
+
<div id="methods">
|
139
|
+
<h3 class="section-bar">Public Instance methods</h3>
|
140
|
+
|
141
|
+
<div id="method-M000018" class="method-detail">
|
142
|
+
<a name="M000018"></a>
|
143
|
+
|
144
|
+
<div class="method-heading">
|
145
|
+
<a href="#M000018" class="method-signature">
|
146
|
+
<span class="method-name">has_signature?</span><span class="method-args">()</span>
|
147
|
+
</a>
|
148
|
+
</div>
|
149
|
+
|
150
|
+
<div class="method-description">
|
151
|
+
<p>
|
152
|
+
Returns whether a signatue for this method was defined via <a
|
153
|
+
href="Module.html#M000015">Module#signature</a>.
|
154
|
+
</p>
|
155
|
+
<p><a class="source-toggle" href="#"
|
156
|
+
onclick="toggleCode('M000018-source');return false;">[Source]</a></p>
|
157
|
+
<div class="method-source-code" id="M000018-source">
|
158
|
+
<pre>
|
159
|
+
<span class="ruby-comment cmt"># File lib/contract/integration.rb, line 608</span>
|
160
|
+
608: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">has_signature?</span>() <span class="ruby-ivar">@has_signature</span> <span class="ruby-keyword kw">end</span>
|
161
|
+
</pre>
|
162
|
+
</div>
|
163
|
+
</div>
|
164
|
+
</div>
|
165
|
+
|
166
|
+
<div id="method-M000017" class="method-detail">
|
167
|
+
<a name="M000017"></a>
|
168
|
+
|
169
|
+
<div class="method-heading">
|
170
|
+
<a href="#M000017" class="method-signature">
|
171
|
+
<span class="method-name">signature</span><span class="method-args">()</span>
|
172
|
+
</a>
|
173
|
+
</div>
|
174
|
+
|
175
|
+
<div class="method-description">
|
176
|
+
<p>
|
177
|
+
Returns the signature of this method in the form of <tt>[fixed types,
|
178
|
+
options]</tt>. If no signature was specified via <a
|
179
|
+
href="Module.html#M000015">Module#signature</a> it will still return
|
180
|
+
something useful.
|
181
|
+
</p>
|
182
|
+
<p>
|
183
|
+
This information can be useful in meta programming.
|
184
|
+
</p>
|
185
|
+
<p><a class="source-toggle" href="#"
|
186
|
+
onclick="toggleCode('M000017-source');return false;">[Source]</a></p>
|
187
|
+
<div class="method-source-code" id="M000017-source">
|
188
|
+
<pre>
|
189
|
+
<span class="ruby-comment cmt"># File lib/contract/integration.rb, line 604</span>
|
190
|
+
604: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">signature</span>() <span class="ruby-ivar">@signature</span> <span class="ruby-keyword kw">end</span>
|
191
|
+
</pre>
|
192
|
+
</div>
|
193
|
+
</div>
|
194
|
+
</div>
|
195
|
+
|
196
|
+
|
197
|
+
</div>
|
198
|
+
|
199
|
+
|
200
|
+
</div>
|
201
|
+
|
202
|
+
|
203
|
+
<div id="validator-badges">
|
204
|
+
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
205
|
+
</div>
|
206
|
+
|
207
|
+
</body>
|
208
|
+
</html>
|
@@ -0,0 +1,526 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
+
<head>
|
8
|
+
<title>Class: Module</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
+
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
+
<script type="text/javascript">
|
13
|
+
// <![CDATA[
|
14
|
+
|
15
|
+
function popupCode( url ) {
|
16
|
+
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
+
}
|
18
|
+
|
19
|
+
function toggleCode( id ) {
|
20
|
+
if ( document.getElementById )
|
21
|
+
elem = document.getElementById( id );
|
22
|
+
else if ( document.all )
|
23
|
+
elem = eval( "document.all." + id );
|
24
|
+
else
|
25
|
+
return false;
|
26
|
+
|
27
|
+
elemStyle = elem.style;
|
28
|
+
|
29
|
+
if ( elemStyle.display != "block" ) {
|
30
|
+
elemStyle.display = "block"
|
31
|
+
} else {
|
32
|
+
elemStyle.display = "none"
|
33
|
+
}
|
34
|
+
|
35
|
+
return true;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Make codeblocks hidden by default
|
39
|
+
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
+
|
41
|
+
// ]]>
|
42
|
+
</script>
|
43
|
+
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
<div id="classHeader">
|
50
|
+
<table class="header-table">
|
51
|
+
<tr class="top-aligned-row">
|
52
|
+
<td><strong>Class</strong></td>
|
53
|
+
<td class="class-name-in-header">Module</td>
|
54
|
+
</tr>
|
55
|
+
<tr class="top-aligned-row">
|
56
|
+
<td><strong>In:</strong></td>
|
57
|
+
<td>
|
58
|
+
<a href="../files/lib/contract/integration_rb.html">
|
59
|
+
lib/contract/integration.rb
|
60
|
+
</a>
|
61
|
+
<br />
|
62
|
+
</td>
|
63
|
+
</tr>
|
64
|
+
|
65
|
+
<tr class="top-aligned-row">
|
66
|
+
<td><strong>Parent:</strong></td>
|
67
|
+
<td>
|
68
|
+
Object
|
69
|
+
</td>
|
70
|
+
</tr>
|
71
|
+
</table>
|
72
|
+
</div>
|
73
|
+
<!-- banner header -->
|
74
|
+
|
75
|
+
<div id="bodyContent">
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
<div id="contextContent">
|
80
|
+
<div id="diagram">
|
81
|
+
<map id="map" name="map">
|
82
|
+
<area shape="RECT" coords="33,117,105,165" href="Method.html" alt="Method" title="Method">
|
83
|
+
<area shape="RECT" coords="259,117,331,165" href="Contract.html" alt="Contract" title="Contract">
|
84
|
+
<area shape="RECT" coords="393,21,465,69" href="Module.html" alt="Module" title="Module">
|
85
|
+
<area shape="RECT" coords="515,21,621,69" href="UnboundMethod.html" alt="UnboundMethod" title="UnboundMethod">
|
86
|
+
<area shape="RECT" coords="355,117,488,165" href="Contract/Check/Any.html" alt="Contract::Check::Any" title="Contract::Check::Any">
|
87
|
+
<area shape="RECT" coords="512,117,635,165" href="Contract/Check/All.html" alt="Contract::Check::All" title="Contract::Check::All">
|
88
|
+
<area shape="RECT" coords="659,117,795,165" href="Contract/Check/None.html" alt="Contract::Check::None" title="Contract::Check::None">
|
89
|
+
<area shape="RECT" coords="819,117,957,165" href="Contract/Check/Block.html" alt="Contract::Check::Block" title="Contract::Check::Block">
|
90
|
+
<area shape="RECT" coords="659,21,795,69" href="Contract/Check/Base.html" alt="Contract::Check::Base" title="Contract::Check::Base">
|
91
|
+
<area shape="RECT" coords="981,117,1123,165" href="Contract/Check/Quack.html" alt="Contract::Check::Quack" title="Contract::Check::Quack">
|
92
|
+
<area shape="RECT" coords="7,17,132,61" href="MethodSignatureMixin.html" alt="MethodSignatureMixin" title="MethodSignatureMixin">
|
93
|
+
<area shape="RECT" coords="127,17,220,61" href="Kernel.html" alt="Kernel" title="Kernel">
|
94
|
+
</map>
|
95
|
+
<img src="../dot/f_6.png" usemap="#map" border=0 alt="lib/contract/integration.rb">
|
96
|
+
</div>
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
</div>
|
101
|
+
|
102
|
+
<div id="method-list">
|
103
|
+
<h3 class="section-bar">Methods</h3>
|
104
|
+
|
105
|
+
<div class="name-list">
|
106
|
+
<a href="#M000016">fulfills</a>
|
107
|
+
<a href="#M000015">signature</a>
|
108
|
+
</div>
|
109
|
+
</div>
|
110
|
+
|
111
|
+
</div>
|
112
|
+
|
113
|
+
|
114
|
+
<!-- if includes -->
|
115
|
+
|
116
|
+
<div id="section">
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
<!-- if method_list -->
|
126
|
+
<div id="methods">
|
127
|
+
<h3 class="section-bar">Public Instance methods</h3>
|
128
|
+
|
129
|
+
<div id="method-M000016" class="method-detail">
|
130
|
+
<a name="M000016"></a>
|
131
|
+
|
132
|
+
<div class="method-heading">
|
133
|
+
<a href="#M000016" class="method-signature">
|
134
|
+
<span class="method-name">fulfills</span><span class="method-args">(*contracts)</span>
|
135
|
+
</a>
|
136
|
+
</div>
|
137
|
+
|
138
|
+
<div class="method-description">
|
139
|
+
<p>
|
140
|
+
Specifies that this <a href="Module.html">Module</a>/Class fulfills one or
|
141
|
+
more contracts. The contracts will automatically be verified after an
|
142
|
+
instance has been successfully created. This only actually does the checks
|
143
|
+
when Contract.check_fulfills is enabled. The method will return
|
144
|
+
<tt>true</tt> in case it actually inserted the check logic and <tt>nil</tt>
|
145
|
+
in case it didn’t.
|
146
|
+
</p>
|
147
|
+
<p>
|
148
|
+
Note that this works by overriding the initialize method which means that
|
149
|
+
you should either add the fulfills statements after your initialize method
|
150
|
+
or call the previously defined initialize method from your new one.
|
151
|
+
</p>
|
152
|
+
<p><a class="source-toggle" href="#"
|
153
|
+
onclick="toggleCode('M000016-source');return false;">[Source]</a></p>
|
154
|
+
<div class="method-source-code" id="M000016-source">
|
155
|
+
<pre>
|
156
|
+
<span class="ruby-comment cmt"># File lib/contract/integration.rb, line 436</span>
|
157
|
+
436: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">fulfills</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">contracts</span>)
|
158
|
+
437: <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-constant">Contract</span>.<span class="ruby-identifier">check_fulfills?</span>
|
159
|
+
438:
|
160
|
+
439: <span class="ruby-identifier">contracts</span>.<span class="ruby-identifier">each</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">contract</span><span class="ruby-operator">|</span>
|
161
|
+
440: <span class="ruby-identifier">contract</span>.<span class="ruby-identifier">implications</span>.<span class="ruby-identifier">each</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">implication</span><span class="ruby-operator">|</span>
|
162
|
+
441: <span class="ruby-identifier">include</span> <span class="ruby-identifier">implication</span>
|
163
|
+
442: <span class="ruby-keyword kw">end</span>
|
164
|
+
443: <span class="ruby-keyword kw">end</span>
|
165
|
+
444:
|
166
|
+
445: <span class="ruby-identifier">old_method</span> = <span class="ruby-identifier">instance_method</span>(<span class="ruby-identifier">:initialize</span>)
|
167
|
+
446: <span class="ruby-identifier">remove_method</span>(<span class="ruby-identifier">:initialize</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">instance_methods</span>(<span class="ruby-keyword kw">false</span>).<span class="ruby-identifier">include?</span>(<span class="ruby-value str">"initialize"</span>)
|
168
|
+
447:
|
169
|
+
448: <span class="ruby-comment cmt"># Keep visible references around so that the GC will not eat these up.</span>
|
170
|
+
449: <span class="ruby-ivar">@fulfills</span> <span class="ruby-operator">||=</span> <span class="ruby-constant">Array</span>.<span class="ruby-identifier">new</span>
|
171
|
+
450: <span class="ruby-ivar">@fulfills</span> <span class="ruby-operator"><<</span> [<span class="ruby-identifier">contracts</span>, <span class="ruby-identifier">old_method</span>]
|
172
|
+
451:
|
173
|
+
452: <span class="ruby-comment cmt"># Have to use class_eval because define_method does not allow methods to take</span>
|
174
|
+
453: <span class="ruby-comment cmt"># blocks. This can be cleaned up when Ruby 1.9 has become current.</span>
|
175
|
+
454: <span class="ruby-identifier">class_eval</span> <span class="ruby-node">%{
|
176
|
+
455: def initialize(*args, &block)
|
177
|
+
456: ObjectSpace._id2ref(#{old_method.object_id}).bind(self).call(*args, &block)
|
178
|
+
457: ObjectSpace._id2ref(#{contracts.object_id}).each do |contract|
|
179
|
+
458: contract.enforce self
|
180
|
+
459: end
|
181
|
+
460: end
|
182
|
+
461: }</span>, <span class="ruby-node">"(post initialization contract check for #{self.inspect})"</span>
|
183
|
+
462:
|
184
|
+
463: <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">true</span>
|
185
|
+
464: <span class="ruby-keyword kw">end</span>
|
186
|
+
</pre>
|
187
|
+
</div>
|
188
|
+
</div>
|
189
|
+
</div>
|
190
|
+
|
191
|
+
<div id="method-M000015" class="method-detail">
|
192
|
+
<a name="M000015"></a>
|
193
|
+
|
194
|
+
<div class="method-heading">
|
195
|
+
<a href="#M000015" class="method-signature">
|
196
|
+
<span class="method-name">signature</span><span class="method-args">(method, *args)</span>
|
197
|
+
</a>
|
198
|
+
</div>
|
199
|
+
|
200
|
+
<div class="method-description">
|
201
|
+
<p>
|
202
|
+
Checks that the arguments and return value of a method match the specified
|
203
|
+
signature. Checks are only actually done when Contract.check_signatures is
|
204
|
+
set to true or if the <tt>:no_adaption</tt> option is <tt>false</tt>. The
|
205
|
+
method will return <tt>true</tt> in case it actually inserted the signature
|
206
|
+
check logic and <tt>nil</tt> in case it didn’t.
|
207
|
+
</p>
|
208
|
+
<p>
|
209
|
+
You will usually specify one type specifier (<tt>:any</tt> which will allow
|
210
|
+
anything to appear at that position of the argument list or something that
|
211
|
+
implements the === case equality operator — samples are Contracts,
|
212
|
+
Ranges, Classes, Modules, Regexps, Contract::Checks and so on) per
|
213
|
+
argument. You can also use objects that implement the <tt>call</tt> method
|
214
|
+
as type specifiers which includes Methods and Procs.
|
215
|
+
</p>
|
216
|
+
<p>
|
217
|
+
If you don’t use the <tt>:repeated</tt> or <tt>:allow_trailing</tt>
|
218
|
+
options the method will take exactly as many arguments as there are type
|
219
|
+
specifiers which means that <tt>signature :a_method</tt> enforces
|
220
|
+
<tt>a_method</tt> having exactly zero arguments.
|
221
|
+
</p>
|
222
|
+
<p>
|
223
|
+
The checks are done by wrapping the type checks around the method.
|
224
|
+
ArgumentError exceptions will be raised in case the signature contract is
|
225
|
+
not adhered to by your caller.
|
226
|
+
</p>
|
227
|
+
<p>
|
228
|
+
An ArgumentError exception will be raised in case the methods natural
|
229
|
+
argument list size and the signature you specified via <a
|
230
|
+
href="Module.html#M000015">Module.signature</a> are incompatible. (Note
|
231
|
+
that they don’t have to be completely equivalent, you can still have
|
232
|
+
a method taking zero or more arguments and apply a signature that limits
|
233
|
+
the actual argument count to three arguments.)
|
234
|
+
</p>
|
235
|
+
<p>
|
236
|
+
This method can take quite a few options. Here’s a complete list:
|
237
|
+
</p>
|
238
|
+
<table>
|
239
|
+
<tr><td valign="top"><tt>:return</tt>:</td><td>A return type that the method must comply to. Note that this check (if
|
240
|
+
failed) will actually raise a StandardError instead of an ArgumentError
|
241
|
+
because the failure likely lies in the method itself and not in what the
|
242
|
+
caller did.
|
243
|
+
|
244
|
+
</td></tr>
|
245
|
+
<tr><td valign="top"><tt>:block</tt>:</td><td><tt>true</tt> or <tt>false</tt> — whether the method must take a
|
246
|
+
block or not. So specifying <tt>:block => false</tt> enforces that the
|
247
|
+
method is not allowed to have a block supplied.
|
248
|
+
|
249
|
+
</td></tr>
|
250
|
+
<tr><td valign="top"><tt>:allow_trailing</tt>:</td><td><tt>true</tt> or <tt>false</tt> — whether the argument list may
|
251
|
+
contain trailing, unchecked arguments.
|
252
|
+
|
253
|
+
</td></tr>
|
254
|
+
<tr><td valign="top"><tt>:optional</tt>:</td><td>An Array specifying optional arguments. These arguments are assumed to be
|
255
|
+
after regular arguments, but <b>before</b> repeated ones. They will be
|
256
|
+
checked if they are present, but don’t actually have to be present.
|
257
|
+
|
258
|
+
<p>
|
259
|
+
This could for example be useful for <tt>File.open(name, mode)</tt> where
|
260
|
+
mode is optional, but has to be either an Integer or String.
|
261
|
+
</p>
|
262
|
+
<p>
|
263
|
+
Note that all optional arguments will have to be specified if you want to
|
264
|
+
use optional and repeated arguments.
|
265
|
+
</p>
|
266
|
+
<p>
|
267
|
+
Specifying an empty Array is like not supplying the option at all.
|
268
|
+
</p>
|
269
|
+
</td></tr>
|
270
|
+
<tr><td valign="top"><tt>:repeated</tt>:</td><td>An Array that specifies arguments of a method that will be repeated over
|
271
|
+
and over again at the end of the argument list.
|
272
|
+
|
273
|
+
<p>
|
274
|
+
A good sample of this are Array#values_at which takes zero or or more
|
275
|
+
Numeric arguments and Enumerable#zip which takes zero or more other
|
276
|
+
Enumerable arguments.
|
277
|
+
</p>
|
278
|
+
<p>
|
279
|
+
Note that the Array that was associated with the <tt>:repeated</tt> option
|
280
|
+
must not be empty or an ArgumentError exception will be raised. If
|
281
|
+
there’s just one repeated type you can omit the Array and directly
|
282
|
+
specify the type identifier.
|
283
|
+
</p>
|
284
|
+
<p>
|
285
|
+
The <tt>:repeated</tt> option overrides the <tt>:allow_trailing</tt>
|
286
|
+
option. Combining them is thus quite meaningless.
|
287
|
+
</p>
|
288
|
+
</td></tr>
|
289
|
+
<tr><td valign="top"><tt>:no_adaption</tt>:</td><td><tt>true</tt> or <tt>false</tt> — whether no type adaption should be
|
290
|
+
performed.
|
291
|
+
|
292
|
+
</td></tr>
|
293
|
+
</table>
|
294
|
+
<p>
|
295
|
+
Usage:
|
296
|
+
</p>
|
297
|
+
<pre>
|
298
|
+
signature(:to_s) # no arguments
|
299
|
+
signature(:+, :any) # one argument, type unchecked
|
300
|
+
signature(:+, Fixnum) # one argument, type Fixnum
|
301
|
+
signature(:+, NumericContract)
|
302
|
+
signature(:+, 1 .. 10)
|
303
|
+
signature(:sqrt, lambda { |arg| arg > 0 })
|
304
|
+
|
305
|
+
signature(:each, :block => true) # has to have block
|
306
|
+
signature(:to_i, :block => false) # not allowed to have block
|
307
|
+
signature(:to_i, :result => Fixnum) # return value must be Fixnum
|
308
|
+
signature(:zip, :allow_trailing => true) # unchecked trailing args
|
309
|
+
signature(:zip, :repeated => [Enumerable]) # repeated trailing args
|
310
|
+
signature(:zip, :repeated => Enumerable)
|
311
|
+
# foo(3, 6, 4, 7) works; foo(5), foo(3, 2) etc. don't
|
312
|
+
signature(:foo, :repeated => [1..4, 5..9])
|
313
|
+
signature(:foo, :optional => [Numeric, String]) # two optional args
|
314
|
+
</pre>
|
315
|
+
<p><a class="source-toggle" href="#"
|
316
|
+
onclick="toggleCode('M000015-source');return false;">[Source]</a></p>
|
317
|
+
<div class="method-source-code" id="M000015-source">
|
318
|
+
<pre>
|
319
|
+
<span class="ruby-comment cmt"># File lib/contract/integration.rb, line 237</span>
|
320
|
+
237: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">signature</span>(<span class="ruby-identifier">method</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">args</span>)
|
321
|
+
238: <span class="ruby-identifier">options</span> = {}
|
322
|
+
239: <span class="ruby-identifier">signature</span> = <span class="ruby-identifier">args</span>.<span class="ruby-identifier">dup</span>
|
323
|
+
240: <span class="ruby-identifier">options</span>.<span class="ruby-identifier">update</span>(<span class="ruby-identifier">signature</span>.<span class="ruby-identifier">pop</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">signature</span>.<span class="ruby-identifier">last</span>.<span class="ruby-identifier">is_a?</span>(<span class="ruby-constant">Hash</span>)
|
324
|
+
241: <span class="ruby-identifier">method</span> = <span class="ruby-identifier">method</span>.<span class="ruby-identifier">to_sym</span>
|
325
|
+
242:
|
326
|
+
243: <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">if</span> <span class="ruby-keyword kw">not</span> <span class="ruby-constant">Contract</span>.<span class="ruby-identifier">check_signatures?</span> <span class="ruby-keyword kw">and</span> <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:no_adaption</span>]
|
327
|
+
244:
|
328
|
+
245: <span class="ruby-identifier">old_method</span> = <span class="ruby-identifier">instance_method</span>(<span class="ruby-identifier">method</span>)
|
329
|
+
246: <span class="ruby-identifier">remove_method</span>(<span class="ruby-identifier">method</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">instance_methods</span>(<span class="ruby-keyword kw">false</span>).<span class="ruby-identifier">include?</span>(<span class="ruby-identifier">method</span>.<span class="ruby-identifier">to_s</span>)
|
330
|
+
247:
|
331
|
+
248: <span class="ruby-identifier">arity</span> = <span class="ruby-identifier">old_method</span>.<span class="ruby-identifier">arity</span>
|
332
|
+
249: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">arity</span> <span class="ruby-operator">!=</span> <span class="ruby-identifier">signature</span>.<span class="ruby-identifier">size</span> <span class="ruby-keyword kw">and</span>
|
333
|
+
250: (<span class="ruby-identifier">arity</span> <span class="ruby-operator">>=</span> <span class="ruby-value">0</span> <span class="ruby-keyword kw">or</span> <span class="ruby-identifier">signature</span>.<span class="ruby-identifier">size</span> <span class="ruby-operator"><</span> <span class="ruby-operator">~</span><span class="ruby-identifier">arity</span>) <span class="ruby-keyword kw">then</span>
|
334
|
+
251: <span class="ruby-identifier">raise</span>(<span class="ruby-constant">ArgumentError</span>, <span class="ruby-value str">"signature isn't compatible with arity"</span>)
|
335
|
+
252: <span class="ruby-keyword kw">end</span>
|
336
|
+
253:
|
337
|
+
254: <span class="ruby-comment cmt"># Normalizes specifiers to Objects that respond to === so that the run-time</span>
|
338
|
+
255: <span class="ruby-comment cmt"># checks only have to deal with that case. Also checks that a specifier is</span>
|
339
|
+
256: <span class="ruby-comment cmt"># actually valid.</span>
|
340
|
+
257: <span class="ruby-identifier">convert_specifier</span> = <span class="ruby-identifier">lambda</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">item</span><span class="ruby-operator">|</span>
|
341
|
+
258: <span class="ruby-comment cmt"># Procs, Methods etc.</span>
|
342
|
+
259: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">item</span>.<span class="ruby-identifier">respond_to?</span>(<span class="ruby-identifier">:call</span>) <span class="ruby-keyword kw">then</span>
|
343
|
+
260: <span class="ruby-constant">Contract</span><span class="ruby-operator">::</span><span class="ruby-constant">Check</span>.<span class="ruby-identifier">block</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">arg</span><span class="ruby-operator">|</span> <span class="ruby-identifier">item</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">arg</span>) }
|
344
|
+
261: <span class="ruby-comment cmt"># Already okay</span>
|
345
|
+
262: <span class="ruby-keyword kw">elsif</span> <span class="ruby-identifier">item</span>.<span class="ruby-identifier">respond_to?</span>(<span class="ruby-identifier">:===</span>) <span class="ruby-keyword kw">or</span> <span class="ruby-identifier">item</span> <span class="ruby-operator">==</span> <span class="ruby-identifier">:any</span> <span class="ruby-keyword kw">then</span>
|
346
|
+
263: <span class="ruby-identifier">item</span>
|
347
|
+
264: <span class="ruby-comment cmt"># Unknown specifier</span>
|
348
|
+
265: <span class="ruby-keyword kw">else</span>
|
349
|
+
266: <span class="ruby-identifier">raise</span>(<span class="ruby-constant">ArgumentError</span>, <span class="ruby-node">"unsupported argument specifier #{item.inspect}"</span>)
|
350
|
+
267: <span class="ruby-keyword kw">end</span>
|
351
|
+
268: <span class="ruby-keyword kw">end</span>
|
352
|
+
269:
|
353
|
+
270: <span class="ruby-identifier">signature</span>.<span class="ruby-identifier">map!</span>(<span class="ruby-operator">&</span><span class="ruby-identifier">convert_specifier</span>)
|
354
|
+
271:
|
355
|
+
272: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">options</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-identifier">:optional</span>) <span class="ruby-keyword kw">then</span>
|
356
|
+
273: <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:optional</span>] = <span class="ruby-constant">Array</span>(<span class="ruby-identifier">options</span>[<span class="ruby-identifier">:optional</span>])
|
357
|
+
274: <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:optional</span>].<span class="ruby-identifier">map!</span>(<span class="ruby-operator">&</span><span class="ruby-identifier">convert_specifier</span>)
|
358
|
+
275: <span class="ruby-identifier">options</span>.<span class="ruby-identifier">delete</span>(<span class="ruby-identifier">:optional</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:optional</span>].<span class="ruby-identifier">empty?</span>
|
359
|
+
276: <span class="ruby-keyword kw">end</span>
|
360
|
+
277:
|
361
|
+
278: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">options</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-identifier">:repeated</span>) <span class="ruby-keyword kw">then</span>
|
362
|
+
279: <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:repeated</span>] = <span class="ruby-constant">Array</span>(<span class="ruby-identifier">options</span>[<span class="ruby-identifier">:repeated</span>])
|
363
|
+
280: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:repeated</span>].<span class="ruby-identifier">size</span> <span class="ruby-operator">==</span> <span class="ruby-value">0</span> <span class="ruby-keyword kw">then</span>
|
364
|
+
281: <span class="ruby-identifier">raise</span>(<span class="ruby-constant">ArgumentError</span>, <span class="ruby-value str">"repeated arguments may not be an empty Array"</span>)
|
365
|
+
282: <span class="ruby-keyword kw">else</span>
|
366
|
+
283: <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:repeated</span>].<span class="ruby-identifier">map!</span>(<span class="ruby-operator">&</span><span class="ruby-identifier">convert_specifier</span>)
|
367
|
+
284: <span class="ruby-keyword kw">end</span>
|
368
|
+
285: <span class="ruby-keyword kw">end</span>
|
369
|
+
286:
|
370
|
+
287: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">options</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-identifier">:return</span>) <span class="ruby-keyword kw">then</span>
|
371
|
+
288: <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:return</span>] = <span class="ruby-identifier">convert_specifier</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">options</span>[<span class="ruby-identifier">:return</span>])
|
372
|
+
289: <span class="ruby-keyword kw">end</span>
|
373
|
+
290:
|
374
|
+
291: <span class="ruby-comment cmt"># We need to keep around references to our arguments because we will</span>
|
375
|
+
292: <span class="ruby-comment cmt"># need to access them via ObjectSpace._id2ref so that they do not</span>
|
376
|
+
293: <span class="ruby-comment cmt"># get garbage collected.</span>
|
377
|
+
294: <span class="ruby-ivar">@signatures</span> <span class="ruby-operator">||=</span> <span class="ruby-constant">Hash</span>.<span class="ruby-identifier">new</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">hash</span>, <span class="ruby-identifier">key</span><span class="ruby-operator">|</span> <span class="ruby-identifier">hash</span>[<span class="ruby-identifier">key</span>] = <span class="ruby-constant">Array</span>.<span class="ruby-identifier">new</span> }
|
378
|
+
295: <span class="ruby-ivar">@signatures</span>[<span class="ruby-identifier">method</span>] <span class="ruby-operator"><<</span> [<span class="ruby-identifier">signature</span>, <span class="ruby-identifier">options</span>, <span class="ruby-identifier">old_method</span>]
|
379
|
+
296:
|
380
|
+
297: <span class="ruby-identifier">adapted</span> = <span class="ruby-constant">Proc</span>.<span class="ruby-identifier">new</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">obj</span>, <span class="ruby-identifier">type</span>, <span class="ruby-identifier">assign_to</span><span class="ruby-operator">|</span>
|
381
|
+
298: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">options</span>[<span class="ruby-identifier">:no_adaption</span>] <span class="ruby-keyword kw">then</span>
|
382
|
+
299: <span class="ruby-identifier">obj</span>
|
383
|
+
300: <span class="ruby-keyword kw">elsif</span> <span class="ruby-identifier">assign_to</span> <span class="ruby-keyword kw">then</span>
|
384
|
+
301: <span class="ruby-node">%{(#{assign_to} = Contract.adapt(#{obj}, #{type}))}</span>
|
385
|
+
302: <span class="ruby-keyword kw">else</span>
|
386
|
+
303: <span class="ruby-node">%{Contract.adapt(#{obj}, #{type})}</span>
|
387
|
+
304: <span class="ruby-keyword kw">end</span>
|
388
|
+
305: <span class="ruby-keyword kw">end</span>
|
389
|
+
306:
|
390
|
+
307: <span class="ruby-comment cmt"># We have to use class_eval so that signatures can be specified for</span>
|
391
|
+
308: <span class="ruby-comment cmt"># methods taking blocks in Ruby 1.8. (This will be obsolete in 1.9)</span>
|
392
|
+
309: <span class="ruby-comment cmt"># We also make the checks as efficient as we can.</span>
|
393
|
+
310: <span class="ruby-identifier">code</span> = <span class="ruby-node">%{
|
394
|
+
311: def #{method}(*args, &block)
|
395
|
+
312: old_args = args.dup
|
396
|
+
313:
|
397
|
+
314: #{if options.include?(:block) then
|
398
|
+
315: if options[:block] then
|
399
|
+
316: %{raise(ArgumentError, "no block given") unless block}
|
400
|
+
317: else
|
401
|
+
318: %{raise(ArgumentError, "block given") if block}
|
402
|
+
319: end
|
403
|
+
320: end
|
404
|
+
321: }
|
405
|
+
322:
|
406
|
+
323: #{if not (options[:allow_trailing] or
|
407
|
+
324: options.include?(:repeated) or options.include?(:optional))
|
408
|
+
325: then
|
409
|
+
326: msg = "wrong number of arguments (\#{args.size} for " +
|
410
|
+
327: "#{signature.size})"
|
411
|
+
328: %{if args.size != #{signature.size} then
|
412
|
+
329: raise(ArgumentError, "#{msg}")
|
413
|
+
330: end
|
414
|
+
331: }
|
415
|
+
332: elsif options.include?(:optional) and
|
416
|
+
333: not options.include?(:allow_trailing) and
|
417
|
+
334: not options.include?(:repeated)
|
418
|
+
335: then
|
419
|
+
336: min = signature.size
|
420
|
+
337: max = signature.size + options[:optional].size
|
421
|
+
338: msg = "wrong number of arguments (\#{args.size} for " +
|
422
|
+
339: "#{min} upto #{max})"
|
423
|
+
340: %{unless args.size.between?(#{min}, #{max})
|
424
|
+
341: raise(ArgumentError, "#{msg}")
|
425
|
+
342: end
|
426
|
+
343: }
|
427
|
+
344: elsif signature.size > 0 then
|
428
|
+
345: msg = "wrong number of arguments (\#{args.size} for " +
|
429
|
+
346: "at least #{signature.size}"
|
430
|
+
347: %{if args.size < #{signature.size} then
|
431
|
+
348: raise(ArgumentError, "#{msg}")
|
432
|
+
349: end
|
433
|
+
350: }
|
434
|
+
351: end
|
435
|
+
352: }
|
436
|
+
353:
|
437
|
+
354: #{index = 0
|
438
|
+
355: signature.map do |part|
|
439
|
+
356: next if part == :any
|
440
|
+
357: index += 1
|
441
|
+
358: msg = "argument #{index} (\#{arg.inspect}) does not match " +
|
442
|
+
359: "#{part.inspect}"
|
443
|
+
360: %{type = ObjectSpace._id2ref(#{part.object_id})
|
444
|
+
361: arg = args.shift
|
445
|
+
362: unless type === #{adapted[%{arg}, %{type}, %{old_args[#{index - 1}]}]}
|
446
|
+
363: raise(ArgumentError, "#{msg}")
|
447
|
+
364: end
|
448
|
+
365: }
|
449
|
+
366: end
|
450
|
+
367: }
|
451
|
+
368:
|
452
|
+
369: #{%{catch(:args_exhausted) do} if options.include?(:optional)}
|
453
|
+
370: #{if optional = options[:optional] then
|
454
|
+
371: index = 0
|
455
|
+
372: optional.map do |part|
|
456
|
+
373: next if part == :any
|
457
|
+
374: index += 1
|
458
|
+
375: msg = "argument #{index + signature.size} " +
|
459
|
+
376: "(\#{arg.inspect}) does not match #{part.inspect}"
|
460
|
+
377: oa_index = index + signature.size - 1
|
461
|
+
378:
|
462
|
+
379: %{throw(:args_exhausted) if args.empty?
|
463
|
+
380: type = ObjectSpace._id2ref(#{part.object_id})
|
464
|
+
381: arg = args.shift
|
465
|
+
382: unless type === #{adapted[%{arg}, %{type}, %{old_args[#{oa_index}]}]}
|
466
|
+
383: raise(ArgumentError, "#{msg}")
|
467
|
+
384: end
|
468
|
+
385: }
|
469
|
+
386: end
|
470
|
+
387: end
|
471
|
+
388: }
|
472
|
+
389:
|
473
|
+
390: #{if repeated = options[:repeated] then
|
474
|
+
391: arg_off = 1 + signature.size
|
475
|
+
392: arg_off += options[:optional].size if options.include?(:optional)
|
476
|
+
393: msg = "argument \#{idx + #{arg_off}} " +
|
477
|
+
394: "(\#{arg.inspect}) does not match \#{part.inspect}"
|
478
|
+
395: %{parts = ObjectSpace._id2ref(#{repeated.object_id})
|
479
|
+
396: args.each_with_index do |arg, idx|
|
480
|
+
397: part = parts[idx % #{repeated.size}]
|
481
|
+
398: if part != :any and
|
482
|
+
399: not part === (#{adapted[%{arg}, %{part}, %{old_args[idx]}]})
|
483
|
+
400: then
|
484
|
+
401: raise(ArgumentError, "#{msg}")
|
485
|
+
402: end
|
486
|
+
403: end
|
487
|
+
404: }
|
488
|
+
405: end
|
489
|
+
406: }
|
490
|
+
407: #{%{end} if options.include?(:optional)}
|
491
|
+
408:
|
492
|
+
409: result = ObjectSpace._id2ref(#{old_method.object_id}).bind(self).
|
493
|
+
410: call(*old_args, &block)
|
494
|
+
411: #{if rt = options[:return] and rt != :any then
|
495
|
+
412: msg = "return value (\#{result.inspect}) does not match #{rt.inspect}"
|
496
|
+
413: %{type = ObjectSpace._id2ref(#{rt.object_id})
|
497
|
+
414: unless type === #{adapted[%{result}, %{type}]}
|
498
|
+
415: raise(StandardError, "#{msg}")
|
499
|
+
416: end
|
500
|
+
417: }
|
501
|
+
418: end
|
502
|
+
419: }
|
503
|
+
420: end
|
504
|
+
421: }</span>
|
505
|
+
422: <span class="ruby-identifier">class_eval</span> <span class="ruby-identifier">code</span>, <span class="ruby-node">"(signature check for #{old_method.inspect[/: (.+?)>\Z/, 1]})"</span>
|
506
|
+
423:
|
507
|
+
424: <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">true</span>
|
508
|
+
425: <span class="ruby-keyword kw">end</span>
|
509
|
+
</pre>
|
510
|
+
</div>
|
511
|
+
</div>
|
512
|
+
</div>
|
513
|
+
|
514
|
+
|
515
|
+
</div>
|
516
|
+
|
517
|
+
|
518
|
+
</div>
|
519
|
+
|
520
|
+
|
521
|
+
<div id="validator-badges">
|
522
|
+
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
523
|
+
</div>
|
524
|
+
|
525
|
+
</body>
|
526
|
+
</html>
|