neuroncheck 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|