inch 0.0.1 → 0.1.0

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