graphql-modernize 0.1.0
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 +7 -0
- data/.rubocop.yml +40 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +106 -0
- data/Rakefile +10 -0
- data/docs/migration-guide.md +23 -0
- data/docs/research/changelog-survey.md +68 -0
- data/docs/rules/GQLM101.md +5 -0
- data/docs/rules/GQLM102.md +12 -0
- data/docs/rules/GQLM103.md +5 -0
- data/docs/rules/GQLM104.md +5 -0
- data/docs/rules/GQLM105.md +9 -0
- data/docs/rules/GQLM106.md +7 -0
- data/docs/rules/GQLM107.md +7 -0
- data/docs/rules/GQLM108.md +4 -0
- data/docs/rules/GQLM201.md +5 -0
- data/docs/rules/GQLM202.md +4 -0
- data/docs/rules/GQLM203.md +5 -0
- data/docs/rules/GQLM204.md +5 -0
- data/docs/rules/GQLM205.md +5 -0
- data/docs/rules/GQLM301.md +5 -0
- data/docs/rules/GQLM302.md +5 -0
- data/docs/rules/GQLM303.md +6 -0
- data/docs/rules/GQLM304.md +4 -0
- data/docs/rules/GQLM305.md +8 -0
- data/docs/rules/GQLM306.md +8 -0
- data/docs/rules/GQLM307.md +11 -0
- data/docs/rules/GQLM308.md +5 -0
- data/docs/rules/GQLM309.md +4 -0
- data/docs/rules/GQLM310.md +9 -0
- data/docs/rules/GQLM401.md +6 -0
- data/docs/rules/GQLM402.md +6 -0
- data/docs/rules/GQLM501.md +6 -0
- data/docs/rules/GQLM502.md +5 -0
- data/docs/rules/README.md +35 -0
- data/docs/writing-rules.md +29 -0
- data/exe/graphql-modernize +6 -0
- data/lib/graphql/modernize/application.rb +172 -0
- data/lib/graphql/modernize/class_hierarchy.rb +329 -0
- data/lib/graphql/modernize/cli.rb +175 -0
- data/lib/graphql/modernize/config.rb +163 -0
- data/lib/graphql/modernize/context_builder.rb +78 -0
- data/lib/graphql/modernize/file_finder.rb +45 -0
- data/lib/graphql/modernize/offense.rb +28 -0
- data/lib/graphql/modernize/reporter.rb +103 -0
- data/lib/graphql/modernize/rule_registry.rb +26 -0
- data/lib/graphql/modernize/rules/base.rb +132 -0
- data/lib/graphql/modernize/rules/deprecation.rb +219 -0
- data/lib/graphql/modernize/rules/legacy.rb +301 -0
- data/lib/graphql/modernize/rules/modernize.rb +69 -0
- data/lib/graphql/modernize/rules/relay.rb +74 -0
- data/lib/graphql/modernize/rules/schema_config.rb +38 -0
- data/lib/graphql/modernize/runner.rb +34 -0
- data/lib/graphql/modernize/suppression_index.rb +88 -0
- data/lib/graphql/modernize/version.rb +7 -0
- data/lib/graphql/modernize.rb +30 -0
- metadata +120 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GraphQL
|
|
4
|
+
module Modernize
|
|
5
|
+
module Rules
|
|
6
|
+
class ComplexityCostMode < Base
|
|
7
|
+
rule id: "GQLM501", safety: :manual, summary: "Choose an explicit complexity cost mode",
|
|
8
|
+
since: "2.5.3", docs: "docs/rules/GQLM501.md"
|
|
9
|
+
node_pattern :class_node, "(class_node)"
|
|
10
|
+
|
|
11
|
+
def on_match(node, _captures)
|
|
12
|
+
context = context_for(node)
|
|
13
|
+
return unless inside?(node, :schema)
|
|
14
|
+
|
|
15
|
+
configured = hierarchy.calls_for(context.class_name).any? do |call|
|
|
16
|
+
call.direct && call.name == :complexity_cost_calculation_mode
|
|
17
|
+
end
|
|
18
|
+
configured ||= hierarchy.class_method_defined?(context.class_name, :complexity_cost_calculation_mode_for)
|
|
19
|
+
return if configured
|
|
20
|
+
|
|
21
|
+
add_offense(node.location, message: "Choose a migration policy for `complexity_cost_calculation_mode`")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class DefaultMaxPageSize < Base
|
|
26
|
+
rule id: "GQLM502", safety: :unsafe, summary: "Migrate default_max_page_size to the new page size settings",
|
|
27
|
+
docs: "docs/rules/GQLM502.md"
|
|
28
|
+
node_pattern :call_node, "(call_node receiver: nil name: :default_max_page_size)"
|
|
29
|
+
|
|
30
|
+
def on_match(node, _captures)
|
|
31
|
+
return unless inside?(node, :schema)
|
|
32
|
+
|
|
33
|
+
add_offense(node.location, message: "Review the split into `default_page_size` and `max_page_size`")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GraphQL
|
|
4
|
+
module Modernize
|
|
5
|
+
class Runner
|
|
6
|
+
def initialize(hierarchy:, config: Config.new, explicit_rule_ids: [])
|
|
7
|
+
@hierarchy = hierarchy
|
|
8
|
+
@config = config
|
|
9
|
+
@explicit_rule_ids = explicit_rule_ids.map { |id| id.to_s.upcase }.freeze
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run(source_file, rules = RuleRegistry.all)
|
|
13
|
+
context = ContextBuilder.new(source_file, @hierarchy)
|
|
14
|
+
rewriter = Astel::Rewriter.new(source_file)
|
|
15
|
+
dispatcher = Astel::Dispatcher.new
|
|
16
|
+
suppression = SuppressionIndex.new(source_file, require_reason: @config.require_suppression_reason)
|
|
17
|
+
edit_rules = {}
|
|
18
|
+
instances = rules.select do |rule|
|
|
19
|
+
@explicit_rule_ids.include?(rule.metadata.id) || @config.rule_enabled?(rule.metadata)
|
|
20
|
+
end
|
|
21
|
+
.map do |rule|
|
|
22
|
+
rule.new(context: context, rewriter: rewriter, config: @config, suppression: suppression,
|
|
23
|
+
hierarchy: @hierarchy, edit_rules: edit_rules)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
instances.each do |rule|
|
|
27
|
+
rule.class.node_types.each { |type| dispatcher.on(type) { |node| rule.visit(node) } }
|
|
28
|
+
end
|
|
29
|
+
dispatcher.run(source_file.ast)
|
|
30
|
+
[instances.flat_map(&:offenses) + suppression.unused_offenses, rewriter]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GraphQL
|
|
4
|
+
module Modernize
|
|
5
|
+
class SuppressionIndex
|
|
6
|
+
Directive = Struct.new(:action, :line, :rules, :location, :inline, :valid, :used, keyword_init: true)
|
|
7
|
+
PATTERN = /graphql-modernize:(?<action>disable-file|disable|enable)\b(?<body>.*)/
|
|
8
|
+
|
|
9
|
+
def initialize(source_file, require_reason: false)
|
|
10
|
+
@source_file = source_file
|
|
11
|
+
first_statement = source_file.ast.statements.body.first
|
|
12
|
+
@directives = source_file.comments.filter_map do |comment|
|
|
13
|
+
match = comment.location.slice.match(PATTERN)
|
|
14
|
+
next unless match
|
|
15
|
+
|
|
16
|
+
reason = match[:body].split("--", 2)[1]
|
|
17
|
+
next if require_reason && match[:action] != "enable" && reason.to_s.strip.empty?
|
|
18
|
+
|
|
19
|
+
rules_text = match[:body].split("--", 2).first.strip
|
|
20
|
+
ids = rules_text.split(/[,\s]+/)
|
|
21
|
+
valid_rules = rules_text.empty? || ids.all? { |id| id.match?(/\AGQLM\d{3}\z/) }
|
|
22
|
+
line_start = source_file.line_start(comment.location.start_offset)
|
|
23
|
+
prefix = source_file.source.byteslice(line_start, comment.location.start_offset - line_start)
|
|
24
|
+
inline = !prefix.strip.empty?
|
|
25
|
+
valid_file_position = match[:action] != "disable-file" || (!inline &&
|
|
26
|
+
(!first_statement || comment.location.start_offset < first_statement.location.start_offset))
|
|
27
|
+
Directive.new(action: match[:action].tr("-", "_").to_sym, line: comment.location.start_line,
|
|
28
|
+
rules: rules_text.empty? ? nil : ids.freeze, location: comment.location,
|
|
29
|
+
inline: inline, valid: valid_rules && valid_file_position, used: false)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def suppressed?(rule_id, location)
|
|
34
|
+
directives = matching_directives(rule_id, location.start_line)
|
|
35
|
+
file_directive = directives.find { |directive| directive.action == :disable_file }
|
|
36
|
+
if file_directive
|
|
37
|
+
file_directive.used = true
|
|
38
|
+
return true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
inline = directives.find do |directive|
|
|
42
|
+
directive.inline && directive.action == :disable &&
|
|
43
|
+
directive.line == location.start_line
|
|
44
|
+
end
|
|
45
|
+
if inline
|
|
46
|
+
inline.used = true
|
|
47
|
+
return true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
active_directive = nil
|
|
51
|
+
directives.reject(&:inline).each do |directive|
|
|
52
|
+
active_directive = directive.action == :disable ? directive : nil
|
|
53
|
+
end
|
|
54
|
+
if active_directive
|
|
55
|
+
active_directive.used = true
|
|
56
|
+
closing = @directives.find do |directive|
|
|
57
|
+
directive.valid && !directive.inline && directive.action == :enable &&
|
|
58
|
+
directive.line > active_directive.line && matches_rule?(directive, rule_id)
|
|
59
|
+
end
|
|
60
|
+
closing.used = true if closing
|
|
61
|
+
end
|
|
62
|
+
!active_directive.nil?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def unused_offenses
|
|
66
|
+
@directives.reject(&:used).map do |directive|
|
|
67
|
+
Offense.new(rule_id: "GQLM000", location: directive.location,
|
|
68
|
+
message: "Unused suppression directive", safety: :manual,
|
|
69
|
+
path: @source_file.path, correctable: false)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def matching_directives(rule_id, line)
|
|
76
|
+
@directives.select do |directive|
|
|
77
|
+
next false unless directive.valid && matches_rule?(directive, rule_id)
|
|
78
|
+
|
|
79
|
+
directive.action == :disable_file || directive.line <= line
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def matches_rule?(directive, rule_id)
|
|
84
|
+
directive.rules.nil? || directive.rules.include?(rule_id)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "modernize/version"
|
|
4
|
+
require "astel"
|
|
5
|
+
require "astel/refactor"
|
|
6
|
+
require "astel/diff"
|
|
7
|
+
|
|
8
|
+
module GraphQL
|
|
9
|
+
module Modernize
|
|
10
|
+
class Error < StandardError; end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
require_relative "modernize/config"
|
|
15
|
+
require_relative "modernize/file_finder"
|
|
16
|
+
require_relative "modernize/class_hierarchy"
|
|
17
|
+
require_relative "modernize/context_builder"
|
|
18
|
+
require_relative "modernize/offense"
|
|
19
|
+
require_relative "modernize/suppression_index"
|
|
20
|
+
require_relative "modernize/rule_registry"
|
|
21
|
+
require_relative "modernize/rules/base"
|
|
22
|
+
require_relative "modernize/runner"
|
|
23
|
+
require_relative "modernize/application"
|
|
24
|
+
require_relative "modernize/reporter"
|
|
25
|
+
require_relative "modernize/cli"
|
|
26
|
+
require_relative "modernize/rules/legacy"
|
|
27
|
+
require_relative "modernize/rules/relay"
|
|
28
|
+
require_relative "modernize/rules/deprecation"
|
|
29
|
+
require_relative "modernize/rules/modernize"
|
|
30
|
+
require_relative "modernize/rules/schema_config"
|
metadata
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: graphql-modernize
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Yudai Takada
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: astel
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.2'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '1.0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '0.2'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '1.0'
|
|
32
|
+
description: A Prism-based codemod for migrating deprecated graphql-ruby APIs.
|
|
33
|
+
email:
|
|
34
|
+
- t.yudai92@gmail.com
|
|
35
|
+
executables:
|
|
36
|
+
- graphql-modernize
|
|
37
|
+
extensions: []
|
|
38
|
+
extra_rdoc_files: []
|
|
39
|
+
files:
|
|
40
|
+
- ".rubocop.yml"
|
|
41
|
+
- CHANGELOG.md
|
|
42
|
+
- LICENSE.txt
|
|
43
|
+
- README.md
|
|
44
|
+
- Rakefile
|
|
45
|
+
- docs/migration-guide.md
|
|
46
|
+
- docs/research/changelog-survey.md
|
|
47
|
+
- docs/rules/GQLM101.md
|
|
48
|
+
- docs/rules/GQLM102.md
|
|
49
|
+
- docs/rules/GQLM103.md
|
|
50
|
+
- docs/rules/GQLM104.md
|
|
51
|
+
- docs/rules/GQLM105.md
|
|
52
|
+
- docs/rules/GQLM106.md
|
|
53
|
+
- docs/rules/GQLM107.md
|
|
54
|
+
- docs/rules/GQLM108.md
|
|
55
|
+
- docs/rules/GQLM201.md
|
|
56
|
+
- docs/rules/GQLM202.md
|
|
57
|
+
- docs/rules/GQLM203.md
|
|
58
|
+
- docs/rules/GQLM204.md
|
|
59
|
+
- docs/rules/GQLM205.md
|
|
60
|
+
- docs/rules/GQLM301.md
|
|
61
|
+
- docs/rules/GQLM302.md
|
|
62
|
+
- docs/rules/GQLM303.md
|
|
63
|
+
- docs/rules/GQLM304.md
|
|
64
|
+
- docs/rules/GQLM305.md
|
|
65
|
+
- docs/rules/GQLM306.md
|
|
66
|
+
- docs/rules/GQLM307.md
|
|
67
|
+
- docs/rules/GQLM308.md
|
|
68
|
+
- docs/rules/GQLM309.md
|
|
69
|
+
- docs/rules/GQLM310.md
|
|
70
|
+
- docs/rules/GQLM401.md
|
|
71
|
+
- docs/rules/GQLM402.md
|
|
72
|
+
- docs/rules/GQLM501.md
|
|
73
|
+
- docs/rules/GQLM502.md
|
|
74
|
+
- docs/rules/README.md
|
|
75
|
+
- docs/writing-rules.md
|
|
76
|
+
- exe/graphql-modernize
|
|
77
|
+
- lib/graphql/modernize.rb
|
|
78
|
+
- lib/graphql/modernize/application.rb
|
|
79
|
+
- lib/graphql/modernize/class_hierarchy.rb
|
|
80
|
+
- lib/graphql/modernize/cli.rb
|
|
81
|
+
- lib/graphql/modernize/config.rb
|
|
82
|
+
- lib/graphql/modernize/context_builder.rb
|
|
83
|
+
- lib/graphql/modernize/file_finder.rb
|
|
84
|
+
- lib/graphql/modernize/offense.rb
|
|
85
|
+
- lib/graphql/modernize/reporter.rb
|
|
86
|
+
- lib/graphql/modernize/rule_registry.rb
|
|
87
|
+
- lib/graphql/modernize/rules/base.rb
|
|
88
|
+
- lib/graphql/modernize/rules/deprecation.rb
|
|
89
|
+
- lib/graphql/modernize/rules/legacy.rb
|
|
90
|
+
- lib/graphql/modernize/rules/modernize.rb
|
|
91
|
+
- lib/graphql/modernize/rules/relay.rb
|
|
92
|
+
- lib/graphql/modernize/rules/schema_config.rb
|
|
93
|
+
- lib/graphql/modernize/runner.rb
|
|
94
|
+
- lib/graphql/modernize/suppression_index.rb
|
|
95
|
+
- lib/graphql/modernize/version.rb
|
|
96
|
+
homepage: https://github.com/ydah/graphql-modernize
|
|
97
|
+
licenses:
|
|
98
|
+
- MIT
|
|
99
|
+
metadata:
|
|
100
|
+
rubygems_mfa_required: 'true'
|
|
101
|
+
homepage_uri: https://github.com/ydah/graphql-modernize
|
|
102
|
+
source_code_uri: https://github.com/ydah/graphql-modernize
|
|
103
|
+
rdoc_options: []
|
|
104
|
+
require_paths:
|
|
105
|
+
- lib
|
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 3.3.0
|
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - ">="
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: '0'
|
|
116
|
+
requirements: []
|
|
117
|
+
rubygems_version: 4.0.19
|
|
118
|
+
specification_version: 4
|
|
119
|
+
summary: Modernize deprecated graphql-ruby APIs
|
|
120
|
+
test_files: []
|