inch 0.2.2 → 0.2.3

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +170 -56
  3. data/TODOS.md +0 -6
  4. data/config/defaults.rb +82 -0
  5. data/lib/inch/cli/command/base.rb +9 -0
  6. data/lib/inch/cli/command/base_list.rb +8 -8
  7. data/lib/inch/cli/command/base_object.rb +1 -1
  8. data/lib/inch/cli/command/list.rb +6 -1
  9. data/lib/inch/cli/command/options/base.rb +1 -1
  10. data/lib/inch/cli/command/options/suggest.rb +3 -1
  11. data/lib/inch/cli/command/output/list.rb +6 -6
  12. data/lib/inch/cli/command/output/show.rb +3 -3
  13. data/lib/inch/cli/command/output/stats.rb +52 -33
  14. data/lib/inch/cli/command/output/suggest.rb +7 -7
  15. data/lib/inch/cli/command/show.rb +5 -0
  16. data/lib/inch/cli/command/stats.rb +6 -1
  17. data/lib/inch/cli/command/suggest.rb +31 -12
  18. data/lib/inch/cli/command.rb +7 -14
  19. data/lib/inch/cli/command_parser.rb +2 -9
  20. data/lib/inch/cli/sparkline_helper.rb +13 -13
  21. data/lib/inch/cli/weighted_list.rb +85 -0
  22. data/lib/inch/cli.rb +2 -1
  23. data/lib/inch/code_object/nodoc_helper.rb +2 -0
  24. data/lib/inch/code_object/proxy/base.rb +36 -13
  25. data/lib/inch/code_object/proxy/method_object.rb +29 -0
  26. data/lib/inch/code_object/proxy/namespace_object.rb +6 -0
  27. data/lib/inch/config.rb +30 -37
  28. data/lib/inch/evaluation/base.rb +53 -1
  29. data/lib/inch/evaluation/constant_object.rb +8 -11
  30. data/lib/inch/evaluation/file.rb +1 -1
  31. data/lib/inch/evaluation/grade.rb +41 -0
  32. data/lib/inch/evaluation/grade_list.rb +32 -0
  33. data/lib/inch/evaluation/method_object.rb +10 -51
  34. data/lib/inch/evaluation/namespace_object.rb +8 -49
  35. data/lib/inch/evaluation/{criteria.rb → object_schema.rb} +12 -22
  36. data/lib/inch/evaluation/read_write_methods.rb +21 -0
  37. data/lib/inch/evaluation/role/method.rb +8 -0
  38. data/lib/inch/evaluation.rb +5 -2
  39. data/lib/inch/version.rb +1 -1
  40. data/lib/inch.rb +3 -1
  41. data/test/fixtures/simple/lib/broken.rb +15 -0
  42. data/test/fixtures/simple/lib/role_methods.rb +15 -0
  43. data/test/inch/cli/weighted_list_test.rb +55 -0
  44. data/test/inch/code_object/proxy/method_object_test.rb +42 -0
  45. data/test/integration/stats_options_test.rb +1 -1
  46. metadata +11 -5
  47. data/lib/inch/evaluation/score_range.rb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a3d046495aa235b1de7a7b672064aa637bd234a9
4
- data.tar.gz: 8c1f011bbae79bebace8b24652bc8d4a91e03423
3
+ metadata.gz: 76a30cfdd0b22157bc5ef102e9f15cc96ec40147
4
+ data.tar.gz: 21d1a3ecb2c12294579f4406059a322e25fb15ff
5
5
  SHA512:
6
- metadata.gz: da0b420bda2854141896e838ab0cb399110415370ceffdc026e686017a796389bd29f66fb4e085d617e42fc30c5e234e436f49b234270b7690fe67000121a549
7
- data.tar.gz: a56f9672e84f23952719ea7c2087aa08ae736ed5b7e20c24f612066abc5fed6dc145e252c11cceae797c4fcb7a138a37a3a04373534ad5b9f1147d47a81580de
6
+ metadata.gz: e60ae99656807e6731978c0b3bd29534ad313bcda1f8aabae5407dc062bb8aa3f1e589f3599b900f917973608047d1e6909bdfc52e872792d07e281b18cda16f
7
+ data.tar.gz: 5bd8e9097b64d1cb9e454ef47e052e1d96ca1d2f562d2c12c9ae470b26de4db456e6c901563f5c9b9267eb013a6976ee25c2f31f768577806e826d6bf6be3b79
data/README.md CHANGED
@@ -1,9 +1,16 @@
1
1
  # Inch [![Build Status](https://travis-ci.org/rrrene/inch.png)](https://travis-ci.org/rrrene/inch)
2
2
 
3
- Take a look at the project page for an [introduction with screenshots (live and in full color)](http://rrrene.github.io/inch/).
3
+ `inch` gives you hints where to improve your docs. One Inch at a time.
4
4
 
5
- Inch is a documentation measurement tool for the Ruby programming language
6
- that gives you hints where to improve your docs. One Inch at a time.
5
+ Take a look at the [project page with screenshots (live and in full color)](http://rrrene.github.io/inch/).
6
+
7
+ ## What can it do?
8
+
9
+ `inch` is a little bit like Code Climate, but for your inline code documentation (and not a webservice).
10
+
11
+ It is a command-line utility that suggests places in your codebase where documentation can be improved.
12
+
13
+ If there are no inline-docs yet, `inch` can tell you where to start.
7
14
 
8
15
 
9
16
 
@@ -31,93 +38,126 @@ To run Inch, simply type
31
38
 
32
39
  Given a `lib` directory with the following code inside:
33
40
 
34
- class Foo
35
- # A complicated method
36
- def complicated(o, i, *args, &block)
37
- # ... snip ...
38
- end
39
-
40
- # An example of a method that takes a parameter (+param1+)
41
- # and does nothing.
42
- #
43
- # Returns nil
44
- def nothing(param1)
45
- end
46
-
47
- def filename
48
- "#{self.class}_#{id}.foo"
49
- end
50
- end
41
+ ```ruby
42
+ class Foo
43
+ # A complicated method
44
+ def complicated(o, i, *args, &block)
45
+ # ... snip ...
46
+ end
47
+
48
+ # An example of a method that takes a parameter (+param1+)
49
+ # and does nothing.
50
+ #
51
+ # Returns nil
52
+ def nothing(param1)
53
+ end
54
+
55
+ def filename
56
+ "#{self.class}_#{id}.foo"
57
+ end
58
+ end
59
+ ```
51
60
 
52
61
  Inch will suggest that the docs could be improved:
53
62
 
54
63
  # Properly documented, could be improved:
55
-
64
+
56
65
  ┃ B ↑ Foo#complicated
57
-
66
+
58
67
  # Undocumented:
59
-
68
+
60
69
  ┃ U ↑ Foo
61
70
  ┃ U ↗ Foo#filename
62
-
71
+
63
72
  You might want to look at these files:
64
-
73
+
65
74
  ┃ lib/foo.rb
66
-
75
+
67
76
  Grade distribution (undocumented, C, B, A): █ ▁ ▄ ▄
68
-
77
+
69
78
  Only considering priority objects: ↑ ↗ → (use `--help` for options).
70
79
 
71
- Inch does not report coverage scores for code objects. It assigns grades and shows you the grade distribution rather then an overall grade.
72
80
 
73
- The grades (A, B, C) show how good the present documentation seems. The grade `U` is assigned to all undocumented objects. The arrows (↑ ↗ → ↘ ↓) hint at the importance of the object being documented.
81
+ ## Philosophy
82
+
83
+ Inch was created to help people document their code, therefore it may be more important to look at **what it does not** do than at what it does.
84
+
85
+ * It does not aim for "fully documented" or "100% documentation coverage".
86
+ * It does not tell you to document all your code (neither does it tell you not to).
87
+ * It does not impose rules on how your documentation should look like.
88
+ * It does not require that, e.g."every method's documentation should be a single line under 80 characters not ending in a period" or that "every class and module should provide a code example of their usage".
89
+
90
+ Inch takes a more relaxed approach towards documentation measurement and tries to show you places where your codebase *could* use more documentation.
91
+
92
+
93
+
94
+ ### The Grade System
95
+
96
+ Inch assigns grades to each class, module, constant or method in a codebase, based on how complete the docs are.
97
+
98
+ The grades are:
99
+
100
+ * `A` - Seems really good
101
+ * `B` - Properly documented, but could be improved
102
+ * `C` - Needs work
103
+ * `U` - Undocumented
104
+
105
+ Using this system has some advantages compared to plain coverage scores:
106
+
107
+ * You can get an `A` even if you "only" get 90 out of 100 possible points.
108
+ * Getting a `B` is basically good enough.
109
+ * Undocumented objects are assigned a special grade, instead of scoring 0%.
110
+
111
+ The last point might be the most important one: If objects are undocumented, there is nothing to evaluate. Therefore you can not simply give them a bad rating, because they might be left undocumented intentionally.
112
+
113
+
114
+
115
+ ### Priorities ↑ ↓
116
+
117
+ Every class, module, constant and method in a codebase is assigned a priority which reflects how important Inch thinks it is to be documented.
74
118
 
119
+ This process follows some reasonable rules, like
75
120
 
76
- ### Inch does not judge
121
+ * it is more important to document public methods than private ones
122
+ * it is more important to document methods with many parameters than methods without parameters
123
+ * it is not important to document objects marked as `:nodoc:`
77
124
 
78
- Inch uses grades instead of scores to take a more relaxed approach. You can
79
- get an `A` without employing every trick from a predetermined list of checks.
125
+ Priorities are displayed as arrows. Arrows pointing north mark high priority objects, arrows pointing south mark low priority objects.
80
126
 
81
- The reason for using the grade distribution instead of an overall score is
82
- that the distribution says more about your codebase than a coverage percentage
83
- ever could:
127
+
128
+
129
+ ### No overall scores or grades
130
+
131
+ Inch does not give you a grade for your whole codebase.
132
+
133
+ "Why?" you might ask. Look at the example below:
84
134
 
85
135
  Grade distribution (undocumented, C, B, A): ▄ ▁ ▄ █
86
136
 
87
- In this example we have a good chunk of code that is still undocumented, but
88
- the vast majority of code is rated A or B. This tells you three things:
137
+ In this example there is a part of code that is still undocumented, but
138
+ the vast majority of code is rated A or B.
139
+
140
+ This tells you three things:
89
141
 
90
142
  * There is a significant amount of documentation present.
91
143
  * The present documentation seems good.
92
144
  * There are still undocumented methods.
93
145
 
94
146
  Inch does not really tell you what to do from here. It suggests objects and
95
- files that could be improved to get a better rating, but that is all.
147
+ files that could be improved to get a better rating, but that is all. This
148
+ way, it is perfectly reasonable to leave parts of your codebase
149
+ undocumented.
96
150
 
97
- This way, it is perfectly reasonable to leave parts of your codebase
98
- undocumented. Instead of reporting
151
+ Instead of reporting
99
152
 
100
153
  coverage: 67.1% 46 ouf of 140 checks failed
101
154
 
102
155
  and leaving you with a bad feeling, Inch tells you there are still
103
156
  undocumented objects without judging.
104
157
 
105
- Inch does not tell you to document all your methods. Neither does it tell you
106
- not to. It does not tell you "a method's documentation should be a single line
107
- under 80 characters not ending in a period".
108
-
109
-
110
-
111
- ### Limitations
112
-
113
- How you document your code is up to you and Inch can't actually tell you how good your docs are.
114
-
115
- It can't tell if your code examples work or if you described parameters
116
- correctly or if you have just added `# TODO: write docs` to each and every
117
- method.
158
+ This provides a lot more insight than an overall grade could, because an overall grade for the above example would either be an `A` (if the evaluation ignores undocumented objects) or a weak `C` (if the evaluation includes them).
118
159
 
119
- It is just a tool, that you can use to find parts of a codebase lacking
120
- documentation.
160
+ The grade distribution does a much better job of painting the bigger picture.
121
161
 
122
162
 
123
163
 
@@ -128,8 +168,67 @@ Inch is build to parse [YARD](http://yardoc.org/),
128
168
  style documentation comments, but works reasonably well with unstructured
129
169
  comments.
130
170
 
131
- It comes with four sub-commands: `suggest`, `stats`, `show`, and `list`
171
+ These inline-docs below all score an `A` despite being written in different styles:
172
+
173
+ ```ruby
174
+ # Detects the size of the blob.
175
+ #
176
+ # @example
177
+ # blob_size(filename, blob) # => some value
178
+ #
179
+ # @param filename [String] the filename
180
+ # @param blob [String] the blob data
181
+ # @param mode [String, nil] optional String mode
182
+ # @return [Fixnum,nil]
183
+ def blob_size(filename, blob, mode = nil)
184
+ ```
185
+
186
+ ```ruby
187
+ # Detects the size of the blob.
188
+ #
189
+ # blob_size(filename, blob) # => some value
190
+ #
191
+ # Params:
192
+ # +filename+:: String filename
193
+ # +blob+:: String blob data
194
+ # +mode+:: Optional String mode (defaults to nil)
195
+ def blob_size(filename, blob, mode = nil)
196
+ ```
197
+
198
+ ```ruby
199
+ # Public: Detects the size of the blob.
200
+ #
201
+ # filename - String filename
202
+ # blob - String blob data
203
+ # mode - Optional String mode (defaults to nil)
204
+ #
205
+ # Examples
206
+ #
207
+ # blob_size(filename, blob)
208
+ # # => some value
209
+ #
210
+ # Returns Fixnum or nil.
211
+ def blob_size(filename, blob, mode = nil)
212
+ ```
213
+
214
+
215
+ But you don't have to adhere to any specific syntax. This gets an `A` as well:
216
+
217
+ ```ruby
218
+ # Returns the size of a +blob+ for a given +filename+.
219
+ #
220
+ # blob_size(filename, blob)
221
+ # # => some value
222
+ #
223
+ def blob_size(filename, blob, mode = nil)
224
+ ```
225
+
226
+ Inch *let's you write your documentation the way you want*.
227
+
228
+
229
+ ## Subcommands
132
230
 
231
+ It comes with four sub-commands: `suggest`, `stats`, `show`, and `list`
133
232
 
134
233
 
135
234
  ### inch suggest
@@ -278,6 +377,21 @@ This creates a rake task named `inch`. Change the name by passing it to the cons
278
377
 
279
378
 
280
379
 
380
+
381
+
382
+ ## Limitations
383
+
384
+ How you document your code is up to you and Inch can't actually tell you how good your docs are.
385
+
386
+ It can't tell if your code examples work or if you described parameters
387
+ correctly or if you have just added `# TODO: write docs` to each and every
388
+ method.
389
+
390
+ It is just a tool, that you can use to find parts in your codebase that are
391
+ lacking documentation.
392
+
393
+
394
+
281
395
  ## How is this different from ...?
282
396
 
283
397
  ### Documentation coverage
data/TODOS.md CHANGED
@@ -9,10 +9,4 @@
9
9
  (realized via the @overload tag in YARD)
10
10
 
11
11
  * Think about implicit cases in terms of evaluation:
12
- * constructors and ?-methods are automatically assigned a @return tag
13
12
  * attr_* methods are automatically assigned a docstring and @param tag
14
-
15
- * Think about limiting the number of `B`-objects in `inch suggest`
16
- `inch suggest` shows too many `B`s even though there are still undocumented
17
- objects in the codebase. this becomes a problem, when one thinks of `B` as
18
- "good enough", which Inch itself suggests.
@@ -0,0 +1,82 @@
1
+ Inch::Config.run do
2
+ # development!
3
+
4
+ evaluation do
5
+ grade(:A) do
6
+ scores 80..100
7
+ label "Seems really good"
8
+ color :green
9
+ end
10
+
11
+ grade(:B) do
12
+ scores 50...80
13
+ label "Proper documentation present"
14
+ color :yellow
15
+ end
16
+
17
+ grade(:C) do
18
+ scores 1...50
19
+ label "Needs work"
20
+ color :red
21
+ end
22
+
23
+ grade(:U) do
24
+ scores 0..0
25
+ label "Undocumented"
26
+ color :color141
27
+ bg_color :color105
28
+ end
29
+
30
+ schema(:ConstantObject) do
31
+ docstring 1.0
32
+
33
+ # optional:
34
+ unconsidered_tag 0.2
35
+ end
36
+
37
+ schema(:ClassObject) do
38
+ docstring 1.0
39
+
40
+ # optional:
41
+ code_example_single 0.1
42
+ code_example_multi 0.2
43
+ unconsidered_tag 0.2
44
+ end
45
+
46
+ schema(:ModuleObject) do
47
+ docstring 1.0
48
+
49
+ # optional:
50
+ code_example_single 0.1
51
+ code_example_multi 0.2
52
+ unconsidered_tag 0.2
53
+ end
54
+
55
+ schema(:MethodObject) do
56
+ docstring 0.5
57
+ parameters 0.4
58
+ return_type 0.1
59
+ return_description 0.3
60
+
61
+ if object.constructor? || object.questioning_name?
62
+ parameters parameters + return_type
63
+ return_type 0.0
64
+ end
65
+
66
+ if object.constructor?
67
+ return_description 0.0
68
+ end
69
+
70
+ if !object.has_parameters? || object.setter?
71
+ return_description docstring + parameters
72
+ docstring docstring + parameters
73
+ parameters 0.0
74
+ end
75
+
76
+ # optional:
77
+ code_example_single 0.1
78
+ code_example_multi 0.25
79
+ unconsidered_tag 0.2
80
+ end
81
+ end
82
+ end
@@ -50,6 +50,15 @@ module Inch
50
50
  command
51
51
  end
52
52
 
53
+ # Registers the current Command in the CommandParser
54
+ #
55
+ # @param name [Symbol] name of the Command
56
+ # @return [void]
57
+ def self.register_command_as(name, default = false)
58
+ CLI::CommandParser.default_command = name if default
59
+ CLI::CommandParser.commands[name] = self
60
+ end
61
+
53
62
  def initialize
54
63
  options_class = "Command::Options::#{self.class.to_s.split('::').last}"
55
64
  @options = eval(options_class).new
@@ -14,10 +14,10 @@ module Inch
14
14
 
15
15
  def initialize
16
16
  super
17
- @ranges = Evaluation.new_score_ranges
17
+ @grade_lists = Evaluation.new_grade_lists
18
18
  end
19
19
 
20
- # Prepares the list of objects and ranges, parsing arguments and
20
+ # Prepares the list of objects and grade_lists, parsing arguments and
21
21
  # running the source parser.
22
22
  #
23
23
  # @param *args [Array<String>] the list of arguments.
@@ -27,17 +27,17 @@ module Inch
27
27
  @options.verify
28
28
  run_source_parser(@options.paths, @options.excluded)
29
29
  filter_objects
30
- assign_objects_to_ranges
30
+ assign_objects_to_grade_lists
31
31
  end
32
32
 
33
33
  private
34
34
 
35
- # Assigns the objects returned by {#objects} to the score ranges in
36
- # +@ranges+ based on their score
35
+ # Assigns the objects returned by {#objects} to the grade_lists
36
+ # based on their score
37
37
  #
38
- def assign_objects_to_ranges
39
- @ranges.each do |range|
40
- list = objects.select { |o| range.range.include?(o.score) }
38
+ def assign_objects_to_grade_lists
39
+ @grade_lists.each do |range|
40
+ list = objects.select { |o| range.scores.include?(o.score) }
41
41
  range.objects = sort_by_priority(list)
42
42
  end
43
43
  end
@@ -15,7 +15,7 @@ module Inch
15
15
 
16
16
  def initialize
17
17
  super
18
- @ranges = Evaluation.new_score_ranges
18
+ @grade_lists = Evaluation.new_grade_lists
19
19
  end
20
20
 
21
21
  # Prepares the given objects, parsing arguments and
@@ -1,7 +1,12 @@
1
+ require_relative 'options/list'
2
+ require_relative 'output/list'
3
+
1
4
  module Inch
2
5
  module CLI
3
6
  module Command
4
7
  class List < BaseList
8
+ register_command_as :list
9
+
5
10
  def description
6
11
  'Lists all objects with their results'
7
12
  end
@@ -17,7 +22,7 @@ module Inch
17
22
  # @return [void]
18
23
  def run(*args)
19
24
  prepare_list(*args)
20
- Output::List.new(@options, objects, @ranges)
25
+ Output::List.new(@options, objects, @grade_lists)
21
26
  end
22
27
  end
23
28
  end
@@ -101,7 +101,7 @@ module Inch
101
101
  #
102
102
  # @return [String]
103
103
  def description_hint_grades
104
- grades = Evaluation.new_score_ranges.map(&:grade)
104
+ grades = Evaluation::Grade.all
105
105
  "School grades (#{grades.join(', ')}) are assigned and " +
106
106
  "displayed with each object."
107
107
  end
@@ -8,6 +8,7 @@ module Inch
8
8
 
9
9
  attribute :proper_grades, [:A, :B]
10
10
  attribute :grades_to_display, [:B, :C, :U]
11
+ attribute :grade_weights, [0.2, 0.4, 0.4]
11
12
  attribute :object_min_priority, 0
12
13
  attribute :object_max_score, ::Inch::Evaluation::Base::MAX_SCORE
13
14
 
@@ -49,7 +50,8 @@ module Inch
49
50
  @object_max_score = object_max_score - 1
50
51
  # only A-listers are regarded as 'proper'
51
52
  @proper_grades = [:A]
52
- @grades_to_display = [:A, :B, :C]
53
+ @grades_to_display = [:A, :B, :C, :U]
54
+ @grade_weights = [0.3, 0.3, 0.2, 0.2]
53
55
  @object_count = 30
54
56
  @pedantic = true
55
57
  end
@@ -7,10 +7,10 @@ module Inch
7
7
 
8
8
  PER_RANGE = 10
9
9
 
10
- def initialize(options, objects, ranges)
10
+ def initialize(options, objects, grade_lists)
11
11
  @options = options
12
12
  @objects = objects
13
- @ranges = ranges
13
+ @grade_lists = grade_lists
14
14
  @omitted = 0
15
15
 
16
16
  display_list
@@ -19,13 +19,13 @@ module Inch
19
19
  private
20
20
 
21
21
  def display_list
22
- @ranges.each do |range|
22
+ @grade_lists.each do |range|
23
23
  if range.objects.empty?
24
24
  # pass
25
25
  else
26
26
  trace
27
- trace_header(range.description, range.color, range.bg_color)
28
- display_range(range)
27
+ trace_header(range.label, range.color, range.bg_color)
28
+ display_grade_list(range)
29
29
  end
30
30
  end
31
31
 
@@ -36,7 +36,7 @@ module Inch
36
36
  end
37
37
  end
38
38
 
39
- def display_range(range)
39
+ def display_grade_list(range)
40
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|
@@ -68,9 +68,9 @@ module Inch
68
68
  end
69
69
 
70
70
  def grade(score)
71
- ranges ||= Evaluation.new_score_ranges
72
- r = ranges.detect { |r| r.range.include?(score) }
73
- "#{r.grade} - #{r.description}".color(r.color)
71
+ grade_lists ||= Evaluation.new_grade_lists
72
+ r = grade_lists.detect { |r| r.scores.include?(score) }
73
+ "#{r.grade} - #{r.label}".color(r.color)
74
74
  end
75
75
  end
76
76
  end