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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +335 -3
  4. data/Rakefile +8 -0
  5. data/TODOS.md +12 -0
  6. data/bin/inch +17 -0
  7. data/inch.gemspec +7 -2
  8. data/lib/inch.rb +6 -1
  9. data/lib/inch/cli.rb +24 -0
  10. data/lib/inch/cli/arguments.rb +45 -0
  11. data/lib/inch/cli/command.rb +29 -0
  12. data/lib/inch/cli/command/base.rb +62 -0
  13. data/lib/inch/cli/command/base_list.rb +75 -0
  14. data/lib/inch/cli/command/base_object.rb +40 -0
  15. data/lib/inch/cli/command/console.rb +22 -0
  16. data/lib/inch/cli/command/inspect.rb +20 -0
  17. data/lib/inch/cli/command/list.rb +25 -0
  18. data/lib/inch/cli/command/options/base.rb +137 -0
  19. data/lib/inch/cli/command/options/base_list.rb +84 -0
  20. data/lib/inch/cli/command/options/base_object.rb +47 -0
  21. data/lib/inch/cli/command/options/console.rb +26 -0
  22. data/lib/inch/cli/command/options/inspect.rb +25 -0
  23. data/lib/inch/cli/command/options/list.rb +30 -0
  24. data/lib/inch/cli/command/options/show.rb +27 -0
  25. data/lib/inch/cli/command/options/stats.rb +20 -0
  26. data/lib/inch/cli/command/options/suggest.rb +61 -0
  27. data/lib/inch/cli/command/output/base.rb +32 -0
  28. data/lib/inch/cli/command/output/console.rb +45 -0
  29. data/lib/inch/cli/command/output/inspect.rb +129 -0
  30. data/lib/inch/cli/command/output/list.rb +87 -0
  31. data/lib/inch/cli/command/output/show.rb +79 -0
  32. data/lib/inch/cli/command/output/stats.rb +111 -0
  33. data/lib/inch/cli/command/output/suggest.rb +104 -0
  34. data/lib/inch/cli/command/show.rb +20 -0
  35. data/lib/inch/cli/command/stats.rb +20 -0
  36. data/lib/inch/cli/command/suggest.rb +104 -0
  37. data/lib/inch/cli/command_parser.rb +82 -0
  38. data/lib/inch/cli/sparkline_helper.rb +31 -0
  39. data/lib/inch/cli/trace_helper.rb +42 -0
  40. data/lib/inch/cli/yardopts_helper.rb +49 -0
  41. data/lib/inch/code_object.rb +8 -0
  42. data/lib/inch/code_object/docstring.rb +97 -0
  43. data/lib/inch/code_object/nodoc_helper.rb +84 -0
  44. data/lib/inch/code_object/proxy.rb +37 -0
  45. data/lib/inch/code_object/proxy/base.rb +194 -0
  46. data/lib/inch/code_object/proxy/class_object.rb +9 -0
  47. data/lib/inch/code_object/proxy/constant_object.rb +8 -0
  48. data/lib/inch/code_object/proxy/method_object.rb +118 -0
  49. data/lib/inch/code_object/proxy/method_parameter_object.rb +81 -0
  50. data/lib/inch/code_object/proxy/module_object.rb +8 -0
  51. data/lib/inch/code_object/proxy/namespace_object.rb +38 -0
  52. data/lib/inch/core_ext.rb +2 -0
  53. data/lib/inch/core_ext/string.rb +3 -0
  54. data/lib/inch/core_ext/yard.rb +4 -0
  55. data/lib/inch/evaluation.rb +35 -0
  56. data/lib/inch/evaluation/base.rb +60 -0
  57. data/lib/inch/evaluation/class_object.rb +6 -0
  58. data/lib/inch/evaluation/constant_object.rb +34 -0
  59. data/lib/inch/evaluation/file.rb +66 -0
  60. data/lib/inch/evaluation/method_object.rb +127 -0
  61. data/lib/inch/evaluation/module_object.rb +6 -0
  62. data/lib/inch/evaluation/namespace_object.rb +94 -0
  63. data/lib/inch/evaluation/role/base.rb +49 -0
  64. data/lib/inch/evaluation/role/constant.rb +43 -0
  65. data/lib/inch/evaluation/role/method.rb +60 -0
  66. data/lib/inch/evaluation/role/method_parameter.rb +46 -0
  67. data/lib/inch/evaluation/role/missing.rb +20 -0
  68. data/lib/inch/evaluation/role/namespace.rb +58 -0
  69. data/lib/inch/evaluation/role/object.rb +64 -0
  70. data/lib/inch/evaluation/score_range.rb +26 -0
  71. data/lib/inch/rake.rb +1 -0
  72. data/lib/inch/rake/suggest.rb +26 -0
  73. data/lib/inch/source_parser.rb +36 -0
  74. data/lib/inch/version.rb +1 -1
  75. data/test/fixtures/code_examples/lib/foo.rb +87 -0
  76. data/test/fixtures/readme/lib/foo.rb +17 -0
  77. data/test/fixtures/simple/README +25 -0
  78. data/test/fixtures/simple/lib/broken.rb +10 -0
  79. data/test/fixtures/simple/lib/foo.rb +214 -0
  80. data/test/fixtures/simple/lib/role_methods.rb +78 -0
  81. data/test/fixtures/simple/lib/role_namespaces.rb +68 -0
  82. data/test/fixtures/visibility/lib/foo.rb +18 -0
  83. data/test/fixtures/yardopts/.yardopts +1 -0
  84. data/test/fixtures/yardopts/foo/bar.rb +6 -0
  85. data/test/inch/cli/arguments_test.rb +70 -0
  86. data/test/inch/cli/command/console_test.rb +59 -0
  87. data/test/inch/cli/command/inspect_test.rb +59 -0
  88. data/test/inch/cli/command/list_test.rb +61 -0
  89. data/test/inch/cli/command/show_test.rb +59 -0
  90. data/test/inch/cli/command/stats_test.rb +57 -0
  91. data/test/inch/cli/command/suggest_test.rb +57 -0
  92. data/test/inch/cli/command_parser_test.rb +33 -0
  93. data/test/inch/cli/yardopts_helper_test.rb +84 -0
  94. data/test/inch/code_object/docstring_test.rb +204 -0
  95. data/test/inch/code_object/nodoc_helper_test.rb +38 -0
  96. data/test/inch/code_object/proxy_test.rb +188 -0
  97. data/test/inch/source_parser_test.rb +23 -0
  98. data/test/integration/stats_options_test.rb +34 -0
  99. data/test/integration/visibility_options_test.rb +79 -0
  100. data/test/test_helper.rb +21 -0
  101. metadata +184 -7
@@ -0,0 +1,84 @@
1
+ module Inch
2
+ module CLI
3
+ module Command
4
+ module Options
5
+ class BaseList < Base
6
+ attribute :full, false
7
+ attribute :visibility, [:public, :protected]
8
+ attribute :namespaces
9
+ attribute :undocumented
10
+ attribute :depth
11
+
12
+ def parse(args)
13
+ opts = OptionParser.new
14
+ opts.banner = usage
15
+
16
+ descriptions.each do |text|
17
+ opts.separator " " + text
18
+ end
19
+
20
+ set_options(opts)
21
+ parse_yardopts_options(opts, args)
22
+ parse_options(opts, args)
23
+
24
+ @paths = get_paths(args)
25
+ end
26
+
27
+ def set_options(opts)
28
+ list_options(opts)
29
+ common_options(opts)
30
+
31
+ yardopts_options(opts)
32
+ end
33
+
34
+ protected
35
+
36
+ def list_options(opts)
37
+ opts.separator ""
38
+ opts.separator "List options:"
39
+
40
+ opts.on("--all", "Show all objects in the output") do
41
+ @full = true
42
+ end
43
+
44
+ opts.on("--only-namespaces", "Only show namespaces (classes, modules)") do
45
+ @namespaces = :only
46
+ end
47
+ opts.on("--no-namespaces", "Only show namespace children (methods, constants, attributes)") do
48
+ @namespaces = :none
49
+ end
50
+
51
+ opts.on("--no-public", "Do not show public objects") do
52
+ set_visibility :public, false
53
+ end
54
+ opts.on("--no-protected", "Do not show protected objects") do
55
+ set_visibility :protected, false
56
+ end
57
+ opts.on("--private", "Show private objects") do
58
+ set_visibility :private, true
59
+ end
60
+
61
+ opts.on("--only-undocumented", "Only show undocumented objects") do
62
+ @undocumented = :only
63
+ end
64
+ opts.on("--no-undocumented", "Only show documented objects") do
65
+ @undocumented = :none
66
+ end
67
+
68
+ opts.on("--depth [DEPTH]", "Only show objects up to a given DEPTH in the class tree") do |depth|
69
+ @depth = depth.to_i
70
+ end
71
+ end
72
+
73
+ def set_visibility(_visibility, true_or_false)
74
+ if true_or_false
75
+ visibility.push(_visibility)
76
+ else
77
+ visibility.delete(_visibility)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,47 @@
1
+ module Inch
2
+ module CLI
3
+ module Command
4
+ module Options
5
+ class BaseObject < Base
6
+ attribute :object_names, []
7
+
8
+ def parse(args)
9
+ opts = OptionParser.new
10
+ opts.banner = usage
11
+
12
+ descriptions.each do |text|
13
+ opts.separator " " + text
14
+ end
15
+
16
+ set_options(opts)
17
+ parse_yardopts_options(opts, args)
18
+ parse_options(opts, args)
19
+
20
+ @object_names = parse_object_names(args)
21
+ @paths = get_paths(args)
22
+ end
23
+
24
+ def set_options(opts)
25
+ common_options(opts)
26
+
27
+ yardopts_options(opts)
28
+ end
29
+
30
+ private
31
+
32
+ # TODO: really check the last parameters if they are globs, files
33
+ # or switches and find the object_name(s) that way
34
+ def parse_object_names(args)
35
+ arguments = Arguments.new(args)
36
+ object_names = arguments.object_names
37
+ object_names.each do |n|
38
+ @yard_files.delete(n)
39
+ args.delete(n)
40
+ end
41
+ object_names
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,26 @@
1
+ module Inch
2
+ module CLI
3
+ module Command
4
+ module Options
5
+ class Console < BaseObject
6
+ def descriptions
7
+ [
8
+ "",
9
+ "Provides a PRY based REPL to inspect objects.",
10
+ "",
11
+ "Example: " + "$ inch console lib/**/*.rb Foo::Bar#initialize".cyan,
12
+ "",
13
+ "Shortcut commands on the prompt are:",
14
+ "",
15
+ "all".ljust(5) + " returns all code objects",
16
+ "f".ljust(5) + " finds an object by its path",
17
+ "ff".ljust(5) + " finds all objects given a partial path",
18
+ "o".ljust(5) + " returns the code object for OBJECT_NAME (if present)",
19
+ ]
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module Inch
2
+ module CLI
3
+ module Command
4
+ module Options
5
+ class Inspect < BaseObject
6
+
7
+ def descriptions
8
+ [
9
+ "",
10
+ "Example: " + "$ inch inspect lib/**/*.rb Foo::Bar#initialize".cyan,
11
+ "",
12
+ "Shows one or more objects in detail."
13
+ ]
14
+ end
15
+
16
+ def verify
17
+ if object_names.empty?
18
+ kill # "Provide a name to an object to show it's evaluation."
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,30 @@
1
+ module Inch
2
+ module CLI
3
+ module Command
4
+ module Options
5
+ class List < BaseList
6
+ attribute :numbers, false
7
+
8
+ def descriptions
9
+ [
10
+ "",
11
+ "Lists objects that can be improved regarding their documentation ordered by their grade.",
12
+ "",
13
+ "Example: " + "$ inch list lib/**/*.rb --all".cyan,
14
+ "",
15
+ description_grades,
16
+ description_arrows
17
+ ]
18
+ end
19
+
20
+ def list_options(opts)
21
+ super
22
+ opts.on("--numbers", "Show numbers instead of grades and arrows") do |depth|
23
+ @numbers = true
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ module Inch
2
+ module CLI
3
+ module Command
4
+ module Options
5
+ class Show < BaseObject
6
+
7
+ def descriptions
8
+ [
9
+ "",
10
+ "Example: " + "$ inch show lib/**/*.rb Foo::Bar#initialize".cyan,
11
+ "",
12
+ "Shows one or more objects in detail.",
13
+ description_grades,
14
+ description_arrows
15
+ ]
16
+ end
17
+
18
+ def verify
19
+ if object_names.empty?
20
+ kill # "Provide a name to an object to show it's evaluation."
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ module Inch
2
+ module CLI
3
+ module Command
4
+ module Options
5
+ class Stats < BaseList
6
+ FORMATS = %w(text json yaml)
7
+
8
+ attribute :format, FORMATS.first
9
+
10
+ def list_options(opts)
11
+ super
12
+ opts.on("-f", "--format [FORMAT]", FORMATS, "Set output FORMAT") do |format|
13
+ @format = format
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,61 @@
1
+ module Inch
2
+ module CLI
3
+ module Command
4
+ module Options
5
+ class Suggest < BaseList
6
+ attribute :object_count, 20
7
+ attribute :file_count, 5
8
+
9
+ attribute :proper_grades, [:A, :B]
10
+ attribute :grades_to_display, [:B, :C, :U]
11
+ attribute :object_min_priority, 0
12
+ attribute :object_max_score, ::Inch::Evaluation::Base::MAX_SCORE
13
+
14
+ attribute :pedantic, false
15
+
16
+ def set_options(opts)
17
+ list_options(opts)
18
+ suggest_options(opts)
19
+ common_options(opts)
20
+
21
+ yardopts_options(opts)
22
+ end
23
+
24
+ def descriptions
25
+ [
26
+ "",
27
+ "Suggests objects and files that can be improved regarding their documentation.",
28
+ "",
29
+ "Example: " + "$ inch suggest lib/**/*.rb --pedantic".cyan,
30
+ "",
31
+ description_grades,
32
+ description_arrows
33
+ ]
34
+ end
35
+
36
+ protected
37
+
38
+ def suggest_options(opts)
39
+ opts.separator ""
40
+ opts.separator "Suggest options:"
41
+
42
+ opts.on("-n", "--objects [COUNT]", "Show COUNT objects") do |count|
43
+ @object_count = count.to_i
44
+ end
45
+ opts.on("--pedantic", "Be excessively concerned with minor details and rules") do |count|
46
+ # all objects are considered a priority
47
+ @object_min_priority = -99
48
+ # only objects with the highest score are omitted from the list
49
+ @object_max_score = object_max_score - 1
50
+ # only A-listers are regarded as 'proper'
51
+ @proper_grades = [:A]
52
+ @grades_to_display = [:A, :B, :C]
53
+ @object_count = 30
54
+ @pedantic = true
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,32 @@
1
+ require 'optparse'
2
+
3
+ module Inch
4
+ module CLI
5
+ module Command
6
+ module Output
7
+ # Abstract base class for CLI output
8
+ #
9
+ class Base
10
+ include TraceHelper
11
+
12
+ PRIORITY_MAP = {
13
+ (4..99) => "\u2191", # north
14
+ (2...4) => "\u2197", # north-east
15
+ (0..1) => "\u2192", # east
16
+ (-2..-1) => "\u2198", # south-east
17
+ (-99..-3) => "\u2193", # south-east
18
+ }
19
+ PRIORITY_ARROWS = PRIORITY_MAP.values
20
+
21
+ def priority_arrow(priority, color = :white)
22
+ PRIORITY_MAP.each do |range, str|
23
+ if range.include?(priority)
24
+ return str.color(color).dark
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ module Inch
2
+ module CLI
3
+ module Command
4
+ module Output
5
+ class Console < Base
6
+ extend Forwardable
7
+
8
+ attr_reader :object, :objects, :source_parser
9
+
10
+ def_delegators :source_parser, :all_objects, :find_object, :find_objects
11
+ alias :all :all_objects
12
+ alias :ff :find_objects
13
+ alias :f :find_object
14
+ alias :o :object
15
+
16
+ COLOR = :color198 # magenta-ish
17
+ BG_COLOR = :color207 # magenta-ish
18
+
19
+ def initialize(options, object, objects, source_parser)
20
+ @options = options
21
+ @object = object
22
+ @objects = objects
23
+ @source_parser = source_parser
24
+
25
+ run
26
+ end
27
+
28
+ def run
29
+ trace
30
+ trace_header("Welcome to Inch's console", COLOR, BG_COLOR)
31
+ trace edged(COLOR, @options.usage)
32
+ @options.descriptions.each do |line|
33
+ trace edged(COLOR, line)
34
+ end
35
+ run_pry
36
+ end
37
+
38
+ def run_pry
39
+ binding.pry
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,129 @@
1
+ module Inch
2
+ module CLI
3
+ module Command
4
+ module Output
5
+ class Inspect < Base
6
+ attr_reader :objects
7
+
8
+ COLOR = :color198 # magenta-ish
9
+ BG_COLOR = :color207 # magenta-ish
10
+ LJUST = 20
11
+
12
+ def initialize(options, objects)
13
+ @options = options
14
+ @objects = objects
15
+
16
+ display_objects
17
+ end
18
+
19
+ private
20
+
21
+ def display_objects
22
+ objects.each do |o|
23
+ print_object(o)
24
+ end
25
+ end
26
+
27
+ def print_object(o)
28
+ trace
29
+ trace_header(o.path, COLOR, BG_COLOR)
30
+
31
+ print_file_info(o)
32
+ print_code_info(o)
33
+ print_doc_info(o)
34
+ print_namespace_info(o)
35
+ print_roles_info(o)
36
+
37
+ echo "Score (min: #{o.evaluation.min_score}, max: #{o.evaluation.max_score})".ljust(40) + "#{o.score.to_i}".rjust(5) + "#{o.priority.to_i}".rjust(4)
38
+ echo
39
+ end
40
+
41
+ def print_file_info(o)
42
+ o.files.each do |f|
43
+ echo "-> #{f[0]}:#{f[1]}".color(COLOR)
44
+ end
45
+ echo separator
46
+ end
47
+
48
+ def print_code_info(o)
49
+ if o.method?
50
+ o.comment_and_abbrev_source.lines.each do |line|
51
+ echo line.gsub(/\n$/m, '').dark
52
+ end
53
+ echo separator
54
+ end
55
+ end
56
+
57
+ def print_roles_info(o)
58
+ if o.roles.empty?
59
+ echo "No roles assigned.".dark
60
+ else
61
+ o.roles.each do |role|
62
+ name = role.class.to_s.split('::Role::').last
63
+ if role.potential_score
64
+ score = "(#{role.potential_score.to_i})".rjust(5).yellow.dark
65
+ else
66
+ value = role.score.to_i
67
+ score = value.abs.to_s.rjust(4)
68
+ if value < 0
69
+ score = ("-" + score).red
70
+ elsif value > 0
71
+ score = ("+" + score).green
72
+ else
73
+ score = " " + score
74
+ end
75
+ end
76
+ priority = role.priority.to_s.rjust(4)
77
+ if role.priority == 0
78
+ priority = priority.dark
79
+ end
80
+ echo name.ljust(40) + score + priority
81
+ if role.max_score
82
+ echo " (set max score to #{role.max_score})"
83
+ end
84
+ if role.min_score
85
+ echo " (set min score to #{role.min_score})"
86
+ end
87
+ end
88
+ end
89
+ echo separator
90
+ end
91
+
92
+ def print_doc_info(o)
93
+ if o.nodoc?
94
+ echo "The object was tagged not to documented.".yellow
95
+ else
96
+ echo "Docstring".ljust(LJUST) + "#{o.has_doc? ? 'Yes' : 'No text'}"
97
+ if o.method?
98
+ echo "Parameters:".ljust(LJUST) + "#{o.has_parameters? ? '' : 'No parameters'}"
99
+ o.parameters.each do |p|
100
+ echo " " + p.name.ljust(LJUST-2) + "#{p.mentioned? ? 'Mentioned' : 'No text'} / #{p.typed? ? 'Typed' : 'Not typed'} / #{p.described? ? 'Described' : 'Not described'}"
101
+ end
102
+ echo "Return type:".ljust(LJUST) + "#{o.return_mentioned? ? 'Defined' : 'Not defined'}"
103
+ end
104
+ end
105
+ echo separator
106
+ end
107
+
108
+ def print_namespace_info(o)
109
+ if o.namespace?
110
+ echo "Children (height: #{o.height}):"
111
+ o.children.each do |child|
112
+ echo "+ " + child.path.color(COLOR)
113
+ end
114
+ echo separator
115
+ end
116
+ end
117
+
118
+ def echo(msg = "")
119
+ trace edged(COLOR, msg)
120
+ end
121
+
122
+ def separator
123
+ "-".color(COLOR) * (CLI::COLUMNS - 2)
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end