yard-junk 0.0.4 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d2951dd9b76ead149237efbb2d837868f334db37
4
- data.tar.gz: 6b9e03ce2ec1b7f2c6eebb3fa7a23fa2bad10c95
2
+ SHA256:
3
+ metadata.gz: 14481796e58baa7573886f326ffebc41d7c8f3ead3bf2231e0835620d0d40ad2
4
+ data.tar.gz: 5124b2c72cc1db00241ba41f40bbe8d72d90da7e93073987382225537067b693
5
5
  SHA512:
6
- metadata.gz: 5b007c4ee552650b8c49d13619cbb98fb3dad7855ebf7a807c0c32ded821535197266e6511ef5754097937286a5bf1832e748fb824c38f9529914322e158e810
7
- data.tar.gz: f58438719e6d9a11a7bd995d336e09f97b59aeaf5b81094e46fe7852ebfebe9c574f0fcd80455163333213c4f5f4da71130dac193a77b7dacdf73f63a07c89b7
6
+ metadata.gz: 395a5dc5d809002190322f4c8b36b105e1b3ebc5e4023563928e7eb7841bc25494a6e8cd01e90b408ab899286e798c77a5e7c30bf677f66430022547b6adcfe2
7
+ data.tar.gz: f186b5edc44b44d3e0a256784f750bf5cfd0f9c105171754e9e88e008a3fac85df7e13d65e4c021d04ffdf6ba5a54887cd5b112cde193cebf73f5aa94029f9ad
@@ -0,0 +1,32 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ main:
11
+ name: >-
12
+ ${{ matrix.ruby }}
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ ruby: [ 2.5, 2.6, 2.7, head ]
18
+
19
+ steps:
20
+ - name: checkout
21
+ uses: actions/checkout@v2
22
+ - name: set up Ruby
23
+ uses: ruby/setup-ruby@v1
24
+ with:
25
+ ruby-version: ${{ matrix.ruby }}
26
+
27
+ - name: install dependencies
28
+ run: bundle install --jobs 3 --retry 3
29
+ - name: spec
30
+ run: bundle exec rake spec
31
+ - name: rubocop
32
+ run: bundle exec rake rubocop
@@ -1,5 +1,23 @@
1
1
  # Yard-Junk changelog
2
2
 
3
+ ## 0.0.8 -- 2020-11-12
4
+
5
+ * Support Ruby 2.7 (and hopefully 3.0)
6
+ * Drop support for Rubies below 2.5 :shrug:
7
+
8
+ ## 0.0.7 -- 2017-09-21
9
+
10
+ * Fix problems with links resolution for RDoc.
11
+
12
+ ## 0.0.6 -- 2017-09-20
13
+
14
+ * More robust (and more logical) colorization on text output (#25);
15
+ * Fast "sanity check" for using in pre-commit hook on large codebases (#24).
16
+
17
+ ## 0.0.5 -- 2017-09-11
18
+
19
+ * Fix gem conflict with `did_you_mean`.
20
+
3
21
  ## 0.0.4 -- 2017-09-09
4
22
 
5
23
  * Support for partial reports `yard-junk --path path/to/folder` (#13)
@@ -0,0 +1,90 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ yard-junk (0.0.9)
5
+ backports (>= 3.18)
6
+ rainbow
7
+ yard
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ ast (2.4.1)
13
+ backports (3.18.2)
14
+ diff-lcs (1.4.4)
15
+ docile (1.1.5)
16
+ fakefs (1.2.2)
17
+ json (2.3.1)
18
+ json (2.3.1-java)
19
+ kramdown (2.3.0)
20
+ rexml
21
+ parallel (1.20.0)
22
+ parser (2.7.2.0)
23
+ ast (~> 2.4.1)
24
+ rainbow (3.0.0)
25
+ rake (13.0.1)
26
+ regexp_parser (1.8.2)
27
+ rexml (3.2.4)
28
+ rspec (3.10.0)
29
+ rspec-core (~> 3.10.0)
30
+ rspec-expectations (~> 3.10.0)
31
+ rspec-mocks (~> 3.10.0)
32
+ rspec-core (3.10.0)
33
+ rspec-support (~> 3.10.0)
34
+ rspec-expectations (3.10.0)
35
+ diff-lcs (>= 1.2.0, < 2.0)
36
+ rspec-support (~> 3.10.0)
37
+ rspec-its (1.2.0)
38
+ rspec-core (>= 3.0.0)
39
+ rspec-expectations (>= 3.0.0)
40
+ rspec-mocks (3.10.0)
41
+ diff-lcs (>= 1.2.0, < 2.0)
42
+ rspec-support (~> 3.10.0)
43
+ rspec-support (3.10.0)
44
+ rubocop (1.3.0)
45
+ parallel (~> 1.10)
46
+ parser (>= 2.7.1.5)
47
+ rainbow (>= 2.2.2, < 4.0)
48
+ regexp_parser (>= 1.8)
49
+ rexml
50
+ rubocop-ast (>= 1.1.1)
51
+ ruby-progressbar (~> 1.7)
52
+ unicode-display_width (>= 1.4.0, < 2.0)
53
+ rubocop-ast (1.1.1)
54
+ parser (>= 2.7.1.5)
55
+ rubocop-rspec (2.0.0)
56
+ rubocop (~> 1.0)
57
+ rubocop-ast (>= 1.1.0)
58
+ ruby-progressbar (1.10.1)
59
+ ruby2_keywords (0.0.2)
60
+ rubygems-tasks (0.2.4)
61
+ saharspec (0.0.8)
62
+ ruby2_keywords
63
+ simplecov (0.15.0)
64
+ docile (~> 1.1.0)
65
+ json (>= 1.8, < 3)
66
+ simplecov-html (~> 0.10.0)
67
+ simplecov-html (0.10.2)
68
+ unicode-display_width (1.7.0)
69
+ yard (0.9.25)
70
+
71
+ PLATFORMS
72
+ java
73
+ ruby
74
+
75
+ DEPENDENCIES
76
+ fakefs
77
+ kramdown
78
+ rake
79
+ rspec (>= 3)
80
+ rspec-its (~> 1)
81
+ rubocop
82
+ rubocop-rspec
83
+ rubygems-tasks
84
+ saharspec
85
+ simplecov (~> 0.9)
86
+ yard
87
+ yard-junk!
88
+
89
+ BUNDLED WITH
90
+ 2.1.2
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Yard-Junk: get rid of junk in your YARD docs!
2
2
 
3
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)
4
+ ![Build Status](https://github.com/zverok/yard-junk/workflows/CI/badge.svg?branch=master)
5
5
 
6
6
  Yard-Junk is [yard](https://github.com/lsegal/yard) plugin/patch, that provides:
7
7
 
@@ -429,10 +429,9 @@ Therefore, this independent tool was made.
429
429
 
430
430
  ## Caveats
431
431
 
432
- * Sometimes YARD doesn't provide enough information to guess in which line of code the problem is;
433
- in those cases `yard-junk` just writes something like `file.rb:1` (to stay consistent and not break
434
- go-to-file tools);
435
- * Checking of links to files and URLs proven to be incomplete ([#12](https://github.com/zverok/yard-junk/issues/12)).
432
+ Sometimes YARD doesn't provide enough information to guess in which line of code the problem is;
433
+ in those cases `yard-junk` just writes something like `file.rb:1` (to stay consistent and not break
434
+ go-to-file tools).
436
435
 
437
436
  ## Roadmap
438
437
 
@@ -8,13 +8,14 @@ require 'yard-junk'
8
8
  require 'optparse'
9
9
 
10
10
  formatters = {}
11
- check_path = nil
11
+ options = {}
12
12
 
13
- OptionParser.new do |opts|
13
+ OptionParser.new do |opts| # rubocop:disable Metrics/BlockLength
14
14
  opts.banner = 'Usage: yard-junk [formatters]'
15
15
  opts.separator ''
16
16
  opts.separator 'Formatters'
17
- opts.separator '(you can use several at once, for example --text to print in console and --html to save HTML report somewhere)'
17
+ opts.separator '(you can use several at once, for example --text to print in console '\
18
+ 'and --html to save HTML report somewhere)'
18
19
  opts.separator 'Default is: text formatter, printing to STDOUT.'
19
20
  opts.separator ''
20
21
 
@@ -22,15 +23,24 @@ OptionParser.new do |opts|
22
23
  formatters[:text] = path
23
24
  end
24
25
 
25
- opts.on('--html [PATH]', 'HTML formatter, useful as CI artifact (prints to STDOUT by default)') do |path|
26
+ opts.on('--html [PATH]',
27
+ 'HTML formatter, useful as CI artifact (prints to STDOUT by default)') do |path|
26
28
  formatters[:html] = path
27
29
  end
28
30
 
29
31
  opts.separator ''
30
32
  opts.separator 'Other options'
31
33
 
32
- opts.on('-f', '--path PATTERN1,PATTERN2,PATTERN3', 'Limit output only to this files. Can be path to file or folder, or glob pattern') do |patterns|
33
- check_path = patterns.split(',')
34
+ opts.on('-f', '--path PATTERN1,PATTERN2,PATTERN3',
35
+ 'Limit output only to this files. '\
36
+ 'Can be path to file or folder, or glob pattern') do |patterns|
37
+ options[:pathes] = patterns.split(',')
38
+ end
39
+
40
+ opts.on('-s', '--sanity',
41
+ 'Sanity check for docs: just catch mistyped tags and similar stuff. '\
42
+ 'On large codebases, MUCH faster than full check.') do
43
+ options[:mode] = :sanity
34
44
  end
35
45
 
36
46
  opts.on_tail('-v', '--version', 'Prints version') do
@@ -46,6 +56,6 @@ end.parse!
46
56
 
47
57
  formatters = {text: nil} if formatters.empty?
48
58
 
49
- janitor = YardJunk::Janitor.new
59
+ janitor = YardJunk::Janitor.new(**options)
50
60
  janitor.run
51
- exit janitor.report(path: check_path, **formatters)
61
+ exit janitor.report(**formatters)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'yard'
3
4
  require_relative 'yard-junk/version'
4
5
  require_relative 'yard-junk/logger'
5
6
  require_relative 'yard-junk/command_line'
@@ -8,11 +8,15 @@ module YardJunk
8
8
  opts.separator ''
9
9
  opts.separator 'YardJunk plugin options'
10
10
 
11
- opts.on('--junk-log-format [FMT]', "YardJunk::Logger format string, by default #{Logger::Message::DEFAULT_FORMAT.inspect}") do |format|
11
+ opts.on('--junk-log-format [FMT]',
12
+ 'YardJunk::Logger format string, by default '\
13
+ "#{Logger::Message::DEFAULT_FORMAT.inspect}") do |format|
12
14
  Logger.instance.format = format
13
15
  end
14
16
 
15
- opts.on('--junk-log-ignore [TYPE1,TYPE2,...]', "YardJunk::Logger message types to ignore, by default #{Logger::DEFAULT_IGNORE.map(&:inspect).join(', ')}") do |ignore|
17
+ opts.on('--junk-log-ignore [TYPE1,TYPE2,...]',
18
+ 'YardJunk::Logger message types to ignore, by default '\
19
+ "#{Logger::DEFAULT_IGNORE.map(&:inspect).join(', ')}") do |ignore|
16
20
  Logger.instance.ignore = ignore.to_s.split(',')
17
21
  end
18
22
 
@@ -2,9 +2,15 @@
2
2
 
3
3
  require 'benchmark'
4
4
  require 'backports/2.3.0/enumerable/grep_v'
5
+ require 'backports/2.6.0/array/to_h'
5
6
 
6
7
  module YardJunk
7
8
  class Janitor
9
+ def initialize(mode: :full, pathes: nil)
10
+ @mode = mode
11
+ @files = expand_pathes(pathes)
12
+ end
13
+
8
14
  def run(*opts)
9
15
  YARD::Registry.clear # Somehow loads all Ruby stdlib classes before Rake task started...
10
16
  Logger.instance.format = nil # Nothing shouuld be printed
@@ -13,27 +19,27 @@ module YardJunk
13
19
 
14
20
  @duration = Benchmark.realtime do
15
21
  command = YARD::CLI::Yardoc.new
16
- command.run('--no-save', '--no-progress', '--no-stats', '--no-output', *opts)
17
- Resolver.resolve_all(command.options)
22
+ command.run(*prepare_options(opts))
23
+ Resolver.resolve_all(command.options) unless mode == :sanity
18
24
  end
19
25
 
20
26
  self
21
27
  end
22
28
 
23
- def stats(path = nil)
29
+ def stats
24
30
  {
25
- errors: filter(errors, path).count,
26
- problems: filter(problems, path).count,
31
+ errors: errors.count,
32
+ problems: problems.count,
27
33
  duration: @duration || 0
28
34
  }
29
35
  end
30
36
 
31
- def report(*args, path: nil, **opts)
37
+ def report(*args, **opts)
32
38
  guess_reporters(*args, **opts).each do |reporter|
33
- reporter.section('Errors', 'severe code or formatting problems', filter(errors, path))
34
- reporter.section('Problems', 'mistyped tags or other typos in documentation', filter(problems, path))
39
+ reporter.section('Errors', 'severe code or formatting problems', errors)
40
+ reporter.section('Problems', 'mistyped tags or other typos in documentation', problems)
35
41
 
36
- reporter.stats(stats(path))
42
+ reporter.stats(**stats)
37
43
  reporter.finalize
38
44
  end
39
45
 
@@ -41,15 +47,43 @@ module YardJunk
41
47
  end
42
48
 
43
49
  def exit_code
44
- return 2 unless errors.empty?
45
- return 1 unless problems.empty?
46
- 0
50
+ case
51
+ when !errors.empty? then 2
52
+ when !problems.empty? then 1
53
+ else 0
54
+ end
47
55
  end
48
56
 
49
57
  private
50
58
 
59
+ attr_reader :mode, :files, :yardopts
60
+
61
+ BASE_OPTS = %w[--no-save --no-progress --no-stats --no-output --no-cache].freeze
62
+
63
+ def prepare_options(opts)
64
+ case
65
+ when mode == :full || mode == :sanity && files.nil?
66
+ [*BASE_OPTS, *opts]
67
+ when mode == :sanity
68
+ # TODO: specs
69
+ [*BASE_OPTS, '--no-yardopts', *yardopts_with_files(files)]
70
+ else
71
+ fail ArgumentError, "Undefined mode: #{mode.inspect}"
72
+ end
73
+ end
74
+
75
+ def yardopts_with_files(files)
76
+ # Use all options from .yardopts file, but replace file lists
77
+ YardOptions.new.remove_option('--files').set_files(*files)
78
+ end
79
+
51
80
  def messages
52
- YardJunk::Logger.instance.messages.grep_v(Logger::Undocumentable) # FIXME: Not DRY
81
+ # FIXME: dropping Undocumentable here is not DRY
82
+ @messages ||= YardJunk::Logger
83
+ .instance
84
+ .messages
85
+ .grep_v(Logger::Undocumentable)
86
+ .select { |m| !files || !m.file || files.include?(File.expand_path(m.file)) }
53
87
  end
54
88
 
55
89
  def errors
@@ -60,22 +94,23 @@ module YardJunk
60
94
  messages.select(&:warn?)
61
95
  end
62
96
 
63
- def filter(messages, pathes)
64
- return messages unless pathes
65
- filters =
66
- Array(pathes)
97
+ def expand_pathes(pathes)
98
+ return unless pathes
99
+
100
+ Array(pathes)
67
101
  .map { |path| File.directory?(path) ? File.join(path, '**', '*.*') : path }
68
102
  .flat_map(&Dir.method(:[]))
69
103
  .map(&File.method(:expand_path))
70
- messages.select { |m| filters.include?(File.expand_path(m.file)) }
71
104
  end
72
105
 
73
106
  # TODO: specs for the logic
74
107
  def guess_reporters(*symbols, **symbols_with_args)
75
108
  symbols
76
- .map { |sym| [sym, nil] }.to_h.merge(symbols_with_args)
109
+ .to_h { |sym| [sym, nil] }.merge(symbols_with_args)
77
110
  .map { |sym, args| ["#{sym.to_s.capitalize}Reporter", args] }
78
- .each { |name, _| Janitor.const_defined?(name) or fail(ArgumentError, "Reporter #{name} not found") }
111
+ .each { |name,|
112
+ Janitor.const_defined?(name) or fail(ArgumentError, "Reporter #{name} not found")
113
+ }
79
114
  .map { |name, args| Janitor.const_get(name).new(*args) }
80
115
  end
81
116
  end
@@ -85,3 +120,4 @@ require_relative 'janitor/base_reporter'
85
120
  require_relative 'janitor/text_reporter'
86
121
  require_relative 'janitor/html_reporter'
87
122
  require_relative 'janitor/resolver'
123
+ require_relative 'janitor/yard_options'
@@ -19,7 +19,7 @@ module YardJunk
19
19
  #
20
20
  # @overload initialize(filename)
21
21
  # @param filename [String] Name of file to save the output.
22
- def initialize(io_or_filename = STDOUT)
22
+ def initialize(io_or_filename = $stdout)
23
23
  @io =
24
24
  case io_or_filename
25
25
  when ->(i) { i.respond_to?(:puts) } # quacks!
@@ -35,6 +35,7 @@ module YardJunk
35
35
 
36
36
  def section(title, explanation, messages)
37
37
  return if messages.empty?
38
+
38
39
  header(title, explanation)
39
40
 
40
41
  messages
@@ -43,7 +44,7 @@ module YardJunk
43
44
  end
44
45
 
45
46
  def stats(**stat)
46
- _stats(stat.merge(duration: humanize_duration(stat[:duration])))
47
+ _stats(**stat.merge(duration: humanize_duration(stat[:duration])))
47
48
  end
48
49
 
49
50
  private
@@ -2,25 +2,39 @@
2
2
 
3
3
  module YardJunk
4
4
  class Janitor
5
- # TODO: Tests
6
5
  class Resolver
7
6
  include YARD::Templates::Helpers::HtmlHelper
7
+ include YARD::Templates::Helpers::MarkupHelper
8
8
 
9
- MESSAGE_PATTERN = 'In file `%{file}\':%{line}: Cannot resolve link to %{name} from text: %{link}'
9
+ # This one is copied from real YARD output
10
+ OBJECT_MESSAGE_PATTERN = "In file `%{file}':%{line}: " \
11
+ 'Cannot resolve link to %{name} from text: %{link}'
12
+
13
+ # ...while this one is totally invented, YARD doesn't check file existance at all
14
+ FILE_MESSAGE_PATTERN = "In file `%{file}':%{line}: File '%{name}' does not exist: %{link}"
10
15
 
11
16
  def self.resolve_all(yard_options)
12
17
  YARD::Registry.all.map(&:base_docstring).each { |ds| new(ds, yard_options).resolve }
18
+ yard_options.files.each { |file| new(file, yard_options).resolve }
13
19
  end
14
20
 
15
- def initialize(docstring, yard_options)
16
- @docstring = docstring
21
+ def initialize(object, yard_options)
17
22
  @options = yard_options
23
+ case object
24
+ when YARD::CodeObjects::ExtraFileObject
25
+ init_file(object)
26
+ when YARD::Docstring
27
+ init_docstring(object)
28
+ else
29
+ fail "Unknown object to resolve #{object.class}"
30
+ end
18
31
  end
19
32
 
20
33
  def resolve
21
- markup_meth = "html_markup_#{options.markup}"
34
+ markup_meth = "html_markup_#{markup}"
22
35
  return unless respond_to?(markup_meth)
23
- send(markup_meth, @docstring)
36
+
37
+ send(markup_meth, @string)
24
38
  .gsub(%r{<(code|tt|pre)[^>]*>(.*?)</\1>}im, '')
25
39
  .scan(/{[^}]+}/).flatten
26
40
  .map(&CGI.method(:unescapeHTML))
@@ -29,20 +43,62 @@ module YardJunk
29
43
 
30
44
  private
31
45
 
32
- attr_reader :options
46
+ def init_file(file)
47
+ @string = file.contents
48
+ @file = file.filename
49
+ @line = 1
50
+ @markup = markup_for_file(file.contents, file.filename)
51
+ end
52
+
53
+ def init_docstring(docstring)
54
+ @string = docstring
55
+ @root_object = docstring.object
56
+ @file = @root_object.file
57
+ @line = @root_object.line
58
+ @markup = options.markup
59
+ end
60
+
61
+ attr_reader :options, :file, :line, :markup
33
62
 
34
63
  def try_resolve(link)
35
64
  name, _comment = link.tr('{}', '').split(/\s+/, 2)
36
- resolved = YARD::Registry.resolve(@docstring.object, name, true, true)
65
+
66
+ # See YARD::Templates::Helpers::BaseHelper#linkify for the source of patterns
67
+ # TODO: there is also {include:}, {include:file:} and {render:} syntaxes, but I've never seen
68
+ # a project using them. /shrug
69
+ case name
70
+ when %r{://}, /^mailto:/ # that's pattern YARD uses
71
+ # do nothing, assume it is correct
72
+ when /^file:(\S+?)(?:#(\S+))?$/
73
+ resolve_file(Regexp.last_match[1], link)
74
+ else
75
+ resolve_code_object(name, link)
76
+ end
77
+ end
78
+
79
+ def resolve_file(name, link)
80
+ return if options.files.any? { |f| f.name == name || f.filename == name }
81
+
82
+ Logger.instance.register(
83
+ FILE_MESSAGE_PATTERN % {file: file, line: line, name: name, link: link}
84
+ )
85
+ end
86
+
87
+ def resolve_code_object(name, link)
88
+ resolved = YARD::Registry.resolve(@root_object, name, true, true)
37
89
  return unless resolved.is_a?(YARD::CodeObjects::Proxy)
38
- Logger.instance.register(MESSAGE_PATTERN % {file: object.file, line: object.line, name: name, link: link})
90
+
91
+ Logger.instance.register(
92
+ OBJECT_MESSAGE_PATTERN % {file: file, line: line, name: name, link: link}
93
+ )
39
94
  end
40
95
 
96
+ # Used by HtmlHelper for RDoc
41
97
  def object
42
- @docstring.object
98
+ @string.object if @string.is_a?(YARD::Docstring)
43
99
  end
44
100
 
45
- # required by HtmlHelper
101
+ # Used by HtmlHelper
46
102
  def serializer
47
103
  nil
48
104
  end
@@ -11,26 +11,24 @@ module YardJunk
11
11
  private
12
12
 
13
13
  def _stats(**stat)
14
- @io.puts "\n#{template_for(stat) % stat}"
14
+ @io.puts "\n#{colorized_stats(**stat)}"
15
15
  end
16
16
 
17
- NO_ISSUES_TEMPLATE = [
18
- Rainbow('%<errors>i failures, %<problems>i problems').green,
19
- Rainbow(', (%<duration>s to run)').gray
20
- ].join('').freeze
21
-
22
- ERROR_COUNT_TEMPLATE = [
23
- Rainbow('%<errors>i failures').red,
24
- Rainbow(',').gray,
25
- Rainbow(' %<problems>i problems').yellow,
26
- Rainbow(', (%<duration>s to run)').gray
27
- ].join('').freeze
28
-
29
- def template_for(stat)
30
- if stat[:errors].zero? && stat[:problems].zero?
31
- NO_ISSUES_TEMPLATE
32
- else
33
- ERROR_COUNT_TEMPLATE
17
+ def colorized_stats(errors:, problems:, duration:)
18
+ colorize(
19
+ format('%i failures, %i problems', errors, problems), status_color(errors, problems)
20
+ ) + format(' (%s to run)', duration)
21
+ end
22
+
23
+ def colorize(text, color)
24
+ Rainbow(text).color(color)
25
+ end
26
+
27
+ def status_color(errors, problems)
28
+ case
29
+ when errors.positive? then :red
30
+ when problems.positive? then :yellow
31
+ else :green
34
32
  end
35
33
  end
36
34
 
@@ -38,7 +36,7 @@ module YardJunk
38
36
  @io.puts
39
37
  @io.puts title
40
38
  @io.puts '-' * title.length
41
- @io.puts explanation + "\n\n"
39
+ @io.puts "#{explanation}\n\n"
42
40
  end
43
41
 
44
42
  def row(msg)
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YardJunk
4
+ class Janitor
5
+ # Allows to properly parse `.yardopts` or other option file YARD supports and gracefully replace
6
+ # or remove some of options.
7
+ class YardOptions
8
+ attr_reader :options, :files, :extra_files
9
+
10
+ def initialize
11
+ internal = Internal.new
12
+ internal.parse_arguments
13
+ @options = internal.option_args
14
+ @files = internal.files
15
+ @extra_files = internal.options.files
16
+ end
17
+
18
+ def set_files(*files) # rubocop:disable Naming/AccessorMethodName
19
+ # TODO: REALLY fragile :(
20
+ @files, @extra_files = files.partition { |f| f =~ /\.(rb|c|cxx|cpp|rake)/ }
21
+ self
22
+ end
23
+
24
+ def remove_option(long, short = nil)
25
+ [short, long].compact.each do |o|
26
+ i = @options.index(o)
27
+ next unless i
28
+
29
+ @options.delete_at(i)
30
+ @options.delete_at(i) unless @options[i].start_with?('-') # it was argument
31
+ end
32
+ self
33
+ end
34
+
35
+ def to_a
36
+ (@options + @files)
37
+ .tap { |res| res.concat(['-', *@extra_files]) unless @extra_files.empty? }
38
+ end
39
+
40
+ # The easiest way to think like Yardoc is to become Yardoc, you know.
41
+ class Internal < YARD::CLI::Yardoc
42
+ attr_reader :option_args
43
+
44
+ def optparse(*args)
45
+ # remember all passed options...
46
+ @all_args = args
47
+ super
48
+ end
49
+
50
+ def parse_files(*args)
51
+ # ...and substract what left after they were parsed as options, and only files left
52
+ @option_args = @all_args - args
53
+ super
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -3,6 +3,8 @@
3
3
  require 'singleton'
4
4
  require 'pp'
5
5
 
6
+ require 'backports/2.7.0/enumerable/filter_map'
7
+
6
8
  module YardJunk
7
9
  class Logger
8
10
  require_relative 'logger/message'
@@ -16,9 +18,10 @@ module YardJunk
16
18
  end
17
19
 
18
20
  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)
21
+ message =
22
+ Message.registry.filter_map { |t|
23
+ t.try_parse(msg, severity: severity, file: @current_parsed_file)
24
+ }.first || Message.new(message: msg, file: @current_parsed_file)
22
25
  messages << message
23
26
  puts message.to_s(@format) if output?(message)
24
27
  end
@@ -44,8 +47,10 @@ module YardJunk
44
47
  end
45
48
 
46
49
  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}") }
50
+ @ignore = Array(list).map(&:to_s).each do |type|
51
+ Message.valid_type?(type) or
52
+ fail(ArgumentError, "Unrecognized message type to ignore: #{type}")
53
+ end
49
54
  end
50
55
 
51
56
  private
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'did_you_mean'
3
+ require_relative 'spellcheck'
4
4
 
5
5
  module YardJunk
6
6
  class Logger
@@ -10,7 +10,7 @@ module YardJunk
10
10
  def initialize(message:, severity: :warn, code_object: nil, file: nil, line: nil, **extra)
11
11
  @message = message.gsub(/\s{2,}/, ' ')
12
12
  @file = file
13
- @line = line && line.to_i
13
+ @line = line&.to_i
14
14
  @code_object = code_object
15
15
  @severity = severity
16
16
  @extra = extra
@@ -25,7 +25,7 @@ module YardJunk
25
25
  type: type,
26
26
  message: message,
27
27
  file: file,
28
- line: (line && line.to_i) || 1
28
+ line: line&.to_i || 1
29
29
  }.merge(extra)
30
30
  end
31
31
 
@@ -43,43 +43,7 @@ module YardJunk
43
43
  self.class.type
44
44
  end
45
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) # 1.0 +
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) # 1.1+
63
- def spell_check(error, dictionary)
64
- DidYouMean::SpellChecker.new(dictionary: dictionary).correct(error)
65
- end
66
- elsif DidYouMean.const_defined?(:BaseFinder) # < 1.0
67
- class SpellFinder < Struct.new(:error, :dictionary) # rubocop:disable Style/StructInheritance
68
- include DidYouMean::BaseFinder
69
-
70
- def searches
71
- {error => dictionary}
72
- end
73
- end
74
-
75
- def spell_check(error, dictionary)
76
- SpellFinder.new(error, dictionary).suggestions
77
- end
78
- else
79
- def spell_check(*)
80
- []
81
- end
82
- end
46
+ include Spellcheck
83
47
 
84
48
  class << self
85
49
  def registry
@@ -98,8 +62,8 @@ module YardJunk
98
62
  def try_parse(line, **context)
99
63
  @pattern or fail StandardError, "Pattern is not defined for #{self}"
100
64
  match = @pattern.match(line) or return nil
101
- data = context.reject { |_, v| v.nil? }
102
- .merge(match.names.map(&:to_sym).zip(match.captures).to_h.reject { |_, v| v.nil? })
65
+ data = context.compact
66
+ .merge(match.names.map(&:to_sym).zip(match.captures).to_h.compact)
103
67
  data = guard_line(data)
104
68
  new(**data)
105
69
  end
@@ -114,17 +78,17 @@ module YardJunk
114
78
 
115
79
  private
116
80
 
117
- def guard_line(data) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
81
+ def guard_line(data) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
118
82
  # FIXME: Ugly, huh?
119
83
  data[:file] && data[:line] && @search_up or return data
120
84
  data = data.merge(line: data[:line].to_i)
121
85
  data = data.merge(code_object: find_object(data[:file], data[:line]))
122
86
  lines = File.readlines(data[:file]) rescue (return data) # rubocop:disable Style/RescueModifier
123
- pattern = Regexp.new(@search_up % data.map { |k, v| [k, Regexp.escape(v.to_s)] }.to_h)
87
+ pattern = Regexp.new(@search_up % data.transform_values { |v| Regexp.escape(v.to_s) })
124
88
  _, num = lines.map
125
89
  .with_index { |ln, i| [ln, i + 1] }
126
90
  .first(data[:line]).reverse
127
- .detect { |ln, _| pattern.match(ln) }
91
+ .detect { |ln,| pattern.match(ln) }
128
92
  num or return data
129
93
 
130
94
  data.merge(line: num)
@@ -136,6 +100,7 @@ module YardJunk
136
100
  end
137
101
  end
138
102
 
103
+ # rubocop:disable Layout/LineLength
139
104
  class UnknownTag < Message
140
105
  pattern %r{^(?<message>Unknown tag (?<tag>@\S+))( in file `(?<file>[^`]+)` near line (?<line>\d+))?$}
141
106
  search_up '%{tag}(\W|$)'
@@ -261,5 +226,11 @@ module YardJunk
261
226
  pattern %r{^In file `(?<file>[^']+)':(?<line>\d+): (?<message>Cannot resolve link to (?<object>\S+) from text:\s+(?<quote>.+))$}
262
227
  search_up '%{quote}'
263
228
  end
229
+
230
+ class InvalidFileLink < Message
231
+ pattern %r{^In file `(?<file>[^']+)':(?<line>\d+): (?<message>File '(?<object>\S+)' does not exist:\s+(?<quote>.+))$}
232
+ search_up '%{quote}'
233
+ end
234
+ # rubocop:enable Layout/LineLength
264
235
  end
265
236
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'did_you_mean'
5
+ rescue LoadError # rubocop:disable Lint/SuppressedException
6
+ end
7
+
8
+ module YardJunk
9
+ class Logger
10
+ module Spellcheck
11
+ # DidYouMean changed API dramatically between 1.0 and 1.1, and different rubies have different
12
+ # versions of it bundled.
13
+ if !Kernel.const_defined?(:DidYouMean)
14
+ def spell_check(*)
15
+ []
16
+ end
17
+ elsif DidYouMean.const_defined?(:SpellCheckable) # 1.0 +
18
+ class SpellChecker < Struct.new(:error, :dictionary) # rubocop:disable Style/StructInheritance
19
+ include DidYouMean::SpellCheckable
20
+
21
+ def candidates
22
+ {error => dictionary}
23
+ end
24
+ end
25
+
26
+ def spell_check(error, dictionary)
27
+ SpellChecker.new(error, dictionary).corrections
28
+ end
29
+ elsif DidYouMean.const_defined?(:SpellChecker) # 1.1+
30
+ def spell_check(error, dictionary)
31
+ DidYouMean::SpellChecker.new(dictionary: dictionary).correct(error)
32
+ end
33
+ elsif DidYouMean.const_defined?(:BaseFinder) # < 1.0
34
+ class SpellFinder < Struct.new(:error, :dictionary) # rubocop:disable Style/StructInheritance
35
+ include DidYouMean::BaseFinder
36
+
37
+ def searches
38
+ {error => dictionary}
39
+ end
40
+ end
41
+
42
+ def spell_check(error, dictionary)
43
+ SpellFinder.new(error, dictionary).suggestions
44
+ end
45
+ else # rubocop:disable Lint/DuplicateBranch -- actually, just impossibility catcher
46
+ def spell_check(*)
47
+ []
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -6,7 +6,7 @@ module YardJunk
6
6
  # @private
7
7
  MINOR = 0
8
8
  # @private
9
- PATCH = 4
9
+ PATCH = 9
10
10
 
11
11
  # @private
12
12
  VERSION = [MINOR, MAJOR, PATCH].join('.')
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  EOF
14
14
  s.licenses = ['MIT']
15
15
 
16
- s.required_ruby_version = '>= 2.1.0'
16
+ s.required_ruby_version = '>= 2.5.0'
17
17
 
18
18
  s.files = `git ls-files`.split($RS).reject do |file|
19
19
  file =~ /^(?:
@@ -33,19 +33,20 @@ Gem::Specification.new do |s|
33
33
  s.bindir = 'exe'
34
34
  s.executables << 'yard-junk'
35
35
 
36
- s.add_dependency 'rainbow'
37
36
  s.add_dependency 'yard'
38
- s.add_dependency 'did_you_mean'
39
- s.add_dependency 'backports'
37
+ s.add_dependency 'did_you_mean' if RUBY_VERSION < '2.3'
38
+ s.add_dependency 'backports', '>= 3.18'
39
+ s.add_dependency 'rainbow'
40
40
 
41
- s.add_development_dependency 'rubocop', '>= 0.49'
41
+ s.add_development_dependency 'rubocop'
42
42
  s.add_development_dependency 'rspec', '>= 3'
43
- s.add_development_dependency 'rubocop-rspec', '= 1.15.1' # 1.16.0 is broken on JRuby
43
+ s.add_development_dependency 'rubocop-rspec'
44
44
  s.add_development_dependency 'rspec-its', '~> 1'
45
- #s.add_development_dependency 'saharspec' # saharspec is moving target!
45
+ s.add_development_dependency 'saharspec'
46
46
  s.add_development_dependency 'fakefs'
47
47
  s.add_development_dependency 'simplecov', '~> 0.9'
48
48
  s.add_development_dependency 'rake'
49
49
  s.add_development_dependency 'rubygems-tasks'
50
50
  s.add_development_dependency 'yard'
51
+ s.add_development_dependency 'kramdown'
51
52
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yard-junk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Shepelev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-09-09 00:00:00.000000000 Z
11
+ date: 2020-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rainbow
14
+ name: yard
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,21 +25,21 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: yard
28
+ name: backports
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '3.18'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '3.18'
41
41
  - !ruby/object:Gem::Dependency
42
- name: did_you_mean
42
+ name: rainbow
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,13 +53,13 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: backports
56
+ name: rubocop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- type: :runtime
62
+ type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
@@ -67,61 +67,61 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rubocop
70
+ name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '0.49'
75
+ version: '3'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '0.49'
82
+ version: '3'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rspec
84
+ name: rubocop-rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '3'
89
+ version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '3'
96
+ version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: rubocop-rspec
98
+ name: rspec-its
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '='
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.15.1
103
+ version: '1'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '='
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 1.15.1
110
+ version: '1'
111
111
  - !ruby/object:Gem::Dependency
112
- name: rspec-its
112
+ name: saharspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '1'
117
+ version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '1'
124
+ version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: fakefs
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -192,6 +192,20 @@ dependencies:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: kramdown
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
195
209
  description: " YardJunk is structured logger/error validator plugin for YARD documentation
196
210
  gem.\n"
197
211
  email: zverok.offline@gmail.com
@@ -200,7 +214,9 @@ executables:
200
214
  extensions: []
201
215
  extra_rdoc_files: []
202
216
  files:
217
+ - ".github/workflows/ci.yml"
203
218
  - Changelog.md
219
+ - Gemfile.lock
204
220
  - README.md
205
221
  - examples/bare_log.rb
206
222
  - examples/formatted_log.rb
@@ -215,8 +231,10 @@ files:
215
231
  - lib/yard-junk/janitor/html_reporter.rb
216
232
  - lib/yard-junk/janitor/resolver.rb
217
233
  - lib/yard-junk/janitor/text_reporter.rb
234
+ - lib/yard-junk/janitor/yard_options.rb
218
235
  - lib/yard-junk/logger.rb
219
236
  - lib/yard-junk/logger/message.rb
237
+ - lib/yard-junk/logger/spellcheck.rb
220
238
  - lib/yard-junk/rake.rb
221
239
  - lib/yard-junk/version.rb
222
240
  - yard-junk.gemspec
@@ -232,15 +250,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
232
250
  requirements:
233
251
  - - ">="
234
252
  - !ruby/object:Gem::Version
235
- version: 2.1.0
253
+ version: 2.5.0
236
254
  required_rubygems_version: !ruby/object:Gem::Requirement
237
255
  requirements:
238
256
  - - ">="
239
257
  - !ruby/object:Gem::Version
240
258
  version: '0'
241
259
  requirements: []
242
- rubyforge_project:
243
- rubygems_version: 2.6.10
260
+ rubygems_version: 3.1.2
244
261
  signing_key:
245
262
  specification_version: 4
246
263
  summary: Get rid of the junk in your YARD docs