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
data/lib/neuroncheck/matcher.rb
CHANGED
@@ -3,243 +3,243 @@ require 'neuroncheck/utils'
|
|
3
3
|
require 'neuroncheck/plugin'
|
4
4
|
|
5
5
|
module NeuronCheckSystem
|
6
|
-
|
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
|
-
|
6
|
+
# 期待する値に対応する、適切なマッチャを取得
|
7
|
+
def self.get_appropriate_matcher(expected, declared_caller_locations)
|
8
|
+
case expected
|
9
|
+
when DeclarationContext # 誤って「self」と記載した場合
|
10
|
+
raise DeclarationError, "`self` cannot be used in declaration - use `:self` instead"
|
11
|
+
when :self # self
|
12
|
+
SelfMatcher.new(declared_caller_locations) # 値がselfであるかどうかチェック
|
13
|
+
|
14
|
+
when String, Symbol, Integer
|
15
|
+
ValueEqualMatcher.new(expected, declared_caller_locations) # 値が等しいかどうかをチェック
|
16
|
+
when true, false, nil
|
17
|
+
ObjectIdenticalMathcer.new(expected, declared_caller_locations) # オブジェクトが同一かどうかをチェック
|
18
|
+
when Class, Module
|
19
|
+
KindOfMatcher.new(expected, declared_caller_locations) # 所属/継承しているかどうかをチェック
|
20
|
+
when Range
|
21
|
+
RangeMatcher.new(expected, declared_caller_locations) # 範囲チェック
|
22
|
+
when Regexp
|
23
|
+
RegexpMatcher.new(expected, declared_caller_locations) # 正規表現チェック
|
24
|
+
# when Encoding
|
25
|
+
# EncodingMatcher.new(expected, declared_caller_locations) # エンコーディングチェック
|
26
|
+
|
27
|
+
when Array
|
28
|
+
OrMatcher.new(expected, declared_caller_locations) # ORチェック
|
29
|
+
|
30
|
+
when Plugin::Keyword # プラグインによって登録されたキーワードの場合
|
31
|
+
KeywordPluginMatcher.new(expected, declared_caller_locations)
|
32
|
+
|
33
|
+
else
|
34
|
+
raise DeclarationError, "#{expected.class.name} cannot be usable for NeuronCheck check parameter\n value: #{expected.inspect}"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
class MatcherBase
|
40
|
+
attr_accessor :declared_caller_locations
|
41
|
+
|
42
|
+
def initialize(expected, declared_caller_locations)
|
43
|
+
@expected = expected
|
44
|
+
@declared_caller_locations = declared_caller_locations
|
45
|
+
end
|
46
|
+
|
47
|
+
def match?(value, self_object)
|
48
|
+
raise NotImplementedError
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_error_message(signature_decl, context_caption, value, phrase_after_but: 'was')
|
52
|
+
locs = Utils.backtrace_locations_to_captions(@declared_caller_locations)
|
53
|
+
|
54
|
+
ret = ""
|
55
|
+
ret.concat(<<MSG)
|
56
56
|
#{context_caption} must be #{expected_caption}, but #{phrase_after_but} #{Utils.truncate(value.inspect, 40)}
|
57
57
|
got: #{value.inspect}
|
58
58
|
MSG
|
59
59
|
|
60
|
-
|
61
|
-
|
60
|
+
if signature_decl and signature_decl.assigned_method then
|
61
|
+
ret.concat(<<MSG)
|
62
62
|
signature: #{signature_decl.signature_caption}
|
63
63
|
MSG
|
64
|
-
|
64
|
+
end
|
65
65
|
|
66
|
-
|
67
|
-
|
66
|
+
if locs.size >= 1 then
|
67
|
+
ret.concat(<<MSG)
|
68
68
|
declared at: #{locs.join("\n" + ' ' * 15)}
|
69
69
|
|
70
70
|
MSG
|
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
|
-
|
71
|
+
end
|
72
|
+
|
73
|
+
ret
|
74
|
+
end
|
75
|
+
|
76
|
+
def expected_caption
|
77
|
+
raise NotImplementedError
|
78
|
+
end
|
79
|
+
|
80
|
+
def expected_short_caption
|
81
|
+
@expected.inspect
|
82
|
+
end
|
83
|
+
|
84
|
+
def meta_info_as_json
|
85
|
+
re = {}
|
86
|
+
re['type'] = self.class.name.split('::')[-1]
|
87
|
+
re['expected'] = @expected
|
88
|
+
|
89
|
+
re
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# 値が == で等しいことを判定する
|
94
|
+
class ValueEqualMatcher < MatcherBase
|
95
|
+
def match?(value, self_object)
|
96
|
+
@expected == value
|
97
|
+
end
|
98
|
+
|
99
|
+
def expected_caption
|
100
|
+
@expected.inspect
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# オブジェクトとして同一であることを判定する
|
105
|
+
class ObjectIdenticalMathcer < MatcherBase
|
106
|
+
def match?(value, self_object)
|
107
|
+
@expected.equal?(value)
|
108
|
+
end
|
109
|
+
|
110
|
+
def expected_caption
|
111
|
+
@expected.inspect
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# 値が指定されたClass / Moduleに所属していることを判定する (kind_of?判定)
|
116
|
+
class KindOfMatcher < MatcherBase
|
117
|
+
def match?(value, self_object)
|
118
|
+
value.kind_of?(@expected)
|
119
|
+
end
|
120
|
+
|
121
|
+
def expected_caption
|
122
|
+
@expected.name
|
123
|
+
end
|
124
|
+
|
125
|
+
def meta_info_as_json
|
126
|
+
super.update('expected' => @expected.name)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
# 指定した範囲に含まれている値であることを判定する
|
132
|
+
class RangeMatcher < MatcherBase
|
133
|
+
def match?(value, self_object)
|
134
|
+
@expected.include?(value)
|
135
|
+
end
|
136
|
+
|
137
|
+
def expected_caption
|
138
|
+
"included in #{@expected.inspect}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# 指定した正規表現にマッチする文字列であることを判定する
|
143
|
+
class RegexpMatcher < MatcherBase
|
144
|
+
def match?(value, self_object)
|
145
|
+
(value.kind_of?(String) and @expected =~ value)
|
146
|
+
end
|
147
|
+
|
148
|
+
def expected_caption
|
149
|
+
"String that matches with #{@expected.inspect}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# # 指定したエンコーディングを持つ文字列であることを判定する
|
154
|
+
# class EncodingMatcher < MatcherBase
|
155
|
+
# def match?(value, self_object)
|
156
|
+
# (value.kind_of?(String) and Encoding.compatible?(value, @expected))
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# def expected_caption
|
160
|
+
# "String that is compatible #{@expected.name} encoding"
|
161
|
+
# end
|
162
|
+
#
|
163
|
+
# def expected_short_caption
|
164
|
+
# "String compatible to #{@expected.name}"
|
165
|
+
# end
|
166
|
+
#
|
167
|
+
# end
|
168
|
+
|
169
|
+
# OR条件。渡されたマッチャ複数のうち、どれか1つでも条件を満たせばOK
|
170
|
+
class OrMatcher < MatcherBase
|
171
|
+
def initialize(child_expecteds, declared_caller_locations)
|
172
|
+
@child_matchers = child_expecteds.map{|x| NeuronCheckSystem.get_appropriate_matcher(x, declared_caller_locations)}
|
173
|
+
@declared_caller_locations = declared_caller_locations
|
174
|
+
end
|
175
|
+
|
176
|
+
def match?(value, self_object)
|
177
|
+
# どれか1つにマッチすればOK
|
178
|
+
@child_matchers.any?{|x| x.match?(value, self_object)}
|
179
|
+
end
|
180
|
+
|
181
|
+
def expected_caption
|
182
|
+
captions = @child_matchers.map{|x| x.expected_caption}
|
183
|
+
|
184
|
+
Utils.string_join_using_or_conjunction(captions)
|
185
|
+
end
|
186
|
+
def expected_short_caption
|
187
|
+
'[' + @child_matchers.map{|x| x.expected_short_caption}.join(', ') + ']'
|
188
|
+
end
|
189
|
+
|
190
|
+
def meta_info_as_json
|
191
|
+
super.update('child_matchers' => @child_matchers.map{|x| x.meta_info_as_json})
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
# selfであるかどうかを判定 (通常はreturns用)
|
197
|
+
class SelfMatcher < MatcherBase
|
198
|
+
def initialize(declared_caller_locations)
|
199
|
+
@declared_caller_locations = declared_caller_locations
|
200
|
+
end
|
201
|
+
|
202
|
+
def match?(value, self_object)
|
203
|
+
self_object.equal?(value)
|
204
|
+
end
|
205
|
+
|
206
|
+
def expected_caption
|
207
|
+
"self"
|
208
|
+
end
|
209
|
+
def expected_short_caption
|
210
|
+
"self"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# プラグインで追加されたキーワード用
|
215
|
+
class KeywordPluginMatcher < MatcherBase
|
216
|
+
def initialize(keyword, declared_caller_locations)
|
217
|
+
@keyword = keyword
|
218
|
+
@declared_caller_locations = declared_caller_locations
|
219
|
+
end
|
220
|
+
|
221
|
+
def match?(value, self_object)
|
222
|
+
@keyword.api = Plugin::KeywordAPI.new(@declared_caller_locations, self_object)
|
223
|
+
@keyword.match?(value)
|
224
|
+
end
|
225
|
+
|
226
|
+
def expected_caption
|
227
|
+
@keyword.api = Plugin::KeywordAPI.new(@declared_caller_locations)
|
228
|
+
@keyword.expected_caption
|
229
|
+
end
|
230
|
+
|
231
|
+
def expected_short_caption
|
232
|
+
@keyword.api = Plugin::KeywordAPI.new(@declared_caller_locations)
|
233
|
+
@keyword.expected_short_caption
|
234
|
+
end
|
235
|
+
|
236
|
+
def meta_info_as_json
|
237
|
+
@keyword.api = Plugin::KeywordAPI.new(@declared_caller_locations)
|
238
|
+
super.update('keyword' => keyword_name, 'expected_caption' => expected_caption).tap{|x| x.delete('expected')}.update(@keyword.get_params_as_json)
|
239
|
+
end
|
240
|
+
|
241
|
+
def keyword_name
|
242
|
+
(@keyword.class).instance_variable_get(:@keyword_name).to_s
|
243
|
+
end
|
244
|
+
end
|
245
245
|
end
|