neuroncheck 0.1.0
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 +7 -0
- data/Rakefile.rb +54 -0
- data/lib/neuroncheck.rb +1 -0
- data/lib/neuroncheck/builtin_keyword.rb +165 -0
- data/lib/neuroncheck/cond_block.rb +42 -0
- data/lib/neuroncheck/declaration.rb +295 -0
- data/lib/neuroncheck/error.rb +13 -0
- data/lib/neuroncheck/kernel.rb +618 -0
- data/lib/neuroncheck/matcher.rb +245 -0
- data/lib/neuroncheck/plugin.rb +149 -0
- data/lib/neuroncheck/syntax.rb +49 -0
- data/lib/neuroncheck/utils.rb +92 -0
- data/lib/neuroncheck/version.rb +3 -0
- data/test/test_advanced_syntactical.rb +125 -0
- data/test/test_inheritance.rb +153 -0
- data/test/test_main.rb +943 -0
- data/test/test_main_syntax.rb +237 -0
- data/test/test_plugin.rb +88 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 48bfd036b69c0f6d509363762c39a3fda0dc97f4
|
4
|
+
data.tar.gz: 49471c3dd25296b6527572ec6fbf37aa6a896784
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 35c0916e4421893c8f1d175585f08586fd8e66f43d4b93a4ac10a99c65c4cee556c2c4ae49d030b1b23274eceab3a592b8e04182a857fc7405ec71a3b2495f5f
|
7
|
+
data.tar.gz: 7f07bda2153ba07a262fae2afd1b3c6e6e078ff197aab19df8a9bb8445c54043cb3713676c380c4d553c33e997956603781a188c3547e53bab5f97c728175037
|
data/Rakefile.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
Rake.application.instance_variable_get('@tasks').delete('release')
|
4
|
+
|
5
|
+
desc 'Run test_unit based test'
|
6
|
+
task :test do
|
7
|
+
Dir.glob('test/**/test_*.rb') do |path|
|
8
|
+
cmd = "bundle exec ruby #{path}"
|
9
|
+
puts cmd
|
10
|
+
system cmd
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
%w(example example_dev).each do |base_dir_name|
|
15
|
+
|
16
|
+
example_dests = []
|
17
|
+
directory "#{base_dir_name}/"
|
18
|
+
Dir.glob("#{base_dir_name}_src/**/*.rb") do |src|
|
19
|
+
# サブディレクトリを持っているかどうかで処理を分岐
|
20
|
+
dest_dir = "#{base_dir_name}/"
|
21
|
+
if src =~ %r|/.+?/| then
|
22
|
+
dest_dir = File.dirname(src).sub(/^example_src/, 'example')
|
23
|
+
end
|
24
|
+
|
25
|
+
# 出力先を取得
|
26
|
+
dest = src.sub(/^#{base_dir_name}_src/, base_dir_name)
|
27
|
+
example_dests << dest
|
28
|
+
|
29
|
+
# タスク定義
|
30
|
+
directory dest_dir
|
31
|
+
desc '-'
|
32
|
+
file dest => [src, dest_dir, __FILE__] + FileList['lib/**/*.rb'] do
|
33
|
+
# NeuronCheckを使用してスクリプト実行
|
34
|
+
cmd = %Q|bundle exec ruby -I lib #{src}|
|
35
|
+
puts cmd
|
36
|
+
system cmd, [:out, :err] => ['_example_out.txt', 'w']
|
37
|
+
|
38
|
+
# スクリプトの実行の結果、出力された内容を、コメントとして後ろに結合したうえで書き込む
|
39
|
+
# ただしこの際、ファイルパスを置換するなどの加工もかける
|
40
|
+
output_lines = File.readlines('_example_out.txt')
|
41
|
+
output = output_lines.map{|x| "# #{x}"}.join.sub('# ', '#=>')
|
42
|
+
output.gsub!(Dir.pwd, '.')
|
43
|
+
output.gsub!(src, 'script.rb')
|
44
|
+
|
45
|
+
File.write(dest, File.read(src) + "\n" + output)
|
46
|
+
$stderr.puts "-> #{dest}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
desc 'make example code'
|
52
|
+
task base_dir_name => example_dests
|
53
|
+
|
54
|
+
end
|
data/lib/neuroncheck.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'neuroncheck/kernel'
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'neuroncheck/plugin'
|
2
|
+
|
3
|
+
# 組み込みキーワードの定義
|
4
|
+
|
5
|
+
# respondable: 指定した名前のメソッドが定義されている(メソッド呼び出しに応答可能である)ことを表す。Duck Typing用
|
6
|
+
NeuronCheckSystem::Plugin.add_keyword(:respondable) do
|
7
|
+
def on_call(*method_names)
|
8
|
+
@method_names = method_names
|
9
|
+
end
|
10
|
+
|
11
|
+
def match?(value)
|
12
|
+
@method_names.all?{|x| value.respond_to?(x)}
|
13
|
+
end
|
14
|
+
|
15
|
+
def expected_caption
|
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
|
+
end
|
19
|
+
|
20
|
+
def expected_short_caption
|
21
|
+
'respondable(' + @method_names.map{|x| x.inspect}.join(', ') + ')'
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_params_as_json
|
25
|
+
{'expected' => @method_names.map(&:to_s)}
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.builtin_keyword?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# respond_to, res: respondableのエイリアス
|
34
|
+
NeuronCheckSystem::Plugin.alias_keyword(:res, :respondable)
|
35
|
+
|
36
|
+
# any: すべての値を受け付ける
|
37
|
+
NeuronCheckSystem::Plugin.add_keyword(:any) do
|
38
|
+
def on_call
|
39
|
+
end
|
40
|
+
|
41
|
+
def match?(value)
|
42
|
+
true # 常にtrue
|
43
|
+
end
|
44
|
+
|
45
|
+
def expected_caption
|
46
|
+
"any value"
|
47
|
+
end
|
48
|
+
|
49
|
+
def expected_short_caption
|
50
|
+
"any"
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_params_as_json
|
54
|
+
{}
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.builtin_keyword?
|
58
|
+
true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# block: ブロック引数用の特殊なキーワード。[Proc, nil]と同じ
|
63
|
+
NeuronCheckSystem::Plugin.add_keyword(:block) do
|
64
|
+
def on_call
|
65
|
+
end
|
66
|
+
|
67
|
+
def match?(value)
|
68
|
+
@api.expected_value_match?(value, [Proc, nil])
|
69
|
+
end
|
70
|
+
|
71
|
+
def expected_caption
|
72
|
+
"block or nil"
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.builtin_keyword?
|
76
|
+
true
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# except: 指定した値以外を許可 (否定 / NOT)
|
82
|
+
NeuronCheckSystem::Plugin.add_keyword(:except) do
|
83
|
+
def on_call(target)
|
84
|
+
@target = target
|
85
|
+
end
|
86
|
+
|
87
|
+
def match?(value)
|
88
|
+
not @api.expected_value_match?(value, @target)
|
89
|
+
end
|
90
|
+
|
91
|
+
def expected_caption
|
92
|
+
"any value except #{@api.get_expected_value_caption(@target)}"
|
93
|
+
end
|
94
|
+
|
95
|
+
def expected_short_caption
|
96
|
+
"except(#{@api.get_expected_value_short_caption(@target)})"
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_params_as_json
|
100
|
+
{'target' => @api.get_expected_value_meta_info_as_json(@target)}
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.builtin_keyword?
|
104
|
+
true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# array_of: 指定した種類の値のみを格納した配列であることを表す
|
110
|
+
NeuronCheckSystem::Plugin.add_keyword(:array_of) do
|
111
|
+
def on_call(item_expected)
|
112
|
+
@item_expected = item_expected
|
113
|
+
end
|
114
|
+
|
115
|
+
def match?(value)
|
116
|
+
return false unless value.kind_of?(Array) # まずは配列であるかどうかチェック
|
117
|
+
|
118
|
+
# 配列であれば、1つ1つの値が型どおりであるかどうかをチェック
|
119
|
+
return value.all?{|x| @api.expected_value_match?(x, @item_expected)}
|
120
|
+
end
|
121
|
+
|
122
|
+
def expected_caption
|
123
|
+
"array of #{@api.get_expected_value_caption(@item_expected)}"
|
124
|
+
end
|
125
|
+
|
126
|
+
def get_params_as_json
|
127
|
+
{'item' => @api.get_expected_value_meta_info_as_json(@item_expected)}
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.builtin_keyword?
|
131
|
+
true
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
# hash_of: 指定した種類のキーと値のみを格納した配列であることを表す
|
137
|
+
NeuronCheckSystem::Plugin.add_keyword(:hash_of) do
|
138
|
+
def on_call(key_expected, value_expected)
|
139
|
+
@key_expected = key_expected
|
140
|
+
@value_expected = value_expected
|
141
|
+
end
|
142
|
+
|
143
|
+
def match?(value)
|
144
|
+
return false unless value.kind_of?(Hash) # まずはHashであるかどうかチェック
|
145
|
+
|
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
|
+
end
|
149
|
+
|
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
|
+
end
|
153
|
+
|
154
|
+
def expected_short_caption
|
155
|
+
"{#{@api.get_expected_value_short_caption(@key_expected)} => #{api.get_expected_value_short_caption(@value_expected)}}"
|
156
|
+
end
|
157
|
+
|
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
|
+
|
162
|
+
def self.builtin_keyword?
|
163
|
+
true
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module NeuronCheckSystem
|
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
|
+
|
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
|
+
|
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
|
+
|
26
|
+
passed = yield
|
27
|
+
|
28
|
+
unless passed
|
29
|
+
locs = Utils.backtrace_locations_to_captions(caller(1, 1))
|
30
|
+
|
31
|
+
msg = <<MSG
|
32
|
+
#{@block_name} assertion failed
|
33
|
+
asserted at: #{locs.join("\n" + ' ' * 15)}
|
34
|
+
|
35
|
+
MSG
|
36
|
+
|
37
|
+
# エラーを発生させる
|
38
|
+
throw :neuron_check_error_tag, msg
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,295 @@
|
|
1
|
+
require 'neuroncheck/matcher'
|
2
|
+
require 'neuroncheck/plugin'
|
3
|
+
require 'neuroncheck/syntax'
|
4
|
+
require 'neuroncheck/builtin_keyword'
|
5
|
+
|
6
|
+
module NeuronCheckSystem
|
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
|
+
end
|