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/plugin.rb
CHANGED
@@ -1,149 +1,149 @@
|
|
1
1
|
module NeuronCheckSystem
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
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
|
-
|
2
|
+
# 追加されたキーワード全てが動的に定義されていくモジュール
|
3
|
+
module Keywords
|
4
|
+
end
|
5
|
+
|
6
|
+
module Plugin
|
7
|
+
|
8
|
+
# NeuronCheckへ登録したキーワード(Symbol)と、それに対応するKeywordクラスの対応を格納したマップ
|
9
|
+
KEYWORD_CLASSES = {}
|
10
|
+
|
11
|
+
# キーワードの追加
|
12
|
+
def self.add_keyword(name, &block)
|
13
|
+
# すでに予約済みのキーワードであればエラー
|
14
|
+
if KEYWORD_CLASSES[name] then
|
15
|
+
raise PluginError, "the `#{name}' keyword has been already reserved"
|
16
|
+
end
|
17
|
+
|
18
|
+
# キーワードを表すクラスを作成
|
19
|
+
keyword_class = Class.new(Keyword, &block)
|
20
|
+
|
21
|
+
# 必要なインスタンスメソッドが全て定義されているかどうかを確認
|
22
|
+
if not keyword_class.method_defined?(:on_call) or
|
23
|
+
not keyword_class.method_defined?(:match?) or
|
24
|
+
not keyword_class.method_defined?(:expected_caption) then
|
25
|
+
raise PluginError, "##{__callee__} requires 3 method definitions - `on_call', `match?' and `expected_caption'"
|
26
|
+
end
|
27
|
+
|
28
|
+
# キーワードを登録
|
29
|
+
keyword_class.instance_variable_set(:@keyword_name, name)
|
30
|
+
KEYWORD_CLASSES[name] = keyword_class
|
31
|
+
|
32
|
+
# キーワードメソッドを定義
|
33
|
+
__define_keyword_method_to_module(name, keyword_class)
|
34
|
+
end
|
35
|
+
|
36
|
+
# キーワードの別名を定義
|
37
|
+
def self.alias_keyword(name, original_keyword_name)
|
38
|
+
# すでに予約済みのキーワードであればエラー
|
39
|
+
if KEYWORD_CLASSES[name] then
|
40
|
+
raise PluginError, "the `#{name}' keyword has been already reserved"
|
41
|
+
end
|
42
|
+
|
43
|
+
# 元キーワードが、自分が追加したキーワードの中になければエラー
|
44
|
+
unless KEYWORD_CLASSES[original_keyword_name] then
|
45
|
+
raise PluginError, "the `#{original_keyword_name}' keyword hasn't been reserved yet"
|
46
|
+
end
|
47
|
+
|
48
|
+
# 継承して別名クラスを作成
|
49
|
+
keyword_class = Class.new(KEYWORD_CLASSES[original_keyword_name])
|
50
|
+
keyword_class.instance_variable_set(:@keyword_name, name)
|
51
|
+
KEYWORD_CLASSES[name] = keyword_class
|
52
|
+
|
53
|
+
# キーワードメソッドを定義
|
54
|
+
__define_keyword_method_to_module(name, keyword_class)
|
55
|
+
end
|
56
|
+
|
57
|
+
# キーワード用のメソッドをKeywordモジュールへ定義する
|
58
|
+
def self.__define_keyword_method_to_module(name, keyword_class)
|
59
|
+
Keywords.module_eval do
|
60
|
+
define_method(name) do |*params|
|
61
|
+
# キーワードを生成
|
62
|
+
kw = keyword_class.new
|
63
|
+
|
64
|
+
# そのキーワードのon_callメソッドを実行
|
65
|
+
kw.on_call(*params)
|
66
|
+
|
67
|
+
# キーワードを返す
|
68
|
+
kw
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# キーワードの削除
|
74
|
+
def self.remove_keyword(name)
|
75
|
+
# 自分が追加したキーワードの中になければエラー
|
76
|
+
unless KEYWORD_CLASSES[name] then
|
77
|
+
raise PluginError, "the `#{name}' keyword hasn't been reserved yet"
|
78
|
+
end
|
79
|
+
|
80
|
+
# 組み込みキーワードを削除使用とした場合はエラー
|
81
|
+
if KEYWORD_CLASSES[name].builtin_keyword? then
|
82
|
+
raise PluginError, "the `#{name}' keyword cannot be removed because it is NeuronCheck builtin keyword"
|
83
|
+
end
|
84
|
+
|
85
|
+
# キーワードを表すクラスを削除
|
86
|
+
KEYWORD_CLASSES.delete(name)
|
87
|
+
|
88
|
+
# キーワードメソッドの定義を削除
|
89
|
+
Keywords.module_eval do
|
90
|
+
remove_method(name)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# キーワードクラス
|
95
|
+
class Keyword
|
96
|
+
attr_accessor :api
|
97
|
+
|
98
|
+
def expected_short_caption
|
99
|
+
expected_caption
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_params_as_json
|
103
|
+
{}
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.builtin_keyword?
|
107
|
+
false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# キーワードの処理内で使用可能なAPI
|
112
|
+
class KeywordAPI
|
113
|
+
def initialize(declared_caller_locations, method_self_object = nil)
|
114
|
+
@declared_caller_locations = declared_caller_locations
|
115
|
+
@method_self_object = method_self_object
|
116
|
+
end
|
117
|
+
|
118
|
+
def get_appropriate_matcher(expected_value)
|
119
|
+
NeuronCheckSystem.get_appropriate_matcher(expected_value, @declared_caller_locations)
|
120
|
+
end
|
121
|
+
|
122
|
+
def expected_value_match?(value, expected_value)
|
123
|
+
get_appropriate_matcher(expected_value).match?(value, @method_self_object)
|
124
|
+
end
|
125
|
+
|
126
|
+
def get_expected_value_caption(expected_value)
|
127
|
+
get_appropriate_matcher(expected_value).expected_caption
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
def get_expected_value_short_caption(expected_value)
|
132
|
+
get_appropriate_matcher(expected_value).expected_short_caption
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
def get_expected_value_meta_info_as_json(expected_value)
|
137
|
+
get_appropriate_matcher(expected_value).meta_info_as_json
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
142
|
end
|
143
143
|
|
144
144
|
module NeuronCheck
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
145
|
+
# プラグイン有効化
|
146
|
+
def self.enable_plugin(plugin_name)
|
147
|
+
require "neuroncheck/plugin/#{plugin_name}"
|
148
|
+
end
|
149
149
|
end
|
data/lib/neuroncheck/syntax.rb
CHANGED
@@ -2,48 +2,48 @@ require 'neuroncheck/builtin_keyword'
|
|
2
2
|
|
3
3
|
# NeuronCheckSyntaxはruby 2.0以前では使用しない (Refinementが実験的機能として定義されているため)
|
4
4
|
unless RUBY_VERSION <= '2.0.9' then
|
5
|
-
|
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
|
-
|
5
|
+
NeuronCheckSystem::RUBY_TOPLEVEL = self
|
6
|
+
|
7
|
+
module NeuronCheckSyntax
|
8
|
+
refine Module do
|
9
|
+
# NeuronCheckの宣言用キーワードを、コード内の全箇所で使用可能にする
|
10
|
+
include NeuronCheckSystem::Keywords
|
11
|
+
|
12
|
+
# ndecl宣言 (このメソッドは初回実行時のみ呼び出されることに注意。1度ndeclを実行したら、次以降はNeuronCheckSystem::DeclarationMethodsの方が有効になるため、そちらが呼ばれる)
|
13
|
+
def ndecl(*expecteds, &block)
|
14
|
+
# モジュール/クラス内の場合の処理
|
15
|
+
# extend NeuronCheckが実行されていない未初期化の場合、NeuronCheck用の初期化を自動実行
|
16
|
+
unless @__neuron_check_extended then
|
17
|
+
extend NeuronCheck
|
18
|
+
end
|
19
|
+
|
20
|
+
# メイン処理実行
|
21
|
+
__neuroncheck_ndecl_main(expecteds, block, caller(1, 1))
|
22
|
+
end
|
23
|
+
|
24
|
+
alias ndeclare ndecl
|
25
|
+
alias ncheck ndecl
|
26
|
+
alias ntypesig ndecl
|
27
|
+
alias nsig ndecl
|
28
|
+
|
29
|
+
alias decl ndecl
|
30
|
+
alias declare ndecl
|
31
|
+
alias sig ndecl
|
32
|
+
end
|
33
|
+
|
34
|
+
# トップレベル定義のエイリアス
|
35
|
+
refine NeuronCheckSystem::RUBY_TOPLEVEL.singleton_class do
|
36
|
+
def decl(*expecteds, &block)
|
37
|
+
ndecl(*expecteds, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def declare(*expecteds, &block)
|
41
|
+
ndecl(*expecteds, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
def sig(*expecteds, &block)
|
45
|
+
ndecl(*expecteds, &block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
49
|
end
|
data/lib/neuroncheck/utils.rb
CHANGED
@@ -1,92 +1,92 @@
|
|
1
1
|
module NeuronCheckSystem
|
2
|
-
|
3
|
-
|
2
|
+
module Utils
|
3
|
+
module_function
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
5
|
+
# From ActiveSupport (Thanks for Rails Team!) <https://github.com/rails/rails/tree/master/activesupport>
|
6
|
+
#
|
7
|
+
# Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>:
|
8
|
+
#
|
9
|
+
# 'Once upon a time in a world far far away'.truncate(27)
|
10
|
+
# # => "Once upon a time in a wo..."
|
11
|
+
#
|
12
|
+
# Pass a string or regexp <tt>:separator</tt> to truncate +text+ at a natural break:
|
13
|
+
#
|
14
|
+
# 'Once upon a time in a world far far away'.truncate(27, separator: ' ')
|
15
|
+
# # => "Once upon a time in a..."
|
16
|
+
#
|
17
|
+
# 'Once upon a time in a world far far away'.truncate(27, separator: /\s/)
|
18
|
+
# # => "Once upon a time in a..."
|
19
|
+
#
|
20
|
+
# The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
|
21
|
+
# for a total length not exceeding <tt>length</tt>:
|
22
|
+
#
|
23
|
+
# 'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
|
24
|
+
# # => "And they f... (continued)"
|
25
|
+
def truncate(str, truncate_at, omission: '...', separator: nil)
|
26
|
+
return str.dup unless str.length > truncate_at
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
28
|
+
omission = omission || '...'
|
29
|
+
length_with_room_for_omission = truncate_at - omission.length
|
30
|
+
stop = \
|
31
|
+
if separator
|
32
|
+
rindex(separator, length_with_room_for_omission) || length_with_room_for_omission
|
33
|
+
else
|
34
|
+
length_with_room_for_omission
|
35
|
+
end
|
36
36
|
|
37
|
-
|
38
|
-
|
37
|
+
"#{str[0, stop]}#{omission}"
|
38
|
+
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
40
|
+
# 1つ以上の文字列をorで結んだ英語文字列にする
|
41
|
+
def string_join_using_or_conjunction(strings)
|
42
|
+
ret = ""
|
43
|
+
strings.each_with_index do |str, i|
|
44
|
+
case i
|
45
|
+
when 0 # 最初の要素
|
46
|
+
when strings.size - 1 # 最後の要素
|
47
|
+
ret << " or "
|
48
|
+
else
|
49
|
+
ret << ", "
|
50
|
+
end
|
51
51
|
|
52
|
-
|
53
|
-
|
52
|
+
ret << str
|
53
|
+
end
|
54
54
|
|
55
|
-
|
56
|
-
|
55
|
+
ret
|
56
|
+
end
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
58
|
+
# Thread::Backtrace::Locationのリストを文字列形式に変換。フレーム数が多すぎる場合は途中を省略
|
59
|
+
def backtrace_locations_to_captions(locations)
|
60
|
+
locs = nil
|
61
|
+
if locations.size > 9 then
|
62
|
+
locs = (locations[0..3].map{|x| "from #{x.to_s}"} + [" ... (#{locations.size - 8} frames) ..."] + locations[-4..-1].map{|x| "from #{x.to_s}"})
|
63
|
+
else
|
64
|
+
locs = locations.map{|x| "from #{x.to_s}"}
|
65
|
+
end
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
if locs.size >= 1 then
|
68
|
+
locs.first.sub!(/\A\s*from /, '')
|
69
|
+
end
|
70
70
|
|
71
|
-
|
72
|
-
|
71
|
+
locs
|
72
|
+
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
74
|
+
# 指定した整数値を序数文字列にする
|
75
|
+
def ordinalize(v)
|
76
|
+
if [11,12,13].include?(v % 100)
|
77
|
+
"#{v}th"
|
78
|
+
else
|
79
|
+
case (v % 10)
|
80
|
+
when 1
|
81
|
+
"#{v}st"
|
82
|
+
when 2
|
83
|
+
"#{v}nd"
|
84
|
+
when 3
|
85
|
+
"#{v}rd"
|
86
|
+
else
|
87
|
+
"#{v}th"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
92
|
end
|