inch 0.2.3 → 0.3.0.rc1

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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +7 -0
  3. data/TODOS.md +0 -5
  4. data/config/defaults.rb +26 -1
  5. data/inch.gemspec +1 -0
  6. data/lib/inch.rb +2 -1
  7. data/lib/inch/api.rb +34 -0
  8. data/lib/inch/api/filter.rb +17 -0
  9. data/lib/inch/api/get.rb +30 -0
  10. data/lib/inch/api/list.rb +10 -0
  11. data/lib/inch/api/options/base.rb +45 -0
  12. data/lib/inch/api/options/filter.rb +25 -0
  13. data/lib/inch/api/options/suggest.rb +36 -0
  14. data/lib/inch/api/stats.rb +7 -0
  15. data/lib/inch/api/suggest.rb +110 -0
  16. data/lib/inch/cli.rb +4 -1
  17. data/lib/inch/cli/command/base.rb +1 -17
  18. data/lib/inch/cli/command/base_list.rb +3 -63
  19. data/lib/inch/cli/command/base_object.rb +6 -28
  20. data/lib/inch/cli/command/list.rb +3 -2
  21. data/lib/inch/cli/command/options/base.rb +1 -1
  22. data/lib/inch/cli/command/options/base_list.rb +4 -2
  23. data/lib/inch/cli/command/options/suggest.rb +9 -8
  24. data/lib/inch/cli/command/output/base.rb +9 -11
  25. data/lib/inch/cli/command/output/list.rb +2 -2
  26. data/lib/inch/cli/command/output/show.rb +2 -10
  27. data/lib/inch/cli/command/output/stats.rb +4 -3
  28. data/lib/inch/cli/command/output/suggest.rb +5 -5
  29. data/lib/inch/cli/command/stats.rb +4 -3
  30. data/lib/inch/cli/command/suggest.rb +4 -94
  31. data/lib/inch/code_object.rb +2 -2
  32. data/lib/inch/code_object/converter.rb +89 -0
  33. data/lib/inch/code_object/provider.rb +36 -0
  34. data/lib/inch/code_object/provider/yard.rb +19 -0
  35. data/lib/inch/code_object/provider/yard/docstring.rb +106 -0
  36. data/lib/inch/code_object/provider/yard/nodoc_helper.rb +93 -0
  37. data/lib/inch/code_object/provider/yard/object.rb +55 -0
  38. data/lib/inch/code_object/provider/yard/object/base.rb +262 -0
  39. data/lib/inch/code_object/provider/yard/object/class_object.rb +12 -0
  40. data/lib/inch/code_object/provider/yard/object/constant_object.rb +12 -0
  41. data/lib/inch/code_object/provider/yard/object/method_object.rb +126 -0
  42. data/lib/inch/code_object/provider/yard/object/method_parameter_object.rb +88 -0
  43. data/lib/inch/code_object/provider/yard/object/module_object.rb +12 -0
  44. data/lib/inch/code_object/provider/yard/object/namespace_object.rb +47 -0
  45. data/lib/inch/code_object/provider/yard/parser.rb +54 -0
  46. data/lib/inch/code_object/proxy.rb +5 -3
  47. data/lib/inch/code_object/proxy/base.rb +103 -110
  48. data/lib/inch/code_object/proxy/class_object.rb +0 -1
  49. data/lib/inch/code_object/proxy/method_object.rb +20 -99
  50. data/lib/inch/code_object/proxy/method_parameter_object.rb +15 -39
  51. data/lib/inch/code_object/proxy/namespace_object.rb +7 -18
  52. data/lib/inch/codebase.rb +19 -0
  53. data/lib/inch/codebase/objects.rb +73 -0
  54. data/lib/inch/codebase/objects_filter.rb +61 -0
  55. data/lib/inch/codebase/proxy.rb +22 -0
  56. data/lib/inch/config.rb +8 -1
  57. data/lib/inch/evaluation.rb +5 -7
  58. data/lib/inch/evaluation/file.rb +1 -1
  59. data/lib/inch/evaluation/grade.rb +1 -1
  60. data/lib/inch/evaluation/object_schema.rb +3 -1
  61. data/lib/inch/evaluation/priority_range.rb +44 -0
  62. data/lib/inch/evaluation/proxy.rb +25 -0
  63. data/lib/inch/evaluation/proxy/base.rb +146 -0
  64. data/lib/inch/evaluation/proxy/class_object.rb +8 -0
  65. data/lib/inch/evaluation/proxy/constant_object.rb +19 -0
  66. data/lib/inch/evaluation/proxy/method_object.rb +65 -0
  67. data/lib/inch/evaluation/proxy/module_object.rb +8 -0
  68. data/lib/inch/evaluation/proxy/namespace_object.rb +27 -0
  69. data/lib/inch/evaluation/role/base.rb +19 -0
  70. data/lib/inch/evaluation/role/constant.rb +16 -0
  71. data/lib/inch/evaluation/role/method.rb +22 -0
  72. data/lib/inch/evaluation/role/method_parameter.rb +31 -1
  73. data/lib/inch/evaluation/role/namespace.rb +15 -0
  74. data/lib/inch/evaluation/role/object.rb +24 -0
  75. data/lib/inch/rake/suggest.rb +1 -0
  76. data/lib/inch/utils/read_write_methods.rb +44 -0
  77. data/lib/inch/{cli → utils}/weighted_list.rb +1 -1
  78. data/lib/inch/version.rb +1 -1
  79. data/test/fixtures/simple/lib/broken.rb +8 -0
  80. data/test/inch/api/filter_test.rb +51 -0
  81. data/test/inch/api/get_test.rb +22 -0
  82. data/test/inch/api/list_test.rb +15 -0
  83. data/test/inch/api/options/base_test.rb +30 -0
  84. data/test/inch/api/stats_test.rb +15 -0
  85. data/test/inch/api/suggest_test.rb +26 -0
  86. data/test/inch/cli/command/list_test.rb +2 -1
  87. data/test/inch/code_object/converter_test.rb +29 -0
  88. data/test/inch/code_object/{docstring_test.rb → provider/yard/docstring_test.rb} +13 -13
  89. data/test/inch/code_object/{nodoc_helper_test.rb → provider/yard/nodoc_helper_test.rb} +6 -6
  90. data/test/inch/code_object/provider/yard_test.rb +11 -0
  91. data/test/inch/code_object/provider_test.rb +9 -0
  92. data/test/inch/code_object/proxy/method_object_test.rb +22 -22
  93. data/test/inch/code_object/proxy_test.rb +10 -10
  94. data/test/inch/codebase/objects_test.rb +28 -0
  95. data/test/inch/codebase/proxy_test.rb +17 -0
  96. data/test/inch/evaluation/role/base_test.rb +71 -0
  97. data/test/inch/{cli → utils}/weighted_list_test.rb +2 -2
  98. data/test/shared/base_list.rb +73 -0
  99. data/test/test_helper.rb +0 -95
  100. metadata +89 -24
  101. data/lib/inch/code_object/docstring.rb +0 -102
  102. data/lib/inch/code_object/nodoc_helper.rb +0 -107
  103. data/lib/inch/evaluation/base.rb +0 -157
  104. data/lib/inch/evaluation/class_object.rb +0 -6
  105. data/lib/inch/evaluation/constant_object.rb +0 -33
  106. data/lib/inch/evaluation/method_object.rb +0 -105
  107. data/lib/inch/evaluation/module_object.rb +0 -6
  108. data/lib/inch/evaluation/namespace_object.rb +0 -52
  109. data/lib/inch/evaluation/read_write_methods.rb +0 -21
  110. data/lib/inch/source_parser.rb +0 -62
  111. data/test/inch/source_parser_test.rb +0 -23
@@ -3,6 +3,6 @@ module Inch
3
3
  end
4
4
  end
5
5
 
6
- require_relative 'code_object/docstring'
7
- require_relative 'code_object/nodoc_helper'
6
+ require_relative 'code_object/converter'
7
+ require_relative 'code_object/provider'
8
8
  require_relative 'code_object/proxy'
@@ -0,0 +1,89 @@
1
+ module Inch
2
+ module CodeObject
3
+ # The Converter takes code object representations from a provider and
4
+ # converts them into attributes hashes.
5
+ # These attributes can then be used to initialize a CodeObject::Proxy.
6
+ #
7
+ # @see CodeObject::Proxy.for
8
+ module Converter
9
+ OBJECT_ATTRIBUTES = %w(
10
+ name
11
+ fullname
12
+ files
13
+ filename
14
+
15
+ children_fullnames
16
+ parent_fullname
17
+
18
+ api_tag?
19
+ attributes
20
+ bang_name?
21
+ constant?
22
+ constructor?
23
+ depth
24
+ docstring
25
+ getter?
26
+ has_alias?
27
+ has_children?
28
+ has_code_example?
29
+ has_doc?
30
+ has_multiple_code_examples?
31
+ has_unconsidered_tags?
32
+ method?
33
+ nodoc?
34
+ namespace?
35
+ overridden?
36
+ overridden_method_fullname
37
+ parameters
38
+ private?
39
+ private_api_tag?
40
+ private_tag?
41
+ protected?
42
+ public?
43
+ questioning_name?
44
+ return_described?
45
+ return_mentioned?
46
+ return_typed?
47
+ in_root?
48
+ setter?
49
+ source
50
+ unconsidered_tag_count
51
+ undocumented?
52
+ visibility
53
+ ).map(&:to_sym)
54
+
55
+ PARAMETER_ATTRIBUTES = %w(
56
+ name
57
+ block?
58
+ described?
59
+ mentioned?
60
+ splat?
61
+ typed?
62
+ wrongly_mentioned?
63
+ ).map(&:to_sym)
64
+
65
+ # Returns an attributes Hash for a given code object
66
+ #
67
+ # @param o [Provider::YARD::Object::Base]
68
+ # @return [Hash]
69
+ def self.to_hash(o)
70
+ attributes = {}
71
+ OBJECT_ATTRIBUTES.each do |name|
72
+ if o.respond_to?(name)
73
+ attributes[name] = o.method(name).call
74
+ end
75
+ end
76
+ attributes[:parameters] = o.parameters.map do |parameter|
77
+ hash = {}
78
+ PARAMETER_ATTRIBUTES.each do |pname|
79
+ if parameter.respond_to?(pname)
80
+ hash[pname] = parameter.method(pname).call
81
+ end
82
+ end
83
+ hash
84
+ end
85
+ attributes
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,36 @@
1
+ module Inch
2
+ module CodeObject
3
+ # Provider modules "provide" a Codebase object with code objects.
4
+ # They are the intermediary between the raw representation that tools
5
+ # like YARD deliver and the "interface" that Inch expects.
6
+ #
7
+ # YARD Example:
8
+ #
9
+ # YARD's SourceParser returns ::YARD::CodeObject objects, which are
10
+ # cast to Provider::YARD::Object::Base objects that can ensure naming
11
+ # conventions et al. follow certain rules. These objects are then again
12
+ # converted into CodeObject::Proxy::Base objects that form the codebase:
13
+ #
14
+ # ::YARD::CodeObject
15
+ # ↓
16
+ # ::Inch::CodeObject::Provider::YARD::Object::Base
17
+ # ↓
18
+ # (Hash)
19
+ # ↓
20
+ # ::Inch::CodeObject::Proxy::Base
21
+ #
22
+ #
23
+ module Provider
24
+ def self.parse(dir, paths, excluded, type = :YARD)
25
+ provider_for(type).parse(dir, paths, excluded)
26
+ end
27
+
28
+ # @return [Module]
29
+ def self.provider_for(type)
30
+ eval("::Inch::CodeObject::Provider::#{type}")
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ require_relative 'provider/yard'
@@ -0,0 +1,19 @@
1
+ module Inch
2
+ module CodeObject
3
+ module Provider
4
+ # Parses the source tree (using YARD)
5
+ module YARD
6
+
7
+ def self.parse(dir, paths, excluded)
8
+ Parser.parse(dir, paths, excluded)
9
+ end
10
+
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ require_relative 'yard/parser'
17
+ require_relative 'yard/docstring'
18
+ require_relative 'yard/nodoc_helper'
19
+ require_relative 'yard/object'
@@ -0,0 +1,106 @@
1
+ module Inch
2
+ module CodeObject
3
+ module Provider
4
+ module YARD
5
+ class Docstring
6
+ def initialize(text)
7
+ @text = text.to_s
8
+ end
9
+
10
+ def empty?
11
+ @text.strip.empty?
12
+ end
13
+
14
+ def contains_code_example?
15
+ !code_examples.empty?
16
+ end
17
+
18
+ def code_examples
19
+ @code_examples ||= parse_code_examples
20
+ end
21
+
22
+ def describes_parameter?(name)
23
+ describe_parameter_regexps(name).any? do |pattern|
24
+ @text.index(pattern)
25
+ end
26
+ end
27
+
28
+ def mentions_parameter?(name)
29
+ mention_parameter_regexps(name).any? do |pattern|
30
+ @text.index(pattern)
31
+ end
32
+ end
33
+
34
+ def mentions_return?
35
+ @text.lines.to_a.last =~ /^Returns\ /
36
+ end
37
+
38
+ def describes_return?
39
+ @text.lines.to_a.last =~ /^Returns\ (\w+\s){2,}/
40
+ end
41
+
42
+ def parse_code_examples
43
+ code_examples = []
44
+ example = nil
45
+ @text.lines.each_with_index do |line, index|
46
+ if line =~/^\s*+$/
47
+ code_examples << example if example
48
+ example = []
49
+ elsif line =~/^\ {2,}\S+/
50
+ example << line if example
51
+ else
52
+ code_examples << example if example
53
+ example = nil
54
+ end
55
+ end
56
+ code_examples << example if example
57
+ code_examples.delete_if(&:empty?).map(&:join)
58
+ end
59
+
60
+ private
61
+
62
+ def mention_parameter_patterns(name)
63
+ [
64
+ "+#{name}+",
65
+ "+#{name}+::",
66
+ "<tt>#{name}</tt>",
67
+ "<tt>#{name}</tt>::",
68
+ "#{name}::",
69
+ /^#{Regexp.escape(name)}\ \-\ /
70
+ ]
71
+ end
72
+
73
+ def describe_parameter_extra_regexps(name)
74
+ [
75
+ "#{name}::",
76
+ "+#{name}+::",
77
+ "<tt>#{name}</tt>::",
78
+ ].map do |pattern|
79
+ r = pattern.is_a?(Regexp) ? pattern : Regexp.escape(pattern)
80
+ /#{r}\n\ {2,}.+/m
81
+ end
82
+ end
83
+
84
+ def describe_parameter_regexps(name)
85
+ same_line_regexps = mention_parameter_patterns(name).map do |pattern|
86
+ r = pattern.is_a?(Regexp) ? pattern : Regexp.escape(pattern)
87
+ /^#{r}\s?\S+/
88
+ end
89
+ same_line_regexps + describe_parameter_extra_regexps(name)
90
+ end
91
+
92
+ def mention_parameter_regexps(name)
93
+ mention_parameter_patterns(name).map do |pattern|
94
+ if pattern.is_a?(Regexp)
95
+ pattern
96
+ else
97
+ r = Regexp.escape(pattern)
98
+ /\W#{r}\W/
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,93 @@
1
+ module Inch
2
+ module CodeObject
3
+ module Provider
4
+ module YARD
5
+ module NodocHelper
6
+
7
+ # Returns true if the code object is somehow marked not to be
8
+ # documented.
9
+ #
10
+ # @note Doesnot recognize ":startdoc:" and ":stopdoc:"
11
+ #
12
+ def nodoc?
13
+ private_tag? || nodoc_comment?
14
+ end
15
+
16
+ NO_DOC_REGEX = /#\s*\:nodoc\:/
17
+ NO_DOC_ALL_REGEX = /#\s*\:nodoc\:\s*all/
18
+ DOC_REGEX = /#\s*\:doc\:/
19
+
20
+ def nodoc_comment?
21
+ explicit_nodoc_comment? || implicit_nodoc_comment?
22
+ end
23
+
24
+ def explicit_nodoc_comment?
25
+ declarations.any? { |str| str =~ NO_DOC_REGEX }
26
+ end
27
+
28
+ def explicit_nodoc_all_comment?
29
+ declarations.any? { |str| str =~ NO_DOC_ALL_REGEX }
30
+ end
31
+
32
+ def explicit_doc_comment?
33
+ declarations.any? { |str| str =~ DOC_REGEX }
34
+ end
35
+
36
+ def implicit_nodoc_all_comment?
37
+ if parent
38
+ parent.explicit_nodoc_all_comment? ||
39
+ parent.implicit_nodoc_all_comment?
40
+ end
41
+ end
42
+
43
+ def implicit_nodoc_comment?
44
+ return false if explicit_doc_comment?
45
+
46
+ if parent
47
+ return false if parent.explicit_doc_comment?
48
+
49
+ if namespace?
50
+ if parent.explicit_nodoc_all_comment?
51
+ return true
52
+ else
53
+ return parent.implicit_nodoc_all_comment?
54
+ end
55
+ else
56
+ if parent.explicit_nodoc_comment?
57
+ return true
58
+ else
59
+ return parent.implicit_nodoc_all_comment?
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ # Returns all lines in all files declaring the object
66
+ #
67
+ # @example
68
+ # declarations # => ["class Base # :nodoc:", "class Foo < Base"]
69
+ #
70
+ # @return [Array<String>]
71
+ def declarations
72
+ @declarations ||= files.map do |f|
73
+ get_line_no(f.filename, f.line_no)
74
+ end
75
+ end
76
+
77
+ # Returns a +line_number+ from a file
78
+ #
79
+ # @param filename [String]
80
+ # @param line_number [Fixnum]
81
+ # @return [String]
82
+ def get_line_no(filename, line_number)
83
+ f = File.open(filename)
84
+ line_number.times{f.gets}
85
+ result = $_
86
+ f.close
87
+ result
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,55 @@
1
+ module Inch
2
+ module CodeObject
3
+ module Provider
4
+ module YARD
5
+ # CodeObject::Provider::YARD::Object object represent code objects.
6
+ #
7
+ module Object
8
+ class << self
9
+ # Returns a Proxy object for the given +yard_object+
10
+ #
11
+ # @param yard_object [YARD::CodeObject]
12
+ # @return [Provider::YARD::Object]
13
+ def for(yard_object)
14
+ @cache ||= {}
15
+ if proxy_object = @cache[cache_key(yard_object)]
16
+ proxy_object
17
+ else
18
+ @cache[cache_key(yard_object)] = class_for(yard_object).new(yard_object)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ # Returns a Proxy class for the given +yard_object+
25
+ #
26
+ # @param yard_object [YARD::CodeObject]
27
+ # @return [Class]
28
+ def class_for(yard_object)
29
+ class_name = yard_object.class.to_s.split('::').last
30
+ eval("::Inch::CodeObject::Provider::YARD::Object::#{class_name}")
31
+ rescue
32
+ Base
33
+ end
34
+
35
+ # Returns a cache key for the given +yard_object+
36
+ #
37
+ # @param yard_object [YARD::CodeObject]
38
+ # @return [String]
39
+ def cache_key(yard_object)
40
+ yard_object.path
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ require_relative 'object/base'
50
+ require_relative 'object/namespace_object'
51
+ require_relative 'object/class_object'
52
+ require_relative 'object/constant_object'
53
+ require_relative 'object/method_object'
54
+ require_relative 'object/method_parameter_object'
55
+ require_relative 'object/module_object'
@@ -0,0 +1,262 @@
1
+ require 'forwardable'
2
+
3
+ module Inch
4
+ module CodeObject
5
+ module Provider
6
+ module YARD
7
+ module Object
8
+ # @abstract
9
+ class Base
10
+ extend Forwardable
11
+ include YARD::NodocHelper
12
+
13
+ # @return [YARD::CodeObjects::Base] the actual (YARD) code object
14
+ attr_reader :object
15
+
16
+ # @return [String] the codebase's directory
17
+ attr_accessor :base_dir
18
+
19
+ # Tags considered by wrapper methods like {#has_code_example?}
20
+ CONSIDERED_YARD_TAGS = %w(api example param private return)
21
+
22
+ # convenient shortcuts to (YARD) code object
23
+ def_delegators :object, :type, :namespace, :source, :source_type, :signature, :group, :dynamic, :visibility
24
+
25
+ # @param object [YARD::CodeObjects::Base] the actual (YARD) code object
26
+ def initialize(object)
27
+ @object = object
28
+ end
29
+
30
+ def api_tag?
31
+ !api_tag.nil?
32
+ end
33
+
34
+ def api_tag
35
+ tag(:api) || (parent && parent.api_tag)
36
+ end
37
+
38
+ # To be overridden
39
+ # @see Proxy::NamespaceObject
40
+ # @return [CodeObject::Proxy::Base,nil] the child inside the current object or +nil+
41
+ def child(name)
42
+ nil
43
+ end
44
+
45
+ # @return [Array,nil] the full names of the children of the current object
46
+ def children_fullnames
47
+ []
48
+ end
49
+
50
+ # To be overridden
51
+ # @see Proxy::NamespaceObject
52
+ def children
53
+ []
54
+ end
55
+
56
+ RUBY_CORE = %w(Array Bignum BasicObject Object Module Class Complex NilClass Numeric String Float Fiber FiberError Continuation Dir File Encoding Enumerator StopIteration Enumerator::Generator Enumerator::Yielder Exception SystemExit SignalException Interrupt StandardError TypeError ArgumentError IndexError KeyError RangeError ScriptError SyntaxError LoadError NotImplementedError NameError NoMethodError RuntimeError SecurityError NoMemoryError EncodingError SystemCallError Encoding::CompatibilityError File::Stat IO Hash ENV IOError EOFError ARGF RubyVM RubyVM::InstructionSequence Math::DomainError ZeroDivisionError FloatDomainError Integer Fixnum Data TrueClass FalseClass Mutex Thread Proc LocalJumpError SystemStackError Method UnboundMethod Binding Process::Status Random Range Rational RegexpError Regexp MatchData Symbol Struct ThreadGroup ThreadError Time Encoding::UndefinedConversionError Encoding::InvalidByteSequenceError Encoding::ConverterNotFoundError Encoding::Converter RubyVM::Env) +
57
+ %w(Comparable Kernel File::Constants Enumerable Errno FileTest GC ObjectSpace GC::Profiler IO::WaitReadable IO::WaitWritable Marshal Math Process Process::UID Process::GID Process::Sys Signal)
58
+ def core?
59
+ RUBY_CORE.include?(name.to_s)
60
+ end
61
+
62
+ # @return [Docstring]
63
+ def docstring
64
+ @docstring ||= Docstring.new(object.docstring)
65
+ end
66
+
67
+ # Returns all files declaring the object in the form of an Array of
68
+ # Arrays containing the filename and the line number of their
69
+ # declaration.
70
+ #
71
+ # @example
72
+ # files # => [["lib/inch.rb", 3],
73
+ # ["lib/inch/cli.rb", 1],
74
+ # ["lib/inch/version.rb", 1],
75
+ #
76
+ # @return [Array<Array(String, Fixnum)>]
77
+ def files
78
+ object.files.map do |(filename, line_no)|
79
+ CodeLocation.new(base_dir, filename, line_no)
80
+ end
81
+ rescue ::YARD::CodeObjects::ProxyMethodError
82
+ # this error is raised by YARD
83
+ # see broken.rb in test fixtures
84
+ []
85
+ end
86
+
87
+ # CodeLocation is a utility class to find declarations of objects in files
88
+ class CodeLocation < Struct.new(:base_dir, :relative_path, :line_no)
89
+ def filename
90
+ File.join(base_dir, relative_path)
91
+ end
92
+ end
93
+
94
+ # Returns the name of the file where the object is declared first
95
+ # @return [String] a filename
96
+ def filename
97
+ # just checking the first file (which is the file where an object
98
+ # is first declared)
99
+ files.first && files.first.filename
100
+ end
101
+
102
+ def fullname
103
+ object.path
104
+ end
105
+
106
+ def name
107
+ object.name
108
+ end
109
+
110
+ def has_alias?
111
+ false
112
+ end
113
+
114
+ def has_children?
115
+ !children.empty?
116
+ end
117
+
118
+ def has_code_example?
119
+ !tags(:example).empty? ||
120
+ docstring.contains_code_example?
121
+ end
122
+
123
+ def has_doc?
124
+ !docstring.empty?
125
+ end
126
+
127
+ def has_multiple_code_examples?
128
+ if tags(:example).size > 1 || docstring.code_examples.size > 1
129
+ true
130
+ else
131
+ if tag = tag(:example)
132
+ multi_code_examples?(tag.text)
133
+ elsif text = docstring.code_examples.first
134
+ multi_code_examples?(text)
135
+ else
136
+ false
137
+ end
138
+ end
139
+ end
140
+
141
+ def has_unconsidered_tags?
142
+ !unconsidered_tags.empty?
143
+ end
144
+
145
+ def in_in_root?
146
+ depth == 1
147
+ end
148
+
149
+ # The depth of the following is 4:
150
+ #
151
+ # Foo::Bar::Baz#initialize
152
+ # ^ ^ ^ ^
153
+ # 1 << 2 << 3 << 4
154
+ #
155
+ # +depth+ answers the question "how many layers of code objects are
156
+ # above this one?"
157
+ #
158
+ # @note top-level counts, that's why Foo has depth 1!
159
+ #
160
+ # @param i [Fixnum] a counter for recursive method calls
161
+ # @return [Fixnum] the depth of the object in terms of namespace
162
+ def depth(i = 0)
163
+ if parent
164
+ parent.depth(i+1)
165
+ else
166
+ i
167
+ end
168
+ end
169
+
170
+ # @return [Boolean] +true+ if the object represents a method
171
+ def method?
172
+ false
173
+ end
174
+
175
+ # @return [Boolean] +true+ if the object represents a namespace
176
+ def namespace?
177
+ false
178
+ end
179
+
180
+ def parameters
181
+ []
182
+ end
183
+
184
+ # @return [Array,nil] the parent of the current object or +nil+
185
+ def parent
186
+ YARD::Object.for(object.parent) if object.parent
187
+ end
188
+
189
+ def private?
190
+ visibility == :private
191
+ end
192
+
193
+ # @return [Boolean]
194
+ # +true+ if the object or its parent is tagged as @private
195
+ def private_tag?
196
+ !private_tag.nil?
197
+ end
198
+
199
+ def private_tag
200
+ tag(:private) || (parent && parent.private_tag)
201
+ end
202
+
203
+ def private_api_tag?
204
+ api_tag && api_tag.text == 'private'
205
+ end
206
+
207
+ def protected?
208
+ visibility == :protected
209
+ end
210
+
211
+ def public?
212
+ visibility == :public
213
+ end
214
+
215
+ def in_root?
216
+ depth == 1
217
+ end
218
+
219
+ # @return [Boolean] +true+ if the object has no documentation at all
220
+ def undocumented?
221
+ docstring.empty? && tags.empty?
222
+ end
223
+
224
+ def unconsidered_tag_count
225
+ unconsidered_tags.size
226
+ end
227
+
228
+ def inspect
229
+ "#<#{self.class.to_s}: #{path}>"
230
+ end
231
+
232
+ protected
233
+
234
+ def multi_code_examples?(text)
235
+ text.scan(/\b(#{Regexp.escape(name)})[^_0-9\!\?]/m).size > 1
236
+ end
237
+
238
+ def tag(name)
239
+ tags(name).first
240
+ end
241
+
242
+ def tags(name = nil)
243
+ object.tags(name)
244
+ rescue ::YARD::CodeObjects::ProxyMethodError
245
+ # this error is raised by YARD
246
+ # see broken.rb in test fixtures
247
+ []
248
+ end
249
+
250
+ # @return [Array]
251
+ # YARD tags that are not already covered by other wrapper methods
252
+ def unconsidered_tags
253
+ @unconsidered_tags ||= tags.reject do |tag|
254
+ CONSIDERED_YARD_TAGS.include?(tag.tag_name)
255
+ end
256
+ end
257
+ end
258
+ end
259
+ end
260
+ end
261
+ end
262
+ end