inch 0.1.3 → 0.1.4

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