yard 0.8.7.6 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of yard might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -1
- data/LICENSE +2 -2
- data/README.md +2 -2
- data/Rakefile +1 -1
- data/bin/yard +0 -0
- data/bin/yardoc +0 -0
- data/bin/yri +0 -0
- data/docs/GettingStarted.md +88 -6
- data/docs/images/handlers-class-diagram.png +0 -0
- data/docs/images/overview-class-diagram.png +0 -0
- data/docs/images/parser-class-diagram.png +0 -0
- data/docs/templates/default/fulldoc/html/full_list_tag.erb +6 -4
- data/lib/yard/autoload.rb +3 -0
- data/lib/yard/cli/yardoc.rb +1 -1
- data/lib/yard/code_objects/base.rb +4 -1
- data/lib/yard/code_objects/extra_file_object.rb +3 -1
- data/lib/yard/code_objects/proxy.rb +2 -2
- data/lib/yard/docstring.rb +11 -6
- data/lib/yard/handlers/base.rb +1 -2
- data/lib/yard/handlers/c/base.rb +19 -0
- data/lib/yard/handlers/c/handler_methods.rb +42 -8
- data/lib/yard/handlers/c/init_handler.rb +1 -1
- data/lib/yard/handlers/c/method_handler.rb +3 -3
- data/lib/yard/handlers/ruby/decorator_handler_methods.rb +132 -0
- data/lib/yard/handlers/ruby/legacy/private_class_method_handler.rb +1 -1
- data/lib/yard/handlers/ruby/private_class_method_handler.rb +6 -39
- data/lib/yard/handlers/ruby/private_constant_handler.rb +36 -30
- data/lib/yard/handlers/ruby/public_class_method_handler.rb +13 -0
- data/lib/yard/handlers/ruby/struct_handler_methods.rb +1 -0
- data/lib/yard/handlers/ruby/visibility_handler.rb +5 -8
- data/lib/yard/logging.rb +1 -0
- data/lib/yard/parser/ruby/ruby_parser.rb +2 -2
- data/lib/yard/parser/source_parser.rb +6 -6
- data/lib/yard/rake/yardoc_task.rb +2 -2
- data/lib/yard/serializers/file_system_serializer.rb +33 -1
- data/lib/yard/server/commands/display_file_command.rb +8 -3
- data/lib/yard/server/commands/display_object_command.rb +7 -3
- data/lib/yard/server/doc_server_helper.rb +2 -8
- data/lib/yard/server/doc_server_serializer.rb +2 -4
- data/lib/yard/server/router.rb +1 -1
- data/lib/yard/server/templates/default/fulldoc/html/css/custom.css +57 -8
- data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +2 -10
- data/lib/yard/server/templates/default/layout/html/script_setup.erb +1 -2
- data/lib/yard/server/templates/default/method_details/html/permalink.erb +3 -3
- data/lib/yard/server/templates/doc_server/processing/html/processing.erb +4 -4
- data/lib/yard/tags/directives.rb +1 -0
- data/lib/yard/tags/library.rb +9 -7
- data/lib/yard/tags/overload_tag.rb +4 -1
- data/lib/yard/templates/helpers/html_helper.rb +4 -3
- data/lib/yard/templates/template_options.rb +3 -0
- data/lib/yard/version.rb +1 -1
- data/spec/cli/command_parser_spec.rb +14 -14
- data/spec/cli/command_spec.rb +11 -11
- data/spec/cli/config_spec.rb +32 -32
- data/spec/cli/diff_spec.rb +86 -90
- data/spec/cli/display_spec.rb +6 -6
- data/spec/cli/gems_spec.rb +28 -28
- data/spec/cli/graph_spec.rb +8 -8
- data/spec/cli/help_spec.rb +8 -8
- data/spec/cli/i18n_spec.rb +33 -37
- data/spec/cli/list_spec.rb +2 -2
- data/spec/cli/markup_types_spec.rb +3 -3
- data/spec/cli/server_spec.rb +74 -88
- data/spec/cli/stats_spec.rb +14 -14
- data/spec/cli/yardoc_spec.rb +316 -321
- data/spec/cli/yri_spec.rb +45 -45
- data/spec/code_objects/base_spec.rb +174 -173
- data/spec/code_objects/class_object_spec.rb +65 -65
- data/spec/code_objects/code_object_list_spec.rb +13 -11
- data/spec/code_objects/constants_spec.rb +68 -58
- data/spec/code_objects/extra_file_object_spec.rb +71 -59
- data/spec/code_objects/macro_object_spec.rb +64 -64
- data/spec/code_objects/method_object_spec.rb +80 -72
- data/spec/code_objects/module_object_spec.rb +47 -47
- data/spec/code_objects/namespace_object_spec.rb +51 -51
- data/spec/code_objects/proxy_spec.rb +54 -54
- data/spec/config_spec.rb +104 -104
- data/spec/core_ext/array_spec.rb +5 -5
- data/spec/core_ext/file_spec.rb +33 -33
- data/spec/core_ext/hash_spec.rb +5 -5
- data/spec/core_ext/insertion_spec.rb +18 -18
- data/spec/core_ext/module_spec.rb +6 -6
- data/spec/core_ext/string_spec.rb +17 -17
- data/spec/core_ext/symbol_hash_spec.rb +42 -39
- data/spec/docstring_parser_spec.rb +65 -65
- data/spec/docstring_spec.rb +137 -130
- data/spec/handlers/alias_handler_spec.rb +39 -39
- data/spec/handlers/attribute_handler_spec.rb +35 -35
- data/spec/handlers/base_spec.rb +60 -51
- data/spec/handlers/c/alias_handler_spec.rb +6 -6
- data/spec/handlers/c/attribute_handler_spec.rb +12 -12
- data/spec/handlers/c/class_handler_spec.rb +35 -22
- data/spec/handlers/c/constant_handler_spec.rb +24 -22
- data/spec/handlers/c/init_handler_spec.rb +10 -10
- data/spec/handlers/c/method_handler_spec.rb +150 -65
- data/spec/handlers/c/mixin_handler_spec.rb +5 -5
- data/spec/handlers/c/module_handler_spec.rb +27 -15
- data/spec/handlers/c/override_comment_handler_spec.rb +14 -14
- data/spec/handlers/c/path_handler_spec.rb +8 -8
- data/spec/handlers/c/spec_helper.rb +10 -0
- data/spec/handlers/c/struct_handler_spec.rb +3 -3
- data/spec/handlers/class_condition_handler_spec.rb +18 -18
- data/spec/handlers/class_handler_spec.rb +97 -97
- data/spec/handlers/class_method_handler_shared_examples.rb +132 -0
- data/spec/handlers/class_variable_handler_spec.rb +3 -3
- data/spec/handlers/constant_handler_spec.rb +32 -29
- data/spec/handlers/decorator_handler_methods_spec.rb +405 -0
- data/spec/handlers/dsl_handler_spec.rb +108 -109
- data/spec/handlers/examples/constant_handler_001.rb.txt +4 -1
- data/spec/handlers/examples/visibility_handler_001.rb.txt +4 -0
- data/spec/handlers/exception_handler_spec.rb +23 -23
- data/spec/handlers/extend_handler_spec.rb +9 -9
- data/spec/handlers/legacy_base_spec.rb +60 -60
- data/spec/handlers/method_condition_handler_spec.rb +5 -5
- data/spec/handlers/method_handler_spec.rb +92 -92
- data/spec/handlers/mixin_handler_spec.rb +25 -25
- data/spec/handlers/module_function_handler_spec.rb +24 -24
- data/spec/handlers/module_handler_spec.rb +15 -15
- data/spec/handlers/private_class_method_handler_spec.rb +4 -48
- data/spec/handlers/private_constant_handler_spec.rb +8 -8
- data/spec/handlers/processor_spec.rb +12 -12
- data/spec/handlers/public_class_method_handler_spec.rb +10 -0
- data/spec/handlers/ruby/base_spec.rb +16 -16
- data/spec/handlers/ruby/legacy/base_spec.rb +20 -18
- data/spec/handlers/spec_helper.rb +1 -1
- data/spec/handlers/visibility_handler_spec.rb +25 -21
- data/spec/handlers/yield_handler_spec.rb +28 -28
- data/spec/i18n/locale_spec.rb +16 -16
- data/spec/i18n/message_spec.rb +8 -8
- data/spec/i18n/messages_spec.rb +14 -14
- data/spec/i18n/pot_generator_spec.rb +32 -32
- data/spec/i18n/text_spec.rb +22 -22
- data/spec/logging_spec.rb +12 -12
- data/spec/options_spec.rb +56 -56
- data/spec/parser/base_spec.rb +9 -9
- data/spec/parser/c_parser_spec.rb +50 -50
- data/spec/parser/ruby/ast_node_spec.rb +7 -7
- data/spec/parser/ruby/legacy/statement_list_spec.rb +106 -106
- data/spec/parser/ruby/legacy/token_list_spec.rb +27 -27
- data/spec/parser/ruby/ruby_parser_spec.rb +123 -113
- data/spec/parser/source_parser_spec.rb +224 -224
- data/spec/parser/tag_parsing_spec.rb +6 -7
- data/spec/rake/yardoc_task_spec.rb +38 -48
- data/spec/registry_spec.rb +143 -143
- data/spec/registry_store_spec.rb +165 -165
- data/spec/rubygems/doc_manager_spec.rb +38 -38
- data/spec/serializers/file_system_serializer_spec.rb +53 -33
- data/spec/serializers/yardoc_serializer_spec.rb +15 -15
- data/spec/server/adapter_spec.rb +15 -15
- data/spec/server/commands/base_spec.rb +29 -29
- data/spec/server/commands/library_command_spec.rb +12 -12
- data/spec/server/commands/static_file_command_spec.rb +28 -28
- data/spec/server/doc_server_helper_spec.rb +8 -8
- data/spec/server/doc_server_serializer_spec.rb +23 -18
- data/spec/server/rack_adapter_spec.rb +6 -6
- data/spec/server/router_spec.rb +39 -39
- data/spec/server/static_caching_spec.rb +16 -16
- data/spec/server/webrick_servlet_spec.rb +6 -7
- data/spec/server_spec.rb +3 -3
- data/spec/spec_helper.rb +11 -2
- data/spec/tags/default_factory_spec.rb +64 -64
- data/spec/tags/default_tag_spec.rb +5 -5
- data/spec/tags/directives_spec.rb +121 -121
- data/spec/tags/library_spec.rb +14 -14
- data/spec/tags/overload_tag_spec.rb +24 -24
- data/spec/tags/ref_tag_list_spec.rb +12 -12
- data/spec/templates/class_spec.rb +3 -3
- data/spec/templates/constant_spec.rb +4 -4
- data/spec/templates/engine_spec.rb +47 -48
- data/spec/templates/examples/class001.html +129 -101
- data/spec/templates/examples/class002.html +31 -27
- data/spec/templates/examples/method001.html +54 -47
- data/spec/templates/examples/method002.html +33 -28
- data/spec/templates/examples/method003.html +70 -64
- data/spec/templates/examples/method004.html +13 -9
- data/spec/templates/examples/method005.html +38 -32
- data/spec/templates/examples/module001.html +343 -339
- data/spec/templates/examples/module002.html +147 -124
- data/spec/templates/examples/module003.html +94 -81
- data/spec/templates/examples/module004.html +40 -33
- data/spec/templates/helpers/base_helper_spec.rb +91 -95
- data/spec/templates/helpers/html_helper_spec.rb +276 -279
- data/spec/templates/helpers/html_syntax_highlight_helper_spec.rb +16 -15
- data/spec/templates/helpers/markup/rdoc_markup_spec.rb +27 -34
- data/spec/templates/helpers/markup_helper_spec.rb +57 -57
- data/spec/templates/helpers/method_helper_spec.rb +20 -20
- data/spec/templates/helpers/shared_signature_examples.rb +33 -31
- data/spec/templates/helpers/text_helper_spec.rb +6 -6
- data/spec/templates/method_spec.rb +7 -7
- data/spec/templates/module_spec.rb +7 -7
- data/spec/templates/onefile_spec.rb +7 -7
- data/spec/templates/section_spec.rb +66 -69
- data/spec/templates/spec_helper.rb +1 -1
- data/spec/templates/tag_spec.rb +5 -5
- data/spec/templates/template_spec.rb +158 -158
- data/spec/verifier_spec.rb +52 -52
- data/templates/default/fulldoc/html/css/full_list.css +32 -31
- data/templates/default/fulldoc/html/css/style.css +212 -77
- data/templates/default/fulldoc/html/frames.erb +6 -15
- data/templates/default/fulldoc/html/full_list.erb +14 -21
- data/templates/default/fulldoc/html/full_list_class.erb +1 -1
- data/templates/default/fulldoc/html/full_list_file.erb +6 -4
- data/templates/default/fulldoc/html/full_list_method.erb +8 -6
- data/templates/default/fulldoc/html/js/app.js +100 -76
- data/templates/default/fulldoc/html/js/full_list.js +170 -135
- data/templates/default/fulldoc/html/setup.rb +50 -7
- data/templates/default/layout/html/breadcrumb.erb +0 -2
- data/templates/default/layout/html/headers.erb +2 -1
- data/templates/default/layout/html/layout.erb +16 -10
- data/templates/default/layout/html/script_setup.erb +1 -2
- data/templates/default/layout/html/search.erb +7 -2
- data/templates/default/layout/html/setup.rb +16 -0
- data/templates/default/method/html/header.erb +7 -6
- data/templates/default/module/html/attribute_summary.erb +1 -1
- data/templates/default/module/html/box_info.erb +24 -18
- data/templates/default/module/html/constant_summary.erb +9 -11
- data/templates/default/module/html/item_summary.erb +1 -1
- data/templates/default/module/html/method_summary.erb +1 -1
- data/templates/guide/fulldoc/html/setup.rb +1 -1
- data/yard.gemspec +1 -2
- metadata +10 -7
- data/spec/handlers/examples/private_class_method_handler_001.rb.txt +0 -9
- data/spec/handlers/examples/private_class_method_handler_002.rb.txt +0 -18
- data/spec/handlers/examples/private_class_method_handler_003.rb.txt +0 -11
@@ -0,0 +1,132 @@
|
|
1
|
+
shared_examples "class method visibility decorator" do
|
2
|
+
# Use let(:visibility) to specify the name of the x_class_method
|
3
|
+
# visibility decorator to test.
|
4
|
+
|
5
|
+
describe do
|
6
|
+
before {
|
7
|
+
StubbedSourceParser.parse_string <<-CODE
|
8
|
+
class A
|
9
|
+
def self.b; end
|
10
|
+
def self.c; end
|
11
|
+
def self.d; end
|
12
|
+
def self.e; end
|
13
|
+
|
14
|
+
#{visibility}_class_method(:c, :d)
|
15
|
+
#{visibility}_class_method("e")
|
16
|
+
end
|
17
|
+
CODE
|
18
|
+
}
|
19
|
+
|
20
|
+
it "handles private_class_method statement" do
|
21
|
+
expect(Registry.at('A.c').visibility).to eq visibility
|
22
|
+
expect(Registry.at('A.d').visibility).to eq visibility
|
23
|
+
expect(Registry.at('A.e').visibility).to eq visibility
|
24
|
+
end
|
25
|
+
|
26
|
+
# Issue #760
|
27
|
+
# https://github.com/lsegal/yard/issues/760
|
28
|
+
it "handles singleton classes" do
|
29
|
+
# Note: It's important to def a method within the singleton class or
|
30
|
+
# the bug may not trigger.
|
31
|
+
code = <<-CODE
|
32
|
+
class SingletonClass
|
33
|
+
private_class_method :new
|
34
|
+
def self.foo
|
35
|
+
"foo"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
CODE
|
39
|
+
|
40
|
+
StubbedSourceParser.parse_string(code) # Should be successful.
|
41
|
+
end unless LEGACY_PARSER
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "handles reopened class" do
|
45
|
+
before {
|
46
|
+
StubbedSourceParser.parse_string <<-CODE
|
47
|
+
class SingletonClass
|
48
|
+
|
49
|
+
#{'private' unless visibility.to_sym == :private}
|
50
|
+
|
51
|
+
# != visibility
|
52
|
+
def self.foo
|
53
|
+
'foo'
|
54
|
+
end
|
55
|
+
|
56
|
+
# == visibility
|
57
|
+
def self.bar
|
58
|
+
end
|
59
|
+
|
60
|
+
# == visibility from reopening class.
|
61
|
+
def self.baz
|
62
|
+
end
|
63
|
+
|
64
|
+
#{visibility}_class_method :new, :bar
|
65
|
+
|
66
|
+
end
|
67
|
+
CODE
|
68
|
+
|
69
|
+
StubbedSourceParser.parse_string <<-CODE
|
70
|
+
# Reopening singleton class.
|
71
|
+
class SingletonClass
|
72
|
+
#{visibility}_class_method :baz
|
73
|
+
|
74
|
+
#{'private' unless visibility.to_sym == :private}
|
75
|
+
# != visibility from reopened class. (Verifies class was reopened.)
|
76
|
+
def self.bat
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
CODE
|
81
|
+
}
|
82
|
+
|
83
|
+
specify do
|
84
|
+
expect(Registry.at('SingletonClass.foo').visibility).not_to eq visibility
|
85
|
+
expect(Registry.at('SingletonClass.bar').visibility).to eq visibility
|
86
|
+
expect(Registry.at('SingletonClass.baz').visibility).to eq visibility
|
87
|
+
expect(Registry.at('SingletonClass.bat').visibility).not_to eq visibility
|
88
|
+
end
|
89
|
+
end unless LEGACY_PARSER # reopened class
|
90
|
+
|
91
|
+
describe "as method definition decorator" do
|
92
|
+
subject { Registry.at('SingletonClass.foo') }
|
93
|
+
|
94
|
+
# Valid as of Ruby 2.1.0:
|
95
|
+
# private_class_method def self.foo; end
|
96
|
+
|
97
|
+
let(:code) {
|
98
|
+
<<-CODE
|
99
|
+
class SingletonClass
|
100
|
+
# Valid Ruby 2.1.0 syntax.
|
101
|
+
#{method_def}
|
102
|
+
'it works'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
CODE
|
106
|
+
}
|
107
|
+
|
108
|
+
let(:method_def) { "#{visibility}_class_method def self.foo param1, param2" }
|
109
|
+
|
110
|
+
before { StubbedSourceParser.parse_string code }
|
111
|
+
|
112
|
+
it "handles self.foo" do
|
113
|
+
expect(subject.visibility).to eq visibility
|
114
|
+
end
|
115
|
+
|
116
|
+
it "handles parameters correctly" do
|
117
|
+
expect(subject.parameters.map { |p| p.first }).to eq ['param1', 'param2']
|
118
|
+
end
|
119
|
+
|
120
|
+
it "attaches documentation to method definition" do
|
121
|
+
expect(subject.docstring).to eq "Valid Ruby 2.1.0 syntax."
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "handles SingletonClass.foo" do
|
125
|
+
let(:method_def) { "#{visibility}_class_method def SingletonClass.foo" }
|
126
|
+
|
127
|
+
specify do
|
128
|
+
expect(subject.visibility).to eq visibility
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end unless LEGACY_PARSER
|
132
|
+
end
|
@@ -3,9 +3,9 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
3
3
|
describe "YARD::Handlers::Ruby::#{LEGACY_PARSER ? "Legacy::" : ""}ClassVariableHandler" do
|
4
4
|
before(:all) { parse_file :class_variable_handler_001, __FILE__ }
|
5
5
|
|
6
|
-
it "
|
6
|
+
it "does not parse class variables inside methods" do
|
7
7
|
obj = Registry.at("A::B::@@somevar")
|
8
|
-
obj.source.
|
9
|
-
obj.value.
|
8
|
+
expect(obj.source).to eq "@@somevar = \"hello\""
|
9
|
+
expect(obj.value).to eq '"hello"'
|
10
10
|
end
|
11
11
|
end
|
@@ -3,62 +3,65 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
3
3
|
describe "YARD::Handlers::Ruby::#{LEGACY_PARSER ? "Legacy::" : ""}ConstantHandler" do
|
4
4
|
before(:all) { parse_file :constant_handler_001, __FILE__ }
|
5
5
|
|
6
|
-
it "
|
7
|
-
Registry.at("A::B::SOMECONSTANT").source.
|
6
|
+
it "does not parse constants inside methods" do
|
7
|
+
expect(Registry.at("A::B::SOMECONSTANT").source).to eq "SOMECONSTANT= \"hello\""
|
8
8
|
end
|
9
9
|
|
10
|
-
it "
|
11
|
-
Registry.at("A::B::notaconstant").
|
10
|
+
it "only parses valid constants" do
|
11
|
+
expect(Registry.at("A::B::notaconstant")).to be nil
|
12
12
|
end
|
13
13
|
|
14
|
-
it "
|
15
|
-
Registry.at("A::B::MYCONSTANT").value.gsub("\r", "").
|
14
|
+
it "maintains newlines" do
|
15
|
+
expect(Registry.at("A::B::MYCONSTANT").value.gsub("\r", "")).to eq "A +\nB +\nC +\nD"
|
16
16
|
end
|
17
17
|
|
18
|
-
it "
|
18
|
+
it "turns Const = Struct.new(:sym) into class Const with attr :sym" do
|
19
19
|
obj = Registry.at("MyClass")
|
20
|
-
obj.
|
20
|
+
expect(obj).to be_kind_of(CodeObjects::ClassObject)
|
21
21
|
attrs = obj.attributes[:instance]
|
22
22
|
[:a, :b, :c].each do |key|
|
23
|
-
attrs.
|
24
|
-
attrs[key][:read].
|
25
|
-
attrs[key][:write].
|
23
|
+
expect(attrs).to have_key(key)
|
24
|
+
expect(attrs[key][:read]).not_to be nil
|
25
|
+
expect(attrs[key][:write]).not_to be nil
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
it "
|
29
|
+
it "turns Const = Struct.new('Name', :sym) into class Const with attr :sym" do
|
30
30
|
obj = Registry.at("NotMyClass")
|
31
|
-
obj.
|
31
|
+
expect(obj).to be_kind_of(CodeObjects::ClassObject)
|
32
32
|
attrs = obj.attributes[:instance]
|
33
33
|
[:b, :c].each do |key|
|
34
|
-
attrs.
|
35
|
-
attrs[key][:read].
|
36
|
-
attrs[key][:write].
|
34
|
+
expect(attrs).to have_key(key)
|
35
|
+
expect(attrs[key][:read]).not_to be nil
|
36
|
+
expect(attrs[key][:write]).not_to be nil
|
37
37
|
end
|
38
38
|
|
39
|
-
Registry.at("NotMyClass2").
|
39
|
+
expect(Registry.at("NotMyClass2")).to be nil
|
40
40
|
end
|
41
41
|
|
42
|
-
it "
|
42
|
+
it "turns Const = Struct.new into empty struct" do
|
43
43
|
obj = Registry.at("MyEmptyStruct")
|
44
|
-
obj.
|
45
|
-
obj.attributes[:instance].
|
44
|
+
expect(obj).not_to be nil
|
45
|
+
expect(obj.attributes[:instance]).to be_empty
|
46
46
|
end
|
47
47
|
|
48
|
-
it "
|
48
|
+
it "maintains docstrings on structs defined via constants" do
|
49
49
|
obj = Registry.at("DocstringStruct")
|
50
|
-
obj.
|
51
|
-
obj.docstring.
|
52
|
-
obj.attributes[:instance].
|
50
|
+
expect(obj).not_to be nil
|
51
|
+
expect(obj.docstring).to eq "A crazy struct."
|
52
|
+
expect(obj.attributes[:instance]).not_to be_empty
|
53
53
|
a1 = Registry.at("DocstringStruct#bar")
|
54
54
|
a2 = Registry.at("DocstringStruct#baz")
|
55
|
-
a1.docstring.
|
56
|
-
a1.tag(:return).types.
|
57
|
-
a2.docstring.
|
58
|
-
a2.tag(:return).types.
|
55
|
+
expect(a1.docstring).to eq "An attr"
|
56
|
+
expect(a1.tag(:return).types).to eq ["String"]
|
57
|
+
expect(a2.docstring).to eq "Another attr"
|
58
|
+
expect(a2.tag(:return).types).to eq ["Number"]
|
59
|
+
a3 = Registry.at("DocstringStruct#new_syntax")
|
60
|
+
expect(a3.docstring).to eq "Attribute defined with the new syntax"
|
61
|
+
expect(a3.tag(:return).types).to eq ["Symbol"]
|
59
62
|
end
|
60
63
|
|
61
|
-
it "
|
64
|
+
it "raises undocumentable error in 1.9 parser for Struct.new assignment to non-const" do
|
62
65
|
undoc_error "nonconst = Struct.new"
|
63
66
|
end unless LEGACY_PARSER
|
64
67
|
end
|
@@ -0,0 +1,405 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "YARD::Handlers::Ruby::DecoratorHandlerMethods" do
|
4
|
+
describe "#process_decorator" do
|
5
|
+
|
6
|
+
# Create a YARD decorator handler.
|
7
|
+
# @param name [Symbol] name of the mock decorator
|
8
|
+
def create_test_handler(name)
|
9
|
+
data[name] = {}
|
10
|
+
|
11
|
+
local_mock_handler_opts = mock_handler_opts
|
12
|
+
local_nodes = nodes
|
13
|
+
local_data = data[name]
|
14
|
+
|
15
|
+
Class.new YARD::Handlers::Ruby::Base do
|
16
|
+
include YARD::Handlers::Ruby::DecoratorHandlerMethods
|
17
|
+
|
18
|
+
handles method_call(:"#{name}_decorator")
|
19
|
+
namespace_only
|
20
|
+
|
21
|
+
process do
|
22
|
+
# process_decorator params written like this due to Ruby 1.8.
|
23
|
+
# A modern handler should splat local_nodes.
|
24
|
+
local_data[:return] =
|
25
|
+
process_decorator *(local_nodes + [local_mock_handler_opts]) do |method, node, name|
|
26
|
+
local_data[:method] = method
|
27
|
+
local_data[:node] = node
|
28
|
+
local_data[:name] = name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Generate method definition.
|
35
|
+
# @param symbols [Symbol] method names
|
36
|
+
# @return [String] method definition code
|
37
|
+
def make_defs(*symbols)
|
38
|
+
symbols.map { |s|
|
39
|
+
s = "self.#{s}" if mock_handler_opts[:scope] == :class
|
40
|
+
"def #{s}; end"
|
41
|
+
}.join("\n")
|
42
|
+
end
|
43
|
+
|
44
|
+
# Generate an AST for the given source code string.
|
45
|
+
def make_ast(code)
|
46
|
+
YARD::Parser::Ruby::RubyParser.new(code, nil).parse.ast
|
47
|
+
end
|
48
|
+
|
49
|
+
subject { data[:mock] }
|
50
|
+
|
51
|
+
let(:data) { Hash.new }
|
52
|
+
let(:nodes) { [] }
|
53
|
+
let(:mock_handler_opts) { {:scope => :instance} }
|
54
|
+
let(:class_name) { 'DecoratorTest' }
|
55
|
+
let(:docstring) { 'the foo method' }
|
56
|
+
let(:param_string) { 'def foo param1, param2; end' }
|
57
|
+
let(:method_defs) { [] }
|
58
|
+
let(:method_string) { "#{class_name}#foo" }
|
59
|
+
let(:code) {"
|
60
|
+
class #{class_name}
|
61
|
+
#{make_defs *method_defs}
|
62
|
+
# #{docstring}
|
63
|
+
mock_decorator #{param_string}
|
64
|
+
end
|
65
|
+
"}
|
66
|
+
|
67
|
+
before {
|
68
|
+
Registry.clear
|
69
|
+
YARD::Handlers::Base.clear_subclasses
|
70
|
+
|
71
|
+
create_test_handler :mock
|
72
|
+
create_test_handler :first
|
73
|
+
create_test_handler :second
|
74
|
+
create_test_handler :third
|
75
|
+
|
76
|
+
StubbedSourceParser.parse_string code
|
77
|
+
}
|
78
|
+
|
79
|
+
it "returns an array of hashes containing the method proxy, node, and name" do
|
80
|
+
expect(subject[:return]).to be_an Array
|
81
|
+
expect(subject[:return].first[:name].to_s).to eq 'foo'
|
82
|
+
expect(subject[:return].first[:method].to_s).to eq method_string
|
83
|
+
expect(subject[:return].first[:node]).to be_a YARD::Parser::Ruby::AstNode
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "method is a MethodObject if the method has been defined" do
|
87
|
+
let(:code) {"class DecoratorTest; mock_decorator def foo; end; end"}
|
88
|
+
|
89
|
+
specify do
|
90
|
+
expect(subject[:return].first[:method]) \
|
91
|
+
.to be_a YARD::CodeObjects::MethodObject
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "method is a Proxy if the method has not been defined" do
|
96
|
+
let(:code) {"class DecoratorTest; mock_decorator :foo; end"}
|
97
|
+
|
98
|
+
specify do
|
99
|
+
expect(subject[:return].first[:method]).to be_a YARD::CodeObjects::Proxy
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
specify "block yields method proxy, node, name" do
|
104
|
+
expect(subject[:name]).to be_a Symbol
|
105
|
+
expect(subject[:name]).to eq :foo
|
106
|
+
|
107
|
+
expect(subject[:method]).to be_a YARD::CodeObjects::MethodObject
|
108
|
+
expect(subject[:method].to_s).to eq method_string
|
109
|
+
|
110
|
+
expect(subject[:node]).to be_a YARD::Parser::Ruby::AstNode
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "capitalized method names" do
|
114
|
+
let(:method_defs) { [:Foo] }
|
115
|
+
let(:param_string) { 'def Foo param1, param2; end' }
|
116
|
+
|
117
|
+
specify do
|
118
|
+
expect(subject[:method].to_s).to eq "#{class_name}#Foo"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "nodes argument" do
|
123
|
+
subject { data[:mock][:return].map { |h| h[:method].to_s } }
|
124
|
+
|
125
|
+
describe "assumes all params refer to methods by default" do
|
126
|
+
let(:method_defs) { [:foo, :bar] }
|
127
|
+
let(:param_string) { method_defs.map(&:inspect).join(',') }
|
128
|
+
let(:nodes) { [] }
|
129
|
+
|
130
|
+
specify do
|
131
|
+
expect(subject).to eq ["#{class_name}#foo", "#{class_name}#bar"]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "can specify which params to capture as methods" do
|
136
|
+
let(:method_defs) { [:foo, :bar, :baz, :bat] }
|
137
|
+
let(:parameters) {
|
138
|
+
[:option_1, :baz, :bat, :option_2, :foo, :bar].map do |s|
|
139
|
+
make_ast s.inspect
|
140
|
+
end
|
141
|
+
}
|
142
|
+
|
143
|
+
describe "as a single param" do
|
144
|
+
let(:nodes) { parameters[4] }
|
145
|
+
|
146
|
+
specify do
|
147
|
+
expect(subject).to eq ["#{class_name}#foo"]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "as a list of params" do
|
152
|
+
let(:nodes) { [parameters[4], parameters[5]] }
|
153
|
+
|
154
|
+
specify do
|
155
|
+
expect(subject).to eq ["#{class_name}#foo", "#{class_name}#bar"]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "as a range" do
|
160
|
+
let(:nodes) { parameters[4..-1] }
|
161
|
+
|
162
|
+
specify do
|
163
|
+
expect(subject).to eq ["#{class_name}#foo", "#{class_name}#bar"]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe "as multiple ranges" do
|
168
|
+
# Written like this due to Ruby 1.8. Can also splat the ranges as
|
169
|
+
# separate params:
|
170
|
+
# *parameters[1..2], *parameters[4..-1]
|
171
|
+
let(:nodes) { parameters[1..2] + parameters[4..-1] }
|
172
|
+
|
173
|
+
specify do
|
174
|
+
expect(subject).to eq [
|
175
|
+
"#{class_name}#baz",
|
176
|
+
"#{class_name}#bat",
|
177
|
+
"#{class_name}#foo",
|
178
|
+
"#{class_name}#bar"
|
179
|
+
]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "can select no nodes by passing nil" do
|
185
|
+
let(:nodes) { [nil] }
|
186
|
+
|
187
|
+
specify do
|
188
|
+
expect(subject).to eq []
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "scope option" do
|
194
|
+
describe "defaults to :instance" do
|
195
|
+
let(:mock_handler_opts) { {} }
|
196
|
+
|
197
|
+
specify do
|
198
|
+
expect(subject[:return].first[:method].to_s).to eq method_string
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "creates method proxies" do
|
203
|
+
|
204
|
+
shared_examples "decorator helper scope" do
|
205
|
+
let(:param_string) { decorator_params.map(&:inspect).join(',') }
|
206
|
+
|
207
|
+
describe "for symbols" do
|
208
|
+
let(:decorator_params) { [:foo, :bar] }
|
209
|
+
|
210
|
+
specify do
|
211
|
+
expect(subject.count).to eq decorator_params.count
|
212
|
+
|
213
|
+
subject.each_with_index do |_, i|
|
214
|
+
expect(subject[i]).to be_a YARD::CodeObjects::MethodObject
|
215
|
+
expect(subject[i].to_s).to eq \
|
216
|
+
"#{class_name}#{mock_handler_opts[:scope] == :class ? '.' : '#'}#{decorator_params[i]}"
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
describe "for string literals" do
|
222
|
+
let(:decorator_params) { ['foo', 'bar'] }
|
223
|
+
|
224
|
+
specify do
|
225
|
+
expect(subject.count).to eq decorator_params.count
|
226
|
+
|
227
|
+
subject.each_with_index do |_, i|
|
228
|
+
expect(subject[i]).to be_a YARD::CodeObjects::MethodObject
|
229
|
+
expect(subject[i].to_s).to eq \
|
230
|
+
"#{class_name}#{mock_handler_opts[:scope] == :class ? '.' : '#'}#{decorator_params[i]}"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe "for methods" do
|
236
|
+
let(:param_string) { decorator_params.join(',') }
|
237
|
+
let(:decorator_params) {[
|
238
|
+
"def #{'self.' if mock_handler_opts[:scope] == :class}foo f1, f2; end",
|
239
|
+
"def #{'self.' if mock_handler_opts[:scope] == :class}bar b1, b2; end"
|
240
|
+
]}
|
241
|
+
|
242
|
+
specify do
|
243
|
+
expect(subject.count).to eq decorator_params.count
|
244
|
+
|
245
|
+
subject.each_with_index do |_, i|
|
246
|
+
expect(subject[i]).to be_a YARD::CodeObjects::MethodObject
|
247
|
+
expect(subject[i].to_s).to eq \
|
248
|
+
class_name +
|
249
|
+
(mock_handler_opts[:scope] == :class ? '.' : '#') +
|
250
|
+
decorator_params[i].split(' ')[1][/\w+$/]
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end # decorator helper scope shared examples
|
255
|
+
|
256
|
+
subject { data[:mock][:return].map { |h| h[:method] } }
|
257
|
+
|
258
|
+
let(:docstring) { 'the foo method' }
|
259
|
+
let(:method_defs) { [:foo, :bar] }
|
260
|
+
|
261
|
+
describe "for :instance" do
|
262
|
+
let(:mock_handler_opts) { {:scope => :instance} }
|
263
|
+
|
264
|
+
include_examples "decorator helper scope"
|
265
|
+
end
|
266
|
+
|
267
|
+
describe "for :class" do
|
268
|
+
let(:mock_handler_opts) { {:scope => :class} }
|
269
|
+
|
270
|
+
include_examples "decorator helper scope"
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe "docstring from decorator" do
|
276
|
+
subject { Registry.at method_string }
|
277
|
+
|
278
|
+
specify "attaches to method definitions as decorator parameters" do
|
279
|
+
expect(subject.docstring).to eq docstring
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "does not attach" do
|
283
|
+
describe "to undefined methods" do
|
284
|
+
let(:code) {"
|
285
|
+
class #{class_name}
|
286
|
+
# #{docstring}
|
287
|
+
mock_decorator :foo
|
288
|
+
end
|
289
|
+
"}
|
290
|
+
|
291
|
+
specify do
|
292
|
+
expect(subject).not_to respond_to :docstring
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
describe "to methods with existing docstring" do
|
297
|
+
let(:code) {"
|
298
|
+
class #{class_name}
|
299
|
+
|
300
|
+
# original docstring
|
301
|
+
def foo; end
|
302
|
+
|
303
|
+
# #{docstring}
|
304
|
+
mock_decorator :foo
|
305
|
+
end
|
306
|
+
"}
|
307
|
+
|
308
|
+
specify do
|
309
|
+
expect(subject.docstring).to eq 'original docstring'
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
describe "chained decorators" do
|
316
|
+
subject { Registry.at method_string }
|
317
|
+
|
318
|
+
let(:param_string) { 'def foo param1, param2; end' }
|
319
|
+
let(:code) {"
|
320
|
+
class #{class_name}
|
321
|
+
#{make_defs *method_defs}
|
322
|
+
# #{docstring}
|
323
|
+
first_decorator second_decorator third_decorator #{param_string}
|
324
|
+
end
|
325
|
+
"}
|
326
|
+
|
327
|
+
specify "register nested method defs" do
|
328
|
+
expect(subject).to be_a YARD::CodeObjects::MethodObject
|
329
|
+
end
|
330
|
+
|
331
|
+
describe "transfer docstring to decorated method defs" do
|
332
|
+
specify do
|
333
|
+
expect(subject.docstring).to eq docstring
|
334
|
+
end
|
335
|
+
|
336
|
+
describe "unless opt-out param is set" do
|
337
|
+
let(:mock_handler_opts) { {:transfer_docstring => false} }
|
338
|
+
|
339
|
+
specify do
|
340
|
+
expect(subject.docstring.empty?).to be true
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
describe "don't transfer docstring to referenced methods" do
|
346
|
+
let(:method_defs) { [:foo] }
|
347
|
+
let(:param_string) { ':foo' }
|
348
|
+
|
349
|
+
specify do
|
350
|
+
expect(subject.docstring.empty?).to be true
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
specify "don't transfer docstring to other decorators" do
|
355
|
+
expect(Registry.at("#{class_name}#second_decorator")) \
|
356
|
+
.not_to respond_to :docstring
|
357
|
+
|
358
|
+
expect(Registry.at("#{class_name}#third_decorator")) \
|
359
|
+
.not_to respond_to :docstring
|
360
|
+
end
|
361
|
+
|
362
|
+
describe "transfer source to decorated method defs" do
|
363
|
+
specify do
|
364
|
+
expect(subject.source).to eq code.lines.to_a[-3].strip
|
365
|
+
end
|
366
|
+
|
367
|
+
describe "unless opt-out param is set" do
|
368
|
+
let(:mock_handler_opts) { {:transfer_source => false} }
|
369
|
+
|
370
|
+
specify do
|
371
|
+
expect(subject.source).to eq param_string
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
describe "don't transfer source to referenced methods" do
|
377
|
+
let(:method_defs) { [:foo] }
|
378
|
+
let(:param_string) { ':foo' }
|
379
|
+
|
380
|
+
specify do
|
381
|
+
expect(subject.source).to eq make_defs(*method_defs)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
describe "are tagged" do
|
386
|
+
let(:method_defs) { [:foo, :bar] }
|
387
|
+
let(:param_string) { method_defs.map(&:inspect).join(',') }
|
388
|
+
|
389
|
+
specify do
|
390
|
+
expect(subject.tags.count).to eq 3
|
391
|
+
|
392
|
+
subject.tags.each do |tag|
|
393
|
+
expect(tag.tag_name).to eq 'decorator'
|
394
|
+
end
|
395
|
+
|
396
|
+
expect(subject.tags.map(&:text)).to eq [
|
397
|
+
'third_decorator',
|
398
|
+
'second_decorator',
|
399
|
+
'first_decorator'
|
400
|
+
]
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end # process_decorator
|
405
|
+
end unless LEGACY_PARSER
|