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,127 @@
|
|
1
|
+
module Inch
|
2
|
+
module Evaluation
|
3
|
+
class MethodObject < Base
|
4
|
+
DOC_SCORE = 50
|
5
|
+
EXAMPLE_SCORE = 10
|
6
|
+
MULTIPLE_EXAMPLES_SCORE = 25
|
7
|
+
PARAM_SCORE = 40
|
8
|
+
RETURN_SCORE = 10
|
9
|
+
|
10
|
+
def evaluate
|
11
|
+
eval_doc
|
12
|
+
eval_parameters
|
13
|
+
eval_return_type
|
14
|
+
eval_code_example
|
15
|
+
|
16
|
+
if object.overridden?
|
17
|
+
add_role Role::Method::Overridden.new(object, object.overridden_method.score)
|
18
|
+
end
|
19
|
+
if object.has_many_lines?
|
20
|
+
add_role Role::Method::WithManyLines.new(object)
|
21
|
+
end
|
22
|
+
if object.bang_name?
|
23
|
+
add_role Role::Method::WithBangName.new(object)
|
24
|
+
end
|
25
|
+
if object.has_alias?
|
26
|
+
add_role Role::Method::HasAlias.new(object)
|
27
|
+
end
|
28
|
+
if object.nodoc?
|
29
|
+
add_role Role::Object::TaggedAsNodoc.new(object)
|
30
|
+
end
|
31
|
+
if object.has_unconsidered_tags?
|
32
|
+
count = object.unconsidered_tags.size
|
33
|
+
add_role Role::Object::Tagged.new(object, TAGGED_SCORE * count)
|
34
|
+
end
|
35
|
+
if object.in_root?
|
36
|
+
add_role Role::Object::InRoot.new(object)
|
37
|
+
end
|
38
|
+
if object.public?
|
39
|
+
add_role Role::Object::Public.new(object)
|
40
|
+
end
|
41
|
+
if object.protected?
|
42
|
+
add_role Role::Object::Protected.new(object)
|
43
|
+
end
|
44
|
+
if object.private?
|
45
|
+
add_role Role::Object::Private.new(object)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def eval_doc
|
52
|
+
if object.has_doc?
|
53
|
+
add_role Role::Object::WithDoc.new(object, DOC_SCORE)
|
54
|
+
else
|
55
|
+
add_role Role::Object::WithoutDoc.new(object, DOC_SCORE)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def eval_code_example
|
60
|
+
if object.has_code_example?
|
61
|
+
if object.has_multiple_code_examples?
|
62
|
+
add_role Role::Object::WithMultipleCodeExamples.new(object, MULTIPLE_EXAMPLES_SCORE)
|
63
|
+
else
|
64
|
+
add_role Role::Object::WithCodeExample.new(object, EXAMPLE_SCORE)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
add_role Role::Object::WithoutCodeExample.new(object, EXAMPLE_SCORE)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def eval_parameters
|
72
|
+
if object.has_parameters?
|
73
|
+
eval_all_parameters
|
74
|
+
else
|
75
|
+
eval_no_parameters
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def eval_no_parameters
|
80
|
+
if score > min_score
|
81
|
+
add_role Role::Method::WithoutParameters.new(object, PARAM_SCORE)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def eval_all_parameters
|
86
|
+
params = object.parameters
|
87
|
+
per_param = PARAM_SCORE.to_f / params.size
|
88
|
+
params.each do |param|
|
89
|
+
if param.mentioned?
|
90
|
+
if param.wrongly_mentioned?
|
91
|
+
add_role Role::MethodParameter::WithWrongMention.new(param, -PARAM_SCORE)
|
92
|
+
else
|
93
|
+
add_role Role::MethodParameter::WithMention.new(param, per_param * 0.5)
|
94
|
+
end
|
95
|
+
else
|
96
|
+
add_role Role::MethodParameter::WithoutMention.new(param, per_param * 0.5)
|
97
|
+
end
|
98
|
+
if param.typed?
|
99
|
+
add_role Role::MethodParameter::WithType.new(param, per_param * 0.5)
|
100
|
+
else
|
101
|
+
add_role Role::MethodParameter::WithoutType.new(param, per_param * 0.5)
|
102
|
+
end
|
103
|
+
if param.bad_name?
|
104
|
+
add_role Role::MethodParameter::WithBadName.new(param)
|
105
|
+
end
|
106
|
+
if param.block?
|
107
|
+
add_role Role::MethodParameter::Block.new(param)
|
108
|
+
end
|
109
|
+
if param.splat?
|
110
|
+
add_role Role::MethodParameter::Splat.new(param)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
if object.has_many_parameters?
|
114
|
+
add_role Role::Method::WithManyParameters.new(object)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def eval_return_type
|
119
|
+
if object.return_mentioned?
|
120
|
+
add_role Role::Method::WithReturnType.new(object, RETURN_SCORE)
|
121
|
+
else
|
122
|
+
add_role Role::Method::WithoutReturnType.new(object, RETURN_SCORE)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Inch
|
2
|
+
module Evaluation
|
3
|
+
# a namespace object can have methods and other namespace objects
|
4
|
+
# inside itself (e.g. classes and modules)
|
5
|
+
class NamespaceObject < Base
|
6
|
+
DOC_SCORE = MAX_SCORE
|
7
|
+
EXAMPLE_SCORE = 10
|
8
|
+
MULTIPLE_EXAMPLES_SCORE = 20
|
9
|
+
|
10
|
+
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) +
|
11
|
+
%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)
|
12
|
+
|
13
|
+
def evaluate
|
14
|
+
eval_doc
|
15
|
+
eval_children
|
16
|
+
eval_code_example
|
17
|
+
|
18
|
+
if object.has_many_attributes?
|
19
|
+
add_role Role::Namespace::WithManyAttributes.new(object)
|
20
|
+
end
|
21
|
+
if object.nodoc?
|
22
|
+
add_role Role::Object::TaggedAsNodoc.new(object)
|
23
|
+
end
|
24
|
+
if object.has_unconsidered_tags?
|
25
|
+
count = object.unconsidered_tags.size
|
26
|
+
add_role Role::Object::Tagged.new(object, TAGGED_SCORE * count)
|
27
|
+
end
|
28
|
+
if object.in_root?
|
29
|
+
add_role Role::Object::InRoot.new(object)
|
30
|
+
end
|
31
|
+
if object.public?
|
32
|
+
add_role Role::Object::Public.new(object)
|
33
|
+
end
|
34
|
+
if object.protected?
|
35
|
+
add_role Role::Object::Protected.new(object)
|
36
|
+
end
|
37
|
+
if object.private?
|
38
|
+
add_role Role::Object::Private.new(object)
|
39
|
+
end
|
40
|
+
|
41
|
+
eval_core
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def eval_core
|
47
|
+
if RUBY_CORE.include?(object.path)
|
48
|
+
add_role Role::Namespace::Core.new(object)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def eval_doc
|
53
|
+
if object.has_doc?
|
54
|
+
add_role Role::Object::WithDoc.new(object, DOC_SCORE)
|
55
|
+
else
|
56
|
+
add_role Role::Object::WithoutDoc.new(object, DOC_SCORE)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def eval_code_example
|
61
|
+
if object.has_code_example?
|
62
|
+
if object.has_multiple_code_examples?
|
63
|
+
add_role Role::Object::WithMultipleCodeExamples.new(object, MULTIPLE_EXAMPLES_SCORE)
|
64
|
+
else
|
65
|
+
add_role Role::Object::WithCodeExample.new(object, EXAMPLE_SCORE)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
add_role Role::Object::WithoutCodeExample.new(object, EXAMPLE_SCORE)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def eval_children
|
73
|
+
if children.empty?
|
74
|
+
add_role Role::Namespace::WithoutChildren.new(object)
|
75
|
+
else
|
76
|
+
add_role Role::Namespace::WithChildren.new(object, children.map(&:score).min)
|
77
|
+
if object.pure_namespace?
|
78
|
+
add_role Role::Namespace::Pure.new(object)
|
79
|
+
end
|
80
|
+
if object.no_methods?
|
81
|
+
add_role Role::Namespace::WithoutMethods.new(object)
|
82
|
+
end
|
83
|
+
if object.has_many_children?
|
84
|
+
add_role Role::Namespace::WithManyChildren.new(object)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def children
|
90
|
+
@children ||= object.children.map(&:evaluation)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Inch
|
2
|
+
module Evaluation
|
3
|
+
module Role
|
4
|
+
class Base
|
5
|
+
attr_reader :object
|
6
|
+
|
7
|
+
def initialize(object, value = nil)
|
8
|
+
@object = object
|
9
|
+
@value = value
|
10
|
+
end
|
11
|
+
|
12
|
+
# Override this method to that a max_score for the evaluation.
|
13
|
+
def max_score
|
14
|
+
end
|
15
|
+
|
16
|
+
# Override this method to that a min_score for the evaluation.
|
17
|
+
def min_score
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns a score that will be added to the associated object's
|
21
|
+
# overall score.
|
22
|
+
#
|
23
|
+
# Override this method to that a score for the role.
|
24
|
+
def score
|
25
|
+
@value.to_f
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Float]
|
29
|
+
# a score that can be achieved by adding the missing thing mentioned
|
30
|
+
# by the role
|
31
|
+
def potential_score
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def priority
|
36
|
+
0
|
37
|
+
end
|
38
|
+
|
39
|
+
def suggestion
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def object_type
|
44
|
+
object.class.to_s.split('::').last.gsub(/Object$/, '').downcase
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Inch
|
2
|
+
module Evaluation
|
3
|
+
module Role
|
4
|
+
module Constant
|
5
|
+
class WithDoc < Object::WithDoc
|
6
|
+
end
|
7
|
+
class WithoutDoc < Object::WithoutDoc
|
8
|
+
end
|
9
|
+
|
10
|
+
class TaggedAsNodoc < Object::TaggedAsNodoc
|
11
|
+
end
|
12
|
+
class InRoot < Object::InRoot
|
13
|
+
end
|
14
|
+
|
15
|
+
class Public < Object::Public
|
16
|
+
def priority
|
17
|
+
-1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
class Protected < Object::Protected
|
21
|
+
def priority
|
22
|
+
-2
|
23
|
+
end
|
24
|
+
end
|
25
|
+
class Private < Object::Private
|
26
|
+
def priority
|
27
|
+
-3
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class WithCodeExample < Object::WithCodeExample
|
32
|
+
end
|
33
|
+
class WithMultipleCodeExamples < Object::WithMultipleCodeExamples
|
34
|
+
end
|
35
|
+
class WithoutCodeExample < Object::WithoutCodeExample
|
36
|
+
def suggestion
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Inch
|
2
|
+
module Evaluation
|
3
|
+
module Role
|
4
|
+
module Method
|
5
|
+
class WithoutParameters < Base
|
6
|
+
end
|
7
|
+
class WithManyParameters < Base
|
8
|
+
# +priority
|
9
|
+
def priority
|
10
|
+
+2
|
11
|
+
end
|
12
|
+
end
|
13
|
+
class WithManyLines < Base
|
14
|
+
# +priority
|
15
|
+
def priority
|
16
|
+
+2
|
17
|
+
end
|
18
|
+
end
|
19
|
+
class WithBangName < Base
|
20
|
+
# +priority
|
21
|
+
def priority
|
22
|
+
+3
|
23
|
+
end
|
24
|
+
end
|
25
|
+
class HasAlias < Base
|
26
|
+
# +priority
|
27
|
+
def priority
|
28
|
+
+2
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class WithReturnType < Base
|
33
|
+
end
|
34
|
+
class WithoutReturnType < Missing
|
35
|
+
def suggestion
|
36
|
+
"Describe the return type of '#{object.name}'"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Overridden < Base
|
41
|
+
# It seems more important to document the overridden method,
|
42
|
+
# than the overriding one
|
43
|
+
def priority
|
44
|
+
-2
|
45
|
+
end
|
46
|
+
|
47
|
+
# This role doesnot assign a score.
|
48
|
+
def score
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# This role sets a min_score.
|
53
|
+
def min_score
|
54
|
+
@value.to_f
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Inch
|
2
|
+
module Evaluation
|
3
|
+
module Role
|
4
|
+
module MethodParameter
|
5
|
+
class WithMention < Base
|
6
|
+
end
|
7
|
+
class WithoutMention < Missing
|
8
|
+
def suggestion
|
9
|
+
"Describe the parameter '#{object.name}'"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class WithType < Base
|
14
|
+
end
|
15
|
+
class WithoutType < Missing
|
16
|
+
end
|
17
|
+
|
18
|
+
class Splat < Base
|
19
|
+
def priority
|
20
|
+
+1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
class Block < Base
|
24
|
+
def priority
|
25
|
+
+1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class WithWrongMention < Missing
|
30
|
+
def suggestion
|
31
|
+
"The parameter '#{object.name}' seems not to be part of the signature."
|
32
|
+
end
|
33
|
+
def priority
|
34
|
+
+1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
class WithBadName < Base
|
38
|
+
# +priority
|
39
|
+
def priority
|
40
|
+
+1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Inch
|
2
|
+
module Evaluation
|
3
|
+
module Role
|
4
|
+
# Missing is the base class for things that can be improved in the doc
|
5
|
+
#
|
6
|
+
class Missing < Base
|
7
|
+
def score
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [Float]
|
12
|
+
# a score that can be achieved by adding the missing thing mentioned
|
13
|
+
# by the role
|
14
|
+
def potential_score
|
15
|
+
@value.to_f
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|