inch 0.0.1 → 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 +4 -4
- data/Gemfile +2 -0
- data/README.md +335 -3
- data/Rakefile +8 -0
- data/TODOS.md +12 -0
- data/bin/inch +17 -0
- data/inch.gemspec +7 -2
- data/lib/inch.rb +6 -1
- data/lib/inch/cli.rb +24 -0
- data/lib/inch/cli/arguments.rb +45 -0
- data/lib/inch/cli/command.rb +29 -0
- data/lib/inch/cli/command/base.rb +62 -0
- data/lib/inch/cli/command/base_list.rb +75 -0
- data/lib/inch/cli/command/base_object.rb +40 -0
- data/lib/inch/cli/command/console.rb +22 -0
- data/lib/inch/cli/command/inspect.rb +20 -0
- data/lib/inch/cli/command/list.rb +25 -0
- data/lib/inch/cli/command/options/base.rb +137 -0
- data/lib/inch/cli/command/options/base_list.rb +84 -0
- data/lib/inch/cli/command/options/base_object.rb +47 -0
- data/lib/inch/cli/command/options/console.rb +26 -0
- data/lib/inch/cli/command/options/inspect.rb +25 -0
- data/lib/inch/cli/command/options/list.rb +30 -0
- data/lib/inch/cli/command/options/show.rb +27 -0
- data/lib/inch/cli/command/options/stats.rb +20 -0
- data/lib/inch/cli/command/options/suggest.rb +61 -0
- data/lib/inch/cli/command/output/base.rb +32 -0
- data/lib/inch/cli/command/output/console.rb +45 -0
- data/lib/inch/cli/command/output/inspect.rb +129 -0
- data/lib/inch/cli/command/output/list.rb +87 -0
- data/lib/inch/cli/command/output/show.rb +79 -0
- data/lib/inch/cli/command/output/stats.rb +111 -0
- data/lib/inch/cli/command/output/suggest.rb +104 -0
- data/lib/inch/cli/command/show.rb +20 -0
- data/lib/inch/cli/command/stats.rb +20 -0
- data/lib/inch/cli/command/suggest.rb +104 -0
- data/lib/inch/cli/command_parser.rb +82 -0
- data/lib/inch/cli/sparkline_helper.rb +31 -0
- data/lib/inch/cli/trace_helper.rb +42 -0
- data/lib/inch/cli/yardopts_helper.rb +49 -0
- data/lib/inch/code_object.rb +8 -0
- data/lib/inch/code_object/docstring.rb +97 -0
- data/lib/inch/code_object/nodoc_helper.rb +84 -0
- data/lib/inch/code_object/proxy.rb +37 -0
- data/lib/inch/code_object/proxy/base.rb +194 -0
- data/lib/inch/code_object/proxy/class_object.rb +9 -0
- data/lib/inch/code_object/proxy/constant_object.rb +8 -0
- data/lib/inch/code_object/proxy/method_object.rb +118 -0
- data/lib/inch/code_object/proxy/method_parameter_object.rb +81 -0
- data/lib/inch/code_object/proxy/module_object.rb +8 -0
- data/lib/inch/code_object/proxy/namespace_object.rb +38 -0
- data/lib/inch/core_ext.rb +2 -0
- data/lib/inch/core_ext/string.rb +3 -0
- data/lib/inch/core_ext/yard.rb +4 -0
- data/lib/inch/evaluation.rb +35 -0
- data/lib/inch/evaluation/base.rb +60 -0
- data/lib/inch/evaluation/class_object.rb +6 -0
- data/lib/inch/evaluation/constant_object.rb +34 -0
- data/lib/inch/evaluation/file.rb +66 -0
- data/lib/inch/evaluation/method_object.rb +127 -0
- data/lib/inch/evaluation/module_object.rb +6 -0
- data/lib/inch/evaluation/namespace_object.rb +94 -0
- data/lib/inch/evaluation/role/base.rb +49 -0
- data/lib/inch/evaluation/role/constant.rb +43 -0
- data/lib/inch/evaluation/role/method.rb +60 -0
- data/lib/inch/evaluation/role/method_parameter.rb +46 -0
- data/lib/inch/evaluation/role/missing.rb +20 -0
- data/lib/inch/evaluation/role/namespace.rb +58 -0
- data/lib/inch/evaluation/role/object.rb +64 -0
- data/lib/inch/evaluation/score_range.rb +26 -0
- data/lib/inch/rake.rb +1 -0
- data/lib/inch/rake/suggest.rb +26 -0
- data/lib/inch/source_parser.rb +36 -0
- data/lib/inch/version.rb +1 -1
- data/test/fixtures/code_examples/lib/foo.rb +87 -0
- data/test/fixtures/readme/lib/foo.rb +17 -0
- data/test/fixtures/simple/README +25 -0
- data/test/fixtures/simple/lib/broken.rb +10 -0
- data/test/fixtures/simple/lib/foo.rb +214 -0
- data/test/fixtures/simple/lib/role_methods.rb +78 -0
- data/test/fixtures/simple/lib/role_namespaces.rb +68 -0
- data/test/fixtures/visibility/lib/foo.rb +18 -0
- data/test/fixtures/yardopts/.yardopts +1 -0
- data/test/fixtures/yardopts/foo/bar.rb +6 -0
- data/test/inch/cli/arguments_test.rb +70 -0
- data/test/inch/cli/command/console_test.rb +59 -0
- data/test/inch/cli/command/inspect_test.rb +59 -0
- data/test/inch/cli/command/list_test.rb +61 -0
- data/test/inch/cli/command/show_test.rb +59 -0
- data/test/inch/cli/command/stats_test.rb +57 -0
- data/test/inch/cli/command/suggest_test.rb +57 -0
- data/test/inch/cli/command_parser_test.rb +33 -0
- data/test/inch/cli/yardopts_helper_test.rb +84 -0
- data/test/inch/code_object/docstring_test.rb +204 -0
- data/test/inch/code_object/nodoc_helper_test.rb +38 -0
- data/test/inch/code_object/proxy_test.rb +188 -0
- data/test/inch/source_parser_test.rb +23 -0
- data/test/integration/stats_options_test.rb +34 -0
- data/test/integration/visibility_options_test.rb +79 -0
- data/test/test_helper.rb +21 -0
- metadata +184 -7
@@ -0,0 +1,82 @@
|
|
1
|
+
# This was adapted from https://github.com/lsegal/yard/blob/master/lib/yard/cli/command_parser.rb
|
2
|
+
module Inch
|
3
|
+
module CLI
|
4
|
+
# This class parses a command name out of the +inch+ CLI command and calls
|
5
|
+
# that command in the form:
|
6
|
+
#
|
7
|
+
# $ inch command_name [options]
|
8
|
+
#
|
9
|
+
# If no command or arguments are specified, or if the arguments immediately
|
10
|
+
# begin with a +--opt+ (not +--help+), the {default_command} will be used
|
11
|
+
# (which itself defaults to +:doc+).
|
12
|
+
#
|
13
|
+
class CommandParser
|
14
|
+
include TraceHelper
|
15
|
+
|
16
|
+
class << self
|
17
|
+
# @return [Hash{Symbol => Command}] the mapping of command names to
|
18
|
+
# command classes to parse the user command.
|
19
|
+
attr_accessor :commands
|
20
|
+
|
21
|
+
# @return [Symbol] the default command name to use when no options
|
22
|
+
# are specified or
|
23
|
+
attr_accessor :default_command
|
24
|
+
end
|
25
|
+
|
26
|
+
self.commands = {
|
27
|
+
:console => Command::Console,
|
28
|
+
:inspect => Command::Inspect,
|
29
|
+
:list => Command::List,
|
30
|
+
:show => Command::Show,
|
31
|
+
:stats => Command::Stats,
|
32
|
+
:suggest => Command::Suggest,
|
33
|
+
}
|
34
|
+
|
35
|
+
self.default_command = :suggest
|
36
|
+
|
37
|
+
# Convenience method to create a new CommandParser and call {#run}
|
38
|
+
# @return (see #run)
|
39
|
+
def self.run(*args)
|
40
|
+
new.run(*args)
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize
|
44
|
+
#log.show_backtraces = false
|
45
|
+
end
|
46
|
+
|
47
|
+
# Runs the {Command} object matching the command name of the first
|
48
|
+
# argument.
|
49
|
+
# @return [void]
|
50
|
+
def run(*args)
|
51
|
+
unless ['--help', '-h'].include?(args.join)
|
52
|
+
if args.size == 0 || args.first =~ /^-/
|
53
|
+
command_name = self.class.default_command
|
54
|
+
else
|
55
|
+
command_name = args.first.to_sym
|
56
|
+
args.shift
|
57
|
+
end
|
58
|
+
if commands.has_key?(command_name)
|
59
|
+
return commands[command_name].run(*args)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
list_commands
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def commands
|
68
|
+
self.class.commands
|
69
|
+
end
|
70
|
+
|
71
|
+
def list_commands
|
72
|
+
trace "Usage: inch <command> [options]"
|
73
|
+
trace
|
74
|
+
trace "Commands:"
|
75
|
+
commands.keys.sort_by {|k| k.to_s }.each do |command_name|
|
76
|
+
command = commands[command_name].new
|
77
|
+
trace " %-8s %s" % [command_name, command.description]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Inch
|
2
|
+
module CLI
|
3
|
+
module SparklineHelper
|
4
|
+
def ranges_sparkline(_ranges)
|
5
|
+
ranges = _ranges.reverse
|
6
|
+
list = ranges.map { |r| r.objects.size }
|
7
|
+
sparkline = Sparkr::Sparkline.new(list)
|
8
|
+
sparkline.format do |tick, count, index|
|
9
|
+
t = tick.color(ranges[index].color)
|
10
|
+
index == 0 ? t + ' ' : t
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def grades_sparkline(objects)
|
15
|
+
grades = {}
|
16
|
+
objects.each do |o|
|
17
|
+
grades[o.grade] ||= 0
|
18
|
+
grades[o.grade] += 1
|
19
|
+
end
|
20
|
+
ranges = Evaluation.new_score_ranges.reverse
|
21
|
+
order = ranges.map(&:grade)
|
22
|
+
list = order.map { |g| grades[g] }
|
23
|
+
sparkline = Sparkr::Sparkline.new(list)
|
24
|
+
sparkline.format do |tick, count, index|
|
25
|
+
t = tick.color(ranges[index].color)
|
26
|
+
index == 0 ? t + ' ' : t
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Inch
|
2
|
+
module CLI
|
3
|
+
module TraceHelper
|
4
|
+
def debug(msg)
|
5
|
+
return unless ENV['DEBUG']
|
6
|
+
msg.to_s.lines.each do |line|
|
7
|
+
trace edged :dark, line.gsub(/\n$/,'').dark
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Writes the given +text+ to stdout
|
12
|
+
# @param text [String]
|
13
|
+
# @return [void]
|
14
|
+
def trace(text = "")
|
15
|
+
puts text
|
16
|
+
end
|
17
|
+
|
18
|
+
def trace_header(text, color, bg_color = nil)
|
19
|
+
trace header(text, color, bg_color)
|
20
|
+
trace if !use_color?
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def edged(color, msg, edge = "┃ ")
|
26
|
+
edge.color(color) + msg
|
27
|
+
end
|
28
|
+
|
29
|
+
def header(text, color, bg_color = nil)
|
30
|
+
bg_color ||= "intense_#{color}"
|
31
|
+
bar = " #{text}".ljust(CLI::COLUMNS-1)
|
32
|
+
.on_color(bg_color).color(:color16)
|
33
|
+
"#".color(color).on_color(color) + bar
|
34
|
+
end
|
35
|
+
|
36
|
+
def use_color?
|
37
|
+
Term::ANSIColor::coloring?
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Inch
|
2
|
+
module CLI
|
3
|
+
module YardoptsHelper
|
4
|
+
# @return [Array<String>] list of Ruby source files to process
|
5
|
+
attr_accessor :yard_files
|
6
|
+
|
7
|
+
# @return [Array<String>] list of excluded paths (regexp matches)
|
8
|
+
attr_accessor :excluded
|
9
|
+
|
10
|
+
VALID_YARD_SWITCHES = %w(--private --no-private --protected --no-public
|
11
|
+
--plugin --load --safe --yardopts --no-yardopts --document --no-document)
|
12
|
+
|
13
|
+
# Parses the option and gracefully handles invalid switches
|
14
|
+
#
|
15
|
+
# @param [OptionParser] opts the option parser object
|
16
|
+
# @param [Array<String>] args the arguments passed from input. This
|
17
|
+
# array will be modified.
|
18
|
+
# @return [void]
|
19
|
+
def parse_yardopts_options(opts, args)
|
20
|
+
wrapper = YardoptsWrapper.new()
|
21
|
+
|
22
|
+
dupped_args = args.dup
|
23
|
+
dupped_args.delete("--help")
|
24
|
+
dupped_args.delete_if do |arg|
|
25
|
+
arg =~ /^\-/ && !VALID_YARD_SWITCHES.include?(arg)
|
26
|
+
end
|
27
|
+
|
28
|
+
debug "Sending args to YARD:\n" \
|
29
|
+
" args: #{dupped_args}"
|
30
|
+
|
31
|
+
wrapper.parse_arguments(*dupped_args)
|
32
|
+
|
33
|
+
self.yard_files = wrapper.files
|
34
|
+
self.excluded = wrapper.excluded
|
35
|
+
end
|
36
|
+
|
37
|
+
def yardopts_options(opts)
|
38
|
+
wrapper = YardoptsWrapper.new()
|
39
|
+
wrapper.add_yardoc_options(opts)
|
40
|
+
end
|
41
|
+
|
42
|
+
class YardoptsWrapper < YARD::CLI::Yardoc
|
43
|
+
def add_yardoc_options(opts)
|
44
|
+
yardopts_options(opts)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Inch
|
2
|
+
module CodeObject
|
3
|
+
class Docstring
|
4
|
+
def initialize(text)
|
5
|
+
@text = text.to_s
|
6
|
+
end
|
7
|
+
|
8
|
+
def empty?
|
9
|
+
@text.strip.empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
def contains_code_example?
|
13
|
+
!code_examples.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
def code_examples
|
17
|
+
@code_examples ||= parse_code_examples
|
18
|
+
end
|
19
|
+
|
20
|
+
def describes_parameter?(name)
|
21
|
+
describe_parameter_regexps(name).any? do |pattern|
|
22
|
+
@text.index(pattern)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def mentions_parameter?(name)
|
27
|
+
mention_parameter_regexps(name).any? do |pattern|
|
28
|
+
@text.index(pattern)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def mentions_return?
|
33
|
+
@text.lines.last =~ /^Returns\ /
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_code_examples
|
37
|
+
code_examples = []
|
38
|
+
example = nil
|
39
|
+
@text.lines.each_with_index do |line, index|
|
40
|
+
if line =~/^\s*+$/
|
41
|
+
code_examples << example if example
|
42
|
+
example = []
|
43
|
+
elsif line =~/^\ {2,}\S+/
|
44
|
+
example << line if example
|
45
|
+
else
|
46
|
+
code_examples << example if example
|
47
|
+
example = nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
code_examples << example if example
|
51
|
+
code_examples.delete_if(&:empty?).map(&:join)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def mention_parameter_patterns(name)
|
57
|
+
[
|
58
|
+
"+#{name}+",
|
59
|
+
"+#{name}+::",
|
60
|
+
"<tt>#{name}</tt>",
|
61
|
+
"<tt>#{name}</tt>::",
|
62
|
+
"#{name}::",
|
63
|
+
/^#{name}\ \-\ /
|
64
|
+
]
|
65
|
+
end
|
66
|
+
|
67
|
+
def describe_parameter_extra_regexps(name)
|
68
|
+
[
|
69
|
+
"#{name}::",
|
70
|
+
"+#{name}+::",
|
71
|
+
"<tt>#{name}</tt>::",
|
72
|
+
].map do |pattern|
|
73
|
+
r = pattern.is_a?(Regexp) ? pattern : Regexp.escape(pattern)
|
74
|
+
/#{r}\n\ {2,}.+/m
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def describe_parameter_regexps(name)
|
79
|
+
mention_parameter_patterns(name).map do |pattern|
|
80
|
+
r = pattern.is_a?(Regexp) ? pattern : Regexp.escape(pattern)
|
81
|
+
/^#{r}\s?\S+/
|
82
|
+
end + describe_parameter_extra_regexps(name)
|
83
|
+
end
|
84
|
+
|
85
|
+
def mention_parameter_regexps(name)
|
86
|
+
mention_parameter_patterns(name).map do |pattern|
|
87
|
+
if pattern.is_a?(Regexp)
|
88
|
+
pattern
|
89
|
+
else
|
90
|
+
r = Regexp.escape(pattern)
|
91
|
+
/\W#{r}\W/
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Inch
|
2
|
+
module CodeObject
|
3
|
+
module NodocHelper
|
4
|
+
|
5
|
+
# Returns true if the code object is somehow marked not to be
|
6
|
+
# documented.
|
7
|
+
#
|
8
|
+
# @note Doesnot recognize ":startdoc:" and ":stopdoc:"
|
9
|
+
#
|
10
|
+
def nodoc?
|
11
|
+
object.tag(:private) || nodoc_comment?
|
12
|
+
end
|
13
|
+
|
14
|
+
NO_DOC_REGEX = /#\s*\:nodoc\:/
|
15
|
+
NO_DOC_ALL_REGEX = /#\s*\:nodoc\:\s*all/
|
16
|
+
DOC_REGEX = /#\s*\:doc\:/
|
17
|
+
|
18
|
+
def nodoc_comment?
|
19
|
+
explicit_nodoc_comment? || implicit_nodoc_comment?
|
20
|
+
end
|
21
|
+
|
22
|
+
def explicit_nodoc_comment?
|
23
|
+
declarations.any? { |str| str =~ NO_DOC_REGEX }
|
24
|
+
end
|
25
|
+
|
26
|
+
def explicit_nodoc_all_comment?
|
27
|
+
declarations.any? { |str| str =~ NO_DOC_ALL_REGEX }
|
28
|
+
end
|
29
|
+
|
30
|
+
def explicit_doc_comment?
|
31
|
+
declarations.any? { |str| str =~ DOC_REGEX }
|
32
|
+
end
|
33
|
+
|
34
|
+
def implicit_nodoc_all_comment?
|
35
|
+
if parent
|
36
|
+
parent.explicit_nodoc_all_comment? ||
|
37
|
+
parent.implicit_nodoc_all_comment?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def implicit_nodoc_comment?
|
42
|
+
return false if explicit_doc_comment?
|
43
|
+
|
44
|
+
if parent
|
45
|
+
return false if parent.explicit_doc_comment?
|
46
|
+
|
47
|
+
if namespace?
|
48
|
+
if parent.explicit_nodoc_all_comment?
|
49
|
+
return true
|
50
|
+
else
|
51
|
+
return parent.implicit_nodoc_all_comment?
|
52
|
+
end
|
53
|
+
else
|
54
|
+
if parent.explicit_nodoc_comment?
|
55
|
+
return true
|
56
|
+
else
|
57
|
+
return parent.implicit_nodoc_all_comment?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def declarations
|
64
|
+
@declarations ||= files.map do |(filename, line_no)|
|
65
|
+
get_line_no(filename, line_no)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def files
|
70
|
+
object.files
|
71
|
+
rescue YARD::CodeObjects::ProxyMethodError
|
72
|
+
[]
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_line_no(filename, n)
|
76
|
+
f = File.open(filename)
|
77
|
+
n.times{f.gets}
|
78
|
+
result = $_
|
79
|
+
f.close
|
80
|
+
result
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Inch
|
2
|
+
module CodeObject
|
3
|
+
module Proxy
|
4
|
+
class << self
|
5
|
+
def for(code_object)
|
6
|
+
@cache ||= {}
|
7
|
+
if proxy_object = @cache[cache_key(code_object)]
|
8
|
+
proxy_object
|
9
|
+
else
|
10
|
+
@cache[cache_key(code_object)] = class_for(code_object).new(code_object)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def class_for(code_object)
|
17
|
+
class_name = code_object.class.to_s.split('::').last
|
18
|
+
eval("::Inch::CodeObject::Proxy::#{class_name}")
|
19
|
+
rescue
|
20
|
+
Base
|
21
|
+
end
|
22
|
+
|
23
|
+
def cache_key(o)
|
24
|
+
o.path
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require_relative 'proxy/base'
|
32
|
+
require_relative 'proxy/namespace_object'
|
33
|
+
require_relative 'proxy/class_object'
|
34
|
+
require_relative 'proxy/constant_object'
|
35
|
+
require_relative 'proxy/method_object'
|
36
|
+
require_relative 'proxy/method_parameter_object'
|
37
|
+
require_relative 'proxy/module_object'
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Inch
|
4
|
+
module CodeObject
|
5
|
+
module Proxy
|
6
|
+
class Base
|
7
|
+
extend Forwardable
|
8
|
+
include NodocHelper
|
9
|
+
|
10
|
+
# the actual (YARD) code object
|
11
|
+
attr_accessor :object
|
12
|
+
|
13
|
+
# @return [Symbol]
|
14
|
+
# when objects are assigned to ScoreRanges, this grade is set to
|
15
|
+
# enable easier querying for objects of a certain grade
|
16
|
+
attr_writer :grade
|
17
|
+
|
18
|
+
# Tags considered by wrapper methods like {#has_code_example?}
|
19
|
+
CONSIDERED_YARD_TAGS = %w(example param private return)
|
20
|
+
|
21
|
+
# convenient shortcuts to (YARD) code object
|
22
|
+
def_delegators :object, :type, :path, :name, :namespace, :source, :source_type, :signature, :group, :dynamic, :visibility, :docstring
|
23
|
+
|
24
|
+
# convenient shortcuts to evalution object
|
25
|
+
def_delegators :evaluation, :score, :roles, :priority
|
26
|
+
|
27
|
+
def initialize(object)
|
28
|
+
self.object = object
|
29
|
+
end
|
30
|
+
|
31
|
+
# To be overridden
|
32
|
+
# @see Proxy::NamespaceObject
|
33
|
+
# @return [Array,nil] the children of the current object or +nil+
|
34
|
+
def children
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def docstring
|
39
|
+
@docstring ||= Docstring.new(object.docstring)
|
40
|
+
end
|
41
|
+
|
42
|
+
def evaluation
|
43
|
+
@evaluation ||= Evaluation.for(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the name of the file where the object is declared first
|
47
|
+
# @return [String] a filename
|
48
|
+
def filename
|
49
|
+
# just checking the first file (which is the file where an object
|
50
|
+
# is first declared)
|
51
|
+
files.size > 0 ? files[0][0] : nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def grade
|
55
|
+
@grade ||= Evaluation.new_score_ranges.detect { |range|
|
56
|
+
range.range.include?(score)
|
57
|
+
}.grade
|
58
|
+
end
|
59
|
+
|
60
|
+
def has_alias?
|
61
|
+
!object.aliases.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
def has_code_example?
|
65
|
+
!object.tags(:example).empty? ||
|
66
|
+
docstring.contains_code_example?
|
67
|
+
end
|
68
|
+
|
69
|
+
def has_doc?
|
70
|
+
!docstring.empty?
|
71
|
+
end
|
72
|
+
|
73
|
+
def has_multiple_code_examples?
|
74
|
+
if object.tags(:example).size > 1 || docstring.code_examples.size > 1
|
75
|
+
true
|
76
|
+
else
|
77
|
+
if tag = object.tag(:example)
|
78
|
+
multi_code_examples?(tag.text)
|
79
|
+
elsif text = docstring.code_examples.first
|
80
|
+
multi_code_examples?(text)
|
81
|
+
else
|
82
|
+
false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def has_unconsidered_tags?
|
88
|
+
!unconsidered_tags.empty?
|
89
|
+
end
|
90
|
+
|
91
|
+
def in_root?
|
92
|
+
depth == 1
|
93
|
+
end
|
94
|
+
|
95
|
+
# The depth of the following is 4:
|
96
|
+
#
|
97
|
+
# Foo::Bar::Baz#initialize
|
98
|
+
# ^ ^ ^ ^
|
99
|
+
# 1 << 2 << 3 << 4
|
100
|
+
#
|
101
|
+
# +depth+ answers the question "how many layers of code objects are
|
102
|
+
# above this one?"
|
103
|
+
#
|
104
|
+
# @note top-level counts, that's why Foo has depth 1!
|
105
|
+
#
|
106
|
+
# @param i [Fixnum] a counter for recursive method calls
|
107
|
+
# @return [Fixnum] the depth of the object in terms of namespace
|
108
|
+
def depth(i = 0)
|
109
|
+
if parent
|
110
|
+
parent.depth(i+1)
|
111
|
+
else
|
112
|
+
i
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# In the following example, the height of +Foo+ is 3
|
117
|
+
# (the height of the top-level is 4):
|
118
|
+
#
|
119
|
+
# Foo::Bar::Baz#initialize
|
120
|
+
# ^ ^ ^ ^
|
121
|
+
# 0 >> 1 >> 2 >> 3
|
122
|
+
#
|
123
|
+
# +height+ answers the question "how many layers of code objects are
|
124
|
+
# underneath this one?"
|
125
|
+
#
|
126
|
+
# @param i [Fixnum] a counter for recursive method calls
|
127
|
+
# @return [Fixnum] the height of the object in terms of namespace
|
128
|
+
def height(i = 0)
|
129
|
+
if children && !children.empty?
|
130
|
+
children.map do |child|
|
131
|
+
child.height(i+1)
|
132
|
+
end.max
|
133
|
+
else
|
134
|
+
i
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# @return [Boolean] +true+ if the object represents a method
|
139
|
+
def method?
|
140
|
+
false
|
141
|
+
end
|
142
|
+
|
143
|
+
# @return [Boolean] +true+ if the object represents a namespace
|
144
|
+
def namespace?
|
145
|
+
false
|
146
|
+
end
|
147
|
+
|
148
|
+
# @return [Array,nil] the parent of the current object or +nil+
|
149
|
+
def parent
|
150
|
+
Proxy.for(object.parent) if object.parent
|
151
|
+
end
|
152
|
+
|
153
|
+
def private?
|
154
|
+
visibility == :private
|
155
|
+
end
|
156
|
+
|
157
|
+
def private_tag?
|
158
|
+
!!object.tag(:private)
|
159
|
+
end
|
160
|
+
|
161
|
+
def protected?
|
162
|
+
visibility == :protected
|
163
|
+
end
|
164
|
+
|
165
|
+
def public?
|
166
|
+
visibility == :public
|
167
|
+
end
|
168
|
+
|
169
|
+
# @return [Boolean] +true+ if the object has no documentation at all
|
170
|
+
def undocumented?
|
171
|
+
docstring.empty? && object.tags.empty?
|
172
|
+
end
|
173
|
+
|
174
|
+
# @return [Array]
|
175
|
+
# YARD tags that are not already covered by other wrapper methods
|
176
|
+
def unconsidered_tags
|
177
|
+
@unconsidered_tags ||= object.tags.reject do |tag|
|
178
|
+
CONSIDERED_YARD_TAGS.include?(tag.tag_name)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def inspect
|
183
|
+
"#<#{self.class.to_s}: #{path}>"
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
def multi_code_examples?(text)
|
189
|
+
text =~ /\b#{Regexp.escape(name)}[^_0-9\!\?]/
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|