inch 0.2.3 → 0.3.0.rc1

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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +7 -0
  3. data/TODOS.md +0 -5
  4. data/config/defaults.rb +26 -1
  5. data/inch.gemspec +1 -0
  6. data/lib/inch.rb +2 -1
  7. data/lib/inch/api.rb +34 -0
  8. data/lib/inch/api/filter.rb +17 -0
  9. data/lib/inch/api/get.rb +30 -0
  10. data/lib/inch/api/list.rb +10 -0
  11. data/lib/inch/api/options/base.rb +45 -0
  12. data/lib/inch/api/options/filter.rb +25 -0
  13. data/lib/inch/api/options/suggest.rb +36 -0
  14. data/lib/inch/api/stats.rb +7 -0
  15. data/lib/inch/api/suggest.rb +110 -0
  16. data/lib/inch/cli.rb +4 -1
  17. data/lib/inch/cli/command/base.rb +1 -17
  18. data/lib/inch/cli/command/base_list.rb +3 -63
  19. data/lib/inch/cli/command/base_object.rb +6 -28
  20. data/lib/inch/cli/command/list.rb +3 -2
  21. data/lib/inch/cli/command/options/base.rb +1 -1
  22. data/lib/inch/cli/command/options/base_list.rb +4 -2
  23. data/lib/inch/cli/command/options/suggest.rb +9 -8
  24. data/lib/inch/cli/command/output/base.rb +9 -11
  25. data/lib/inch/cli/command/output/list.rb +2 -2
  26. data/lib/inch/cli/command/output/show.rb +2 -10
  27. data/lib/inch/cli/command/output/stats.rb +4 -3
  28. data/lib/inch/cli/command/output/suggest.rb +5 -5
  29. data/lib/inch/cli/command/stats.rb +4 -3
  30. data/lib/inch/cli/command/suggest.rb +4 -94
  31. data/lib/inch/code_object.rb +2 -2
  32. data/lib/inch/code_object/converter.rb +89 -0
  33. data/lib/inch/code_object/provider.rb +36 -0
  34. data/lib/inch/code_object/provider/yard.rb +19 -0
  35. data/lib/inch/code_object/provider/yard/docstring.rb +106 -0
  36. data/lib/inch/code_object/provider/yard/nodoc_helper.rb +93 -0
  37. data/lib/inch/code_object/provider/yard/object.rb +55 -0
  38. data/lib/inch/code_object/provider/yard/object/base.rb +262 -0
  39. data/lib/inch/code_object/provider/yard/object/class_object.rb +12 -0
  40. data/lib/inch/code_object/provider/yard/object/constant_object.rb +12 -0
  41. data/lib/inch/code_object/provider/yard/object/method_object.rb +126 -0
  42. data/lib/inch/code_object/provider/yard/object/method_parameter_object.rb +88 -0
  43. data/lib/inch/code_object/provider/yard/object/module_object.rb +12 -0
  44. data/lib/inch/code_object/provider/yard/object/namespace_object.rb +47 -0
  45. data/lib/inch/code_object/provider/yard/parser.rb +54 -0
  46. data/lib/inch/code_object/proxy.rb +5 -3
  47. data/lib/inch/code_object/proxy/base.rb +103 -110
  48. data/lib/inch/code_object/proxy/class_object.rb +0 -1
  49. data/lib/inch/code_object/proxy/method_object.rb +20 -99
  50. data/lib/inch/code_object/proxy/method_parameter_object.rb +15 -39
  51. data/lib/inch/code_object/proxy/namespace_object.rb +7 -18
  52. data/lib/inch/codebase.rb +19 -0
  53. data/lib/inch/codebase/objects.rb +73 -0
  54. data/lib/inch/codebase/objects_filter.rb +61 -0
  55. data/lib/inch/codebase/proxy.rb +22 -0
  56. data/lib/inch/config.rb +8 -1
  57. data/lib/inch/evaluation.rb +5 -7
  58. data/lib/inch/evaluation/file.rb +1 -1
  59. data/lib/inch/evaluation/grade.rb +1 -1
  60. data/lib/inch/evaluation/object_schema.rb +3 -1
  61. data/lib/inch/evaluation/priority_range.rb +44 -0
  62. data/lib/inch/evaluation/proxy.rb +25 -0
  63. data/lib/inch/evaluation/proxy/base.rb +146 -0
  64. data/lib/inch/evaluation/proxy/class_object.rb +8 -0
  65. data/lib/inch/evaluation/proxy/constant_object.rb +19 -0
  66. data/lib/inch/evaluation/proxy/method_object.rb +65 -0
  67. data/lib/inch/evaluation/proxy/module_object.rb +8 -0
  68. data/lib/inch/evaluation/proxy/namespace_object.rb +27 -0
  69. data/lib/inch/evaluation/role/base.rb +19 -0
  70. data/lib/inch/evaluation/role/constant.rb +16 -0
  71. data/lib/inch/evaluation/role/method.rb +22 -0
  72. data/lib/inch/evaluation/role/method_parameter.rb +31 -1
  73. data/lib/inch/evaluation/role/namespace.rb +15 -0
  74. data/lib/inch/evaluation/role/object.rb +24 -0
  75. data/lib/inch/rake/suggest.rb +1 -0
  76. data/lib/inch/utils/read_write_methods.rb +44 -0
  77. data/lib/inch/{cli → utils}/weighted_list.rb +1 -1
  78. data/lib/inch/version.rb +1 -1
  79. data/test/fixtures/simple/lib/broken.rb +8 -0
  80. data/test/inch/api/filter_test.rb +51 -0
  81. data/test/inch/api/get_test.rb +22 -0
  82. data/test/inch/api/list_test.rb +15 -0
  83. data/test/inch/api/options/base_test.rb +30 -0
  84. data/test/inch/api/stats_test.rb +15 -0
  85. data/test/inch/api/suggest_test.rb +26 -0
  86. data/test/inch/cli/command/list_test.rb +2 -1
  87. data/test/inch/code_object/converter_test.rb +29 -0
  88. data/test/inch/code_object/{docstring_test.rb → provider/yard/docstring_test.rb} +13 -13
  89. data/test/inch/code_object/{nodoc_helper_test.rb → provider/yard/nodoc_helper_test.rb} +6 -6
  90. data/test/inch/code_object/provider/yard_test.rb +11 -0
  91. data/test/inch/code_object/provider_test.rb +9 -0
  92. data/test/inch/code_object/proxy/method_object_test.rb +22 -22
  93. data/test/inch/code_object/proxy_test.rb +10 -10
  94. data/test/inch/codebase/objects_test.rb +28 -0
  95. data/test/inch/codebase/proxy_test.rb +17 -0
  96. data/test/inch/evaluation/role/base_test.rb +71 -0
  97. data/test/inch/{cli → utils}/weighted_list_test.rb +2 -2
  98. data/test/shared/base_list.rb +73 -0
  99. data/test/test_helper.rb +0 -95
  100. metadata +89 -24
  101. data/lib/inch/code_object/docstring.rb +0 -102
  102. data/lib/inch/code_object/nodoc_helper.rb +0 -107
  103. data/lib/inch/evaluation/base.rb +0 -157
  104. data/lib/inch/evaluation/class_object.rb +0 -6
  105. data/lib/inch/evaluation/constant_object.rb +0 -33
  106. data/lib/inch/evaluation/method_object.rb +0 -105
  107. data/lib/inch/evaluation/module_object.rb +0 -6
  108. data/lib/inch/evaluation/namespace_object.rb +0 -52
  109. data/lib/inch/evaluation/read_write_methods.rb +0 -21
  110. data/lib/inch/source_parser.rb +0 -62
  111. data/test/inch/source_parser_test.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 76a30cfdd0b22157bc5ef102e9f15cc96ec40147
4
- data.tar.gz: 21d1a3ecb2c12294579f4406059a322e25fb15ff
3
+ metadata.gz: fb172151aa6a4cebe01d50b2e38a5b43bc1d10ba
4
+ data.tar.gz: c19f22f6081241b240eeaee8bdbf2b2d910e7c68
5
5
  SHA512:
6
- metadata.gz: e60ae99656807e6731978c0b3bd29534ad313bcda1f8aabae5407dc062bb8aa3f1e589f3599b900f917973608047d1e6909bdfc52e872792d07e281b18cda16f
7
- data.tar.gz: 5bd8e9097b64d1cb9e454ef47e052e1d96ca1d2f562d2c12c9ae470b26de4db456e6c901563f5c9b9267eb013a6976ee25c2f31f768577806e826d6bf6be3b79
6
+ metadata.gz: c612a1a55be07cc3d6d120eb21a6e94670d16f3399b260b5837fc91f427cf89f4c54d2fa6bfd73aff747353543eb242032c7325fe871553fdff483f29bfb142e
7
+ data.tar.gz: ea91964f803278cea9ff25d202090ac67e709a08b96e046490198a48b42ec4e87c7f672c272f01e2ef63534053b80f16b6cc5cdca5f808132cf323a7b5e10ec9
@@ -0,0 +1,7 @@
1
+ SimpleCov.start do
2
+ add_filter '/test/'
3
+
4
+ add_group 'CLI', 'lib/inch/cli'
5
+ add_group 'Code Objects', 'lib/inch/code_object'
6
+ add_group 'Evaluation', 'lib/inch/evaluation'
7
+ end
data/TODOS.md CHANGED
@@ -3,10 +3,5 @@
3
3
  * Recognize all relevant options in .yardopts file
4
4
  * --plugin
5
5
  * --[no-]api API
6
- * Provide reusable context that filters code objects according to the
7
- visibility options
8
6
  * Add support for multiple signatures for methods
9
7
  (realized via the @overload tag in YARD)
10
-
11
- * Think about implicit cases in terms of evaluation:
12
- * attr_* methods are automatically assigned a docstring and @param tag
@@ -27,6 +27,31 @@ Inch::Config.run do
27
27
  bg_color :color105
28
28
  end
29
29
 
30
+ priority(:N) do
31
+ priorities 4..99
32
+ arrow "\u2191"
33
+ end
34
+
35
+ priority(:NE) do
36
+ priorities 2...4
37
+ arrow "\u2197"
38
+ end
39
+
40
+ priority(:E) do
41
+ priorities 0...2
42
+ arrow "\u2192"
43
+ end
44
+
45
+ priority(:SE) do
46
+ priorities -2...0
47
+ arrow "\u2198"
48
+ end
49
+
50
+ priority(:S) do
51
+ priorities -99...-2
52
+ arrow "\u2193"
53
+ end
54
+
30
55
  schema(:ConstantObject) do
31
56
  docstring 1.0
32
57
 
@@ -62,7 +87,7 @@ Inch::Config.run do
62
87
  parameters parameters + return_type
63
88
  return_type 0.0
64
89
  end
65
-
90
+
66
91
  if object.constructor?
67
92
  return_description 0.0
68
93
  end
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.add_development_dependency "bundler", "~> 1.5"
27
27
  spec.add_development_dependency "rake"
28
28
  spec.add_development_dependency "pry"
29
+ spec.add_development_dependency "minitest", "~> 5.2"
29
30
 
30
31
  spec.add_dependency 'sparkr', ">= 0.2.0"
31
32
  spec.add_dependency "term-ansicolor"
@@ -3,8 +3,9 @@ require "inch/version"
3
3
  module Inch
4
4
  end
5
5
 
6
+ require_relative 'inch/api'
6
7
  require_relative 'inch/core_ext'
7
- require_relative 'inch/source_parser'
8
+ require_relative 'inch/codebase'
8
9
  require_relative 'inch/code_object'
9
10
  require_relative 'inch/evaluation'
10
11
  require_relative 'inch/cli'
@@ -0,0 +1,34 @@
1
+ module Inch
2
+ # The API module is the entry point for Inch's APIs
3
+ #
4
+ # APIs are kind of "use cases" that are utilized by the CLI classes to
5
+ # actually "do things".
6
+ #
7
+ # Example:
8
+ #
9
+ # $ inch list lib/**/*.rb --private
10
+ #
11
+ # This basically calls something like this:
12
+ #
13
+ # codebase = Codebase::Proxy.new(Dir.pwd, ["lib/**/*.rb"], [])
14
+ # options = {:visibility => [:public, :protected, :private]}
15
+ # context = API::List.new(codebase, options)
16
+ # context.objects # => Array
17
+ #
18
+ # The List API takes a Codebase::Proxy object and an options
19
+ # hash or a class in API::Options and returns objects and grade_lists
20
+ # matching that options.
21
+ #
22
+ module API
23
+ end
24
+ end
25
+
26
+ require_relative 'api/options/base'
27
+ require_relative 'api/options/filter'
28
+ require_relative 'api/options/suggest'
29
+
30
+ require_relative 'api/filter'
31
+ require_relative 'api/get'
32
+ require_relative 'api/list'
33
+ require_relative 'api/suggest'
34
+ require_relative 'api/stats'
@@ -0,0 +1,17 @@
1
+ module Inch
2
+ module API
3
+ # Filters a codebase's objects based on given options
4
+ class Filter
5
+ attr_reader :codebase
6
+ attr_reader :objects
7
+ attr_reader :grade_lists
8
+
9
+ def initialize(codebase, options)
10
+ @codebase = codebase
11
+ codebase.objects.filter! Options::Filter(options)
12
+ @objects = codebase.objects.to_a
13
+ @grade_lists = @codebase.grade_lists
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ module Inch
2
+ module API
3
+ # Gets all objects matching the given +object_names+
4
+ class Get < Filter
5
+ attr_reader :object
6
+
7
+ def initialize(codebase, object_names)
8
+ super(codebase, {})
9
+ @objects = find_objects_with_names(object_names)
10
+ @object = objects.first
11
+ end
12
+
13
+ private
14
+
15
+ # Returns all objects matching the given +object_names+
16
+ #
17
+ # @param object_names [Array<String>]
18
+ # @return [Array<CodeObject::Proxy::Base>]
19
+ def find_objects_with_names(object_names)
20
+ object_names.map do |object_name|
21
+ if object = codebase.objects.find(object_name)
22
+ object
23
+ else
24
+ codebase.objects.starting_with(object_name)
25
+ end
26
+ end.flatten
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ module Inch
2
+ module API
3
+ class List < Filter
4
+ def initialize(codebase, options)
5
+ super
6
+ @options = options
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,45 @@
1
+ module Inch
2
+ module API
3
+ module Options
4
+ class Base
5
+ class << self
6
+ # Creates an attribute with an optional default value
7
+ #
8
+ # @param name [Symbol] the name of the attribute
9
+ # @param default [nil] the default value of the attribute
10
+ # @return [void]
11
+ def attribute(name, default = nil)
12
+ define_method(name) do
13
+ instance_variable_get("@#{name}") || default
14
+ end
15
+ @attributes ||= {}
16
+ @attributes[to_s] ||= []
17
+ @attributes[to_s] << name
18
+ end
19
+
20
+ def attribute_names
21
+ @attributes ||= {}
22
+ @attributes[to_s] ||= []
23
+ end
24
+ end
25
+
26
+ def initialize(options_or_hash)
27
+ self.class.attribute_names.each do |name|
28
+ read options_or_hash, name
29
+ end
30
+ end
31
+
32
+ protected
33
+
34
+ def read(options_or_hash, name)
35
+ value = if options_or_hash.is_a?(Hash)
36
+ options_or_hash[name]
37
+ else
38
+ options_or_hash.send(name)
39
+ end
40
+ instance_variable_set("@#{name}", value)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ module Inch
2
+ module API
3
+ module Options
4
+ class Filter < Base
5
+ # This module is included here and in Command::Options::BaseList
6
+ # to ensure the same default values for the command-line and library
7
+ # interface
8
+ module DefaultAttributeValues
9
+ DEFAULT_VISIBILITY = [:public, :protected]
10
+ end
11
+
12
+ include DefaultAttributeValues
13
+
14
+ attribute :visibility, DEFAULT_VISIBILITY
15
+ attribute :namespaces
16
+ attribute :undocumented
17
+ attribute :depth
18
+ end
19
+
20
+ def self.Filter(options_or_hash)
21
+ Filter.new(options_or_hash)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ require 'inch/evaluation/proxy/base'
2
+
3
+ module Inch
4
+ module API
5
+ module Options
6
+ class Suggest < Base
7
+ # This module is included here and in Command::Options::Suggest
8
+ # to ensure the same default values for the command-line and library
9
+ # interface
10
+ module DefaultAttributeValues
11
+ DEFAULT_OBJECT_COUNT = 20
12
+ DEFAULT_FILE_COUNT = 5
13
+ DEFAULT_PROPER_GRADES = [:A, :B]
14
+ DEFAULT_GRADES_TO_DISPLAY = [:B, :C, :U]
15
+ DEFAULT_GRADE_WEIGHTS = [0.2, 0.4, 0.4]
16
+ DEFAULT_OBJECT_MIN_PRIORITY = 0
17
+ DEFAULT_OBJECT_MAX_SCORE = ::Inch::Evaluation::Proxy::Base::MAX_SCORE
18
+ end
19
+
20
+ include DefaultAttributeValues
21
+
22
+ attribute :object_count, DEFAULT_OBJECT_COUNT
23
+ attribute :file_count, DEFAULT_FILE_COUNT
24
+ attribute :proper_grades, DEFAULT_PROPER_GRADES
25
+ attribute :grades_to_display, DEFAULT_GRADES_TO_DISPLAY
26
+ attribute :grade_weights, DEFAULT_GRADE_WEIGHTS
27
+ attribute :object_min_priority, DEFAULT_OBJECT_MIN_PRIORITY
28
+ attribute :object_max_score, DEFAULT_OBJECT_MAX_SCORE
29
+ end
30
+
31
+ def self.Suggest(options_or_hash)
32
+ Suggest.new(options_or_hash)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ module Inch
2
+ module API
3
+ class Stats < Filter
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,110 @@
1
+ require 'inch/utils/weighted_list'
2
+
3
+ module Inch
4
+ module API
5
+ class Suggest < Filter
6
+ def initialize(codebase, options)
7
+ super
8
+ @options = Options::Suggest(options)
9
+ end
10
+
11
+ def files
12
+ list = files_sorted_by_importance
13
+ how_many = @options.file_count || list.size
14
+ list[0...how_many]
15
+ end
16
+
17
+ # @return [Array] the +@options.object_count+ objects the API suggests
18
+ def objects
19
+ filter_objects_to_display
20
+ end
21
+
22
+
23
+ # @return [Array] all the objects that match +@options+
24
+ def all_objects
25
+ relevant_objects
26
+ end
27
+
28
+ private
29
+
30
+ # @return [Fixnum] how many objects should be displayed in the output
31
+ def object_count
32
+ @options.object_count
33
+ end
34
+
35
+ # @return [Array<Fixnum>]
36
+ # how many objects of each grade should be displayed in the output
37
+ def object_list_counts
38
+ @options.grade_weights.map { |w| w * object_count }
39
+ end
40
+
41
+ # @return [Array] the objects that should be displayed in the output
42
+ def filter_objects_to_display
43
+ graded_list = []
44
+ @options.grades_to_display.map do |grade|
45
+ r = grade_list(grade)
46
+ arr = select_by_priority(r.objects, @options.object_min_priority)
47
+ arr = arr.select { |o| o.score <= @options.object_max_score }
48
+ graded_list << arr
49
+ end
50
+
51
+ weighted_list = Utils::WeightedList.new(graded_list, object_list_counts)
52
+
53
+ list = Codebase::Objects.sort_by_priority(weighted_list.to_a.flatten)
54
+
55
+ if list.size > object_count
56
+ list = list[0...object_count]
57
+ end
58
+ list
59
+ end
60
+
61
+ def files_sorted_by_importance
62
+ list = all_filenames(relevant_objects).uniq.map do |filename|
63
+ f = Evaluation::File.for(filename, relevant_objects)
64
+ end
65
+
66
+ priority_list = list.select do |f|
67
+ relevant_grades.include?(f.grade) &&
68
+ relevant_priorities.include?(f.priority)
69
+ end
70
+
71
+ Codebase::Objects.sort_by_priority(priority_list.empty? ? list : priority_list)
72
+ end
73
+
74
+ def all_filenames(objects)
75
+ codebase.objects.map do |o|
76
+ o.files.map(&:first)
77
+ end.flatten
78
+ end
79
+
80
+ # Returns the unique grades assigned to objects
81
+ #
82
+ # grades # => [:A, :B, :C, :U]
83
+ #
84
+ # @return [Array<Symbol>]
85
+ def grades
86
+ codebase.objects.map(&:grade).uniq
87
+ end
88
+
89
+ def grade_list(grade_symbol)
90
+ grade_lists.detect { |r| r.grade.to_sym == grade_symbol }
91
+ end
92
+
93
+ def select_by_priority(list, min_priority)
94
+ list.select { |o| o.priority >= min_priority }
95
+ end
96
+
97
+ def relevant_grades
98
+ grades.size >= 2 ? grades[-2..-1] : [grades.last].compact
99
+ end
100
+
101
+ def relevant_objects
102
+ select_by_priority(codebase.objects, @options.object_min_priority)
103
+ end
104
+
105
+ def relevant_priorities
106
+ (@options.object_min_priority..99)
107
+ end
108
+ end
109
+ end
110
+ end
@@ -1,4 +1,8 @@
1
1
  module Inch
2
+ # The CLI module is tasked with the deconstruction of CLI calls
3
+ # into API calls.
4
+ #
5
+ # @see Inch::API
2
6
  module CLI
3
7
  class << self
4
8
  # Returns the columns of the terminal window
@@ -17,7 +21,6 @@ module Inch
17
21
  end
18
22
 
19
23
  require_relative 'cli/arguments'
20
- require_relative 'cli/weighted_list'
21
24
  require_relative 'cli/sparkline_helper'
22
25
  require_relative 'cli/trace_helper'
23
26
  require_relative 'cli/yardopts_helper'
@@ -38,7 +38,7 @@ module Inch
38
38
  class Base
39
39
  include TraceHelper
40
40
 
41
- attr_reader :source_parser # @return [SourceParser]
41
+ attr_reader :codebase # @return [Codebase::Proxy]
42
42
 
43
43
  # Helper method to run an instance with the given +args+
44
44
  #
@@ -97,22 +97,6 @@ module Inch
97
97
  def usage
98
98
  "Usage: inch #{name} [options]"
99
99
  end
100
-
101
- private
102
-
103
- # Returns the source parser against the given +paths+, while
104
- # excluding all paths given in +excluded+
105
- #
106
- # @param paths [Array<String>]
107
- # @param excluded [Array<String>]
108
- # @return [void]
109
- def run_source_parser(paths, excluded)
110
- debug "Parsing:\n" \
111
- " files: #{paths.inspect}\n" \
112
- " excluded: #{excluded.inspect}"
113
-
114
- @source_parser = SourceParser.run(paths, excluded)
115
- end
116
100
  end
117
101
  end
118
102
  end