inch 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|