inch 0.1.3 → 0.1.4

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -6
  3. data/TODOS.md +7 -0
  4. data/lib/inch/cli/arguments.rb +36 -2
  5. data/lib/inch/cli/command/base.rb +56 -8
  6. data/lib/inch/cli/command/base_list.rb +17 -3
  7. data/lib/inch/cli/command/base_object.rb +17 -4
  8. data/lib/inch/cli/command/options/base.rb +55 -10
  9. data/lib/inch/cli/command/options/base_list.rb +25 -5
  10. data/lib/inch/cli/command/options/base_object.rb +0 -2
  11. data/lib/inch/cli/command/options/list.rb +2 -2
  12. data/lib/inch/cli/command/options/show.rb +2 -2
  13. data/lib/inch/cli/command/options/suggest.rb +2 -2
  14. data/lib/inch/cli/command/output/base.rb +9 -0
  15. data/lib/inch/cli/command/output/console.rb +4 -0
  16. data/lib/inch/cli/command/output/inspect.rb +2 -2
  17. data/lib/inch/cli/command/output/list.rb +1 -1
  18. data/lib/inch/cli/command_parser.rb +30 -9
  19. data/lib/inch/code_object/nodoc_helper.rb +23 -2
  20. data/lib/inch/code_object/proxy.rb +16 -2
  21. data/lib/inch/code_object/proxy/base.rb +2 -23
  22. data/lib/inch/code_object/proxy/method_object.rb +1 -0
  23. data/lib/inch/code_object/proxy/method_parameter_object.rb +4 -1
  24. data/lib/inch/evaluation.rb +0 -2
  25. data/lib/inch/evaluation/base.rb +1 -0
  26. data/lib/inch/evaluation/constant_object.rb +0 -3
  27. data/lib/inch/evaluation/file.rb +0 -4
  28. data/lib/inch/evaluation/namespace_object.rb +1 -7
  29. data/lib/inch/evaluation/role/base.rb +29 -5
  30. data/lib/inch/evaluation/role/constant.rb +0 -5
  31. data/lib/inch/evaluation/role/object.rb +1 -5
  32. data/lib/inch/evaluation/score_range.rb +12 -0
  33. data/lib/inch/rake/suggest.rb +3 -0
  34. data/lib/inch/source_parser.rb +27 -1
  35. data/lib/inch/version.rb +1 -1
  36. data/test/fixtures/simple/lib/foo.rb +6 -0
  37. data/test/fixtures/simple/lib/role_namespaces.rb +15 -3
  38. data/test/inch/cli/command/base_test.rb +15 -0
  39. data/test/inch/cli/command/inspect_test.rb +9 -0
  40. data/test/inch/cli/command/list_test.rb +3 -0
  41. data/test/inch/cli/command/options/base_list_test.rb +50 -0
  42. data/test/inch/cli/command/options/base_object_test.rb +14 -0
  43. data/test/inch/cli/command/options/base_test.rb +8 -0
  44. data/test/inch/cli/command/suggest_test.rb +11 -0
  45. data/test/inch/cli/trace_helper_test.rb +47 -0
  46. data/test/inch/code_object/proxy_test.rb +10 -0
  47. data/test/integration/visibility_options_test.rb +24 -17
  48. data/test/test_helper.rb +80 -0
  49. metadata +13 -3
@@ -2,13 +2,18 @@ module Inch
2
2
  module CLI
3
3
  module Command
4
4
  module Options
5
+ # Abstract base class for CLI options concerning lists of objects
6
+ #
7
+ # @abstract Subclass and override #set_options
5
8
  class BaseList < Base
6
- attribute :full, false
9
+ attribute :show_all, false
7
10
  attribute :visibility, [:public, :protected]
8
11
  attribute :namespaces
9
12
  attribute :undocumented
10
13
  attribute :depth
11
14
 
15
+ alias :show_all? :show_all
16
+
12
17
  def parse(args)
13
18
  opts = OptionParser.new
14
19
  opts.banner = usage
@@ -33,12 +38,17 @@ module Inch
33
38
 
34
39
  protected
35
40
 
41
+
42
+ # Sets all list related options for the current Options object
43
+ #
44
+ # @param opts [OptionParser]
45
+ # @return [void]
36
46
  def list_options(opts)
37
47
  opts.separator ""
38
48
  opts.separator "List options:"
39
49
 
40
50
  opts.on("--all", "Show all objects in the output") do
41
- @full = true
51
+ @show_all = true
42
52
  end
43
53
 
44
54
  opts.on("--only-namespaces", "Only show namespaces (classes, modules)") do
@@ -70,11 +80,21 @@ module Inch
70
80
  end
71
81
  end
72
82
 
73
- def set_visibility(_visibility, true_or_false)
83
+ # Sets the visibility of a given +kind+ of objects
84
+ #
85
+ # @example
86
+ # set_visibility :private, false
87
+ # set_visibility :protected, true
88
+ #
89
+ # @param kind [Symbol] +:public+, +:protected:, or +:private+
90
+ # @param true_or_false [Boolean]
91
+ # @return [void]
92
+ def set_visibility(kind, true_or_false)
93
+ @visibility ||= visibility.dup # initialize with attribute default
74
94
  if true_or_false
75
- visibility.push(_visibility)
95
+ @visibility.push(kind)
76
96
  else
77
- visibility.delete(_visibility)
97
+ @visibility.delete(kind)
78
98
  end
79
99
  end
80
100
  end
@@ -29,8 +29,6 @@ module Inch
29
29
 
30
30
  private
31
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
32
  def parse_object_names(args)
35
33
  arguments = Arguments.new(args)
36
34
  object_names = arguments.object_names
@@ -12,8 +12,8 @@ module Inch
12
12
  "",
13
13
  "Example: " + "$ inch list lib/**/*.rb --all".cyan,
14
14
  "",
15
- description_grades,
16
- description_arrows
15
+ description_hint_grades,
16
+ description_hint_arrows
17
17
  ]
18
18
  end
19
19
 
@@ -10,8 +10,8 @@ module Inch
10
10
  "Example: " + "$ inch show lib/**/*.rb Foo::Bar#initialize".cyan,
11
11
  "",
12
12
  "Shows one or more objects in detail.",
13
- description_grades,
14
- description_arrows
13
+ description_hint_grades,
14
+ description_hint_arrows
15
15
  ]
16
16
  end
17
17
 
@@ -28,8 +28,8 @@ module Inch
28
28
  "",
29
29
  "Example: " + "$ inch suggest lib/**/*.rb --pedantic".cyan,
30
30
  "",
31
- description_grades,
32
- description_arrows
31
+ description_hint_grades,
32
+ description_hint_arrows
33
33
  ]
34
34
  end
35
35
 
@@ -3,9 +3,18 @@ require 'optparse'
3
3
  module Inch
4
4
  module CLI
5
5
  module Command
6
+ # The classes in the Command::Output namespace act as presenter
7
+ # objects to the classes in the Command namespace.
8
+ #
9
+ # They are given all the objects and data they are supposed
10
+ # to display to the user. They do not filter the received data.
11
+ #
12
+ # @see Inch::CLI::Command::Suggest
13
+ # @see Inch::CLI::Command::Output::Suggest
6
14
  module Output
7
15
  # Abstract base class for CLI output
8
16
  #
17
+ # @abstract
9
18
  class Base
10
19
  include TraceHelper
11
20
 
@@ -16,6 +16,10 @@ module Inch
16
16
  COLOR = :color198 # magenta-ish
17
17
  BG_COLOR = :color207 # magenta-ish
18
18
 
19
+ # @param options [Options::Console]
20
+ # @param object [CodeObject::Proxy::Base]
21
+ # @param objects [Array<CodeObject::Proxy::Base>]
22
+ # @param source_parser [SourceParser]
19
23
  def initialize(options, object, objects, source_parser)
20
24
  @options = options
21
25
  @object = object
@@ -91,7 +91,7 @@ module Inch
91
91
 
92
92
  def print_doc_info(o)
93
93
  if o.nodoc?
94
- echo "The object was tagged not to documented.".yellow
94
+ echo "The object was tagged not to be documented.".yellow
95
95
  else
96
96
  echo "Docstring".ljust(LJUST) + "#{o.has_doc? ? 'Yes' : 'No text'}"
97
97
  if o.method?
@@ -107,7 +107,7 @@ module Inch
107
107
 
108
108
  def print_namespace_info(o)
109
109
  if o.namespace?
110
- echo "Children (height: #{o.height}):"
110
+ echo "Children:"
111
111
  o.children.each do |child|
112
112
  echo "+ " + child.path.color(COLOR)
113
113
  end
@@ -37,7 +37,7 @@ module Inch
37
37
  end
38
38
 
39
39
  def display_range(range)
40
- display_count = @options.full ? range.objects.size : PER_RANGE
40
+ display_count = @options.show_all? ? range.objects.size : PER_RANGE
41
41
  list = range.objects[0...display_count]
42
42
  list.each do |o|
43
43
  echo range.color, result(o, range.color)
@@ -1,12 +1,34 @@
1
- # This was adapted from https://github.com/lsegal/yard/blob/master/lib/yard/cli/command_parser.rb
2
1
  module Inch
3
2
  module CLI
4
- # This class parses a command name out of the +inch+ CLI command and calls
5
- # that command in the form:
3
+ # CommandParser parses a command-line arguments to decide which Command to run.
4
+ #
5
+ # The basic form translates this shell command
6
6
  #
7
7
  # $ inch command_name [options]
8
8
  #
9
- # If no command_name is specified, the {default_command} will be used.
9
+ # into a method call on the corresponding Command class.
10
+ #
11
+ # Some examples:
12
+ #
13
+ # $ inch
14
+ # # >>> Command::Suggest.new.run()
15
+ #
16
+ # $ inch --pedantic
17
+ # # >>> Command::Suggest.new.run("--pedantic")
18
+ #
19
+ # As you can see, if no command_name is given, the {default_command}
20
+ # will be used.
21
+ #
22
+ # $ inch list --all
23
+ # # >>> Command::List.new.run("--all")
24
+ #
25
+ # If a command_name is found to match a Command, that Command will be
26
+ # used.
27
+ #
28
+ # $ inch --help
29
+ # # >>> CommandParser#list_commands
30
+ #
31
+ # The +--help+ switch is an exception and lists all available commands.
10
32
  #
11
33
  class CommandParser
12
34
  include TraceHelper
@@ -38,13 +60,9 @@ module Inch
38
60
  new.run(*args)
39
61
  end
40
62
 
41
- def initialize
42
- #log.show_backtraces = false
43
- end
44
-
45
63
  # Runs the {Command} object matching the command name of the first
46
64
  # argument.
47
- # @return [void]
65
+ # @return [Command::Base]
48
66
  def run(*args)
49
67
  if ['--help', '-h'].include?(args.join)
50
68
  list_commands
@@ -69,6 +87,9 @@ module Inch
69
87
  end
70
88
  end
71
89
 
90
+ # Runs the {Command} object matching the command name of the first
91
+ # argument.
92
+ # @return [Command::Base]
72
93
  def run_command(*args)
73
94
  if args.empty?
74
95
  command_name = self.class.default_command
@@ -60,21 +60,42 @@ module Inch
60
60
  end
61
61
  end
62
62
 
63
+ # Returns all lines in all files declaring the object
64
+ #
65
+ # @example
66
+ # declarations # => ["class Base # :nodoc:", "class Foo < Base"]
67
+ #
68
+ # @return [Array<String>]
63
69
  def declarations
64
70
  @declarations ||= files.map do |(filename, line_no)|
65
71
  get_line_no(filename, line_no)
66
72
  end
67
73
  end
68
74
 
75
+ # Returns all files declaring the object in the form of an Array of
76
+ # Arrays containing the filename and the line number of their
77
+ # declaration.
78
+ #
79
+ # @example
80
+ # files # => [["lib/inch.rb", 3],
81
+ # ["lib/inch/cli.rb", 1],
82
+ # ["lib/inch/version.rb", 1],
83
+ #
84
+ # @return [Array<Array(String, Fixnum)>]
69
85
  def files
70
86
  object.files
71
87
  rescue YARD::CodeObjects::ProxyMethodError
72
88
  []
73
89
  end
74
90
 
75
- def get_line_no(filename, n)
91
+ # Returns a +line_number+ from a file
92
+ #
93
+ # @param filename [String]
94
+ # @param line_number [Fixnum]
95
+ # @return [String]
96
+ def get_line_no(filename, line_number)
76
97
  f = File.open(filename)
77
- n.times{f.gets}
98
+ line_number.times{f.gets}
78
99
  result = $_
79
100
  f.close
80
101
  result
@@ -1,7 +1,14 @@
1
1
  module Inch
2
2
  module CodeObject
3
+ # CodeObject::Proxy object represent code objects in the analaysed
4
+ # codebase.
5
+ #
3
6
  module Proxy
4
7
  class << self
8
+ # Returns a Proxy object for the given +code_object+
9
+ #
10
+ # @param code_object [YARD::CodeObject]
11
+ # @return [CodeObject::Proxy::Base]
5
12
  def for(code_object)
6
13
  @cache ||= {}
7
14
  if proxy_object = @cache[cache_key(code_object)]
@@ -13,6 +20,10 @@ module Inch
13
20
 
14
21
  private
15
22
 
23
+ # Returns a Proxy class for the given +code_object+
24
+ #
25
+ # @param code_object [YARD::CodeObject]
26
+ # @return [Class]
16
27
  def class_for(code_object)
17
28
  class_name = code_object.class.to_s.split('::').last
18
29
  eval("::Inch::CodeObject::Proxy::#{class_name}")
@@ -20,8 +31,11 @@ module Inch
20
31
  Base
21
32
  end
22
33
 
23
- def cache_key(o)
24
- o.path
34
+ # Returns a cache key for the given +code_object+
35
+ #
36
+ # @return [String]
37
+ def cache_key(code_object)
38
+ code_object.path
25
39
  end
26
40
  end
27
41
  end
@@ -3,6 +3,7 @@ require 'forwardable'
3
3
  module Inch
4
4
  module CodeObject
5
5
  module Proxy
6
+ # @abstract
6
7
  class Base
7
8
  extend Forwardable
8
9
  include NodocHelper
@@ -113,28 +114,6 @@ module Inch
113
114
  end
114
115
  end
115
116
 
116
- # In the following example, the height of +Foo+ is 3
117
- # (the height of the top-level is 4):
118
- #
119
- # Foo::Bar::Baz#initialize
120
- # ^ ^ ^ ^
121
- # 0 >> 1 >> 2 >> 3
122
- #
123
- # +height+ answers the question "how many layers of code objects are
124
- # underneath this one?"
125
- #
126
- # @param i [Fixnum] a counter for recursive method calls
127
- # @return [Fixnum] the height of the object in terms of namespace
128
- def height(i = 0)
129
- if children && !children.empty?
130
- children.map do |child|
131
- child.height(i+1)
132
- end.max
133
- else
134
- i
135
- end
136
- end
137
-
138
117
  # @return [Boolean] +true+ if the object represents a method
139
118
  def method?
140
119
  false
@@ -186,7 +165,7 @@ module Inch
186
165
  private
187
166
 
188
167
  def multi_code_examples?(text)
189
- text =~ /\b#{Regexp.escape(name)}[^_0-9\!\?]/
168
+ text.scan(/\b(#{Regexp.escape(name)})[^_0-9\!\?]/m).size > 1
190
169
  end
191
170
  end
192
171
  end
@@ -1,6 +1,7 @@
1
1
  module Inch
2
2
  module CodeObject
3
3
  module Proxy
4
+ # Proxy class for methods
4
5
  class MethodObject < Base
5
6
  def comment_and_abbrev_source
6
7
  comments.join('') + abbrev_source
@@ -1,8 +1,9 @@
1
1
  module Inch
2
2
  module CodeObject
3
3
  module Proxy
4
+ # Proxy class for method parameters
4
5
  class MethodParameterObject
5
- attr_reader :name
6
+ attr_reader :name # @return [String]
6
7
 
7
8
  # @param method [Inch::CodeObject::Proxy::MethodObject] the method the parameter belongs_to
8
9
  # @param name [String] the name of the parameter
@@ -17,6 +18,8 @@ module Inch
17
18
 
18
19
  BAD_NAME_EXCEPTIONS = %w(id)
19
20
  BAD_NAME_THRESHOLD = 3
21
+
22
+ # @return [Boolean] +true+ if the name of the parameter is uncommunicative
20
23
  def bad_name?
21
24
  return false if BAD_NAME_EXCEPTIONS.include?(name)
22
25
  name.size < BAD_NAME_THRESHOLD || name =~ /[0-9]$/
@@ -9,8 +9,6 @@ module Inch
9
9
  def self.class_for(code_object)
10
10
  class_name = code_object.class.to_s.split('::').last
11
11
  eval(class_name)
12
- rescue
13
- Base
14
12
  end
15
13
  end
16
14
  end
@@ -1,5 +1,6 @@
1
1
  module Inch
2
2
  module Evaluation
3
+ # @abstract
3
4
  class Base
4
5
  extend Forwardable
5
6
 
@@ -22,9 +22,6 @@ module Inch
22
22
  if object.public?
23
23
  add_role Role::Constant::Public.new(object)
24
24
  end
25
- if object.protected?
26
- add_role Role::Constant::Protected.new(object)
27
- end
28
25
  if object.private?
29
26
  add_role Role::Constant::Private.new(object)
30
27
  end
@@ -42,10 +42,6 @@ module Inch
42
42
  objects.map(&:priority)
43
43
  end
44
44
 
45
- def scores
46
- objects.map(&:score)
47
- end
48
-
49
45
  def median(sorted_list)
50
46
  index = (sorted_list.size / 2).round
51
47
  sorted_list[index]
@@ -28,15 +28,9 @@ module Inch
28
28
  if object.in_root?
29
29
  add_role Role::Object::InRoot.new(object)
30
30
  end
31
- if object.public?
31
+ if object.public? # this is always true for classes and modules
32
32
  add_role Role::Object::Public.new(object)
33
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
34
 
41
35
  eval_core
42
36
  end