yard-junk 0.0.1

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.
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: []