yard-junk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e2e9b802aa1bb3391b0962165574b75f10e05cad
4
+ data.tar.gz: 6b279f93f06feb8ea1c10595d10cc8661f7bcc8d
5
+ SHA512:
6
+ metadata.gz: 381f8c03346812eef369dabc6548c675aef0c309f7cd08b767c0e3603ef1267f08b589acb994789f410039601108aa7cd3de46b42f3e8fc539d683a28b50975b
7
+ data.tar.gz: d9c65f218d51d23bb573671f9e89c62497bbed28063487a06ede45a1e1d97abd54dd5311e095d2944936d665ef86471dd0f1b385279906a17e5d7be9316a874a
data/.rubocop_todo.yml ADDED
@@ -0,0 +1 @@
1
+
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --markup markdown
2
+ -e ./lib/yard-junk.rb
data/README.md ADDED
@@ -0,0 +1,297 @@
1
+ # Yard-Junk: get rid of junk in your YARD docs!
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/yard-junk.svg)](http://badge.fury.io/rb/yard-junk)
4
+ [![Build Status](https://travis-ci.org/zverok/yard-junk.svg?branch=master)](https://travis-ci.org/zverok/yard-junk)
5
+
6
+ Yard-Junk is [yard](https://github.com/lsegal/yard) plugin/patch, that provides:
7
+
8
+ * structured documentation error logging;
9
+ * documentation errors validator, ready to be integrated into CI pipeline.
10
+
11
+ ## Showcase
12
+
13
+ Let's generate the docs for the [rom](https://github.com/rom-rb/rom) library.
14
+
15
+ Output of `yard doc` without JunkYard: [too huge to embed in README](https://gist.github.com/zverok/6dcf946d674e63545cee9f8a74e08728).
16
+
17
+ Things to notice:
18
+
19
+ * irregular and frequently approximate addresses (`in file 'core/lib/rom/types.rb':9`,
20
+ `in file 'core/lib/rom/global.rb' near line 41`, sometimes in separate line, sometimes inline),
21
+ hard to jump-to with any tool;
22
+ * a lot of ununderstood metaprogramming (grep for "Undocumentable mixin") -- nothing to fix here,
23
+ but YARD still notifies you;
24
+ * verbose and not very informative errors (look at that "Undocumentable mixin" -- and then grep
25
+ for "The proxy Coercible has not yet been recognized." and compare).
26
+
27
+ Output of `yard doc` with Yard-Junk:
28
+
29
+ ```
30
+ core/lib/rom/global.rb:40: [InvalidTagFormat] Invalid tag format for @example
31
+ core/lib/rom/schema.rb:144: [MissingParamName] @param tag has empty parameter name
32
+ core/lib/rom/schema.rb:300: [MissingParamName] @param tag has empty parameter name
33
+ core/lib/rom/schema.rb:311: [MissingParamName] @param tag has empty parameter name
34
+ core/lib/rom/gateway.rb:171: [UnknownParam] @param tag has unknown parameter name: Transaction
35
+ core/lib/rom/relation.rb:297: [UnknownParam] @param tag has unknown parameter name: options
36
+ core/lib/rom/relation.rb:406: [UnknownParam] @param tag has unknown parameter name: new_options
37
+ core/lib/rom/relation.rb:524: [UnknownParam] @param tag has unknown parameter name: klass
38
+ core/lib/rom/attribute.rb:339: [MissingParamName] @param tag has empty parameter name
39
+ core/lib/rom/plugin_base.rb:38: [UnknownParam] @param tag has unknown parameter name: base. Did you mean `_base`?
40
+ core/lib/rom/configuration.rb:46: [UnknownParam] @param tag has unknown parameter name: The
41
+ core/lib/rom/configuration.rb:47: [UnknownParam] @param tag has unknown parameter name: Plugin. Did you mean `plugin`?
42
+ core/lib/rom/memory/dataset.rb:54: [UnknownParam] @param tag has unknown parameter name: names
43
+ core/lib/rom/plugin_registry.rb:140: [UnknownTag] Unknown tag @raises. Did you mean @raise?
44
+ core/lib/rom/plugin_registry.rb:187: [UnknownTag] Unknown tag @raises. Did you mean @raise?
45
+ core/lib/rom/relation/loaded.rb:91: [UnknownTag] Unknown tag @raises. Did you mean @raise?
46
+ core/lib/rom/command_registry.rb:52: [UnknownParam] @param tag has unknown parameter name: name
47
+ core/lib/rom/relation/curried.rb:69: [UnknownTag] Unknown tag @raises. Did you mean @raise?
48
+ core/lib/rom/global/plugin_dsl.rb:41: [UnknownParam] @param tag has unknown parameter name: adapter
49
+ core/lib/rom/relation/combined.rb:28: [MissingParamName] @param tag has empty parameter name
50
+ core/lib/rom/commands/class_interface.rb:78: [UnknownParam] @param tag has unknown parameter name: command
51
+ core/lib/rom/commands/class_interface.rb:79: [UnknownParam] @param tag has unknown parameter name: parent
52
+ core/lib/rom/commands/class_interface.rb:108: [UnknownParam] @param tag has unknown parameter name: options. Did you mean `_options`?
53
+ core/lib/rom/commands/class_interface.rb:118: [MissingParamName] @param tag has empty parameter name
54
+ core/lib/rom/associations/definitions/abstract.rb:66: [UnknownParam] @param tag has unknown parameter name: options
55
+ changeset/lib/rom/changeset.rb:79: [UnknownParam] @param tag has unknown parameter name: options. Did you mean `new_options`?
56
+ changeset/lib/rom/changeset/stateful.rb:219: [UnknownParam] @param tag has unknown parameter name: assoc
57
+ mapper/lib/rom/header.rb:47: [UnknownParam] @param tag has unknown parameter name: model
58
+ mapper/lib/rom/processor/transproc.rb:212: [MissingParamName] @param tag has empty parameter name
59
+ core/lib/rom/types.rb:1: [UnknownNamespace] namespace Coercible is not recognized
60
+ core/lib/rom/types.rb:1: [UnknownNamespace] namespace Coercible is not recognized
61
+ core/lib/rom/types.rb:1: [UnknownNamespace] namespace Coercible is not recognized
62
+ ```
63
+
64
+ Things to notice:
65
+
66
+ * Regular output style with clearly recognizable addresses (and fixed to point at actual line with
67
+ the problematic tag, not the method which tag is related for);
68
+ * Error classes, allowing grouping, grepping, and configuring (notice no "Undocumentable xxx" errors:
69
+ I've just configured `yard-junk` to drop them for this repo);
70
+ * Usage of Ruby's bundled `did_you_mean` gem to show reasonable suggestions:
71
+ ```
72
+ Unknown tag @raises. Did you mean @raise?
73
+ @param tag has unknown parameter name: options. Did you mean `new_options`?
74
+ ```
75
+ * Rephrased and cleaned up messages.
76
+
77
+ `yard-junk` tool output:
78
+
79
+ ```
80
+ Problems
81
+ --------
82
+ mistyped tags or other typos in documentation
83
+
84
+ changeset/lib/rom/changeset.rb:79: [UnknownParam] @param tag has unknown parameter name: options. Did you mean `new_options`?
85
+ changeset/lib/rom/changeset/stateful.rb:219: [UnknownParam] @param tag has unknown parameter name: assoc
86
+ core/lib/rom/associations/definitions/abstract.rb:66: [UnknownParam] @param tag has unknown parameter name: options
87
+ core/lib/rom/attribute.rb:339: [MissingParamName] @param tag has empty parameter name
88
+ core/lib/rom/command_registry.rb:52: [UnknownParam] @param tag has unknown parameter name: name
89
+ core/lib/rom/commands/class_interface.rb:78: [UnknownParam] @param tag has unknown parameter name: command
90
+ core/lib/rom/commands/class_interface.rb:79: [UnknownParam] @param tag has unknown parameter name: parent
91
+ core/lib/rom/commands/class_interface.rb:108: [UnknownParam] @param tag has unknown parameter name: options. Did you mean `_options`?
92
+ core/lib/rom/commands/class_interface.rb:118: [MissingParamName] @param tag has empty parameter name
93
+ core/lib/rom/configuration.rb:46: [UnknownParam] @param tag has unknown parameter name: The
94
+ core/lib/rom/configuration.rb:47: [UnknownParam] @param tag has unknown parameter name: Plugin. Did you mean `plugin`?
95
+ core/lib/rom/gateway.rb:171: [UnknownParam] @param tag has unknown parameter name: Transaction
96
+ core/lib/rom/global.rb:40: [InvalidTagFormat] Invalid tag format for @example
97
+ core/lib/rom/global/plugin_dsl.rb:41: [UnknownParam] @param tag has unknown parameter name: adapter
98
+ core/lib/rom/memory/dataset.rb:54: [UnknownParam] @param tag has unknown parameter name: names
99
+ core/lib/rom/plugin_base.rb:38: [UnknownParam] @param tag has unknown parameter name: base. Did you mean `_base`?
100
+ core/lib/rom/plugin_registry.rb:140: [UnknownTag] Unknown tag @raises. Did you mean @raise?
101
+ core/lib/rom/plugin_registry.rb:187: [UnknownTag] Unknown tag @raises. Did you mean @raise?
102
+ core/lib/rom/relation.rb:297: [UnknownParam] @param tag has unknown parameter name: options
103
+ core/lib/rom/relation.rb:406: [UnknownParam] @param tag has unknown parameter name: new_options
104
+ core/lib/rom/relation.rb:524: [UnknownParam] @param tag has unknown parameter name: klass
105
+ core/lib/rom/relation/combined.rb:28: [MissingParamName] @param tag has empty parameter name
106
+ core/lib/rom/relation/curried.rb:69: [UnknownTag] Unknown tag @raises. Did you mean @raise?
107
+ core/lib/rom/relation/loaded.rb:91: [UnknownTag] Unknown tag @raises. Did you mean @raise?
108
+ core/lib/rom/schema.rb:144: [MissingParamName] @param tag has empty parameter name
109
+ core/lib/rom/schema.rb:300: [MissingParamName] @param tag has empty parameter name
110
+ core/lib/rom/schema.rb:311: [MissingParamName] @param tag has empty parameter name
111
+ core/lib/rom/types.rb:1: [UnknownNamespace] namespace Coercible is not recognized
112
+ core/lib/rom/types.rb:1: [UnknownNamespace] namespace Coercible is not recognized
113
+ core/lib/rom/types.rb:1: [UnknownNamespace] namespace Coercible is not recognized
114
+ mapper/lib/rom/header.rb:47: [UnknownParam] @param tag has unknown parameter name: model
115
+ mapper/lib/rom/processor/transproc.rb:212: [MissingParamName] @param tag has empty parameter name
116
+
117
+ 0 failures, 32 problems (2 seconds to run)
118
+ ```
119
+
120
+ It is basically the same as above, and:
121
+
122
+ * sorted by files/lines instead of "reported when found" approach;
123
+ * with short stats at the end;
124
+ * returning proper exit code (0 if no problems/parsing errors, non-0 otherwise), which allows `yard-junk`
125
+ to be integrated into CI pipeline, and control that new PRs will not screw docs (forgetting to
126
+ rename parameters in docs when they are renamed in code, for example).
127
+
128
+ As a nice addition, `yard-junk` command uses its own links to code objects resolver, which is 10x
129
+ faster (and, eventually, more correct) than YARD's own approach to resolve links when rendering docs.
130
+
131
+ ## Usage
132
+
133
+ It is a `yard-junk` gem, install it as usual, or add to your `Gemfile`.
134
+
135
+ ### Better logs
136
+
137
+ Add this to your `.yardopts` file:
138
+ ```
139
+ --plugin junk
140
+ ```
141
+
142
+ After that, just run `yard` or `yard doc` as usual, and enjoy better logs! You can also setup JunkYard
143
+ logs by passing options (in the same `.yardopts`):
144
+ ```
145
+ --junk-log-format FORMAT_STR
146
+ --junk-log-ignore ERROR_TYPE1,ERROR_TYPE2,...
147
+ ```
148
+
149
+ Format is usual Ruby's [#format](https://ruby-doc.org/core-2.2.3/Kernel.html#method-i-format) method
150
+ with named fields:
151
+ * `message` -- error message;
152
+ * `file` -- error file;
153
+ * `line` -- error line;
154
+ * `type` -- error type.
155
+
156
+ Default format is `%{file}:%{line}: [%{type}] %{message}`, as shown above.
157
+
158
+ `--junk-log-ignore` option allows to ingore error classes by their type names (shown in logs in `[]`).
159
+ By default, `Undocumentable` error is ignored: it is produced as metaprogramming pieces of code like
160
+ ```ruby
161
+ attr_reader *OPTIONS
162
+ ```
163
+ or
164
+ ```ruby
165
+ include Rails.routes
166
+ ```
167
+ ...and typically have no way to fix, while polluting logs with a lot of, well, junk.
168
+
169
+ ### Standalone docs check
170
+
171
+ Just run `yard-junk` command after gem is installed. It should work :)
172
+
173
+ ### Rake task (integrating in CI)
174
+
175
+ Add this to your `Rakefile`:
176
+
177
+ ```ruby
178
+ require 'yard-junk/rake'
179
+ YardJunk::Rake.task
180
+ ```
181
+
182
+ and then run it (or add to your `.travis.yml`) as
183
+ ```
184
+ rake yard:junk
185
+ ```
186
+
187
+ ## Reasons
188
+
189
+ Small problems in docs lead to decrease of readability and usability. But it is hard to check for
190
+ all those problems manually due to YARD's cumbersome output, and lack of CI-ready doc checking tools.
191
+
192
+ Idea of regularly structured logger was initially [proposed](https://github.com/lsegal/yard/issues/1007)
193
+ as an enchancement for YARD itself, and even some steps were maid by YARD's author in that direction,
194
+ but the idea was abandoned since.
195
+
196
+ Therefore, this independent tool was made.
197
+
198
+ ## Caveats
199
+
200
+ * Sometimes YARD doesn't provide enough information to guess in which line of code the problem is;
201
+ in those cases `junk-yard` just writes something like `file.rb:1` (to stay consistent and not break
202
+ go-to-file tools);
203
+ * Checking of links to files and URLs proven to be incomplete.
204
+
205
+ ## Roadmap
206
+
207
+ * Docs for usage as a system-wide YARD plugin;
208
+ * Docs for internals;
209
+ * Colorized output for text reporter;
210
+ * HTML reporter for CIs allowing to store build artifacts;
211
+ * Documentation quality checks as a next level of YARD checker;
212
+ * Option to check new/updated code only (integration with git history)?
213
+
214
+ ## Some examples of problems found in popular gems:
215
+
216
+ **NB: All of those are excellent libs! The showcase is of "how hard it is to maintain docs quality",
217
+ not of "how ignorant other programmers are".**
218
+
219
+ httparty:
220
+ ```
221
+ lib/httparty/exceptions.rb:2: [UnknownTag] Unknown tag @abstact. Did you mean @abstract?
222
+ lib/httparty/exceptions.rb:20: [MissingParamName] @param tag has empty parameter name
223
+ ```
224
+
225
+ vcr:
226
+ ```
227
+ lib/vcr/deprecations.rb:71: [UnknownParam] @param tag has unknown parameter name: name
228
+ lib/vcr/deprecations.rb:73: [UnknownParam] @param tag has unknown parameter name: options
229
+ lib/vcr/linked_cassette.rb:12: [UnknownParam] @param tag has unknown parameter name: context-owned
230
+ lib/vcr/linked_cassette.rb:13: [UnknownParam] @param tag has unknown parameter name: context-unowned
231
+ lib/vcr/linked_cassette.rb:55: [UnknownParam] @param tag has unknown parameter name: context-owned
232
+ lib/vcr/linked_cassette.rb:56: [UnknownParam] @param tag has unknown parameter name: context-unowned
233
+ lib/vcr/test_frameworks/cucumber.rb:27: [UnknownParam] @param tag has unknown parameter name: options
234
+ ```
235
+
236
+ eventmachine:
237
+ ```
238
+ lib/em/channel.rb:39: [UnknownParam] @param tag has unknown parameter name: Subscriber
239
+ lib/em/connection.rb:603: [InvalidLink] Cannot resolve link to Socket.unpack_sockaddr_in from text: {Socket.unpack_sockaddr_in}
240
+ lib/em/connection.rb:726: [InvalidLink] Cannot resolve link to EventMachine.notify_readable from text: {EventMachine.notify_readable}
241
+ lib/em/connection.rb:726: [InvalidLink] Cannot resolve link to EventMachine.notify_writable from text: {EventMachine.notify_writable}
242
+ lib/em/connection.rb:739: [InvalidLink] Cannot resolve link to EventMachine.notify_readable from text: {EventMachine.notify_readable}
243
+ lib/em/connection.rb:739: [InvalidLink] Cannot resolve link to EventMachine.notify_writable from text: {EventMachine.notify_writable}
244
+ lib/em/protocols/httpclient2.rb:263: [InvalidLink] Cannot resolve link to |response| from text: {|response| puts response.content }
245
+ lib/em/protocols/httpclient2.rb:276: [InvalidLink] Cannot resolve link to |response| from text: {|response| puts response.content }
246
+ lib/em/protocols/line_protocol.rb:9: [InvalidLink] Cannot resolve link to line from text: {line}
247
+ lib/em/protocols/object_protocol.rb:9: [InvalidLink] Cannot resolve link to 'you from text: {'you said' => obj}
248
+ lib/em/protocols/smtpclient.rb:138: [InvalidLink] Cannot resolve link to "Subject" from text: {"Subject" => "Bogus", "CC" => "<a href="mailto:myboss@example.com">myboss@example.com</a>"}
249
+ lib/em/protocols/smtpclient.rb:138: [InvalidLink] Cannot resolve link to :type=>:plain, from text: {:type=>:plain, :username=>"<a href="mailto:mickey@disney.com">mickey@disney.com</a>", :password=>"mouse"}
250
+ lib/em/protocols/smtpserver.rb:435: [InvalidLink] Cannot resolve link to :cert_chain_file from text: {:cert_chain_file => "/etc/ssl/cert.pem", :private_key_file => "/etc/ssl/private/cert.key"}
251
+ lib/em/protocols/socks4.rb:13: [InvalidLink] Cannot resolve link to data from text: {data}
252
+ lib/em/spawnable.rb:47: [InvalidLink] Cannot resolve link to xxx from text: {xxx}
253
+ lib/eventmachine.rb:215: [InvalidLink] Cannot resolve link to EventMachine.stop from text: {EventMachine.stop}
254
+ lib/eventmachine.rb:231: [InvalidLink] Cannot resolve link to EventMachine::Callback from text: {EventMachine::Callback}
255
+ lib/eventmachine.rb:319: [UnknownParam] @param tag has unknown parameter name: delay
256
+ lib/eventmachine.rb:345: [UnknownParam] @param tag has unknown parameter name: delay
257
+ ```
258
+
259
+ addressable:
260
+ ```
261
+ lib/addressable/template.rb:197: [UnknownParam] @param tag has unknown parameter name: *indexes. Did you mean `indexes`?
262
+ lib/addressable/uri.rb:296: [UnknownParam] @param tag has unknown parameter name: *uris. Did you mean `uris`?
263
+ lib/addressable/uri.rb:1842: [UnknownParam] @param tag has unknown parameter name: The
264
+ lib/addressable/uri.rb:1943: [UnknownParam] @param tag has unknown parameter name: The
265
+ lib/addressable/uri.rb:1958: [UnknownParam] @param tag has unknown parameter name: The
266
+ lib/addressable/uri.rb:2023: [UnknownParam] @param tag has unknown parameter name: The
267
+ lib/addressable/uri.rb:2244: [UnknownParam] @param tag has unknown parameter name: *components. Did you mean `components`?
268
+ lib/addressable/uri.rb:2275: [UnknownParam] @param tag has unknown parameter name: *components. Did you mean `components`?
269
+ ```
270
+
271
+ hashie:
272
+ ```
273
+ lib/hashie/extensions/coercion.rb:68: [UnknownParam] @param tag has unknown parameter name: key
274
+ lib/hashie/extensions/coercion.rb:69: [UnknownParam] @param tag has unknown parameter name: into
275
+ lib/hashie/extensions/deep_find.rb:7: [InvalidLink] Cannot resolve link to user: from text: {user: {location: {address: '123 Street'}
276
+ lib/hashie/extensions/deep_find.rb:7: [InvalidLink] Cannot resolve link to user: from text: {user: {location: {address: '123 Street'}
277
+ lib/hashie/extensions/deep_find.rb:16: [InvalidLink] Cannot resolve link to location: from text: {location: {address: '123 Street'}
278
+ lib/hashie/extensions/deep_find.rb:16: [InvalidLink] Cannot resolve link to location: from text: {location: {address: '123 Street'}
279
+ lib/hashie/extensions/deep_find.rb:27: [InvalidLink] Cannot resolve link to users: from text: {users: [{location: {address: '123 Street'}
280
+ lib/hashie/extensions/deep_find.rb:27: [InvalidLink] Cannot resolve link to users: from text: {users: [{location: {address: '123 Street'}
281
+ lib/hashie/extensions/deep_find.rb:36: [InvalidLink] Cannot resolve link to location: from text: {location: {address: '123 Street'}
282
+ lib/hashie/extensions/deep_find.rb:36: [InvalidLink] Cannot resolve link to location: from text: {location: {address: '123 Street'}
283
+ lib/hashie/extensions/deep_find.rb:36: [InvalidLink] Cannot resolve link to location: from text: {location: {address: '234 Street'}
284
+ lib/hashie/extensions/deep_find.rb:36: [InvalidLink] Cannot resolve link to location: from text: {location: {address: '234 Street'}
285
+ lib/hashie/extensions/deep_find.rb:36: [InvalidLink] Cannot resolve link to location: from text: {location: {address: '234 Street'}
286
+ lib/hashie/extensions/deep_find.rb:36: [InvalidLink] Cannot resolve link to location: from text: {location: {address: '234 Street'}
287
+ lib/hashie/mash.rb:32: [InvalidLink] Cannot resolve link to :a from text: {:a => {:b => 23, :d => {:e => "abc"}
288
+ lib/hashie/mash.rb:32: [InvalidLink] Cannot resolve link to :g from text: {:g => 44, :h => 29}
289
+ ```
290
+
291
+ ## Authors
292
+
293
+ [Victor Shepelev](https://github.com/zverok)
294
+
295
+ ## License
296
+
297
+ MIT
data/bin/yard-junk ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift(File.join(File.dirname(File.expand_path(__FILE__)), '..', 'lib'))
5
+
6
+ require 'yard'
7
+ require 'yard-junk'
8
+
9
+ janitor = YardJunk::Janitor.new
10
+ janitor.run
11
+ exit janitor.report(YardJunk::Janitor::TextReporter.new(STDOUT))
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ exec('cd examples; yard doc -o doc/ --no-stats input/*.rb')
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ exec('cd examples; yard doc -o doc/ --no-stats -e ../lib/junk_yard.rb input/*.rb')
4
+
5
+
@@ -0,0 +1,6 @@
1
+ class Foo
2
+ # @param (see #b)
3
+ def a; end
4
+ # @param (see #a)
5
+ def b; end
6
+ end
@@ -0,0 +1,42 @@
1
+ # This file tries to show as much errors in documentation as possible
2
+
3
+ # Macros attached to class
4
+ # @!macro [attach] attached4
5
+ # $1 $2 $3
6
+ class A
7
+ # Wrong macro directive format:
8
+ #
9
+ # @!macro
10
+ #
11
+ # Unknown directive:
12
+ # @!wtf
13
+
14
+
15
+ # @wrong Free hanging unknown tag
16
+
17
+ # Unknown macro name:
18
+ # @!macro wtf
19
+ # Points to unknown class: {B}
20
+ #
21
+ # @wrong This is unknown tag
22
+ #
23
+ # @param arg1 [C] Link to unknown class.
24
+ # @param arg3 This is unknown argument.
25
+ #
26
+ def foo(arg1, arg2)
27
+ end
28
+
29
+ # @param para
30
+ # @param para
31
+ # @example
32
+ # @see {invalid}
33
+ def bar(para)
34
+ end
35
+
36
+ OPTIONS = %i[foo bar baz]
37
+ # undocumentable attr_reader
38
+ attr_reader *OPTIONS
39
+ end
40
+
41
+ # not recognize namespace
42
+ Bar::BOOKS = 5
@@ -0,0 +1,7 @@
1
+ class
2
+ def m1
3
+ end
4
+ end
5
+
6
+ class B
7
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YardJunk
4
+ module CommandLineOptions
5
+ def common_options(opts) # rubocop:disable Metrics/MethodLength
6
+ super
7
+
8
+ opts.separator ''
9
+ opts.separator 'YardJunk plugin options'
10
+
11
+ opts.on('--junk-log-format [FMT]', "YardJunk::Logger format string, by default #{Logger::Message::DEFAULT_FORMAT.inspect}") do |format|
12
+ Logger.instance.format = format
13
+ end
14
+
15
+ opts.on('--junk-log-ignore [TYPE1,TYPE2,...]', "YardJunk::Logger message types to ignore, by default #{Logger::DEFAULT_IGNORE.map(&:inspect).join(', ')}") do |ignore|
16
+ Logger.instance.ignore = ignore.to_s.split(',')
17
+ end
18
+
19
+ opts.separator ''
20
+ opts.separator 'Generic options'
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YardJunk
4
+ class Janitor
5
+ # This class is a base for reporters that could be passed to
6
+ # {Janitor#report}.
7
+ #
8
+ # Basically, the reporter should define methods:
9
+ # * `header(title, explanation)` for printing problems section header;
10
+ # * `row(msg)` for printing instance of {Logger::Message};
11
+ # * `_stats(**statistics)` for printing statistics.
12
+ #
13
+ # Reporter also could redefine `finalize()` method, if it wants to do
14
+ # something at the end of a report (like "add footer and save to file").
15
+ #
16
+ class BaseReporter
17
+ # @overload initialize(io)
18
+ # @param io [#puts] Any IO-alike object that defines `puts` method.
19
+ #
20
+ # @overload initialize(filename)
21
+ # @param filename [String] Name of file to save the output.
22
+ def initialize(io_or_filename)
23
+ @io =
24
+ case io_or_filename
25
+ when ->(i) { i.respond_to?(:puts) } # quacks!
26
+ io_or_filename
27
+ when String
28
+ File.open(io_or_filename, 'w')
29
+ else
30
+ fail ArgumentError, "Can't create reporter with #{io_or_filename.class}"
31
+ end
32
+ end
33
+
34
+ def finalize; end
35
+
36
+ def section(title, explanation, messages)
37
+ return if messages.empty?
38
+ header(title, explanation)
39
+
40
+ messages
41
+ .sort_by { |m| [m.file || '\uFFFF', m.line || 1000, m.message] }
42
+ .each(&method(:row))
43
+ end
44
+
45
+ def stats(**stat)
46
+ _stats(stat.merge(duration: humanize_duration(stat[:duration])))
47
+ end
48
+
49
+ private
50
+
51
+ def _stats
52
+ fail NotImplementedError
53
+ end
54
+
55
+ def header(_title, _explanation)
56
+ fail NotImplementedError
57
+ end
58
+
59
+ def row(_message)
60
+ fail NotImplementedError
61
+ end
62
+
63
+ def humanize_duration(duration)
64
+ if duration < 60
65
+ '%i seconds' % duration
66
+ else
67
+ '%.1f minutes' % (duration / 60)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YardJunk
4
+ class Janitor
5
+ # TODO: Tests
6
+ class Resolver
7
+ include YARD::Templates::Helpers::HtmlHelper
8
+
9
+ MESSAGE_PATTERN = 'In file `%{file}\':%{line}: Cannot resolve link to %{name} from text: %{link}'
10
+
11
+ def self.resolve_all(yard_options)
12
+ YARD::Registry.all.map(&:base_docstring).each { |ds| new(ds, yard_options).resolve }
13
+ end
14
+
15
+ def initialize(docstring, yard_options)
16
+ @docstring = docstring
17
+ @options = yard_options
18
+ end
19
+
20
+ def resolve
21
+ markup_meth = "html_markup_#{options.markup}"
22
+ return unless respond_to?(markup_meth)
23
+ send(markup_meth, @docstring)
24
+ .gsub(%r{<(code|tt|pre)[^>]*>(.*?)</\1>}im, '')
25
+ .scan(/{[^}]+}/).flatten
26
+ .map(&CGI.method(:unescapeHTML))
27
+ .each(&method(:try_resolve))
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :options
33
+
34
+ def try_resolve(link)
35
+ name, _comment = link.tr('{}', '').split(/\s+/, 2)
36
+ resolved = YARD::Registry.resolve(@docstring.object, name, true, true)
37
+ return unless resolved.is_a?(YARD::CodeObjects::Proxy)
38
+ Logger.instance.register(MESSAGE_PATTERN % {file: object.file, line: object.line, name: name, link: link})
39
+ end
40
+
41
+ def object
42
+ @docstring.object
43
+ end
44
+
45
+ # required by HtmlHelper
46
+ def serializer
47
+ nil
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YardJunk
4
+ class Janitor
5
+ # Reporter that just outputs everything in plaintext format. Useful
6
+ # for commandline usage. See {BaseReporter} for details about reporters.
7
+ #
8
+ class TextReporter < BaseReporter
9
+ private
10
+
11
+ def _stats(**stat)
12
+ line =
13
+ '%<errors>i failures, %<problems>i problems (%<duration>s to run)' % stat
14
+ @io.puts "\n#{line}"
15
+ end
16
+
17
+ def header(title, explanation)
18
+ @io.puts
19
+ @io.puts title
20
+ @io.puts '-' * title.length
21
+ @io.puts explanation + "\n\n"
22
+ end
23
+
24
+ def row(msg)
25
+ @io.puts msg.to_s # default Message#to_s is good enough
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark'
4
+
5
+ module YardJunk
6
+ class Janitor
7
+ def run(*opts)
8
+ YARD::Registry.clear # Somehow loads all Ruby stdlib classes before Rake task started...
9
+ Logger.instance.format = nil
10
+
11
+ puts "Running YardJunk janitor...\n\n"
12
+
13
+ @duration = Benchmark.realtime do
14
+ command = YARD::CLI::Yardoc.new
15
+ command.run('--no-save', '--no-progress', '--no-stats', '--no-output', *opts)
16
+ Resolver.resolve_all(command.options)
17
+ end
18
+
19
+ self
20
+ end
21
+
22
+ def stats
23
+ {
24
+ errors: errors.count,
25
+ problems: problems.count,
26
+ duration: @duration || 0
27
+ }
28
+ end
29
+
30
+ def report(*reporters)
31
+ reporters.each do |reporter|
32
+ reporter.section('Errors', 'severe code or formatting problems', errors)
33
+ reporter.section('Problems', 'mistyped tags or other typos in documentation', problems)
34
+
35
+ reporter.stats(stats)
36
+ reporter.finalize
37
+ end
38
+
39
+ exit_code
40
+ end
41
+
42
+ def exit_code
43
+ return 2 unless errors.empty?
44
+ return 1 unless problems.empty?
45
+ 0
46
+ end
47
+
48
+ private
49
+
50
+ def messages
51
+ YardJunk::Logger.instance.messages.grep_v(Logger::Undocumentable) # FIXME: Not DRY
52
+ end
53
+
54
+ def errors
55
+ messages.select(&:error?)
56
+ end
57
+
58
+ def problems
59
+ messages.select(&:warn?)
60
+ end
61
+ end
62
+ end
63
+
64
+ require_relative 'janitor/base_reporter'
65
+ require_relative 'janitor/text_reporter'
66
+ require_relative 'janitor/resolver'
@@ -0,0 +1,253 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'did_you_mean'
4
+
5
+ module YardJunk
6
+ class Logger
7
+ class Message
8
+ attr_reader :message, :severity, :file, :line, :extra
9
+
10
+ def initialize(message:, severity: :warn, code_object: nil, file: nil, line: nil, **extra)
11
+ @message = message.gsub(/\s{2,}/, ' ')
12
+ @file = file
13
+ @line = line&.to_i
14
+ @code_object = code_object
15
+ @severity = severity
16
+ @extra = extra
17
+ end
18
+
19
+ %i[error warn].each do |sev|
20
+ define_method("#{sev}?") { severity == sev }
21
+ end
22
+
23
+ def to_h
24
+ {
25
+ type: type,
26
+ message: message,
27
+ file: file,
28
+ line: line&.to_i || 1
29
+ }.merge(extra)
30
+ end
31
+
32
+ def ==(other)
33
+ other.is_a?(self.class) && to_h == other.to_h
34
+ end
35
+
36
+ DEFAULT_FORMAT = '%{file}:%{line}: [%{type}] %{message}'
37
+
38
+ def to_s(format = DEFAULT_FORMAT)
39
+ format % to_h
40
+ end
41
+
42
+ def type
43
+ self.class.type
44
+ end
45
+
46
+ private
47
+
48
+ # DidYouMean changed API dramatically between 1.0 and 1.1, and different rubies have different
49
+ # versions of it bundled.
50
+ if DidYouMean.const_defined?(:SpellCheckable)
51
+ class SpellChecker < Struct.new(:error, :dictionary) # rubocop:disable Style/StructInheritance
52
+ include DidYouMean::SpellCheckable
53
+
54
+ def candidates
55
+ {error => dictionary}
56
+ end
57
+ end
58
+
59
+ def spell_check(error, dictionary)
60
+ SpellChecker.new(error, dictionary).corrections
61
+ end
62
+ elsif DidYouMean.const_defined?(:SpellChecker)
63
+ def spell_check(error, dictionary)
64
+ DidYouMean::SpellChecker.new(dictionary: dictionary).correct(error)
65
+ end
66
+ else
67
+ def spell_check(*)
68
+ []
69
+ end
70
+ end
71
+
72
+ class << self
73
+ def registry
74
+ @registry ||= []
75
+ end
76
+
77
+ def pattern(regexp)
78
+ @pattern = regexp
79
+ Message.registry << self
80
+ end
81
+
82
+ def search_up(pattern) # rubocop:disable Style/TrivialAccessors
83
+ @search_up = pattern
84
+ end
85
+
86
+ def try_parse(line, **context)
87
+ @pattern or fail StandardError, "Pattern is not defined for #{self}"
88
+ match = @pattern.match(line) or return nil
89
+ data = context.reject { |_, v| v.nil? }
90
+ .merge(match.names.map(&:to_sym).zip(match.captures).to_h.reject { |_, v| v.nil? })
91
+ data = guard_line(data)
92
+ new(**data)
93
+ end
94
+
95
+ def type
96
+ name&.end_with?('::Message') ? 'UnknownError' : name&.sub(/^.+::/, '')
97
+ end
98
+
99
+ def valid_type?(type)
100
+ type == 'UnknownError' || registry.any? { |m| m.type == type }
101
+ end
102
+
103
+ private
104
+
105
+ def guard_line(data) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
106
+ # FIXME: Ugly, huh?
107
+ data[:file] && data[:line] && @search_up or return data
108
+ data = data.merge(line: data[:line].to_i)
109
+ data = data.merge(code_object: find_object(data[:file], data[:line]))
110
+ lines = File.readlines(data[:file]) rescue (return data) # rubocop:disable Style/RescueModifier
111
+ pattern = Regexp.new(@search_up % data.map { |k, v| [k, Regexp.escape(v.to_s)] }.to_h)
112
+ _, num = lines.map
113
+ .with_index { |ln, i| [ln, i + 1] }
114
+ .first(data[:line]).reverse
115
+ .detect { |ln, _| pattern.match(ln) }
116
+ num or return data
117
+
118
+ data.merge(line: num)
119
+ end
120
+
121
+ def find_object(file, line)
122
+ YARD::Registry.detect { |o| o.file == file && o.line == line }
123
+ end
124
+ end
125
+ end
126
+
127
+ class UnknownTag < Message
128
+ pattern %r{^(?<message>Unknown tag (?<tag>@\S+))( in file `(?<file>[^`]+)` near line (?<line>\d+))?$}
129
+ search_up '%{tag}(\W|$)'
130
+
131
+ def message
132
+ corrections.empty? ? super : "#{super}. Did you mean #{corrections.map { |c| "@#{c}" }.join(', ')}?"
133
+ end
134
+
135
+ private
136
+
137
+ def corrections
138
+ spell_check(extra[:tag], YARD::Tags::Library.labels.keys.map(&:to_s))
139
+ end
140
+ end
141
+
142
+ class InvalidTagFormat < Message
143
+ pattern %r{^(?<message>Invalid tag format for (?<tag>@\S+))( in file `(?<file>[^`]+)` near line (?<line>\d+))?$}
144
+ search_up '%{tag}(\W|$)'
145
+ end
146
+
147
+ class UnknownDirective < Message
148
+ pattern %r{^(?<message>Unknown directive (?<directive>@!\S+))( in file `(?<file>[^`]+)` near line (?<line>\d+))?$}
149
+ search_up '%{directive}(\W|$)'
150
+
151
+ # TODO: did_you_mean?
152
+ end
153
+
154
+ class InvalidDirectiveFormat < Message
155
+ pattern %r{^(?<message>Invalid directive format for (?<directive>@!\S+))( in file `(?<file>[^`]+)` near line (?<line>\d+))?$}
156
+ search_up '%{directive}(\W|$)'
157
+ end
158
+
159
+ class UnknownParam < Message
160
+ pattern %r{^(?<message>@param tag has unknown parameter name: (?<param_name>\S+))\s+ in file `(?<file>[^']+)' near line (?<line>\d+)$}
161
+ search_up '@param(\s+\[.+?\])?\s+?%{param_name}(\W|$)'
162
+
163
+ def message
164
+ corrections.empty? ? super : "#{super}. Did you mean #{corrections.map { |c| "`#{c}`" }.join(', ')}?"
165
+ end
166
+
167
+ private
168
+
169
+ def corrections
170
+ spell_check(extra[:param_name], known_params)
171
+ end
172
+
173
+ def known_params
174
+ @code_object.is_a?(YARD::CodeObjects::MethodObject) or return []
175
+ @code_object.parameters.map(&:first).map { |p| p.tr('*&:', '') }
176
+ end
177
+ end
178
+
179
+ class MissingParamName < Message
180
+ pattern %r{^(?<message>@param tag has unknown parameter name):\s+in file `(?<file>[^']+)' near line (?<line>\d+)$}
181
+ search_up '@param(\s+\[.+?\])?\s*$'
182
+
183
+ def message
184
+ '@param tag has empty parameter name'
185
+ end
186
+ end
187
+
188
+ class DuplicateParam < Message
189
+ pattern %r{^(?<message>@param tag has duplicate parameter name: (?<param_name>\S+))\s+ in file `(?<file>[^']+)' near line (?<line>\d+)$}
190
+ search_up '@param\s+(\[.+?\]\s+)?%{param_name}(\W|$)'
191
+ end
192
+
193
+ class RedundantBraces < Message
194
+ pattern %r{^(?<message>@see tag \(\#\d+\) should not be wrapped in \{\} \(causes rendering issues\)):\s+in file `(?<file>[^']+)' near line (?<line>\d+)$}
195
+ search_up '@see.*{.*}'
196
+
197
+ def message
198
+ super.sub(/\s+\(\#\d+\)\s+/, ' ')
199
+ end
200
+ end
201
+
202
+ class SyntaxError < Message
203
+ pattern %r{^Syntax error in `(?<file>[^`]+)`:\((?<line>\d+),(?:\d+)\): (?<message>.+)$}
204
+
205
+ # Honestly, IDK why YARD considers it "warning"... So, rewriting
206
+ def severity
207
+ :error
208
+ end
209
+ end
210
+
211
+ class CircularReference < Message
212
+ pattern %r{^(?<file>.+?):(?<line>\d+): (?<message>Detected circular reference tag in `(?<object>[^']+)', ignoring all reference tags for this object \((?<context>[^)]+)\)\.)$}
213
+ end
214
+
215
+ class Undocumentable < Message
216
+ pattern %r{^in (?:\S+): (?<message>Undocumentable (?<object>.+?))\n\s*in file '(?<file>[^']+)':(?<line>\d+):\s+(?:\d+):\s*(?<quote>.+?)\s*$}
217
+
218
+ def message
219
+ super + ": `#{quote}`"
220
+ end
221
+
222
+ def quote
223
+ extra[:quote]
224
+ end
225
+ end
226
+
227
+ class UnknownNamespace < Message
228
+ pattern %r{^(?<message>The proxy (?<namespace>\S+?) has not yet been recognized).\nIf this class/method is part of your source tree, this will affect your documentation results.\nYou can correct this issue by loading the source file for this object before `(?<file>[^']+)'\n$}
229
+
230
+ def namespace
231
+ extra[:namespace]
232
+ end
233
+
234
+ def message
235
+ "namespace #{namespace} is not recognized"
236
+ end
237
+ end
238
+
239
+ class MacroAttachError < Message
240
+ pattern %r{^(?<message>Attaching macros to non-methods is unsupported, ignoring: (?<object>\S+)) \((?<file>.+?):(?<line>\d+)\)$}
241
+ search_up '@!macro \[attach\]'
242
+ end
243
+
244
+ class MacroNameError < Message
245
+ pattern %r{^(?<message>Invalid/missing macro name for (?<object>\S+)) \((?<file>.+?):(?<line>\d+)\)$}
246
+ end
247
+
248
+ class InvalidLink < Message
249
+ pattern %r{^In file `(?<file>[^']+)':(?<line>\d+): (?<message>Cannot resolve link to (?<object>\S+) from text:\s+(?<quote>.+))$}
250
+ search_up '%{quote}'
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+ require 'pp'
5
+
6
+ module YardJunk
7
+ class Logger
8
+ require_relative 'logger/message'
9
+
10
+ include Singleton
11
+
12
+ DEFAULT_IGNORE = %w[Undocumentable].freeze
13
+
14
+ def messages
15
+ @messages ||= []
16
+ end
17
+
18
+ def register(msg, severity = :warn)
19
+ message = Message.registry
20
+ .map { |t| t.try_parse(msg, severity: severity, file: @current_parsed_file) }
21
+ .compact.first || Message.new(message: msg, file: @current_parsed_file)
22
+ messages << message
23
+ puts message.to_s(@format) if output?(message)
24
+ end
25
+
26
+ def notify(msg)
27
+ case msg
28
+ when /Parsing (\w\S+)$/
29
+ # TODO: fragile regexp; cleanup it after everything is parsed.
30
+ @current_parsed_file = Regexp.last_match(1)
31
+ when /^Generating/ # end of parsing of any file
32
+ @current_parsed_file = nil
33
+ end
34
+ end
35
+
36
+ def clear
37
+ messages.clear
38
+ @format = Message::DEFAULT_FORMAT
39
+ @ignore = DEFAULT_IGNORE
40
+ end
41
+
42
+ def format=(fmt)
43
+ @format = fmt.to_s
44
+ end
45
+
46
+ def ignore=(list)
47
+ @ignore = Array(list).map(&:to_s)
48
+ .each { |type| Message.valid_type?(type) or fail(ArgumentError, "Unrecognized message type to ignore: #{type}") }
49
+ end
50
+
51
+ private
52
+
53
+ def output?(message)
54
+ !@format.empty? && !@ignore.include?(message.type)
55
+ end
56
+
57
+ module Mixin
58
+ def debug(msg)
59
+ YardJunk::Logger.instance.notify(msg)
60
+ super
61
+ end
62
+
63
+ def warn(msg)
64
+ YardJunk::Logger.instance.register(msg, :warn)
65
+ end
66
+
67
+ def error(msg)
68
+ YardJunk::Logger.instance.register(msg, :error)
69
+ end
70
+
71
+ def backtrace(exception, level_meth = :error)
72
+ super if %i[error fatal].include?(level_meth)
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ YardJunk::Logger.instance.clear
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YardJunk
4
+ module Rake
5
+ extend ::Rake::DSL
6
+
7
+ def self.define_task
8
+ desc 'Check th junk in your YARD Documentation'
9
+ task('yard:junk') do
10
+ require 'yard'
11
+ require_relative '../yard-junk'
12
+ exit Janitor.new.run.report(Janitor::TextReporter.new(STDOUT))
13
+ end
14
+ end
15
+ end
16
+ end
data/lib/yard-junk.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'yard-junk/logger'
4
+ require_relative 'yard-junk/command_line'
5
+ require_relative 'yard-junk/janitor'
6
+
7
+ YARD::Logger.prepend YardJunk::Logger::Mixin
8
+ YARD::CLI::Command.prepend YardJunk::CommandLineOptions
data/yard-junk.gemspec ADDED
@@ -0,0 +1,48 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'yard-junk'
3
+ s.version = '0.0.1'
4
+ s.authors = ['Victor Shepelev']
5
+ s.email = 'zverok.offline@gmail.com'
6
+ s.homepage = 'https://github.com/zverok/junk_yard'
7
+
8
+ s.summary = 'Get rid of the junk in your YARD docs'
9
+ s.description = <<-EOF
10
+ YardJunk is structured logger/error validator plugin for YARD documentation gem.
11
+ EOF
12
+ s.licenses = ['MIT']
13
+
14
+ s.required_ruby_version = '>= 2.3.0'
15
+
16
+ s.files = `git ls-files`.split($RS).reject do |file|
17
+ file =~ /^(?:
18
+ spec\/.*
19
+ |Gemfile
20
+ |Rakefile
21
+ |\.rspec
22
+ |\.gitignore
23
+ |\.rubocop.yml
24
+ |\.travis.yml
25
+ )$/x
26
+ end
27
+ s.require_paths = ["lib"]
28
+ s.bindir = 'bin'
29
+ s.executables << 'yard-junk'
30
+
31
+ s.add_dependency 'yard'
32
+ if RUBY_VERSION < '2.4'
33
+ s.add_dependency 'did_you_mean', '~> 1.0'
34
+ else
35
+ s.add_dependency 'did_you_mean', '~> 1.1'
36
+ end
37
+
38
+ s.add_development_dependency 'rubocop', '>= 0.30'
39
+ s.add_development_dependency 'rspec', '>= 3'
40
+ s.add_development_dependency 'rubocop-rspec'
41
+ s.add_development_dependency 'rspec-its', '~> 1'
42
+ #s.add_development_dependency 'saharspec'
43
+ s.add_development_dependency 'fakefs'
44
+ s.add_development_dependency 'simplecov', '~> 0.9'
45
+ s.add_development_dependency 'rake'
46
+ s.add_development_dependency 'rubygems-tasks'
47
+ s.add_development_dependency 'yard'
48
+ end
metadata ADDED
@@ -0,0 +1,218 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yard-junk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Victor Shepelev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: yard
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: did_you_mean
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0.30'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0.30'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-its
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: fakefs
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.9'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.9'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rake
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubygems-tasks
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: yard
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: " YardJunk is structured logger/error validator plugin for YARD documentation
168
+ gem.\n"
169
+ email: zverok.offline@gmail.com
170
+ executables:
171
+ - yard-junk
172
+ extensions: []
173
+ extra_rdoc_files: []
174
+ files:
175
+ - ".rubocop_todo.yml"
176
+ - ".yardopts"
177
+ - README.md
178
+ - bin/yard-junk
179
+ - examples/bare_log.rb
180
+ - examples/formatted_log.rb
181
+ - examples/input/circular_ref.rb
182
+ - examples/input/lot_of_errors.rb
183
+ - examples/input/unparseable.rb
184
+ - lib/yard-junk.rb
185
+ - lib/yard-junk/command_line.rb
186
+ - lib/yard-junk/janitor.rb
187
+ - lib/yard-junk/janitor/base_reporter.rb
188
+ - lib/yard-junk/janitor/resolver.rb
189
+ - lib/yard-junk/janitor/text_reporter.rb
190
+ - lib/yard-junk/logger.rb
191
+ - lib/yard-junk/logger/message.rb
192
+ - lib/yard-junk/rake.rb
193
+ - yard-junk.gemspec
194
+ homepage: https://github.com/zverok/junk_yard
195
+ licenses:
196
+ - MIT
197
+ metadata: {}
198
+ post_install_message:
199
+ rdoc_options: []
200
+ require_paths:
201
+ - lib
202
+ required_ruby_version: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - ">="
205
+ - !ruby/object:Gem::Version
206
+ version: 2.3.0
207
+ required_rubygems_version: !ruby/object:Gem::Requirement
208
+ requirements:
209
+ - - ">="
210
+ - !ruby/object:Gem::Version
211
+ version: '0'
212
+ requirements: []
213
+ rubyforge_project:
214
+ rubygems_version: 2.6.10
215
+ signing_key:
216
+ specification_version: 4
217
+ summary: Get rid of the junk in your YARD docs
218
+ test_files: []