rubocop-schema-gen 0.1.1 → 0.1.2
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 +4 -4
- data/lib/rubocop/schema/cached_http_client.rb +6 -4
- data/lib/rubocop/schema/cli.rb +52 -14
- data/lib/rubocop/schema/diff.rb +67 -0
- data/lib/rubocop/schema/document_loader.rb +17 -4
- data/lib/rubocop/schema/extension_spec.rb +17 -9
- data/lib/rubocop/schema/generator.rb +1 -3
- data/lib/rubocop/schema/helpers.rb +10 -0
- data/lib/rubocop/schema/repo.rb +79 -0
- data/lib/rubocop/schema/value_objects.rb +8 -2
- data/lib/rubocop/schema/version.rb +1 -1
- metadata +5 -16
- data/.gitignore +0 -19
- data/.rspec +0 -3
- data/.rubocop.yml +0 -74
- data/.ruby-version +0 -1
- data/.travis.yml +0 -10
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -15
- data/LICENSE.txt +0 -21
- data/Rakefile +0 -6
- data/bin/console +0 -15
- data/bin/setup +0 -8
- data/rubocop-schema.gemspec +0 -32
- data/rubocop-schema.json +0 -22198
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad2887f7e9c6ed387de3ea9c44a785c2c846c351681226752d334bad5e42ac42
|
4
|
+
data.tar.gz: dd3787e2db023d2dfc5a391bbc628e9796dc63d4578e604d2bd0eb2f9fb86ca6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cb67d04acc4d37ba1c8d4e05fb269b6f22be79b0928666c5e1639cb0d7840caacc3140c0320cead6fe311fe9aae3fd6cf9ff6474854f65ff3f07d28849204ab
|
7
|
+
data.tar.gz: 9f663797d40199ab878106996f4d6272c57c67f698ab9bb55fb222330c047330f49985eedd66cbcbd15acc0330e8da47dba38463f6039332d12d6fae2bc8514c
|
@@ -2,9 +2,13 @@ require 'pathname'
|
|
2
2
|
require 'uri'
|
3
3
|
require 'net/http'
|
4
4
|
|
5
|
+
require 'rubocop/schema/helpers'
|
6
|
+
|
5
7
|
module RuboCop
|
6
8
|
module Schema
|
7
9
|
class CachedHTTPClient
|
10
|
+
include Helpers
|
11
|
+
|
8
12
|
def initialize(cache_dir, &event_handler)
|
9
13
|
@cache_dir = Pathname(cache_dir)
|
10
14
|
@event_handler = event_handler
|
@@ -18,11 +22,9 @@ module RuboCop
|
|
18
22
|
return path.read if path.readable?
|
19
23
|
|
20
24
|
path.parent.mkpath
|
21
|
-
|
25
|
+
Event.dispatch type: :request, &@event_handler
|
22
26
|
|
23
|
-
|
24
|
-
res.body = '' unless res.is_a? Net::HTTPOK
|
25
|
-
res.body.force_encoding(Encoding::UTF_8).tap(&path.method(:write))
|
27
|
+
http_get(url).tap(&path.method(:write))
|
26
28
|
end
|
27
29
|
|
28
30
|
private
|
data/lib/rubocop/schema/cli.rb
CHANGED
@@ -5,6 +5,7 @@ require 'rubocop/schema/document_loader'
|
|
5
5
|
require 'rubocop/schema/cached_http_client'
|
6
6
|
require 'rubocop/schema/generator'
|
7
7
|
require 'rubocop/schema/extension_spec'
|
8
|
+
require 'rubocop/schema/repo'
|
8
9
|
|
9
10
|
module RuboCop
|
10
11
|
module Schema
|
@@ -22,19 +23,14 @@ module RuboCop
|
|
22
23
|
@args = args
|
23
24
|
@out_file = out_file
|
24
25
|
@log_file = log_file
|
25
|
-
@out_path = args.first
|
26
26
|
|
27
|
-
raise ArgumentError, 'Cannot accept an out_file and an argument' if @out_file &&
|
27
|
+
raise ArgumentError, 'Cannot accept an out_file and an argument' if @out_file && args.first
|
28
28
|
end
|
29
29
|
|
30
30
|
def run
|
31
|
-
|
32
|
-
|
31
|
+
read_flag while @args.first&.start_with?('--')
|
32
|
+
assign_outfile
|
33
33
|
|
34
|
-
spec = ExtensionSpec.from_lockfile(lockfile_path)
|
35
|
-
fail 'RuboCop is not part of this project' if spec.empty?
|
36
|
-
|
37
|
-
assign_outfile(spec)
|
38
34
|
print "Generating #{@out_path} … " if @out_path
|
39
35
|
|
40
36
|
schema = report_duration(lowercase: @out_path) { Generator.new(spec.specs, document_loader).schema }
|
@@ -43,18 +39,55 @@ module RuboCop
|
|
43
39
|
|
44
40
|
private
|
45
41
|
|
46
|
-
def
|
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
|
47
74
|
return if @out_file
|
48
75
|
|
49
|
-
|
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
|
50
83
|
when '-'
|
51
84
|
@out_file = $stdout
|
52
|
-
|
85
|
+
nil
|
53
86
|
when nil
|
54
|
-
|
87
|
+
"#{spec}-config-schema.json"
|
88
|
+
else
|
89
|
+
arg
|
55
90
|
end
|
56
|
-
|
57
|
-
@out_file ||= File.open(@out_path, 'w') # rubocop:disable Naming/MemoizedInstanceVariableName
|
58
91
|
end
|
59
92
|
|
60
93
|
def report_duration(lowercase: false)
|
@@ -79,6 +112,11 @@ module RuboCop
|
|
79
112
|
end
|
80
113
|
end
|
81
114
|
|
115
|
+
def info(msg)
|
116
|
+
$stdout.puts msg
|
117
|
+
exit
|
118
|
+
end
|
119
|
+
|
82
120
|
def fail(msg)
|
83
121
|
@log_file.puts msg.to_s
|
84
122
|
exit 1
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rubocop/schema/helpers'
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Schema
|
5
|
+
class Diff
|
6
|
+
include Helpers
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def instance
|
10
|
+
@instance ||= new
|
11
|
+
end
|
12
|
+
|
13
|
+
def diff(old, new)
|
14
|
+
instance.diff old, new
|
15
|
+
end
|
16
|
+
|
17
|
+
def apply(old, diff)
|
18
|
+
instance.apply old, diff
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def diff(old, new)
|
23
|
+
return diff_hashes old, new if old.is_a?(Hash) && new.is_a?(Hash)
|
24
|
+
|
25
|
+
new
|
26
|
+
end
|
27
|
+
|
28
|
+
def apply(old, diff)
|
29
|
+
return apply_hash(old, diff) if old.is_a?(Hash) && diff.is_a?(Hash)
|
30
|
+
|
31
|
+
diff
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def diff_hashes(old, new)
|
37
|
+
(old.keys - new.keys).map { |k| [k, nil] }.to_h.tap do |result|
|
38
|
+
new.each do |k, v|
|
39
|
+
if old.key? k
|
40
|
+
result[k] = diff(old[k], v) unless old[k] == v
|
41
|
+
else
|
42
|
+
result[k] = v
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def apply_hash(old, diff)
|
49
|
+
deep_dup(old).tap do |result|
|
50
|
+
diff.each do |k, v|
|
51
|
+
apply_hash_pair result, k, v
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def apply_hash_pair(hash, key, value)
|
57
|
+
if value.nil?
|
58
|
+
hash.delete key
|
59
|
+
elsif hash.key? key
|
60
|
+
hash[key] = apply(hash[key], value)
|
61
|
+
else
|
62
|
+
hash[key] = value
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -1,10 +1,19 @@
|
|
1
|
+
require 'asciidoctor'
|
2
|
+
|
1
3
|
module RuboCop
|
2
4
|
module Schema
|
3
5
|
class DocumentLoader
|
4
6
|
DOCS_URL_TEMPLATE =
|
5
|
-
-'https://raw.githubusercontent.com/rubocop/%s
|
7
|
+
-'https://raw.githubusercontent.com/rubocop/%s/%s/docs/modules/ROOT/pages/cops%s.adoc'
|
6
8
|
DEFAULTS_URL_TEMPLATE =
|
7
|
-
-'https://raw.githubusercontent.com/rubocop/%s
|
9
|
+
-'https://raw.githubusercontent.com/rubocop/%s/%s/config/default.yml'
|
10
|
+
|
11
|
+
CORRECTIONS = {
|
12
|
+
'rubocop' => {
|
13
|
+
# Fixes a typo that causes Asciidoctor to crash
|
14
|
+
'1.10.0' => '174bda389c2c23cffb17e9d6128f5e6bdbc0e8a0'
|
15
|
+
}
|
16
|
+
}.freeze
|
8
17
|
|
9
18
|
# @param [CachedHTTPClient] http_client
|
10
19
|
def initialize(http_client)
|
@@ -30,11 +39,15 @@ module RuboCop
|
|
30
39
|
private
|
31
40
|
|
32
41
|
def url_for_doc(spec, department)
|
33
|
-
format DOCS_URL_TEMPLATE, spec.name, spec
|
42
|
+
format DOCS_URL_TEMPLATE, spec.name, correct_version(spec), department && "_#{department.to_s.downcase}"
|
34
43
|
end
|
35
44
|
|
36
45
|
def url_for_defaults(spec)
|
37
|
-
format DEFAULTS_URL_TEMPLATE, spec.name, spec
|
46
|
+
format DEFAULTS_URL_TEMPLATE, spec.name, correct_version(spec)
|
47
|
+
end
|
48
|
+
|
49
|
+
def correct_version(spec)
|
50
|
+
CORRECTIONS.dig(spec.name, spec.version) || "v#{spec.version}"
|
38
51
|
end
|
39
52
|
end
|
40
53
|
end
|
@@ -28,16 +28,24 @@ module RuboCop
|
|
28
28
|
end.compact)
|
29
29
|
end
|
30
30
|
|
31
|
+
# @param [Pathname] lockfile
|
31
32
|
def self.from_lockfile(lockfile)
|
32
|
-
new(
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
33
|
+
new(lockfile.readlines.map do |line|
|
34
|
+
next unless line =~ /\A\s+(rubocop(?:-\w+)?) \((\d+(?:\.\d+)+)\)\s*\z/
|
35
|
+
next unless KNOWN_GEMS.include? $1
|
36
|
+
|
37
|
+
Spec.new(name: $1, version: $2)
|
38
|
+
end.compact)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.from_string(string)
|
42
|
+
new(string.split('-').each_slice(2).map do |(name, version)|
|
43
|
+
name = "rubocop-#{name}" unless name == 'rubocop'
|
44
|
+
|
45
|
+
raise ArgumentError, "Unknown gem '#{name}'" unless KNOWN_GEMS.include? name
|
46
|
+
raise ArgumentError, "Invalid version '#{version}'" unless version&.match? /\A\d+(?:\.\d+)+\z/
|
47
|
+
|
48
|
+
Spec.new(name: name, version: version)
|
41
49
|
end)
|
42
50
|
end
|
43
51
|
|
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'asciidoctor'
|
2
|
-
require 'nokogiri'
|
3
|
-
|
4
1
|
require 'rubocop/schema/value_objects'
|
5
2
|
require 'rubocop/schema/cop_schema'
|
6
3
|
require 'rubocop/schema/helpers'
|
@@ -32,6 +29,7 @@ module RuboCop
|
|
32
29
|
|
33
30
|
def generate
|
34
31
|
@specs.each &method(:generate_spec)
|
32
|
+
@props.delete 'AllCops' unless @specs.any? { |s| s.name == 'rubocop' }
|
35
33
|
end
|
36
34
|
|
37
35
|
def generate_spec(spec)
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'uri'
|
3
|
+
|
1
4
|
module RuboCop
|
2
5
|
module Schema
|
3
6
|
module Helpers
|
@@ -46,6 +49,13 @@ module RuboCop
|
|
46
49
|
def strip_html(str)
|
47
50
|
Nokogiri::HTML(str).text
|
48
51
|
end
|
52
|
+
|
53
|
+
def http_get(url)
|
54
|
+
url = URI(url)
|
55
|
+
res = Net::HTTP.get_response(url)
|
56
|
+
res.body = '' unless res.is_a? Net::HTTPOK
|
57
|
+
res.body.force_encoding Encoding::UTF_8
|
58
|
+
end
|
49
59
|
end
|
50
60
|
end
|
51
61
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require 'rubocop/schema/helpers'
|
4
|
+
require 'rubocop/schema/diff'
|
5
|
+
|
6
|
+
module RuboCop
|
7
|
+
module Schema
|
8
|
+
class Repo
|
9
|
+
include Helpers
|
10
|
+
|
11
|
+
TAGS_URL_TEMPLATE = -'https://api.github.com/repos/rubocop/%s/tags'
|
12
|
+
|
13
|
+
def initialize(dir, loader, &event_handler)
|
14
|
+
@dir = Pathname(dir)
|
15
|
+
@loader = loader
|
16
|
+
@event_handler = event_handler
|
17
|
+
@dir.mkpath
|
18
|
+
end
|
19
|
+
|
20
|
+
def build
|
21
|
+
ExtensionSpec::KNOWN_GEMS.each &method(:build_for_gem)
|
22
|
+
Event.dispatch message: "Repo updated: #{@dir}", &@event_handler
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def build_for_gem(name)
|
28
|
+
existing = read(name).map { |h| [h['version'], h['diff']] }.to_h
|
29
|
+
previous = nil
|
30
|
+
body = versions_of(name).map do |version|
|
31
|
+
previous, diff = fetch_for_spec(Spec.new(name: name, version: version), existing, previous)
|
32
|
+
{
|
33
|
+
'version' => version,
|
34
|
+
'diff' => diff
|
35
|
+
}
|
36
|
+
end
|
37
|
+
write name, body.compact
|
38
|
+
end
|
39
|
+
|
40
|
+
def fetch_for_spec(spec, existing, previous)
|
41
|
+
if existing.key? spec.version
|
42
|
+
diff = existing[spec.version]
|
43
|
+
schema = Diff.apply(previous, diff)
|
44
|
+
else
|
45
|
+
schema = build_for_spec(spec)
|
46
|
+
diff = Diff.diff(previous, schema)
|
47
|
+
end
|
48
|
+
[schema, diff]
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_for_spec(spec)
|
52
|
+
Event.dispatch message: "Generating: #{spec}", &@event_handler
|
53
|
+
Generator.new([spec], @loader).schema
|
54
|
+
end
|
55
|
+
|
56
|
+
def write(name, body)
|
57
|
+
path_for(name).binwrite JSON.pretty_generate body
|
58
|
+
end
|
59
|
+
|
60
|
+
def read(name)
|
61
|
+
path = path_for(name)
|
62
|
+
return [] unless path.exist?
|
63
|
+
|
64
|
+
JSON.parse path.read
|
65
|
+
end
|
66
|
+
|
67
|
+
def path_for(name)
|
68
|
+
@dir.join("#{name}.json")
|
69
|
+
end
|
70
|
+
|
71
|
+
def versions_of(name)
|
72
|
+
json = http_get(format(TAGS_URL_TEMPLATE, name))
|
73
|
+
raise "No tags available for #{name}" if json == ''
|
74
|
+
|
75
|
+
JSON.parse(json).reverse.map { |obj| obj['name'].to_s[/(?<=\Av)\d.+/] }.compact
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -2,8 +2,14 @@ module RuboCop
|
|
2
2
|
module Schema
|
3
3
|
CopInfo = Struct.new(:name, :description, :attributes, :supports_autocorrect, :enabled_by_default)
|
4
4
|
Attribute = Struct.new(:name, :type, :default)
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
Event = Struct.new(:type, :message) do
|
7
|
+
def self.dispatch(**kwargs)
|
8
|
+
yield new(**kwargs) if block_given?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
Spec = Struct.new(:name, :version) do
|
7
13
|
def short_name
|
8
14
|
return nil if name == 'rubocop'
|
9
15
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-schema-gen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Neil E. Pearson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|
@@ -60,21 +60,10 @@ executables:
|
|
60
60
|
extensions: []
|
61
61
|
extra_rdoc_files: []
|
62
62
|
files:
|
63
|
-
- ".gitignore"
|
64
|
-
- ".rspec"
|
65
|
-
- ".rubocop.yml"
|
66
|
-
- ".ruby-version"
|
67
|
-
- ".travis.yml"
|
68
|
-
- CODE_OF_CONDUCT.md
|
69
|
-
- Gemfile
|
70
63
|
- LICENSE
|
71
|
-
- LICENSE.txt
|
72
64
|
- README.md
|
73
|
-
- Rakefile
|
74
65
|
- assets/templates/cop_schema.yml
|
75
66
|
- assets/templates/schema.yml
|
76
|
-
- bin/console
|
77
|
-
- bin/setup
|
78
67
|
- exe/rubocop-schema-gen
|
79
68
|
- lib/rubocop/schema.rb
|
80
69
|
- lib/rubocop/schema/ascii_doc/base.rb
|
@@ -87,14 +76,14 @@ files:
|
|
87
76
|
- lib/rubocop/schema/cop_info_merger.rb
|
88
77
|
- lib/rubocop/schema/cop_schema.rb
|
89
78
|
- lib/rubocop/schema/defaults_ripper.rb
|
79
|
+
- lib/rubocop/schema/diff.rb
|
90
80
|
- lib/rubocop/schema/document_loader.rb
|
91
81
|
- lib/rubocop/schema/extension_spec.rb
|
92
82
|
- lib/rubocop/schema/generator.rb
|
93
83
|
- lib/rubocop/schema/helpers.rb
|
84
|
+
- lib/rubocop/schema/repo.rb
|
94
85
|
- lib/rubocop/schema/value_objects.rb
|
95
86
|
- lib/rubocop/schema/version.rb
|
96
|
-
- rubocop-schema.gemspec
|
97
|
-
- rubocop-schema.json
|
98
87
|
homepage: https://github.com/hx/rubocop-schema
|
99
88
|
licenses:
|
100
89
|
- MIT
|
@@ -117,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
106
|
- !ruby/object:Gem::Version
|
118
107
|
version: '0'
|
119
108
|
requirements: []
|
120
|
-
rubygems_version: 3.
|
109
|
+
rubygems_version: 3.0.8
|
121
110
|
signing_key:
|
122
111
|
specification_version: 4
|
123
112
|
summary: Generate JSON schemas for IDE integration with RuboCop
|