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.
- checksums.yaml +4 -4
- data/.simplecov +7 -0
- data/TODOS.md +0 -5
- data/config/defaults.rb +26 -1
- data/inch.gemspec +1 -0
- data/lib/inch.rb +2 -1
- data/lib/inch/api.rb +34 -0
- data/lib/inch/api/filter.rb +17 -0
- data/lib/inch/api/get.rb +30 -0
- data/lib/inch/api/list.rb +10 -0
- data/lib/inch/api/options/base.rb +45 -0
- data/lib/inch/api/options/filter.rb +25 -0
- data/lib/inch/api/options/suggest.rb +36 -0
- data/lib/inch/api/stats.rb +7 -0
- data/lib/inch/api/suggest.rb +110 -0
- data/lib/inch/cli.rb +4 -1
- data/lib/inch/cli/command/base.rb +1 -17
- data/lib/inch/cli/command/base_list.rb +3 -63
- data/lib/inch/cli/command/base_object.rb +6 -28
- data/lib/inch/cli/command/list.rb +3 -2
- data/lib/inch/cli/command/options/base.rb +1 -1
- data/lib/inch/cli/command/options/base_list.rb +4 -2
- data/lib/inch/cli/command/options/suggest.rb +9 -8
- data/lib/inch/cli/command/output/base.rb +9 -11
- data/lib/inch/cli/command/output/list.rb +2 -2
- data/lib/inch/cli/command/output/show.rb +2 -10
- data/lib/inch/cli/command/output/stats.rb +4 -3
- data/lib/inch/cli/command/output/suggest.rb +5 -5
- data/lib/inch/cli/command/stats.rb +4 -3
- data/lib/inch/cli/command/suggest.rb +4 -94
- data/lib/inch/code_object.rb +2 -2
- data/lib/inch/code_object/converter.rb +89 -0
- data/lib/inch/code_object/provider.rb +36 -0
- data/lib/inch/code_object/provider/yard.rb +19 -0
- data/lib/inch/code_object/provider/yard/docstring.rb +106 -0
- data/lib/inch/code_object/provider/yard/nodoc_helper.rb +93 -0
- data/lib/inch/code_object/provider/yard/object.rb +55 -0
- data/lib/inch/code_object/provider/yard/object/base.rb +262 -0
- data/lib/inch/code_object/provider/yard/object/class_object.rb +12 -0
- data/lib/inch/code_object/provider/yard/object/constant_object.rb +12 -0
- data/lib/inch/code_object/provider/yard/object/method_object.rb +126 -0
- data/lib/inch/code_object/provider/yard/object/method_parameter_object.rb +88 -0
- data/lib/inch/code_object/provider/yard/object/module_object.rb +12 -0
- data/lib/inch/code_object/provider/yard/object/namespace_object.rb +47 -0
- data/lib/inch/code_object/provider/yard/parser.rb +54 -0
- data/lib/inch/code_object/proxy.rb +5 -3
- data/lib/inch/code_object/proxy/base.rb +103 -110
- data/lib/inch/code_object/proxy/class_object.rb +0 -1
- data/lib/inch/code_object/proxy/method_object.rb +20 -99
- data/lib/inch/code_object/proxy/method_parameter_object.rb +15 -39
- data/lib/inch/code_object/proxy/namespace_object.rb +7 -18
- data/lib/inch/codebase.rb +19 -0
- data/lib/inch/codebase/objects.rb +73 -0
- data/lib/inch/codebase/objects_filter.rb +61 -0
- data/lib/inch/codebase/proxy.rb +22 -0
- data/lib/inch/config.rb +8 -1
- data/lib/inch/evaluation.rb +5 -7
- data/lib/inch/evaluation/file.rb +1 -1
- data/lib/inch/evaluation/grade.rb +1 -1
- data/lib/inch/evaluation/object_schema.rb +3 -1
- data/lib/inch/evaluation/priority_range.rb +44 -0
- data/lib/inch/evaluation/proxy.rb +25 -0
- data/lib/inch/evaluation/proxy/base.rb +146 -0
- data/lib/inch/evaluation/proxy/class_object.rb +8 -0
- data/lib/inch/evaluation/proxy/constant_object.rb +19 -0
- data/lib/inch/evaluation/proxy/method_object.rb +65 -0
- data/lib/inch/evaluation/proxy/module_object.rb +8 -0
- data/lib/inch/evaluation/proxy/namespace_object.rb +27 -0
- data/lib/inch/evaluation/role/base.rb +19 -0
- data/lib/inch/evaluation/role/constant.rb +16 -0
- data/lib/inch/evaluation/role/method.rb +22 -0
- data/lib/inch/evaluation/role/method_parameter.rb +31 -1
- data/lib/inch/evaluation/role/namespace.rb +15 -0
- data/lib/inch/evaluation/role/object.rb +24 -0
- data/lib/inch/rake/suggest.rb +1 -0
- data/lib/inch/utils/read_write_methods.rb +44 -0
- data/lib/inch/{cli → utils}/weighted_list.rb +1 -1
- data/lib/inch/version.rb +1 -1
- data/test/fixtures/simple/lib/broken.rb +8 -0
- data/test/inch/api/filter_test.rb +51 -0
- data/test/inch/api/get_test.rb +22 -0
- data/test/inch/api/list_test.rb +15 -0
- data/test/inch/api/options/base_test.rb +30 -0
- data/test/inch/api/stats_test.rb +15 -0
- data/test/inch/api/suggest_test.rb +26 -0
- data/test/inch/cli/command/list_test.rb +2 -1
- data/test/inch/code_object/converter_test.rb +29 -0
- data/test/inch/code_object/{docstring_test.rb → provider/yard/docstring_test.rb} +13 -13
- data/test/inch/code_object/{nodoc_helper_test.rb → provider/yard/nodoc_helper_test.rb} +6 -6
- data/test/inch/code_object/provider/yard_test.rb +11 -0
- data/test/inch/code_object/provider_test.rb +9 -0
- data/test/inch/code_object/proxy/method_object_test.rb +22 -22
- data/test/inch/code_object/proxy_test.rb +10 -10
- data/test/inch/codebase/objects_test.rb +28 -0
- data/test/inch/codebase/proxy_test.rb +17 -0
- data/test/inch/evaluation/role/base_test.rb +71 -0
- data/test/inch/{cli → utils}/weighted_list_test.rb +2 -2
- data/test/shared/base_list.rb +73 -0
- data/test/test_helper.rb +0 -95
- metadata +89 -24
- data/lib/inch/code_object/docstring.rb +0 -102
- data/lib/inch/code_object/nodoc_helper.rb +0 -107
- data/lib/inch/evaluation/base.rb +0 -157
- data/lib/inch/evaluation/class_object.rb +0 -6
- data/lib/inch/evaluation/constant_object.rb +0 -33
- data/lib/inch/evaluation/method_object.rb +0 -105
- data/lib/inch/evaluation/module_object.rb +0 -6
- data/lib/inch/evaluation/namespace_object.rb +0 -52
- data/lib/inch/evaluation/read_write_methods.rb +0 -21
- data/lib/inch/source_parser.rb +0 -62
- data/test/inch/source_parser_test.rb +0 -23
@@ -3,31 +3,16 @@ module Inch
|
|
3
3
|
module Proxy
|
4
4
|
# Proxy class for methods
|
5
5
|
class MethodObject < Base
|
6
|
-
|
7
6
|
def constructor?
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
|
-
def comment_and_abbrev_source
|
12
|
-
comments.join('') + abbrev_source
|
7
|
+
self[:constructor?]
|
13
8
|
end
|
14
9
|
|
15
10
|
def bang_name?
|
16
|
-
|
11
|
+
self[:bang_name?]
|
17
12
|
end
|
18
13
|
|
19
14
|
def getter?
|
20
|
-
|
21
|
-
read_info = attr_info[:read]
|
22
|
-
if read_info
|
23
|
-
read_info.path == path
|
24
|
-
else
|
25
|
-
parent.child(:"#{name}=")
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def has_doc?
|
30
|
-
super && !implicit_docstring?
|
15
|
+
self[:getter?]
|
31
16
|
end
|
32
17
|
|
33
18
|
def has_parameters?
|
@@ -42,7 +27,7 @@ module Inch
|
|
42
27
|
MANY_LINES_THRESHOLD = 20
|
43
28
|
def has_many_lines?
|
44
29
|
# for now, this includes the 'def' line and comments
|
45
|
-
if source
|
30
|
+
if source
|
46
31
|
size = source.lines.count
|
47
32
|
size > MANY_LINES_THRESHOLD
|
48
33
|
else
|
@@ -50,110 +35,46 @@ module Inch
|
|
50
35
|
end
|
51
36
|
end
|
52
37
|
|
53
|
-
def
|
54
|
-
|
38
|
+
def parameter(name)
|
39
|
+
parameters.detect { |p| p.name == name.to_s }
|
55
40
|
end
|
56
41
|
|
57
42
|
def parameters
|
58
|
-
@parameters ||=
|
59
|
-
|
60
|
-
tag = parameter_tag(name)
|
61
|
-
MethodParameterObject.new(self, name, tag, in_signature)
|
43
|
+
@parameters ||= self[:parameters].map do |param_attr|
|
44
|
+
MethodParameterObject.new(param_attr)
|
62
45
|
end
|
63
46
|
end
|
64
47
|
|
65
|
-
def parameter(name)
|
66
|
-
parameters.detect { |p| p.name == name.to_s }
|
67
|
-
end
|
68
|
-
|
69
48
|
def overridden?
|
70
|
-
|
49
|
+
self[:overridden?]
|
71
50
|
end
|
72
51
|
|
73
52
|
def overridden_method
|
74
|
-
@overridden_method ||=
|
53
|
+
@overridden_method ||= object_lookup.find(self[:overridden_method_fullname])
|
75
54
|
end
|
76
55
|
|
77
56
|
def return_mentioned?
|
78
|
-
|
57
|
+
self[:return_mentioned?]
|
79
58
|
end
|
80
59
|
|
81
60
|
def return_described?
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
def setter?
|
86
|
-
name =~ /\=$/ && parameters.size == 1
|
87
|
-
end
|
88
|
-
|
89
|
-
def questioning_name?
|
90
|
-
name =~ /\?$/
|
91
|
-
end
|
92
|
-
|
93
|
-
private
|
94
|
-
|
95
|
-
def all_parameter_names
|
96
|
-
names = signature_parameter_names
|
97
|
-
names.concat parameter_tags.map(&:name)
|
98
|
-
names.compact.uniq
|
99
|
-
end
|
100
|
-
|
101
|
-
def abbrev_source
|
102
|
-
lines = object.source.to_s.lines.to_a
|
103
|
-
if lines.size >= 5
|
104
|
-
indent = lines[1].scan(/^(\s+)/).flatten.join('')
|
105
|
-
lines = lines[0..1] +
|
106
|
-
["#{indent}# ... snip ...\n"] +
|
107
|
-
lines[-2..-1]
|
108
|
-
end
|
109
|
-
lines.join('')
|
61
|
+
self[:return_described?]
|
110
62
|
end
|
111
63
|
|
112
|
-
def
|
113
|
-
|
114
|
-
get_lines_up_while(filename, line_no - 1) do |line|
|
115
|
-
line =~ /^\s*#/
|
116
|
-
end.flatten.join('')
|
117
|
-
end
|
64
|
+
def return_typed?
|
65
|
+
self[:return_typed?]
|
118
66
|
end
|
119
67
|
|
120
|
-
def
|
121
|
-
|
122
|
-
line = get_line_no(filename, line_no)
|
123
|
-
if yield(line) && line_no > 0
|
124
|
-
lines << line.gsub(/^(\s+)/, '')
|
125
|
-
lines << get_lines_up_while(filename, line_no - 1, &block)
|
126
|
-
end
|
127
|
-
lines.reverse
|
128
|
-
end
|
129
|
-
|
130
|
-
def implicit_docstring?
|
131
|
-
if getter?
|
132
|
-
docstring == "Returns the value of attribute #{name}"
|
133
|
-
elsif setter?
|
134
|
-
basename = name.to_s.gsub(/(\=)$/, '')
|
135
|
-
docstring == "Sets the attribute #{basename}"
|
136
|
-
else
|
137
|
-
false
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def signature_parameter_names
|
142
|
-
object.parameters.map(&:first)
|
143
|
-
end
|
144
|
-
|
145
|
-
def parameter_tag(param_name)
|
146
|
-
parameter_tags.detect do |tag|
|
147
|
-
tag.name == param_name
|
148
|
-
end
|
68
|
+
def setter?
|
69
|
+
self[:setter?]
|
149
70
|
end
|
150
71
|
|
151
|
-
def
|
152
|
-
|
72
|
+
def source
|
73
|
+
self[:source?]
|
153
74
|
end
|
154
75
|
|
155
|
-
def
|
156
|
-
|
76
|
+
def questioning_name?
|
77
|
+
self[:questioning_name?]
|
157
78
|
end
|
158
79
|
end
|
159
80
|
end
|
@@ -3,17 +3,12 @@ module Inch
|
|
3
3
|
module Proxy
|
4
4
|
# Proxy class for method parameters
|
5
5
|
class MethodParameterObject
|
6
|
-
|
6
|
+
def initialize(attributes)
|
7
|
+
@attributes = attributes
|
8
|
+
end
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
# @param tag [YARD::Tags::Tag] the Tag object for the parameter
|
11
|
-
# @param in_signature [Boolean] +true+ if the method's signature contains the parameter
|
12
|
-
def initialize(method, name, tag, in_signature)
|
13
|
-
@method = method
|
14
|
-
@name = name
|
15
|
-
@tag = tag
|
16
|
-
@in_signature = in_signature
|
10
|
+
def [](key)
|
11
|
+
@attributes[key]
|
17
12
|
end
|
18
13
|
|
19
14
|
BAD_NAME_EXCEPTIONS = %w(id)
|
@@ -27,57 +22,38 @@ module Inch
|
|
27
22
|
|
28
23
|
# @return [Boolean] +true+ if the parameter is a block
|
29
24
|
def block?
|
30
|
-
|
25
|
+
self[:block?]
|
31
26
|
end
|
32
27
|
|
33
28
|
# @return [Boolean] +true+ if an additional description given?
|
34
29
|
def described?
|
35
|
-
|
30
|
+
self[:described?]
|
36
31
|
end
|
37
32
|
|
38
33
|
# @return [Boolean] +true+ if the parameter is mentioned in the docs
|
39
34
|
def mentioned?
|
40
|
-
|
35
|
+
self[:mentioned?]
|
36
|
+
end
|
37
|
+
|
38
|
+
def name
|
39
|
+
self[:name]
|
41
40
|
end
|
42
41
|
|
43
42
|
# @return [Boolean] +true+ if the parameter is a splat argument
|
44
43
|
def splat?
|
45
|
-
|
44
|
+
self[:splat?]
|
46
45
|
end
|
47
46
|
|
48
47
|
# @return [Boolean] +true+ if the type of the parameter is defined
|
49
48
|
def typed?
|
50
|
-
|
49
|
+
self[:typed?]
|
51
50
|
end
|
52
51
|
|
53
52
|
# @return [Boolean] +true+ if the parameter is mentioned in the docs, but not present in the method's signature
|
54
53
|
def wrongly_mentioned?
|
55
|
-
|
54
|
+
self[:wrongly_mentioned?]
|
56
55
|
end
|
57
56
|
|
58
|
-
private
|
59
|
-
|
60
|
-
def described_by_tag?
|
61
|
-
@tag && !@tag.text.empty?
|
62
|
-
end
|
63
|
-
|
64
|
-
def described_by_docstring?
|
65
|
-
if @method.docstring.describes_parameter?(name)
|
66
|
-
true
|
67
|
-
else
|
68
|
-
unsplatted = name.gsub(/^[\&\*]/, '')
|
69
|
-
@method.docstring.describes_parameter?(unsplatted)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def mentioned_by_docstring?
|
74
|
-
if @method.docstring.mentions_parameter?(name)
|
75
|
-
true
|
76
|
-
else
|
77
|
-
unsplatted = name.gsub(/^[\&\*]/, '')
|
78
|
-
@method.docstring.mentions_parameter?(unsplatted)
|
79
|
-
end
|
80
|
-
end
|
81
57
|
end
|
82
58
|
end
|
83
59
|
end
|
@@ -4,22 +4,15 @@ module Inch
|
|
4
4
|
# a namespace object can have methods and other namespace objects
|
5
5
|
# inside itself (e.g. classes and modules)
|
6
6
|
class NamespaceObject < Base
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def children
|
14
|
-
object.children.map do |o|
|
15
|
-
Proxy.for(o)
|
16
|
-
end
|
7
|
+
# The wording is a bit redundant, but this means the class and
|
8
|
+
# instance attributes of the namespace
|
9
|
+
def attributes
|
10
|
+
self[:attributes]
|
17
11
|
end
|
18
12
|
|
19
13
|
MANY_ATTRIBUTES_THRESHOLD = 5
|
20
14
|
def has_many_attributes?
|
21
|
-
|
22
|
-
n > MANY_ATTRIBUTES_THRESHOLD
|
15
|
+
attributes.size > MANY_ATTRIBUTES_THRESHOLD
|
23
16
|
end
|
24
17
|
|
25
18
|
MANY_CHILDREN_THRESHOLD = 20
|
@@ -27,12 +20,8 @@ module Inch
|
|
27
20
|
children.size > MANY_CHILDREN_THRESHOLD
|
28
21
|
end
|
29
22
|
|
30
|
-
def
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
def no_methods?
|
35
|
-
!children.any?(&:method?)
|
23
|
+
def has_methods?
|
24
|
+
children.any?(&:method?)
|
36
25
|
end
|
37
26
|
|
38
27
|
def pure_namespace?
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Inch
|
2
|
+
# Codebases are one of the building blocks of Inch's analysis (the other
|
3
|
+
# being "code objects" inside these "codebases").
|
4
|
+
module Codebase
|
5
|
+
# Parses a codebase
|
6
|
+
#
|
7
|
+
# @param dir [String]
|
8
|
+
# @param paths [Array<String>]
|
9
|
+
# @param excluded [Array<String>]
|
10
|
+
# @return [Codebase::Proxy]
|
11
|
+
def self.parse(dir, paths = nil, excluded = nil)
|
12
|
+
Proxy.new(dir, paths, excluded)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require_relative 'codebase/proxy'
|
18
|
+
require_relative 'codebase/objects'
|
19
|
+
require_relative 'codebase/objects_filter'
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Inch
|
2
|
+
module Codebase
|
3
|
+
class Objects
|
4
|
+
include Enumerable
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_delegators :@list, :each, :empty?, :size
|
8
|
+
|
9
|
+
# @param objects [Array<CodeObject::Proxy::Base>]
|
10
|
+
# @return [Array<CodeObject::Proxy::Base>]
|
11
|
+
def self.sort_by_priority(objects)
|
12
|
+
objects.sort_by do |o|
|
13
|
+
[o.priority, o.score, o.fullname.size]
|
14
|
+
end.reverse
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(objects)
|
18
|
+
list = objects.map do |o|
|
19
|
+
proxy = CodeObject::Proxy.for(o)
|
20
|
+
proxy.object_lookup = self
|
21
|
+
proxy
|
22
|
+
end
|
23
|
+
@list = list
|
24
|
+
# the @list has to be set for the priority sorting
|
25
|
+
# since the priority needs the object_lookup, which
|
26
|
+
# in turn depends on @list - it's a crazy world
|
27
|
+
@list = self.class.sort_by_priority(@list)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns all parsed objects as code object proxies
|
31
|
+
#
|
32
|
+
# @see CodeObject::Proxy.for
|
33
|
+
# @return [Array<CodeObject::Proxy::Base>]
|
34
|
+
def all
|
35
|
+
@list
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the object with the given +fullname+
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
#
|
42
|
+
# find("Foo#bar")
|
43
|
+
# # => returns the code object proxy for Foo#bar
|
44
|
+
#
|
45
|
+
# @param fullname [String] partial fullname/name of an object
|
46
|
+
# @return [CodeObject::Proxy::Base]
|
47
|
+
def find(fullname)
|
48
|
+
all.detect { |o| o.fullname == fullname }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns all objects where the +fullname+ starts_with the given
|
52
|
+
# +partial_name+
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
#
|
56
|
+
# find("Foo#")
|
57
|
+
# # => returns the code object proxies for all instance methods of Foo
|
58
|
+
#
|
59
|
+
# @param partial_name [String] partial name of an object
|
60
|
+
# @return [Array<CodeObject::Proxy::Base>]
|
61
|
+
def starting_with(partial_name)
|
62
|
+
all.select { |o| o.fullname.start_with?(partial_name) }
|
63
|
+
end
|
64
|
+
|
65
|
+
# Filters the list based on the settings in +options+
|
66
|
+
#
|
67
|
+
# @return [void]
|
68
|
+
def filter!(options)
|
69
|
+
@list = ObjectsFilter.new(all, options).objects
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Inch
|
2
|
+
module Codebase
|
3
|
+
# ObjectsFilter can be used to filter a list of objects by given a set of
|
4
|
+
# given +options+
|
5
|
+
class ObjectsFilter
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
def initialize(list, options)
|
9
|
+
@list = list
|
10
|
+
@options = options
|
11
|
+
filter
|
12
|
+
end
|
13
|
+
|
14
|
+
def objects
|
15
|
+
@list
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def filter
|
21
|
+
filter_namespaces
|
22
|
+
filter_undocumented
|
23
|
+
filter_depth
|
24
|
+
filter_visibility
|
25
|
+
end
|
26
|
+
|
27
|
+
def filter_namespaces
|
28
|
+
if options.namespaces == :only
|
29
|
+
@list = @list.select(&:namespace?)
|
30
|
+
elsif options.namespaces == :none
|
31
|
+
@list = @list.reject(&:namespace?)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def filter_undocumented
|
36
|
+
if options.undocumented == :only
|
37
|
+
@list = @list.select(&:undocumented?)
|
38
|
+
elsif options.undocumented == :none
|
39
|
+
@list = @list.reject(&:undocumented?)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def filter_depth
|
44
|
+
if options.depth
|
45
|
+
@list = @list.select { |o| o.depth <= options.depth }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def filter_visibility
|
50
|
+
@list = @list.select do |o|
|
51
|
+
options.visibility.include?(o.visibility)
|
52
|
+
end
|
53
|
+
if !options.visibility.include?(:private)
|
54
|
+
@list = @list.reject do |o|
|
55
|
+
o.private_tag?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|