neuroncheck 0.1.0 → 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.
- checksums.yaml +4 -4
- data/lib/neuroncheck/builtin_keyword.rb +55 -55
- data/lib/neuroncheck/cond_block.rb +30 -30
- data/lib/neuroncheck/declaration.rb +288 -288
- data/lib/neuroncheck/error.rb +6 -6
- data/lib/neuroncheck/kernel.rb +598 -598
- data/lib/neuroncheck/matcher.rb +229 -229
- data/lib/neuroncheck/plugin.rb +144 -144
- data/lib/neuroncheck/syntax.rb +44 -44
- data/lib/neuroncheck/utils.rb +80 -80
- data/lib/neuroncheck/version.rb +1 -1
- data/test/test_advanced_syntactical.rb +101 -101
- data/test/test_inheritance.rb +140 -140
- data/test/test_main.rb +863 -863
- data/test/test_main_syntax.rb +219 -219
- data/test/test_plugin.rb +77 -77
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d973bb5daf0142efc6ec453f3cec14766e4419f7
|
4
|
+
data.tar.gz: 55bfaa6ef9d5fe5bff49a6f9d5c51d907136c8cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b87e50fcfa401cd18f17f766248c305b1585d4c86effa564ac1fc4ec0b6a5261930fcefe37dd5a65fd5e06a9183ce939556bfb0e0af3c8ffa69aaffcb91cf88
|
7
|
+
data.tar.gz: e05cc9382ec1d88a8a5084cf5209a7758c3be5557b68c01a94f65abad6e200a124fc0281045028c554257de33c85c50d96933a7f768cb5b1978d4ca942349557
|
@@ -5,7 +5,7 @@ require 'neuroncheck/plugin'
|
|
5
5
|
# respondable: 指定した名前のメソッドが定義されている(メソッド呼び出しに応答可能である)ことを表す。Duck Typing用
|
6
6
|
NeuronCheckSystem::Plugin.add_keyword(:respondable) do
|
7
7
|
def on_call(*method_names)
|
8
|
-
|
8
|
+
@method_names = method_names
|
9
9
|
end
|
10
10
|
|
11
11
|
def match?(value)
|
@@ -13,21 +13,21 @@ NeuronCheckSystem::Plugin.add_keyword(:respondable) do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def expected_caption
|
16
|
-
|
17
|
-
|
16
|
+
in_cap = NeuronCheckSystem::Utils.string_join_using_or_conjunction(@method_names.map{|x| "##{x}"}) # 複数の文字列を結合し、orを使ったフレーズの形にするUtilityメソッド。 ['A', 'B', 'C'] => "A, B or C"
|
17
|
+
"respondable to #{in_cap}"
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
def expected_short_caption
|
21
21
|
'respondable(' + @method_names.map{|x| x.inspect}.join(', ') + ')'
|
22
22
|
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
def get_params_as_json
|
25
|
+
{'expected' => @method_names.map(&:to_s)}
|
26
|
+
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def self.builtin_keyword?
|
29
|
+
true
|
30
|
+
end
|
31
31
|
end
|
32
32
|
|
33
33
|
# respond_to, res: respondableのエイリアス
|
@@ -46,17 +46,17 @@ NeuronCheckSystem::Plugin.add_keyword(:any) do
|
|
46
46
|
"any value"
|
47
47
|
end
|
48
48
|
|
49
|
-
|
49
|
+
def expected_short_caption
|
50
50
|
"any"
|
51
51
|
end
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
def get_params_as_json
|
54
|
+
{}
|
55
|
+
end
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
def self.builtin_keyword?
|
58
|
+
true
|
59
|
+
end
|
60
60
|
end
|
61
61
|
|
62
62
|
# block: ブロック引数用の特殊なキーワード。[Proc, nil]と同じ
|
@@ -72,16 +72,16 @@ NeuronCheckSystem::Plugin.add_keyword(:block) do
|
|
72
72
|
"block or nil"
|
73
73
|
end
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
75
|
+
def self.builtin_keyword?
|
76
|
+
true
|
77
|
+
end
|
78
78
|
end
|
79
79
|
|
80
80
|
|
81
81
|
# except: 指定した値以外を許可 (否定 / NOT)
|
82
82
|
NeuronCheckSystem::Plugin.add_keyword(:except) do
|
83
83
|
def on_call(target)
|
84
|
-
|
84
|
+
@target = target
|
85
85
|
end
|
86
86
|
|
87
87
|
def match?(value)
|
@@ -92,74 +92,74 @@ NeuronCheckSystem::Plugin.add_keyword(:except) do
|
|
92
92
|
"any value except #{@api.get_expected_value_caption(@target)}"
|
93
93
|
end
|
94
94
|
|
95
|
-
|
95
|
+
def expected_short_caption
|
96
96
|
"except(#{@api.get_expected_value_short_caption(@target)})"
|
97
97
|
end
|
98
98
|
|
99
|
-
|
100
|
-
|
101
|
-
|
99
|
+
def get_params_as_json
|
100
|
+
{'target' => @api.get_expected_value_meta_info_as_json(@target)}
|
101
|
+
end
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
103
|
+
def self.builtin_keyword?
|
104
|
+
true
|
105
|
+
end
|
106
106
|
end
|
107
107
|
|
108
108
|
|
109
109
|
# array_of: 指定した種類の値のみを格納した配列であることを表す
|
110
110
|
NeuronCheckSystem::Plugin.add_keyword(:array_of) do
|
111
111
|
def on_call(item_expected)
|
112
|
-
|
112
|
+
@item_expected = item_expected
|
113
113
|
end
|
114
114
|
|
115
115
|
def match?(value)
|
116
|
-
|
116
|
+
return false unless value.kind_of?(Array) # まずは配列であるかどうかチェック
|
117
117
|
|
118
|
-
|
119
|
-
|
118
|
+
# 配列であれば、1つ1つの値が型どおりであるかどうかをチェック
|
119
|
+
return value.all?{|x| @api.expected_value_match?(x, @item_expected)}
|
120
120
|
end
|
121
121
|
|
122
122
|
def expected_caption
|
123
123
|
"array of #{@api.get_expected_value_caption(@item_expected)}"
|
124
124
|
end
|
125
125
|
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
def get_params_as_json
|
127
|
+
{'item' => @api.get_expected_value_meta_info_as_json(@item_expected)}
|
128
|
+
end
|
129
129
|
|
130
|
-
|
131
|
-
|
132
|
-
|
130
|
+
def self.builtin_keyword?
|
131
|
+
true
|
132
|
+
end
|
133
133
|
end
|
134
134
|
|
135
135
|
|
136
136
|
# hash_of: 指定した種類のキーと値のみを格納した配列であることを表す
|
137
137
|
NeuronCheckSystem::Plugin.add_keyword(:hash_of) do
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
def on_call(key_expected, value_expected)
|
139
|
+
@key_expected = key_expected
|
140
|
+
@value_expected = value_expected
|
141
141
|
end
|
142
142
|
|
143
|
-
|
144
|
-
|
143
|
+
def match?(value)
|
144
|
+
return false unless value.kind_of?(Hash) # まずはHashであるかどうかチェック
|
145
145
|
|
146
|
-
|
147
|
-
|
146
|
+
# ハッシュであれば、1つ1つのキーと値をチェック
|
147
|
+
return value.all?{|k, v| @api.expected_value_match?(k, @key_expected) and @api.expected_value_match?(v, @value_expected)}
|
148
148
|
end
|
149
149
|
|
150
|
-
|
151
|
-
|
150
|
+
def expected_caption
|
151
|
+
"hash that has keys of #{@api.get_expected_value_caption(@key_expected)} and values of #{@api.get_expected_value_caption(@value_expected)}, #{expected_short_caption}"
|
152
152
|
end
|
153
153
|
|
154
|
-
|
155
|
-
|
154
|
+
def expected_short_caption
|
155
|
+
"{#{@api.get_expected_value_short_caption(@key_expected)} => #{api.get_expected_value_short_caption(@value_expected)}}"
|
156
156
|
end
|
157
157
|
|
158
|
-
|
159
|
-
|
160
|
-
|
158
|
+
def get_params_as_json
|
159
|
+
{'key' => @api.get_expected_value_meta_info_as_json(@key_expected), 'value' => @api.get_expected_value_meta_info_as_json(@value_expected)}
|
160
|
+
end
|
161
161
|
|
162
|
-
|
163
|
-
|
164
|
-
|
162
|
+
def self.builtin_keyword?
|
163
|
+
true
|
164
|
+
end
|
165
165
|
end
|
@@ -1,42 +1,42 @@
|
|
1
1
|
module NeuronCheckSystem
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
class CondBlockContext
|
3
|
+
def initialize(block_name, method_self, allow_instance_method)
|
4
|
+
@block_name = block_name
|
5
|
+
@method_self = method_self
|
6
|
+
@allow_instance_method = allow_instance_method
|
7
|
+
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
def method_missing(name, *args, &block)
|
10
|
+
if @method_self.respond_to?(name, true) then
|
11
|
+
if @allow_instance_method then
|
12
|
+
@method_self.send(name, *args, &block)
|
13
|
+
else
|
14
|
+
raise NeuronCheckSystem::DeclarationError, "instance method `#{name}' cannot be called in #{@block_name}, it is forbidden", (NeuronCheck.debug? ? caller : caller(1))
|
15
|
+
end
|
16
|
+
else
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
def assert(*dummy)
|
22
|
+
unless block_given? then
|
23
|
+
raise NeuronCheckSystem::DeclarationError, "no block given for `assert' in #{@block_name}", (NeuronCheck.debug? ? caller : caller(1))
|
24
|
+
end
|
25
25
|
|
26
|
-
|
26
|
+
passed = yield
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
unless passed
|
29
|
+
locs = Utils.backtrace_locations_to_captions(caller(1, 1))
|
30
30
|
|
31
|
-
|
31
|
+
msg = <<MSG
|
32
32
|
#{@block_name} assertion failed
|
33
33
|
asserted at: #{locs.join("\n" + ' ' * 15)}
|
34
34
|
|
35
35
|
MSG
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
# エラーを発生させる
|
38
|
+
throw :neuron_check_error_tag, msg
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
42
|
end
|
@@ -4,292 +4,292 @@ require 'neuroncheck/syntax'
|
|
4
4
|
require 'neuroncheck/builtin_keyword'
|
5
5
|
|
6
6
|
module NeuronCheckSystem
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
7
|
+
# 宣言用のメソッドやメソッド追加時の処理を定義したモジュール。NeuronCheckを行いたい対象のモジュールやクラスにextendすることで使用する
|
8
|
+
module DeclarationMethods
|
9
|
+
# 宣言を実行
|
10
|
+
def ndecl(*expecteds, &block)
|
11
|
+
# 未初期化の場合、NeuronCheck用の初期化を自動実行
|
12
|
+
unless @__neuron_check_initialized then
|
13
|
+
NeuronCheckSystem.initialize_module_for_neuron_check(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
# メイン処理実行
|
17
|
+
__neuroncheck_ndecl_main(expecteds, block, caller(1, 1))
|
18
|
+
end
|
19
|
+
|
20
|
+
# ndeclのエイリアス
|
21
|
+
alias ncheck ndecl
|
22
|
+
alias ndeclare ndecl
|
23
|
+
alias nsig ndecl
|
24
|
+
alias ntypesig ndecl
|
25
|
+
|
26
|
+
# ndeclのメイン処理
|
27
|
+
def __neuroncheck_ndecl_main(expecteds, block, declared_caller_locations)
|
28
|
+
# 2回連続で宣言された場合はエラー
|
29
|
+
if @__neuron_check_last_declaration then
|
30
|
+
raise DeclarationError, "repeated declarations - Declaration block and method definition must correspond one-to-one"
|
31
|
+
end
|
32
|
+
|
33
|
+
# ブロックが渡されたかどうかで処理を分岐
|
34
|
+
if block then
|
35
|
+
# ブロックが渡された場合
|
36
|
+
__neuroncheck_ndecl_main_with_block(block, declared_caller_locations)
|
37
|
+
else
|
38
|
+
# 短縮記法はNeuronCheckSyntax使用可能時のみ
|
39
|
+
unless defined?(NeuronCheckSyntax) then
|
40
|
+
raise DeclarationError, "NeuronCheck shorthand syntax (without block) can be used only in Ruby 2.1 or later"
|
41
|
+
end
|
42
|
+
|
43
|
+
# ブロックが渡されていない場合 (短縮記法)
|
44
|
+
__neuroncheck_ndecl_main_without_block(expecteds, declared_caller_locations)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# ndeclの通常記法
|
49
|
+
def __neuroncheck_ndecl_main_with_block(block, declared_caller_locations)
|
50
|
+
# 宣言ブロック実行用のコンテキストを作成
|
51
|
+
context = NeuronCheckSystem::DeclarationContext.new
|
52
|
+
|
53
|
+
# 宣言ブロックの内容を実行
|
54
|
+
context.instance_eval(&block)
|
55
|
+
|
56
|
+
# 呼び出し場所を記憶
|
57
|
+
context.declaration.declared_caller_locations = declared_caller_locations
|
58
|
+
|
59
|
+
# 宣言の内容を「最後の宣言」として保持
|
60
|
+
@__neuron_check_last_declaration = context.declaration
|
61
|
+
end
|
62
|
+
|
63
|
+
# ndeclの短縮記法
|
64
|
+
def __neuroncheck_ndecl_main_without_block(expecteds, declared_caller_locations)
|
65
|
+
# 宣言ブロック実行用のコンテキストを作成
|
66
|
+
context = NeuronCheckSystem::DeclarationContext.new
|
67
|
+
|
68
|
+
# 引数の解釈
|
69
|
+
expected_args = nil
|
70
|
+
expected_return = nil
|
71
|
+
if expecteds.last.kind_of?(Hash) and expecteds.last.size == 1 then
|
72
|
+
# expectedsの最後が、値が1つだけ格納されたHashであれば、キーを最後の引数、値を戻り値と解釈する
|
73
|
+
# 例: String, String => Numeric
|
74
|
+
last_hash = expecteds.pop
|
75
|
+
expected_args = expecteds.concat([last_hash.keys.first])
|
76
|
+
expected_return = last_hash.values.first
|
77
|
+
else
|
78
|
+
# 上記以外の場合はすべて引数と見なす
|
79
|
+
expected_args = expecteds
|
80
|
+
end
|
81
|
+
|
82
|
+
# 引数1つで、かつ空配列が渡された場合は、「引数なし」と宣言されたとみなす
|
83
|
+
if expected_args[0].kind_of?(Array) and expected_args.size == 1 then
|
84
|
+
expected_args = []
|
85
|
+
end
|
86
|
+
|
87
|
+
# 簡易宣言を実行
|
88
|
+
context.instance_eval do
|
89
|
+
unless expected_args.empty? then
|
90
|
+
args *expected_args
|
91
|
+
end
|
92
|
+
|
93
|
+
if expected_return then
|
94
|
+
returns expected_return
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# 短縮記法フラグON
|
99
|
+
context.declaration.shorthand = true
|
100
|
+
|
101
|
+
# 呼び出し場所を記憶
|
102
|
+
context.declaration.declared_caller_locations = declared_caller_locations
|
103
|
+
context.declaration.arg_matchers.each do |matcher|
|
104
|
+
matcher.declared_caller_locations = context.declaration.declared_caller_locations
|
105
|
+
end
|
106
|
+
if context.declaration.return_matcher then
|
107
|
+
context.declaration.return_matcher.declared_caller_locations = context.declaration.declared_caller_locations
|
108
|
+
end
|
109
|
+
|
110
|
+
# 宣言の内容を「最後の宣言」として保持 (通常のndeclと同じ)
|
111
|
+
@__neuron_check_last_declaration = context.declaration
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class DeclarationContext
|
116
|
+
include Keywords
|
117
|
+
attr_reader :declaration
|
118
|
+
|
119
|
+
def initialize
|
120
|
+
@declaration = Declaration.new
|
121
|
+
end
|
122
|
+
|
123
|
+
def args(*expecteds)
|
124
|
+
declared_caller_locations = caller(1, 1)
|
125
|
+
@declaration.arg_matchers = expecteds.map{|x| NeuronCheckSystem.get_appropriate_matcher(x, declared_caller_locations)}
|
126
|
+
end
|
127
|
+
|
128
|
+
def returns(expected)
|
129
|
+
declared_caller_locations = caller(1, 1)
|
130
|
+
@declaration.return_matcher = NeuronCheckSystem.get_appropriate_matcher(expected, declared_caller_locations)
|
131
|
+
end
|
132
|
+
|
133
|
+
def precond(allow_instance_method: false, &cond_block)
|
134
|
+
@declaration.precond = cond_block
|
135
|
+
@declaration.precond_allow_instance_method = allow_instance_method
|
136
|
+
end
|
137
|
+
|
138
|
+
def postcond(allow_instance_method: false, &cond_block)
|
139
|
+
@declaration.postcond = cond_block
|
140
|
+
@declaration.postcond_allow_instance_method = allow_instance_method
|
141
|
+
end
|
142
|
+
|
143
|
+
def val(expected)
|
144
|
+
declared_caller_locations = caller(1, 1)
|
145
|
+
@declaration.attr_matcher = NeuronCheckSystem.get_appropriate_matcher(expected, declared_caller_locations)
|
146
|
+
end
|
147
|
+
alias must_be val
|
148
|
+
alias value val
|
149
|
+
end
|
150
|
+
|
151
|
+
class Declaration
|
152
|
+
attr_accessor :arg_matchers
|
153
|
+
attr_accessor :return_matcher
|
154
|
+
attr_accessor :attr_matcher
|
155
|
+
|
156
|
+
attr_accessor :precond
|
157
|
+
attr_accessor :precond_allow_instance_method
|
158
|
+
attr_accessor :postcond
|
159
|
+
attr_accessor :postcond_allow_instance_method
|
160
|
+
|
161
|
+
attr_accessor :assigned_class_or_module
|
162
|
+
attr_accessor :assigned_method
|
163
|
+
attr_accessor :assigned_singleton_original_class
|
164
|
+
attr_accessor :assigned_attribute_name
|
165
|
+
attr_accessor :shorthand
|
166
|
+
attr_accessor :declared_caller_locations
|
167
|
+
|
168
|
+
|
169
|
+
def initialize
|
170
|
+
@arg_matchers = []
|
171
|
+
@return_matcher = nil
|
172
|
+
@attr_matcher = nil
|
173
|
+
@precond = nil
|
174
|
+
@precond_allow_instance_method = false
|
175
|
+
@postcond = nil
|
176
|
+
@postcond_allow_instance_method = false
|
177
|
+
|
178
|
+
@assigned_class_or_module = nil
|
179
|
+
@assigned_method = nil
|
180
|
+
@assigned_singleton_original_class = nil
|
181
|
+
@assigned_attribute_name = nil
|
182
|
+
|
183
|
+
@shorthand = false
|
184
|
+
@declared_caller_locations = nil
|
185
|
+
end
|
186
|
+
|
187
|
+
def attribute?
|
188
|
+
(@assigned_attribute_name ? true : false)
|
189
|
+
end
|
190
|
+
|
191
|
+
def assinged_to_toplevel_method?
|
192
|
+
@assigned_class_or_module == Object
|
193
|
+
end
|
194
|
+
def assinged_to_singleton_method?
|
195
|
+
@assigned_singleton_original_class
|
196
|
+
end
|
197
|
+
|
198
|
+
# メソッド名/属性名の表記文字列を取得
|
199
|
+
def signature_caption_name_only
|
200
|
+
if @assigned_class_or_module and (@assigned_method or attribute?) then
|
201
|
+
ret = ""
|
202
|
+
|
203
|
+
# 属性、特異メソッド、インスタンスメソッドのそれぞれで処理を分岐
|
204
|
+
if attribute? then
|
205
|
+
if @assigned_class_or_module.name then
|
206
|
+
ret << @assigned_class_or_module.name
|
207
|
+
end
|
208
|
+
|
209
|
+
# 属性名出力
|
210
|
+
ret << "##{@assigned_attribute_name}"
|
211
|
+
|
212
|
+
elsif assinged_to_toplevel_method? then
|
213
|
+
# メソッド名出力
|
214
|
+
ret << "#{@assigned_method.name}"
|
215
|
+
|
216
|
+
elsif assinged_to_singleton_method? then
|
217
|
+
if @assigned_singleton_original_class.name then
|
218
|
+
ret << @assigned_singleton_original_class.name
|
219
|
+
end
|
220
|
+
|
221
|
+
# メソッド名出力
|
222
|
+
ret << ".#{@assigned_method.name}"
|
223
|
+
else
|
224
|
+
if @assigned_class_or_module.name then
|
225
|
+
ret << @assigned_class_or_module.name
|
226
|
+
end
|
227
|
+
|
228
|
+
# メソッド名出力
|
229
|
+
ret << "##{@assigned_method.name}"
|
230
|
+
end
|
231
|
+
else
|
232
|
+
nil
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# メソッド名/属性名+引数+戻り値の表記文字列を取得
|
237
|
+
def signature_caption
|
238
|
+
ret = signature_caption_name_only
|
239
|
+
if ret then
|
240
|
+
if attribute? then
|
241
|
+
|
242
|
+
if @attr_matcher then
|
243
|
+
ret << " -> #{@attr_matcher.expected_short_caption}"
|
244
|
+
end
|
245
|
+
else
|
246
|
+
|
247
|
+
# 引数出力
|
248
|
+
unless @assigned_method.parameters.empty? then
|
249
|
+
ret << "("
|
250
|
+
@assigned_method.parameters.each_with_index do |param_info, i|
|
251
|
+
_, param_name = param_info
|
252
|
+
if i >= 1 then
|
253
|
+
ret << ", "
|
254
|
+
end
|
255
|
+
|
256
|
+
if (matcher = @arg_matchers[i]) then
|
257
|
+
ret << "#{param_name}:#{matcher.expected_short_caption}"
|
258
|
+
else
|
259
|
+
ret << "#{param_name}:any"
|
260
|
+
end
|
261
|
+
end
|
262
|
+
ret << ")"
|
263
|
+
end
|
264
|
+
|
265
|
+
if @return_matcher then
|
266
|
+
ret << " -> #{@return_matcher.expected_short_caption}"
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
return ret
|
271
|
+
else
|
272
|
+
nil
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def meta_info_as_json
|
277
|
+
re = {}
|
278
|
+
|
279
|
+
if attribute? then
|
280
|
+
re['value'] = (@attr_matcher ? @attr_matcher.meta_info_as_json : nil)
|
281
|
+
re['signature_caption'] = signature_caption
|
282
|
+
re['signature_caption_name_only'] = signature_caption_name_only
|
283
|
+
else
|
284
|
+
re['args'] = @arg_matchers.map{|x| x.meta_info_as_json}
|
285
|
+
re['returns'] = (@return_matcher ? @return_matcher.meta_info_as_json : nil)
|
286
|
+
re['signature_caption'] = signature_caption
|
287
|
+
re['signature_caption_name_only'] = signature_caption_name_only
|
288
|
+
end
|
289
|
+
re['precond_source_location'] = (@precond ? @precond.source_location : nil)
|
290
|
+
re['postcond_source_location'] = (@postcond ? @postcond.source_location : nil)
|
291
|
+
|
292
|
+
re
|
293
|
+
end
|
294
|
+
end
|
295
295
|
end
|