solargraph 0.40.1 → 0.40.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e02cce6c25457bb0284d221d1a9bef97730b7d7be18129cdee0dcfa1aae9c02b
4
- data.tar.gz: 5143879ae0f89fd7ca608646cfe96fccc1e6c15afd7940fc7948dff358f286f3
3
+ metadata.gz: eff7d664014ae6d25990957afb4328baafe88ff76ef892db8b3d50791860845e
4
+ data.tar.gz: 8038c884a63ce269f1a0faaf635e4c295fadd61c456ba2665c84a17b4f03a031
5
5
  SHA512:
6
- metadata.gz: 7c868fd6c6bb344f532eeee02ef06f9b80df086b51a49e408f5c04961303524f36d6b27cfae37b200a92bf0b65e15a3e68be029aad66bf912dd1aa73b1f48714
7
- data.tar.gz: 6a9cbcd839ab51d1c71d83a30a73464f337faffda715059e91de57a3519783793574901f23d738c83a49d1116d41268c4992fa304c08d8892e394e12bb5011c8
6
+ metadata.gz: a7b95e2ba342b191642a1d5ea228243a60b9211f6c05cab2acf09ddcaab3efb25cef488ca910964e0ac1c32edacc2f0ced4eef09fa819b03d2919af4ac734ca7
7
+ data.tar.gz: 6990c07591d43fdb583484c00fc5221d228850fa75e12b5cd2632413a21c1984f634ce2655371d9be7016a035e23fe622469418779bf3285f03a087a38c394ae
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## 0.40.4 - March 3, 2021
2
+ - Fix optarg and blockarg ordering
3
+ - Override specialization for #initialize
4
+ - Find definitions with cursor after double colon
5
+
6
+ ## 0.40.3 - February 7, 2021
7
+ - Simplify and allow to configure rubocop formatter (#403)
8
+ - Type checker shows tag in param type errors (#398)
9
+ - Handle bare private_constant (#408)
10
+ - Type checker handles splatted variables (#396)
11
+
12
+ ## 0.40.2 - January 18, 2021
13
+ - Type checker ignores splatted calls in arity (#396)
14
+ - Allow Parser 3.0 (#400)
15
+
1
16
  ## 0.40.1 - December 28, 2020
2
17
  - Use temp directory for RuboCop formatting (#397)
3
18
  - NodeMethods reads splatted hashes (#396)
@@ -238,11 +238,16 @@ module Solargraph
238
238
  pins_by_class(Pin::Reference::Override).each do |ovr|
239
239
  pin = get_path_pins(ovr.name).first
240
240
  next if pin.nil?
241
+ new_pin = if pin.path.end_with?('#initialize')
242
+ get_path_pins(pin.path.sub(/#initialize/, '.new')).first
243
+ end
241
244
  (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
242
245
  pin.docstring.delete_tags tag.to_sym
246
+ new_pin.docstring.delete_tags tag.to_sym if new_pin
243
247
  end
244
248
  ovr.tags.each do |tag|
245
249
  pin.docstring.add_tag(tag)
250
+ new_pin.docstring.add_tag(tag) if new_pin
246
251
  end
247
252
  end
248
253
  end
@@ -13,32 +13,13 @@ module Solargraph
13
13
  # @param code [String]
14
14
  # @return [Array(Array<String>, Array<String>)]
15
15
  def generate_options filename, code
16
- args = ['-f', 'j']
17
- rubocop_file = find_rubocop_file(filename)
18
- args.push('-c', fix_drive_letter(rubocop_file)) unless rubocop_file.nil?
19
- args.push filename
16
+ args = ['-f', 'j', filename]
20
17
  base_options = RuboCop::Options.new
21
18
  options, paths = base_options.parse(args)
22
19
  options[:stdin] = code
23
20
  [options, paths]
24
21
  end
25
22
 
26
- # Find a RuboCop configuration file in a file's directory tree.
27
- #
28
- # @param filename [String]
29
- # @return [String, nil]
30
- def find_rubocop_file filename
31
- return nil unless File.exist?(filename)
32
- filename = File.realpath(filename)
33
- dir = File.dirname(filename)
34
- until File.dirname(dir) == dir
35
- here = File.join(dir, '.rubocop.yml')
36
- return here if File.exist?(here)
37
- dir = File.dirname(dir)
38
- end
39
- nil
40
- end
41
-
42
23
  # RuboCop internally uses capitalized drive letters for Windows paths,
43
24
  # so we need to convert the paths provided to the command.
44
25
  #
@@ -494,6 +494,11 @@ module Solargraph
494
494
  library.read_text(filename)
495
495
  end
496
496
 
497
+ def formatter_config uri
498
+ library = library_for(uri)
499
+ library.workspace.config.formatter
500
+ end
501
+
497
502
  # @param uri [String]
498
503
  # @param line [Integer]
499
504
  # @param column [Integer]
@@ -11,29 +11,58 @@ module Solargraph
11
11
  class Formatting < Base
12
12
  include Solargraph::Diagnostics::RubocopHelpers
13
13
 
14
+ class BlankRubocopFormatter < ::RuboCop::Formatter::BaseFormatter; end
15
+
14
16
  def process
15
- filename = uri_to_file(params['textDocument']['uri'])
16
- Dir.mktmpdir do |tempdir|
17
- tempfile = File.join(tempdir, File.basename(filename))
18
- rubocop_file = Diagnostics::RubocopHelpers.find_rubocop_file(filename)
19
- original = host.read_text(params['textDocument']['uri'])
20
- File.write tempfile, original
21
- begin
22
- args = ['-a', '-f', 'fi', tempfile]
23
- args.unshift('-c', fix_drive_letter(rubocop_file)) unless rubocop_file.nil?
24
- options, paths = RuboCop::Options.new.parse(args)
25
- store = RuboCop::ConfigStore.new
26
- redirect_stdout { RuboCop::Runner.new(options, store).run(paths) }
27
- result = File.read(tempfile)
28
- format original, result
29
- rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
30
- set_error(Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}")
31
- end
17
+ file_uri = params['textDocument']['uri']
18
+ config = config_for(file_uri)
19
+ original = host.read_text(file_uri)
20
+ args = cli_args(file_uri, config)
21
+
22
+ options, paths = RuboCop::Options.new.parse(args)
23
+ options[:stdin] = original
24
+ redirect_stdout do
25
+ RuboCop::Runner.new(options, RuboCop::ConfigStore.new).run(paths)
32
26
  end
27
+ result = options[:stdin]
28
+
29
+ format original, result
30
+ rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
31
+ set_error(Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}")
33
32
  end
34
33
 
35
34
  private
36
35
 
36
+ def config_for(file_uri)
37
+ conf = host.formatter_config(file_uri)
38
+ return {} unless conf.is_a?(Hash)
39
+
40
+ conf['rubocop'] || {}
41
+ end
42
+
43
+ def cli_args file, config
44
+ args = [
45
+ config['cops'] == 'all' ? '--auto-correct-all' : '--auto-correct',
46
+ '--cache', 'false',
47
+ '--format', 'Solargraph::LanguageServer::Message::' \
48
+ 'TextDocument::Formatting::BlankRubocopFormatter',
49
+ ]
50
+
51
+ ['except', 'only'].each do |arg|
52
+ cops = cop_list(config[arg])
53
+ args += ["--#{arg}", cops] if cops
54
+ end
55
+
56
+ args += config['extra_args'] if config['extra_args']
57
+ args + [file]
58
+ end
59
+
60
+ def cop_list(value)
61
+ value = value.join(',') if value.respond_to?(:join)
62
+ return nil if value == '' || !value.is_a?(String)
63
+ value
64
+ end
65
+
37
66
  # @param original [String]
38
67
  # @param result [String]
39
68
  # @return [void]
@@ -123,6 +123,10 @@ module Solargraph
123
123
  Parser.is_ast_node?(node.children[0]) && node.children[0].type == :kwsplat
124
124
  end
125
125
 
126
+ def splatted_call? node
127
+ Parser.is_ast_node?(node.children[0]) && node.children[0].type == :kwsplat && node.children[0].children[0].type != :hash
128
+ end
129
+
126
130
  # @todo Temporarily here for testing. Move to Solargraph::Parser.
127
131
  def call_nodes_from node
128
132
  return [] unless node.is_a?(::Parser::AST::Node)
@@ -106,11 +106,18 @@ module Solargraph
106
106
  end
107
107
 
108
108
  def splatted_hash? node
109
+ splatted_node?(node) && node.children[0].children[1].type == :HASH
110
+ end
111
+
112
+ def splatted_node? node
109
113
  node?(node.children[0]) &&
110
114
  [:ARRAY, :LIST].include?(node.children[0].type) &&
111
115
  node.children[0].children[0].nil? &&
112
- node?(node.children[0].children[1]) &&
113
- node.children[0].children[1].type == :HASH
116
+ node?(node.children[0].children[1])
117
+ end
118
+
119
+ def splatted_call? node
120
+ splatted_node?(node) && node.children[0].children[1].type != :HASH
114
121
  end
115
122
 
116
123
  def node? node
@@ -55,19 +55,19 @@ module Solargraph
55
55
  )
56
56
  region.closure.parameters.push locals.last
57
57
  end
58
- if node.children.last
59
- locals.push Solargraph::Pin::Parameter.new(
60
- location: region.closure.location,
61
- closure: region.closure,
62
- comments: comments_for(node),
63
- name: node.children.last.to_s,
64
- presence: region.closure.location.range,
65
- decl: :blockarg
66
- )
67
- region.closure.parameters.push locals.last
68
- end
69
58
  end
70
59
  process_children
60
+ if node.children.last
61
+ locals.push Solargraph::Pin::Parameter.new(
62
+ location: region.closure.location,
63
+ closure: region.closure,
64
+ comments: comments_for(node),
65
+ name: node.children.last.to_s,
66
+ presence: region.closure.location.range,
67
+ decl: :blockarg
68
+ )
69
+ region.closure.parameters.push locals.last
70
+ end
71
71
  end
72
72
 
73
73
  private
@@ -16,12 +16,7 @@ module Solargraph
16
16
  presence: region.closure.location.range,
17
17
  decl: :optarg
18
18
  )
19
- idx = region.closure.parameters.find_index { |par| par.decl != :arg }
20
- if idx
21
- region.closure.parameters.insert idx, locals.last
22
- else
23
- region.closure.parameters.push locals.last
24
- end
19
+ region.closure.parameters.push locals.last
25
20
  node.children[1] && NodeProcessor.process(node.children[1], region, pins, locals)
26
21
  end
27
22
  end
@@ -226,7 +226,7 @@ module Solargraph
226
226
 
227
227
  # @return [void]
228
228
  def process_private_constant
229
- # @todo Bare `private_constant` causes an error
229
+ return unless Parser.is_ast_node?(node.children.last)
230
230
  node.children.last.children[0..-2].each do |child|
231
231
  if [:LIT, :STR].include?(child.type)
232
232
  cn = child.children[0].to_s
@@ -175,7 +175,7 @@ module Solargraph
175
175
  synced
176
176
  end
177
177
 
178
- # @param position [Position]
178
+ # @param position [Position, Array(Integer, Integer)]
179
179
  # @return [Source::Cursor]
180
180
  def cursor_at position
181
181
  Cursor.new(self, position)
@@ -64,7 +64,7 @@ module Solargraph
64
64
  elsif end_of_phrase.strip == '::'
65
65
  chain.links.push Chain::UNDEFINED_CONSTANT
66
66
  end
67
- elsif chain.links.last.is_a?(Source::Chain::Constant) && end_of_phrase.strip == '::'
67
+ elsif chain.links.last.is_a?(Source::Chain::Constant) && end_of_phrase.strip == '::' && !source.code[Position.to_offset(source.code, position)].match?(/[a-z]/i)
68
68
  chain.links.push Source::Chain::UNDEFINED_CONSTANT
69
69
  end
70
70
  chain
@@ -95,7 +95,7 @@ module Solargraph
95
95
  result.push Problem.new(pin.location, "Untyped method #{pin.path} could not be inferred")
96
96
  end
97
97
  elsif rules.validate_tags?
98
- unless pin.node.nil? || declared.void? || macro_pin?(pin) || abstract?(pin)
98
+ unless pin.node.nil? || declared.void? || virtual_pin?(pin) || abstract?(pin)
99
99
  inferred = pin.probe(api_map).self_to(pin.full_context.namespace)
100
100
  if inferred.undefined?
101
101
  unless rules.ignore_all_undefined? || external?(pin)
@@ -111,7 +111,7 @@ module Solargraph
111
111
  result
112
112
  end
113
113
 
114
- def macro_pin? pin
114
+ def virtual_pin? pin
115
115
  pin.location && source_map.source.comment_at?(pin.location.range.ending)
116
116
  end
117
117
 
@@ -129,10 +129,10 @@ module Solargraph
129
129
  end
130
130
  end
131
131
  end
132
- params.each_pair do |name, tag|
133
- type = tag.qualify(api_map, pin.full_context.namespace)
132
+ params.each_pair do |name, data|
133
+ type = data[:qualified]
134
134
  if type.undefined?
135
- result.push Problem.new(pin.location, "Unresolved type #{tag} for #{name} param on #{pin.path}", pin: pin)
135
+ result.push Problem.new(pin.location, "Unresolved type #{data[:tagged]} for #{name} param on #{pin.path}", pin: pin)
136
136
  end
137
137
  end
138
138
  result
@@ -266,12 +266,12 @@ module Solargraph
266
266
  result.concat kwarg_problems_for argchain, api_map, block_pin, locals, location, pin, params, idx
267
267
  break
268
268
  else
269
- ptype = params[par.name]
269
+ ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
270
270
  if ptype.nil?
271
271
  # @todo Some level (strong, I guess) should require the param here
272
272
  else
273
273
  argtype = argchain.infer(api_map, block_pin, locals)
274
- if argtype.defined? && ptype && !any_types_match?(api_map, ptype, argtype)
274
+ if argtype.defined? && ptype.defined? && !any_types_match?(api_map, ptype, argtype)
275
275
  result.push Problem.new(location, "Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
276
276
  end
277
277
  end
@@ -299,19 +299,19 @@ module Solargraph
299
299
  result.concat kwrestarg_problems_for(api_map, block_pin, locals, location, pin, params, kwargs)
300
300
  else
301
301
  if argchain
302
- ptype = params[par.name]
303
- if ptype.nil?
302
+ data = params[par.name]
303
+ if data.nil?
304
304
  # @todo Some level (strong, I guess) should require the param here
305
305
  else
306
+ ptype = data[:qualified]
307
+ next if ptype.undefined?
306
308
  argtype = argchain.infer(api_map, block_pin, locals)
307
309
  if argtype.defined? && ptype && !any_types_match?(api_map, ptype, argtype)
308
310
  result.push Problem.new(location, "Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
309
311
  end
310
312
  end
311
- else
312
- if par.decl == :kwarg
313
- result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
314
- end
313
+ elsif par.decl == :kwarg
314
+ result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
315
315
  end
316
316
  end
317
317
  end
@@ -321,31 +321,34 @@ module Solargraph
321
321
  def kwrestarg_problems_for(api_map, block_pin, locals, location, pin, params, kwargs)
322
322
  result = []
323
323
  kwargs.each_pair do |pname, argchain|
324
- ptype = params[pname.to_s]
325
- if ptype.nil?
326
- # Probably nothing to do here. All of these args should be optional.
327
- else
328
- argtype = argchain.infer(api_map, block_pin, locals)
329
- if argtype.defined? && ptype && !any_types_match?(api_map, ptype, argtype)
330
- result.push Problem.new(location, "Wrong argument type for #{pin.path}: #{pname} expected #{ptype}, received #{argtype}")
331
- end
324
+ next unless params.key?(pname.to_s)
325
+ ptype = params[pname.to_s][:qualified]
326
+ argtype = argchain.infer(api_map, block_pin, locals)
327
+ if argtype.defined? && ptype && !any_types_match?(api_map, ptype, argtype)
328
+ result.push Problem.new(location, "Wrong argument type for #{pin.path}: #{pname} expected #{ptype}, received #{argtype}")
332
329
  end
333
330
  end
334
331
  result
335
332
  end
336
333
 
334
+ # @param [Pin::Method]
335
+ # @return [Hash]
337
336
  def param_hash(pin)
338
337
  tags = pin.docstring.tags(:param)
339
338
  return {} if tags.empty?
340
339
  result = {}
341
340
  tags.each do |tag|
342
341
  next if tag.types.nil? || tag.types.empty?
343
- result[tag.name.to_s] = Solargraph::ComplexType.try_parse(*tag.types).qualify(api_map, pin.full_context.namespace)
342
+ result[tag.name.to_s] = {
343
+ tagged: tag.types.join(', '),
344
+ qualified: Solargraph::ComplexType.try_parse(*tag.types).qualify(api_map, pin.full_context.namespace)
345
+ }
344
346
  end
345
347
  result
346
348
  end
347
349
 
348
350
  # @param [Array<Pin::Method>]
351
+ # @return [Hash]
349
352
  def first_param_hash(pins)
350
353
  pins.each do |pin|
351
354
  result = param_hash(pin)
@@ -413,24 +416,28 @@ module Solargraph
413
416
  end
414
417
  settled_kwargs = 0
415
418
  unless unchecked.empty?
416
- kwargs = convert_hash(unchecked.last.node)
417
- if pin.parameters.any? { |param| [:kwarg, :kwoptarg].include?(param.decl) || param.kwrestarg? }
418
- if kwargs.empty?
419
- add_params += 1
420
- else
421
- unchecked.pop
422
- pin.parameters.each do |param|
423
- next unless param.keyword?
424
- if kwargs.key?(param.name.to_sym)
425
- kwargs.delete param.name.to_sym
426
- settled_kwargs += 1
427
- elsif param.decl == :kwarg
428
- return [Problem.new(location, "Missing keyword argument #{param.name} to #{pin.path}")]
419
+ if Parser.is_ast_node?(unchecked.last.node) && splatted_call?(unchecked.last.node)
420
+ settled_kwargs = pin.parameters.count(&:keyword?)
421
+ else
422
+ kwargs = convert_hash(unchecked.last.node)
423
+ if pin.parameters.any? { |param| [:kwarg, :kwoptarg].include?(param.decl) || param.kwrestarg? }
424
+ if kwargs.empty?
425
+ add_params += 1
426
+ else
427
+ unchecked.pop
428
+ pin.parameters.each do |param|
429
+ next unless param.keyword?
430
+ if kwargs.key?(param.name.to_sym)
431
+ kwargs.delete param.name.to_sym
432
+ settled_kwargs += 1
433
+ elsif param.decl == :kwarg
434
+ return [Problem.new(location, "Missing keyword argument #{param.name} to #{pin.path}")]
435
+ end
436
+ end
437
+ kwargs.clear if pin.parameters.any?(&:kwrestarg?)
438
+ unless kwargs.empty?
439
+ return [Problem.new(location, "Unrecognized keyword argument #{kwargs.keys.first} to #{pin.path}")]
429
440
  end
430
- end
431
- kwargs.clear if pin.parameters.any?(&:kwrestarg?)
432
- unless kwargs.empty?
433
- return [Problem.new(location, "Unrecognized keyword argument #{kwargs.keys.first} to #{pin.path}")]
434
441
  end
435
442
  end
436
443
  end
@@ -443,6 +450,9 @@ module Solargraph
443
450
  if unchecked.length == req + opt + 1 && unchecked.last.links.last.is_a?(Source::Chain::BlockVariable)
444
451
  return []
445
452
  end
453
+ if req + add_params + 1 == unchecked.length && splatted_call?(unchecked.last.node) && (pin.parameters.map(&:decl) & [:kwarg, :kwoptarg, :kwrestarg]).any?
454
+ return []
455
+ end
446
456
  return [Problem.new(location, "Too many arguments to #{pin.path}")]
447
457
  elsif unchecked.length < req - settled_kwargs && (arguments.empty? || !arguments.last.splat?)
448
458
  return [Problem.new(location, "Not enough arguments to #{pin.path}")]
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Solargraph
2
4
  class TypeChecker
5
+ # Helper methods for performing type checks
6
+ #
3
7
  module Checks
4
8
  module_function
5
9
 
@@ -62,7 +66,7 @@ module Solargraph
62
66
  # @param inferred [ComplexType]
63
67
  # @return [Boolean]
64
68
  def duck_types_match? api_map, expected, inferred
65
- raise ArgumentError, "Expected type must be duck type" unless expected.duck_type?
69
+ raise ArgumentError, 'Expected type must be duck type' unless expected.duck_type?
66
70
  expected.each do |exp|
67
71
  next unless exp.duck_type?
68
72
  quack = exp.to_s[1..-1]
@@ -1,12 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Solargraph
2
4
  class TypeChecker
5
+ # Definitions of type checking rules to be performed at various levels
6
+ #
3
7
  class Rules
4
8
  LEVELS = {
5
9
  normal: 0,
6
10
  typed: 1,
7
11
  strict: 2,
8
12
  strong: 3
9
- }
13
+ }.freeze
10
14
 
11
15
  # @return [Symbol]
12
16
  attr_reader :level
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.40.1'
4
+ VERSION = '0.40.4'
5
5
  end
@@ -85,6 +85,13 @@ module Solargraph
85
85
  raw_data['reporters']
86
86
  end
87
87
 
88
+ # A hash of options supported by the formatter
89
+ #
90
+ # @return [Hash]
91
+ def formatter
92
+ raw_data['formatter']
93
+ end
94
+
88
95
  # An array of plugins to require.
89
96
  #
90
97
  # @return [Array<String>]
@@ -144,6 +151,14 @@ module Solargraph
144
151
  'require' => [],
145
152
  'domains' => [],
146
153
  'reporters' => %w[rubocop require_not_found],
154
+ 'formatter' => {
155
+ 'rubocop' => {
156
+ 'cops' => 'safe',
157
+ 'except' => [],
158
+ 'only' => [],
159
+ 'extra_args' =>[]
160
+ }
161
+ },
147
162
  'require_paths' => [],
148
163
  'plugins' => [],
149
164
  'max_files' => MAX_FILES
data/solargraph.gemspec CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.add_runtime_dependency 'jaro_winkler', '~> 1.5'
27
27
  s.add_runtime_dependency 'kramdown', '~> 2.3'
28
28
  s.add_runtime_dependency 'kramdown-parser-gfm', '~> 1.1'
29
- s.add_runtime_dependency 'parser', '~> 2.3'
29
+ s.add_runtime_dependency 'parser', '~> 3.0'
30
30
  s.add_runtime_dependency 'reverse_markdown', '>= 1.0.5', '< 3'
31
31
  s.add_runtime_dependency 'rubocop', '>= 0.52'
32
32
  s.add_runtime_dependency 'thor', '~> 1.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.40.1
4
+ version: 0.40.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-28 00:00:00.000000000 Z
11
+ date: 2021-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backport
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '2.3'
117
+ version: '3.0'
118
118
  type: :runtime
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: '2.3'
124
+ version: '3.0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: reverse_markdown
127
127
  requirement: !ruby/object:Gem::Requirement