solargraph-rails 1.1.2 → 1.2.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.
@@ -9,11 +9,35 @@ module Solargraph
9
9
  filename.include?('app/models')
10
10
  end
11
11
 
12
+ # @param source_map [Solargraph::SourceMap]
13
+ # @param ns [Solargraph::Pin::Namespace]
12
14
  def process(source_map, ns)
13
15
  return [] unless self.class.valid_filename?(source_map.filename)
14
16
 
15
- walker = Walker.from_source(source_map.source)
16
17
  pins = []
18
+ abstract = false
19
+
20
+ # ActiveRecord defines a hidden subclass of ActiveRecord::Relation for
21
+ # each model class that inherits from ActiveRecord::Base.
22
+ pins << relation = Solargraph::Pin::Namespace.new(
23
+ name: 'ActiveRecord_Relation',
24
+ type: :class,
25
+ visibility: :private,
26
+ closure: ns,
27
+ )
28
+ pins << Solargraph::Pin::Reference::Superclass.new(
29
+ name: "ActiveRecord::Relation",
30
+ closure: relation,
31
+ )
32
+
33
+ pins << Solargraph::Pin::Method.new(
34
+ name: 'model',
35
+ scope: :instance,
36
+ closure: relation,
37
+ comments: "@return [Class<#{ns.name}>]"
38
+ )
39
+
40
+ walker = Walker.from_source(source_map.source)
17
41
 
18
42
  walker.on :send, [nil, :belongs_to] do |ast|
19
43
  pins << singular_association(ns, ast)
@@ -31,75 +55,272 @@ module Solargraph
31
55
  pins << plural_association(ns, ast)
32
56
  end
33
57
 
58
+ walker.on :send, [:self, :abstract_class=, :true] do |ast|
59
+ abstract = true
60
+ end
61
+
34
62
  walker.on :send, [nil, :scope] do |ast|
35
63
  next if ast.children[2].nil?
36
64
  name = ast.children[2].children.last
37
65
 
38
- method_pin =
39
- Util.build_public_method(
40
- ns,
41
- name.to_s,
42
- types: ns.return_type.map(&:tag),
43
- scope: :class,
44
- location: Util.build_location(ast, ns.filename)
45
- )
66
+ parameters = []
46
67
 
47
68
  if ast.children.last.type == :block
48
69
  location = ast.children.last.location
49
- block_pin =
50
- source_map.locate_block_pin(location.line, location.column)
51
- method_pin.parameters.concat(block_pin.parameters.clone)
70
+ block_pin = source_map.locate_block_pin(location.line, location.column)
71
+ parameters.concat(block_pin.parameters.clone)
72
+ block_pin.instance_variable_set(:@binder, ComplexType.parse(relation.path))
52
73
  end
53
- pins << method_pin
74
+
75
+ location = Util.build_location(ast, ns.filename)
76
+ # define scopes as a class methods on the model, and instance methods
77
+ # on the hidden relation class
78
+ pins << Util.build_public_method(
79
+ ns,
80
+ name.to_s,
81
+ scope: :class,
82
+ parameters: parameters,
83
+ types: [relation_type(ns.name)],
84
+ location: location
85
+ )
86
+ pins << Util.build_public_method(
87
+ relation,
88
+ name.to_s,
89
+ scope: :instance,
90
+ parameters: parameters,
91
+ types: [relation_type(ns.name)],
92
+ location: location
93
+ )
54
94
  end
55
95
 
56
96
  walker.walk
57
- if pins.any?
58
- Solargraph.logger.debug(
59
- "[Rails][Model] added #{pins.map(&:name)} to #{ns.path}"
60
- )
97
+
98
+ # Class methods on the model are exposed as *instance* methods on the
99
+ # hidden ActiveRecord_Relation class.
100
+ #
101
+ # Uses DelegatedMethod pins (instead of build_public_method) so Solargraph
102
+ # will show the "real" method pin for type inference, probing, docs etc.
103
+ source_map.pins.each do |pin|
104
+ next unless Delegate.supported?
105
+ next unless pin.is_a?(Solargraph::Pin::Method) && pin.scope == :class && pin.closure == ns
106
+
107
+ pins << Solargraph::Pin::DelegatedMethod.new(closure: relation, scope: :instance, method: pin)
108
+ end
109
+
110
+ unless abstract
111
+ pins += relation_method_pins(ns, :class, ns.path)
112
+ pins += relation_method_pins(relation, :instance, ns.path)
61
113
  end
114
+
115
+ Solargraph.logger.debug("[Rails][Model] added #{pins.map(&:name)} to #{ns.path}")
116
+
62
117
  pins
63
118
  end
64
119
 
120
+
65
121
  def plural_association(ns, ast)
66
- relation_name = ast.children[2].children.first
122
+ association_name = ast.children[2].children.first
67
123
  class_name =
68
124
  extract_custom_class_name(ast) ||
69
- relation_name.to_s.singularize.camelize
125
+ association_name.to_s.singularize.camelize
70
126
 
71
127
  Util.build_public_method(
72
128
  ns,
73
- relation_name.to_s,
74
- types: ["ActiveRecord::Associations::CollectionProxy<#{class_name}>"],
129
+ association_name.to_s,
130
+ types: [relation_type(class_name)],
75
131
  location: Util.build_location(ast, ns.filename)
76
132
  )
77
133
  end
78
134
 
79
135
  def singular_association(ns, ast)
80
- relation_name = ast.children[2].children.first
136
+ association_name = ast.children[2].children.first
81
137
  class_name =
82
- extract_custom_class_name(ast) || relation_name.to_s.camelize
138
+ extract_custom_class_name(ast) || association_name.to_s.camelize
83
139
 
84
140
  Util.build_public_method(
85
141
  ns,
86
- relation_name.to_s,
142
+ association_name.to_s,
87
143
  types: [class_name],
88
144
  location: Util.build_location(ast, ns.filename)
89
145
  )
90
146
  end
91
147
 
92
148
  def extract_custom_class_name(ast)
93
- options = ast.children[3..-1].find { |n| n.type == :hash }
94
- return unless options
149
+ node = Util.extract_option(ast, :class_name)
150
+ return unless node && node.type == :str
151
+
152
+ node.children.last
153
+ end
154
+
155
+ # Generate method pins for ActiveRecord methods in the given namespace/scope, where the
156
+ # the return types will be templated with the provided model class.
157
+ #
158
+ # These method pins don't need to include any documentation, as Solargraph will merge
159
+ # documentation from Rails when it resolves the "method stack" for each pin.
160
+ #
161
+ # @param ns [Solargraph::Pin::Namespace] the namespace (model or relation class) in which to define methods.
162
+ # @param scope [:instance, :class] the method scope (:class for the model and :instance for the relation).
163
+ # @param model_class [String] the model class (e.g. "Person") that should be used in return types.
164
+ # @return [Array<Solargraph::Pin::Method>]
165
+ def relation_method_pins(namespace, scope, model_class)
166
+ pins = []
167
+ finalize_type = ->(template) { template.gsub '$T', model_class }
168
+ RETURNS_RELATION.each do |method_name, params|
169
+ next if OVERLOADED.key(method_name)
95
170
 
96
- class_name_pair =
97
- options.children.find do |n|
98
- n.children[0].deconstruct == %i[sym class_name] &&
99
- n.children[1].type == :str
171
+ method = Util.build_public_method(namespace, method_name, scope: scope, parameters: [], types: [relation_type(model_class)])
172
+ params.each do |name, type|
173
+ decl = :arg
174
+ # TODO: maybe I can remove this and go back to letting solargraph parse a comment block
175
+ # @see https://github.com/castwide/solargraph/pull/601
176
+ if name.start_with?('**')
177
+ name = name[2..]
178
+ decl = :kwrestarg
179
+ elsif name.start_with?('*')
180
+ name = name[1..]
181
+ decl = :restarg
182
+ end
183
+ method.parameters << Solargraph::Pin::Parameter.new(name: name, decl: decl, closure: method,
184
+ comments: "@return [#{type}]")
100
185
  end
101
- class_name_pair && class_name_pair.children.last.children.last
186
+ pins << method
187
+ end
188
+
189
+ RETURNS_INSTANCE.each do |method|
190
+ pins << Util.build_public_method(namespace, method, scope: scope, types: [model_class])
191
+ end
192
+
193
+ OVERLOADED.each do |method, overloads|
194
+ comments = overloads.map do |arg_list, lines|
195
+ lines = ["@return [#{lines}]"] if lines.is_a?(String)
196
+ lines = ["@overload #{method}#{arg_list}"] + lines
197
+ lines.map(&finalize_type).join("\n ")
198
+ end
199
+ pins << Util.build_public_method(namespace, method, scope: scope, comments: comments.join("\n"))
200
+ end
201
+ pins
202
+ end
203
+
204
+ # construct the type name for the models hidden relation class.
205
+ # the additional type parameter is _not_ redundant, it makes enumerable methods work.
206
+ def relation_type(model_path)
207
+ "#{model_path}::ActiveRecord_Relation"
102
208
  end
209
+
210
+ ANY_ARGS = {"*args" => nil}
211
+
212
+ # @todo can this be replaced with rbs_collection's
213
+ # _ActiveRecord_Relation interface? Potential leads:
214
+ # https://github.com/pocke/rbs_rails
215
+ # https://github.com/ruby/gem_rbs_collection/blob/6f2d93ab244008bec51db7b4fffae68b40232502/gems/paranoia/2.5/paranoia.rbs#L6C1-L7C1
216
+ # https://github.com/ksss/orthoses-rails
217
+ # https://github.com/PawCorp/walltaker/blob/728682baa56a267611aca1ddb9f44fdcd97f6c80/sig/rbs_rails/app/models/user.rbs#L2
218
+ RETURNS_RELATION = {
219
+ "all" => {},
220
+ "and" => {"other" => "ActiveRecord::Relation"},
221
+ "annotate" => ANY_ARGS,
222
+ "distinct" => ANY_ARGS,
223
+ "eager_load" => ANY_ARGS,
224
+ "excluding" => ANY_ARGS,
225
+ "from" => {"source" => "ActiveRecord::Relation"},
226
+ "group" => ANY_ARGS,
227
+ "having" => ANY_ARGS,
228
+ "in_order_of" => ANY_ARGS,
229
+ "includes" => ANY_ARGS,
230
+ "invert_where" => {},
231
+ "joins" => ANY_ARGS,
232
+ "left_joins" => ANY_ARGS,
233
+ "left_outer_joins" => ANY_ARGS,
234
+ "limit" => {"value" => "Integer"},
235
+ "lock" => {"locks" => "true, false"},
236
+ "none" => {},
237
+ "offset" => {"value" => "Integer"},
238
+ "or" => {"other" => "ActiveRecord::Relation"},
239
+ "order" => ANY_ARGS,
240
+ "preload" => ANY_ARGS,
241
+ "readonly" => {"value" => "true, false"},
242
+ "references" => {"*table_names" => nil},
243
+ "reorder" => ANY_ARGS,
244
+ "reselect" => ANY_ARGS,
245
+ "reverse_order" => {},
246
+ "rewhere" => {"conditions" => "Hash"},
247
+ "select" => ANY_ARGS,
248
+ "strict_loading" => {"value" => "true, false"},
249
+ "unscope" => ANY_ARGS,
250
+ "without" => ANY_ARGS,
251
+ }
252
+
253
+ RETURNS_INSTANCE = %w[
254
+ take take! sole
255
+ first second third fourth fifth third_to_last second_to_last last
256
+ first! second! third! fourth! fifth! third_to_last! second_to_last! last!
257
+ forty_two forty_two!
258
+ ]
259
+
260
+ OVERLOADED = {
261
+ "where" => {
262
+ "()" => "ActiveRecord::QueryMethods::WhereChain<$T::ActiveRecord_Relation>",
263
+ "(sql, *args)" => [
264
+ "@return [$T::ActiveRecord_Relation]",
265
+ ],
266
+ },
267
+ "select" => {
268
+ "()" => [
269
+ "@yieldparam [$T]",
270
+ "@return [Array<$T>]",
271
+ ],
272
+ "(*args)" => "$T::ActiveRecord_Relation",
273
+ },
274
+ "find" => {
275
+ "(id)" => [
276
+ "@param id [Integer, String]",
277
+ "@return [$T]"
278
+ ],
279
+ "(*ids)" => "Array<$T>",
280
+ },
281
+ "find_by" => {
282
+ "(hash)" => [
283
+ "@param hash [Hash] attributes to match by",
284
+ "@return [$T, nil]",
285
+ ],
286
+ "(sql, *args)" => [
287
+ "@param sql [String] a SQL snippet for the WHERE clause",
288
+ "@return [$T, nil]"
289
+ ]
290
+ },
291
+ "find_by!" => {
292
+ "(hash)" => [
293
+ "@param hash [Hash] attributes to match by",
294
+ "@return [$T]",
295
+ ],
296
+ "(sql, *args)" => [
297
+ "@param sql [String] a SQL snippet for the WHERE clause",
298
+ "@return [$T]"
299
+ ]
300
+ },
301
+ "find_sole_by" => {
302
+ "(hash)" => [
303
+ "@param hash [Hash] attributes to match by",
304
+ "@return [$T]",
305
+ ],
306
+ "(sql, *args)" => [
307
+ "@param sql [String] a SQL snippet for the WHERE clause",
308
+ "@return [$T]"
309
+ ]
310
+ },
311
+ "take" => {
312
+ "()" => "T, nil",
313
+ "(limit)" => "Array<$T>",
314
+ },
315
+ "first" => {
316
+ "()" => "$T, nil",
317
+ "(limit)" => "Array<$T>",
318
+ },
319
+ "last" => {
320
+ "()" => "$T, nil",
321
+ "(limit)" => "Array<$T>"
322
+ },
323
+ }
103
324
  end
104
325
  end
105
326
  end
@@ -14,8 +14,8 @@ module Solargraph
14
14
  end
15
15
  end
16
16
 
17
- # @param yard_map [YardMap]
18
- def global(_yard_map)
17
+ # @param yard_map [Solargraph::DocMap]
18
+ def global(_doc_map)
19
19
  extra_source_maps.values.flat_map(&:pins)
20
20
  end
21
21
 
@@ -43,15 +43,34 @@ module Solargraph
43
43
 
44
44
  return [] unless table
45
45
 
46
- pins =
47
- table.map do |column, data|
48
- Util.build_public_method(
49
- ns,
50
- column,
51
- types: [RUBY_TYPES.fetch(data.type.to_sym)],
52
- location: Util.build_location(data.ast, 'db/schema.rb')
53
- )
46
+ pins = []
47
+ table.each do |column, data|
48
+ location = Util.build_location(data.ast, 'db/schema.rb')
49
+ type = RUBY_TYPES[data.type.to_sym] || 'String'
50
+ %w[% %_in_database %_before_last_save].each do |tpl|
51
+ name = tpl.sub('%', column)
52
+ pins << Util.build_public_method(ns, name, types: [type], location: location)
54
53
  end
54
+ %w[%? %_changed? saved_change_to_%? will_save_change_to_%?].each do |tpl|
55
+ name = tpl.sub('%', column)
56
+ pins << Util.build_public_method(ns, name, types: ['Boolean'], location: location)
57
+ end
58
+ %w[%_change_to_be_saved saved_change_to_%].each do |tpl|
59
+ name = tpl.sub('%', column)
60
+ types = ["Array(#{type}, #{type})"]
61
+ pins << Util.build_public_method(ns, name, types: types, location: location)
62
+ end
63
+ pins << Util.build_public_method(ns, "#{column}=", types: [type],
64
+ params: { 'value' => [type] },
65
+ location: location)
66
+
67
+ # Note on this: its the starting step of dynamic filters. Technically, you can also do Model.find_by_col1_and_col2(val1, val2)
68
+ # However, if we start suggestion all of those possibilities, it will simply be bad UX because of having too many suggestions
69
+ pins << Util.build_public_method(ns, "find_by_#{column}", types: ['self', 'nil'],
70
+ params: { 'value' => [type] },
71
+ location: location,
72
+ scope: :class)
73
+ end
55
74
 
56
75
  if pins.any?
57
76
  Solargraph.logger.debug(
@@ -4,25 +4,45 @@ module Solargraph
4
4
  def self.build_public_method(
5
5
  ns,
6
6
  name,
7
+ comments: nil,
8
+ parameters: [],
7
9
  types: nil,
10
+ params: {},
8
11
  location: nil,
9
12
  attribute: false,
10
13
  scope: :instance
11
14
  )
12
15
  opts = {
13
16
  name: name,
17
+ parameters: parameters,
14
18
  location: location,
15
19
  closure: ns,
16
20
  scope: scope,
17
21
  attribute: attribute
18
22
  }
19
23
 
20
- comments = []
21
- comments << "@return [#{types.join(',')}]" if types
24
+ comments_arr = [comments].compact
25
+ params.each do |name, types|
26
+ comments_arr << "@param [#{types.join(',')}] #{name}"
27
+ end
28
+ comments_arr << "@return [#{types.join(',')}]" if types
22
29
 
23
- opts[:comments] = comments.join("\n")
30
+ opts[:comments] ||= comments_arr.join("\n")
24
31
 
25
- Solargraph::Pin::Method.new(**opts)
32
+ m = Solargraph::Pin::Method.new(**opts)
33
+ parameters = parameters + params.map do |name, type|
34
+ Solargraph::Pin::Parameter.new(
35
+ location: nil,
36
+ closure: m,
37
+ comments: '',
38
+ name: name,
39
+ presence: nil,
40
+ decl: :arg,
41
+ asgn_code: nil
42
+ )
43
+ end
44
+ m.parameters.concat(parameters)
45
+ m
26
46
  end
27
47
 
28
48
  def self.build_module_include(ns, module_name, location)
@@ -63,6 +83,27 @@ module Solargraph
63
83
  def self.method_return(path, type)
64
84
  Solargraph::Pin::Reference::Override.method_return(path, type)
65
85
  end
86
+
87
+ # Extract the value of a given option from a :send syntax node.
88
+ #
89
+ # E.g. given an AST node for `foo(:bar, baz: qux)`, you can use
90
+ # `extract_option(node, :baz)` to get the AST node for `qux`.
91
+ #
92
+ # @param call_node [AST::Node]
93
+ # @param option_name [Symbol]
94
+ # @return [AST::Node, nil]
95
+ def self.extract_option(call_node, option_name)
96
+ options = call_node.children[3..-1].find { |n| n.type == :hash }
97
+ return unless options
98
+
99
+ pair =
100
+ options.children.find do |n|
101
+ n.children[0] && n.children[0].deconstruct == [:sym, option_name]
102
+ end
103
+ return unless pair
104
+
105
+ pair.children[1]
106
+ end
66
107
  end
67
108
  end
68
109
  end
@@ -1,5 +1,5 @@
1
1
  module Solargraph
2
2
  module Rails
3
- VERSION = '1.1.2'
3
+ VERSION = '1.2.0'
4
4
  end
5
5
  end
@@ -50,7 +50,7 @@ module Solargraph
50
50
  pins += run_feature { Storage.instance.process(source_map, ns) }
51
51
  pins += run_feature { Autoload.instance.process(source_map, ns, ds) }
52
52
  pins += run_feature { Devise.instance.process(source_map, ns) }
53
- pins += run_feature { Delegate.instance.process(source_map, ns) }
53
+ pins += run_feature { Delegate.instance.process(source_map, ns) } if Delegate.supported?
54
54
  pins += run_feature { RailsApi.instance.local(source_map, ns) }
55
55
 
56
56
  Solargraph::Environ.new(pins: pins)
@@ -1,28 +1,42 @@
1
1
  require File.join(Dir.pwd, ARGV.first, 'config/environment')
2
2
 
3
- class Model < ActiveRecord::Base
3
+ require 'method_source'
4
+
5
+ def _instance_methods(klass, test = klass.new)
6
+ klass
7
+ .instance_methods(true)
8
+ .sort
9
+ .reject { |m| m.to_s.start_with?('_') || (test && !test.respond_to?(m)) }
10
+ .map { |m| klass.instance_method(m) }
4
11
  end
5
12
 
6
13
  def own_instance_methods(klass, test = klass.new)
7
- (instance_methods(klass, test) - Object.methods).select do |m|
8
- m.source_location && m.source_location.first.include?('gem')
14
+ reject_meth_names = (Module.methods + Module.private_methods + [:to_yaml, :to_json]).to_set
15
+ _instance_methods(klass, test).select do |m|
16
+ !reject_meth_names.include?(m.name) &&
17
+ m.source_location &&
18
+ m.source_location.first.include?('gem') &&
19
+ m.source_location &&
20
+ m.source_location.first.include?('gem') &&
21
+ !m.source_location.first.include?('/pp-') &&
22
+ m.comment &&
23
+ !m.comment.empty? &&
24
+ m.comment != ':nodoc:'
9
25
  end
10
26
  end
11
27
 
12
28
  def own_class_methods(klass)
13
- (class_methods(klass) - Object.methods).select do |m|
14
- m.source_location && m.source_location.first.include?('gem')
29
+ reject_meth_names = (Module.methods + Module.private_methods + [:to_yaml, :to_json]).to_set
30
+ class_methods(klass).select do |m|
31
+ !reject_meth_names.include?(m.name) &&
32
+ m.source_location &&
33
+ m.source_location.first.include?('gem') &&
34
+ m.comment &&
35
+ !m.comment.empty? &&
36
+ m.comment != ':nodoc:'
15
37
  end
16
38
  end
17
39
 
18
- def instance_methods(klass, test = klass.new)
19
- klass
20
- .instance_methods(true)
21
- .sort
22
- .reject { |m| m.to_s.start_with?('_') || (test && !test.respond_to?(m)) }
23
- .map { |m| klass.instance_method(m) }
24
- end
25
-
26
40
  def class_methods(klass)
27
41
  klass
28
42
  .methods(true)
@@ -53,6 +67,18 @@ def build_report(klass, test: klass.new)
53
67
  result
54
68
  end
55
69
 
70
+ def add_new_methods(klass, test, yaml_filename)
71
+ new_report = build_report(klass, test: test)
72
+ existing_report = {}
73
+ existing_report = YAML.load_file(yaml_filename) if File.exist?(yaml_filename)
74
+ report = { **new_report, **existing_report }
75
+ class_methods, instance_methods = report.partition { |k, _| k.include?('.') }
76
+ class_methods = class_methods.sort_by { |k, _v| k }.to_h
77
+ instance_methods = instance_methods.sort_by { |k, _v| k }.to_h
78
+ report = { **class_methods, **instance_methods }
79
+ File.write(yaml_filename, report.deep_stringify_keys.to_yaml)
80
+ end
81
+
56
82
  def core_ext_report(klass, test = klass.new)
57
83
  result = {}
58
84
  distribution = {}
@@ -73,7 +99,7 @@ def core_ext_report(klass, test = klass.new)
73
99
  }
74
100
  end
75
101
 
76
- instance_methods(klass, test)
102
+ _instance_methods(klass, test)
77
103
  .select(&:source_location)
78
104
  .select do |meth|
79
105
  loc = meth.source_location.first
@@ -92,18 +118,18 @@ def core_ext_report(klass, test = klass.new)
92
118
  result
93
119
  end
94
120
 
95
- report = build_report(ActiveRecord::Base, test: Model.new)
96
- File.write('activerecord.yml', report.deep_stringify_keys.to_yaml)
121
+ add_new_methods(ActiveRecord::Base, Model.new, '../definitions/activerecord.yml')
122
+ add_new_methods(ActionController::Base, false, '../definitions/actioncontroller.yml')
123
+ add_new_methods(ActiveJob::Base, false, '../definitions/activejob.yml')
97
124
 
98
- report = build_report(ActionController::Base)
99
- File.write('actioncontroller.yml', report.deep_stringify_keys.to_yaml)
125
+ Rails.application.routes.draw do
126
+ add_new_methods(self.class, false, '../definitions/routes.yml')
127
+ end
100
128
 
101
- report = build_report(ActiveJob::Base)
102
- File.write('activejob.yml', report.deep_stringify_keys.to_yaml)
129
+ add_new_methods(Rails::Application, false, '../definitions/application.yml')
103
130
 
104
131
  Rails.application.routes.draw do
105
- report = build_report(self.class, test: false)
106
- File.write('routes.yml', report.deep_stringify_keys.to_yaml)
132
+ add_new_methods(self.class, false, '../definitions/routes.yml')
107
133
  end
108
134
 
109
135
  [
@@ -134,8 +160,7 @@ end
134
160
  end
135
161
  end
136
162
 
137
- report = core_ext_report(klass, test = test)
138
- File.write("#{klass.to_s}.yml", report.deep_stringify_keys.to_yaml)
163
+ add_new_methods(klass, test, "../definitions/core/#{klass.to_s}.yml")
139
164
  end
140
165
 
141
166
  # binding.pry
@@ -4,7 +4,23 @@ require 'solargraph/rails/version'
4
4
 
5
5
 
6
6
  solargraph_force_ci_version = (ENV['CI'] && ENV['MATRIX_SOLARGRAPH_VERSION'])
7
- solargraph_version = solargraph_force_ci_version ? [solargraph_force_ci_version] : [">= 0.48.0", '<0.53.0']
7
+ solargraph_version =
8
+ if solargraph_force_ci_version
9
+ [solargraph_force_ci_version]
10
+ else
11
+ [
12
+ # below this isn't tested in CI
13
+ '>= 0.48.0',
14
+ # did not have support for global conventions
15
+ '!=0.53.0', '!=0.53.1', '!=0.53.2', '!=0.53.3', '!=0.53.4',
16
+ # did not have support for global conventions
17
+ '!=0.54.0', '!=0.54.1', '!=0.54.2', '!=0.54.3', '!=0.54.4', '!=0.54.5',
18
+ # did not have support for global conventions
19
+ '!=0.55.0', '!=0.55.1', '!=0.55.2', '!=0.55.3', '!=0.55.4', '!=0.55.5', '!=0.55.6', '!=0.55.7',
20
+ # above this hasn't been tested
21
+ '< 0.57'
22
+ ]
23
+ end
8
24
 
9
25
  Gem::Specification.new do |spec|
10
26
  spec.name = 'solargraph-rails'
@@ -30,11 +46,10 @@ Gem::Specification.new do |spec|
30
46
  spec.add_development_dependency 'bundler', '~> 2.3'
31
47
  spec.add_development_dependency 'rake', '~> 12.3.3'
32
48
  spec.add_development_dependency 'rspec', '~> 3.0'
49
+ spec.add_development_dependency 'rubocop', '~> 1.76'
50
+ spec.add_development_dependency 'simplecov', '~> 0.22.0'
51
+ spec.add_development_dependency 'simplecov-lcov', '~> 0.8.0'
33
52
 
34
- # Solargraph temporarily dropped support for Convention.global in
35
- # 0.53 - this should be lifted after it returns:
36
- #
37
- # https://github.com/castwide/solargraph/pull/877
38
53
  spec.add_runtime_dependency 'solargraph', *solargraph_version
39
54
 
40
55
  spec.add_runtime_dependency 'activesupport'