rubocop-schema-gen 0.1.0 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +13 -0
  3. data/README.md +20 -25
  4. data/assets/templates/cop_schema.yml +1 -3
  5. data/assets/templates/schema.yml +4 -0
  6. data/exe/rubocop-schema-gen +4 -2
  7. data/lib/rubocop/schema.rb +0 -4
  8. data/lib/rubocop/schema/ascii_doc/base.rb +52 -0
  9. data/lib/rubocop/schema/ascii_doc/cop.rb +93 -0
  10. data/lib/rubocop/schema/ascii_doc/department.rb +21 -0
  11. data/lib/rubocop/schema/ascii_doc/index.rb +20 -0
  12. data/lib/rubocop/schema/ascii_doc/stringifier.rb +49 -0
  13. data/lib/rubocop/schema/{cache.rb → cached_http_client.rb} +9 -12
  14. data/lib/rubocop/schema/cli.rb +94 -26
  15. data/lib/rubocop/schema/cop_info_merger.rb +54 -0
  16. data/lib/rubocop/schema/cop_schema.rb +69 -26
  17. data/lib/rubocop/schema/defaults_ripper.rb +48 -0
  18. data/lib/rubocop/schema/diff.rb +67 -0
  19. data/lib/rubocop/schema/document_loader.rb +55 -0
  20. data/lib/rubocop/schema/extension_spec.rb +67 -0
  21. data/lib/rubocop/schema/generator.rb +91 -0
  22. data/lib/rubocop/schema/helpers.rb +62 -0
  23. data/lib/rubocop/schema/repo.rb +91 -0
  24. data/lib/rubocop/schema/value_objects.rb +29 -3
  25. data/lib/rubocop/schema/version.rb +1 -1
  26. metadata +20 -36
  27. data/.gitignore +0 -19
  28. data/.rspec +0 -3
  29. data/.rubocop.yml +0 -38
  30. data/.ruby-version +0 -1
  31. data/.travis.yml +0 -6
  32. data/CODE_OF_CONDUCT.md +0 -74
  33. data/Gemfile +0 -10
  34. data/LICENSE.txt +0 -21
  35. data/Rakefile +0 -6
  36. data/bin/console +0 -14
  37. data/bin/setup +0 -8
  38. data/lib/rubocop/schema/lockfile_inspector.rb +0 -51
  39. data/lib/rubocop/schema/scraper.rb +0 -183
  40. data/lib/rubocop/schema/templates.rb +0 -8
  41. data/rubocop-schema.gemspec +0 -31
  42. data/rubocop-schema.json +0 -21110
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9896f77d8a3c4c39bd31f21878bffdb2d8979dee897b5fe38b3ef090bd11043d
4
- data.tar.gz: bfa9fe9b715b977f1dc973f48e80eafe59a448545bbef559247055bd98cfc5bd
3
+ metadata.gz: 99db5861b36cfdf148861814554c532213934e810770b8ed61f570b81a51ea1c
4
+ data.tar.gz: f7a310fbab5d4889cf24d8e138ca3acacf1fe66ab823699561d60b6db4320b02
5
5
  SHA512:
6
- metadata.gz: 074f101c7a87e0ce7e1de730a82b6bc83682bf0068d60519c1b042ca6bbcc7d3ca574e5ed47f3fec0f2cb63ce3639b98ab2915b90644b1e349aa4c589c3d6cab
7
- data.tar.gz: aeafc3e4661bed171c7d182ffbf6c752ded81d002623984bd0e146072c70fca9609d79410a8f5c23fe031c49caf15755d8ad5a3fe120955e7f23b9ddbd813398
6
+ metadata.gz: 6b646939f86c4db226daf43887e9039fb487143d8ceea498124d9b84f0297a0815558494982531edab03a2754e2a26c8f6c6f06e04f6d3a406f63f3ac7d526e9
7
+ data.tar.gz: 42c0d2d6769be3de1ec6aec0dbb8efa8a609bfd59f82615587757a8bcbe5b79cad6e7ccbda6186cbe0f6ae59b4dc4fb84c106182b58ea05dcecabf8b059dc660
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2021 Neil E. Pearson
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md CHANGED
@@ -1,44 +1,39 @@
1
- # Rubocop::Schema
1
+ # RuboCop Config Schema Generator
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rubocop/schema`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ This gem generates a JSON schema for your RuboCop configuration files, which you can use in your IDE (e.g. RubyMine) for autocompletion and validation.
6
4
 
7
5
  ## Installation
8
6
 
9
- Add this line to your application's Gemfile:
10
-
11
- ```ruby
12
- gem 'rubocop-schema'
13
- ```
14
-
15
- And then execute:
7
+ $ gem install rubocop-schema-gem
16
8
 
17
- $ bundle install
9
+ ## Usage
18
10
 
19
- Or install it yourself as:
11
+ Change to a directory containing a `Gemfile.lock`, which the generator will use to target your version of `rubocop`, and any extensions you may be using (e.g. `rubocop-rails`).
20
12
 
21
- $ gem install rubocop-schema
13
+ ```
14
+ $ cd ./my_project
15
+ $ rubocop-schema-gen
16
+ Generating rubocop-1.13.1-config-schema.json … complete in 5.2s
17
+ ```
22
18
 
23
- ## Usage
19
+ The name of the generated file is based on your gem version(s). You can override it with an argument.
24
20
 
25
- TODO: Write usage instructions here
21
+ ```
22
+ $ rubocop-schema-gen rubocop-schema.json
23
+ Generating rubocop-schema.json … complete in 0.7s
24
+ ```
26
25
 
27
- ## Development
26
+ Pass `-` to write to standard output.
28
27
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
28
+ The generator caches pages from https://raw.githubusercontent.com/rubocop in `~/.rubocop-schema-cache`.
30
29
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
30
+ Please refer to your IDE's documentation regarding applying the schema to your `.rubocop.yml` file.
32
31
 
33
32
  ## Contributing
34
33
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rubocop-schema. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/rubocop-schema/blob/master/CODE_OF_CONDUCT.md).
34
+ Bug reports and pull requests are welcome on GitHub at https://github.com/hx/rubocop-schema. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/hx/rubocop-schema/blob/master/CODE_OF_CONDUCT.md).
36
35
 
37
36
 
38
37
  ## License
39
38
 
40
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
41
-
42
- ## Code of Conduct
43
-
44
- Everyone interacting in the Rubocop::Schema project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/rubocop-schema/blob/master/CODE_OF_CONDUCT.md).
39
+ The gem is available as open source under the terms of the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
@@ -1,9 +1,7 @@
1
1
  type: object
2
2
  additionalProperties: true
3
3
 
4
- propertyNames:
5
- type: string
6
- pattern: '^[A-Z][A-Za-z]*$'
4
+ propertyNames: { $ref: '#/definitions/attributeName' }
7
5
 
8
6
  properties:
9
7
  Enabled: { type: boolean }
@@ -41,6 +41,10 @@ definitions:
41
41
  - type: array
42
42
  items: { type: string }
43
43
 
44
+ attributeName:
45
+ type: string
46
+ pattern: '^[A-Z][A-Za-z]*$'
47
+
44
48
  properties:
45
49
  inherit_from: { type: string }
46
50
 
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'bundler/setup'
3
+ Dir.chdir File.expand_path('..', __dir__) do
4
+ require 'bundler/setup'
5
+ end
4
6
  require 'rubocop/schema'
5
7
  require 'rubocop/schema/cli'
6
8
  require 'json'
7
9
 
8
- RuboCop::Schema::CLI.new(Dir.pwd, ENV, ARGV).run
10
+ RuboCop::Schema::CLI.new.run
@@ -1,10 +1,6 @@
1
1
  require 'pathname'
2
- require 'rubocop'
3
2
 
4
3
  require 'rubocop/schema/version'
5
- require 'rubocop/schema/cache'
6
- require 'rubocop/schema/scraper'
7
- require 'rubocop/schema/lockfile_inspector'
8
4
 
9
5
  module RuboCop
10
6
  module Schema
@@ -0,0 +1,52 @@
1
+ require 'rubocop/schema/ascii_doc/stringifier'
2
+ require 'rubocop/schema/helpers'
3
+
4
+ module RuboCop
5
+ module Schema
6
+ module AsciiDoc
7
+ class Base
8
+ include Helpers
9
+
10
+ # @param [Asciidoctor::AbstractBlock] ascii_block
11
+ def initialize(ascii_block)
12
+ @root = ascii_block
13
+ scan
14
+ end
15
+
16
+ protected
17
+
18
+ # @return [Asciidoctor::Document]
19
+ attr_reader :root
20
+
21
+ def scan
22
+ raise NotImplementedError
23
+ end
24
+
25
+ def link_text(str)
26
+ # The Asciidoctor API doesn't provide access to the raw title, or parts of it.
27
+ str[%r{<a\s.+?>(.+?)</a>}, 1]&.then &method(:strip_html)
28
+ end
29
+
30
+ # @param [Asciidoctor::Table] table
31
+ # @return [Array<Hash>] A hash for each row, with table headings as keys
32
+ def table_to_hash(table)
33
+ headings = table.rows.head.first.map(&:text)
34
+ table.rows.body.map do |row|
35
+ headings.each_with_index.map do |heading, i|
36
+ [heading, strip_html(row[i].text)]
37
+ end.to_h
38
+ end
39
+ end
40
+
41
+ def stringify_section(section)
42
+ @stringifier ||= Stringifier.new
43
+ @stringifier.stringify section
44
+ end
45
+
46
+ def presence(str)
47
+ str unless str.strip == ''
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,93 @@
1
+ require 'rubocop/schema/ascii_doc/base'
2
+ require 'rubocop/schema/value_objects'
3
+
4
+ module RuboCop
5
+ module Schema
6
+ module AsciiDoc
7
+ class Cop < Base
8
+ # @return [String]
9
+ attr_reader :name
10
+
11
+ # @return [String]
12
+ attr_reader :description
13
+
14
+ # @return [TrueClass, FalseClass]
15
+ attr_reader :enabled_by_default
16
+
17
+ # @return [TrueClass, FalseClass]
18
+ attr_reader :supports_autocorrect
19
+
20
+ # @return [Array<Attribute>]
21
+ attr_reader :attributes
22
+
23
+ ATTRS = public_instance_methods(false).freeze
24
+
25
+ def to_h
26
+ ATTRS.map { |k| [k, __send__(k)] }.to_h
27
+ end
28
+
29
+ protected
30
+
31
+ def scan
32
+ @name = root.title
33
+ read_stats_table
34
+ read_description
35
+ read_attributes
36
+ end
37
+
38
+ private
39
+
40
+ def read_stats_table
41
+ return unless stats_table
42
+
43
+ @enabled_by_default = stats_table['Enabled by default'] == 'Enabled'
44
+ @supports_autocorrect = stats_table['Supports autocorrection'] == 'Yes'
45
+ end
46
+
47
+ def read_description
48
+ blocks = root.blocks[find_description_range]
49
+ @description = blocks.map(&method(:stringify_section)).join("\n\n") if blocks.any?
50
+ end
51
+
52
+ def read_attributes
53
+ return unless attr_table_block
54
+
55
+ @attributes = table_to_hash(attr_table_block).map do |row|
56
+ Attribute.new(
57
+ name: row['Name'],
58
+ default: presence(row['Default value']),
59
+ type: presence(row['Configurable values'])
60
+ )
61
+ end
62
+ end
63
+
64
+ def find_description_range
65
+ top = stats_table_block ? root.blocks.index(stats_table_block) + 1 : 0
66
+ bottom = root.blocks.index(root.sections.first) || 0
67
+ top..(bottom - 1)
68
+ end
69
+
70
+ # @return [Asciidoctor::Block, nil]
71
+ def stats_table_block
72
+ @stats_table_block ||= root
73
+ .query(context: :table) { |t| t.rows.head.first.first.text == 'Enabled by default' }
74
+ .first
75
+ end
76
+
77
+ # @return [Asciidoctor::Block, nil]
78
+ def attr_table_block
79
+ @attr_table_block ||= root
80
+ .query(context: :section) { |s| s.title == 'Configurable attributes' }
81
+ &.first
82
+ &.query(context: :table)
83
+ &.first
84
+ end
85
+
86
+ # @return [Array<Hash>, nil]
87
+ def stats_table
88
+ @stats_table ||= stats_table_block && table_to_hash(stats_table_block).first
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,21 @@
1
+ require 'rubocop/schema/ascii_doc/base'
2
+ require 'rubocop/schema/ascii_doc/cop'
3
+
4
+ module RuboCop
5
+ module Schema
6
+ module AsciiDoc
7
+ class Department < Base
8
+ # @return [Array<Cop>]
9
+ attr_reader :cops
10
+
11
+ protected
12
+
13
+ def scan
14
+ @cops = root
15
+ .query(context: :section) { |s| s.title.start_with? "#{root.title}/" }
16
+ .map &Cop.method(:new)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ require 'rubocop/schema/ascii_doc/base'
2
+
3
+ module RuboCop
4
+ module Schema
5
+ module AsciiDoc
6
+ class Index < Base
7
+ # @return [Array<string>]
8
+ attr_reader :department_names
9
+
10
+ protected
11
+
12
+ def scan
13
+ @department_names = root
14
+ .query(context: :section) { |s| s.title.start_with? 'Department ' }
15
+ .map { |section| link_text section.title }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,49 @@
1
+ require 'rubocop/schema/helpers'
2
+
3
+ module RuboCop
4
+ module Schema
5
+ module AsciiDoc
6
+ class Stringifier
7
+ include Helpers
8
+
9
+ # @param [Asciidoctor::Section] section
10
+ def stringify(section)
11
+ method = :"stringify_#{section.context}"
12
+ raise "Don't know what to do with #{section.context}" unless private_methods(false).include? method
13
+
14
+ __send__(method, section)
15
+ end
16
+
17
+ private
18
+
19
+ # @param [Asciidoctor::Section] section
20
+ def stringify_paragraph(section)
21
+ section.lines.join ' '
22
+ end
23
+
24
+ alias stringify_admonition stringify_paragraph
25
+ alias stringify_listing stringify_paragraph
26
+
27
+ # @param [Asciidoctor::Section] section
28
+ def stringify_literal(section)
29
+ section.lines.map { |l| " #{l}" }.join "\n"
30
+ end
31
+
32
+ # @param [Asciidoctor::Section] section
33
+ def stringify_ulist(section)
34
+ section.blocks.map { |b| " - #{strip_html b.text}" }.join "\n\n" # TODO: single newline
35
+ end
36
+
37
+ # @param [Asciidoctor::Section] section
38
+ def stringify_olist(section)
39
+ section.blocks.map.with_index { |b, i| " #{i + 1}. #{strip_html b.text}" }.join "\n\n" # TODO: single newline
40
+ end
41
+
42
+ # @param [Asciidoctor::Section] section
43
+ def stringify_dlist(section)
44
+ strip_html section.convert # Too hard, just go HTML for now
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,30 +1,29 @@
1
1
  require 'pathname'
2
2
  require 'uri'
3
- require 'net/http'
3
+
4
+ require 'rubocop/schema/helpers'
4
5
 
5
6
  module RuboCop
6
7
  module Schema
7
- class Cache
8
- # @return [URI]
9
- attr_reader :base_url
8
+ class CachedHTTPClient
9
+ include Helpers
10
10
 
11
- def initialize(cache_dir, base_url: nil, &event_handler)
11
+ def initialize(cache_dir, &event_handler)
12
12
  @cache_dir = Pathname(cache_dir)
13
- @base_url = validate_url(base_url)
14
13
  @event_handler = event_handler
15
14
  end
16
15
 
17
16
  def get(url)
18
17
  url = URI(url)
19
- url = @base_url + url if @base_url && url.relative?
20
18
  validate_url url
21
19
 
22
20
  path = path_for_url(url)
23
21
  return path.read if path.readable?
24
22
 
25
23
  path.parent.mkpath
26
- @event_handler&.call Event.new(type: :request)
27
- Net::HTTP.get(url).force_encoding(Encoding::UTF_8).tap(&path.method(:write))
24
+ Event.dispatch type: :request, &@event_handler
25
+
26
+ http_get(url).tap(&path.method(:write))
28
27
  end
29
28
 
30
29
  private
@@ -34,13 +33,11 @@ module RuboCop
34
33
 
35
34
  raise ArgumentError, 'Expected an absolute URL' unless url.absolute?
36
35
  raise ArgumentError, 'Expected an HTTP URL' unless url.is_a? URI::HTTP
37
-
38
- url
39
36
  end
40
37
 
41
38
  # @param [URI::HTTP] url
42
39
  def path_for_url(url)
43
- @cache_dir + url.scheme + url.hostname + url.path[1..]
40
+ @cache_dir + url.scheme + url.hostname + url.path[1..-1]
44
41
  end
45
42
  end
46
43
  end
@@ -1,67 +1,135 @@
1
1
  require 'pathname'
2
2
  require 'json'
3
3
 
4
+ require 'rubocop/schema/document_loader'
5
+ require 'rubocop/schema/cached_http_client'
6
+ require 'rubocop/schema/generator'
7
+ require 'rubocop/schema/extension_spec'
8
+ require 'rubocop/schema/repo'
9
+
4
10
  module RuboCop
5
11
  module Schema
6
12
  class CLI
7
13
  # @param [Pathname] working_dir
8
14
  # @param [Hash] env
9
15
  # @param [Array<String>] args
10
- def initialize(working_dir, env, args)
16
+ # @param [String] home
17
+ # @param [IO] out_file
18
+ # @param [IO] log_file
19
+ def initialize(working_dir: Dir.pwd, env: ENV, args: ARGV, home: Dir.home, out_file: nil, log_file: $stderr)
11
20
  @working_dir = Pathname(working_dir)
21
+ @home_dir = Pathname(home)
12
22
  @env = env
13
23
  @args = args
24
+ @out_file = out_file
25
+ @log_file = log_file
26
+
27
+ raise ArgumentError, 'Cannot accept an out_file and an argument' if @out_file && args.first
14
28
  end
15
29
 
16
30
  def run
17
- fail "Cannot read #{lockfile_path}" unless lockfile_path.readable?
18
- fail 'RuboCop is not part of this project' unless lockfile.specs.any?
31
+ read_flag while @args.first&.start_with?('--')
32
+ assign_outfile
19
33
 
20
- schema = report_duration { Scraper.new(lockfile, cache).schema }
21
- puts JSON.pretty_generate schema
34
+ print "Generating #{@out_path} " if @out_path
35
+
36
+ schema = report_duration(lowercase: @out_path) { Generator.new(spec.specs, document_loader).schema }
37
+ @out_file.puts JSON.pretty_generate schema
22
38
  end
23
39
 
24
40
  private
25
41
 
26
- def report_duration
27
- started = Time.now
42
+ def read_flag
43
+ case @args.shift
44
+ when '--version'
45
+ info VERSION
46
+ when '--spec'
47
+ info spec
48
+ when /\A--spec=(\S+)/
49
+ @spec = ExtensionSpec.from_string($1)
50
+ when /\A--build-repo=(.+)/
51
+ build_repo $1
52
+ end
53
+ end
54
+
55
+ def build_repo(dir)
56
+ Repo.new(dir, document_loader, &method(:handle_event)).build
57
+ exit
58
+ end
59
+
60
+ def spec
61
+ @spec ||=
62
+ begin
63
+ lockfile_path = @working_dir + 'Gemfile.lock'
64
+ fail "Cannot read #{lockfile_path}" unless lockfile_path.readable?
65
+
66
+ spec = ExtensionSpec.from_lockfile(lockfile_path)
67
+ fail 'RuboCop is not part of this project' if spec.empty?
68
+
69
+ spec
70
+ end
71
+ end
72
+
73
+ def assign_outfile
74
+ return if @out_file
75
+
76
+ @out_path = path_from_arg(@args.first)
77
+
78
+ @out_file ||= File.open(@out_path, 'w') # rubocop:disable Naming/MemoizedInstanceVariableName
79
+ end
80
+
81
+ def path_from_arg(arg)
82
+ case arg
83
+ when '-'
84
+ @out_file = $stdout
85
+ nil
86
+ when nil
87
+ "#{spec}-config-schema.json"
88
+ else
89
+ arg
90
+ end
91
+ end
92
+
93
+ def report_duration(lowercase: false)
94
+ started = Time.now
28
95
  yield
29
96
  ensure
30
97
  finished = Time.now
31
- handle_event Event.new(message: "Complete in #{(finished - started).round 1}s")
98
+ message = "Complete in #{(finished - started).round 1}s"
99
+ message.downcase! if lowercase
100
+ handle_event Event.new(message: message)
32
101
  end
33
102
 
34
103
  def handle_event(event)
35
104
  case event.type
36
105
  when :request
37
- $stderr << '.'
106
+ @log_file << '.'
38
107
  @line_dirty = true
39
108
  else
40
- $stderr.puts '' if @line_dirty
109
+ @log_file.puts '' if @line_dirty
41
110
  @line_dirty = false
42
- $stderr.puts event.message.to_s
111
+ @log_file.puts event.message.to_s
43
112
  end
44
113
  end
45
114
 
46
- def fail(msg)
47
- $stderr.puts msg.to_s
48
- exit 1
49
- end
50
-
51
- def lockfile
52
- @lockfile ||= LockfileInspector.new(lockfile_path)
115
+ def info(msg)
116
+ $stdout.puts msg
117
+ exit
53
118
  end
54
119
 
55
- def lockfile_path
56
- @lockfile_path ||= @working_dir + 'Gemfile.lock'
57
- end
58
-
59
- def cache
60
- @cache ||= Cache.new(cache_dir, &method(:handle_event))
120
+ def fail(msg)
121
+ @log_file.puts msg.to_s
122
+ exit 1
61
123
  end
62
124
 
63
- def cache_dir
64
- @cache_dir ||= Pathname(Dir.home) + '.rubocop-schema-cache'
125
+ def document_loader
126
+ @document_loader ||=
127
+ DocumentLoader.new(
128
+ CachedHTTPClient.new(
129
+ @home_dir + '.rubocop-schema-cache',
130
+ &method(:handle_event)
131
+ )
132
+ )
65
133
  end
66
134
  end
67
135
  end