solargraph 0.56.2 → 0.58.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 +4 -4
- data/.github/workflows/linting.yml +127 -0
- data/.github/workflows/plugins.yml +183 -7
- data/.github/workflows/rspec.yml +55 -5
- data/.github/workflows/typecheck.yml +6 -3
- data/.gitignore +5 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +1279 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +69 -0
- data/README.md +8 -4
- data/Rakefile +125 -13
- data/bin/solargraph +8 -5
- data/lib/solargraph/api_map/cache.rb +3 -2
- data/lib/solargraph/api_map/constants.rb +279 -0
- data/lib/solargraph/api_map/index.rb +49 -31
- data/lib/solargraph/api_map/source_to_yard.rb +13 -4
- data/lib/solargraph/api_map/store.rb +144 -26
- data/lib/solargraph/api_map.rb +217 -245
- data/lib/solargraph/bench.rb +1 -0
- data/lib/solargraph/complex_type/type_methods.rb +6 -0
- data/lib/solargraph/complex_type/unique_type.rb +19 -12
- data/lib/solargraph/complex_type.rb +24 -3
- data/lib/solargraph/convention/active_support_concern.rb +111 -0
- data/lib/solargraph/convention/base.rb +17 -0
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +4 -2
- data/lib/solargraph/convention/data_definition.rb +2 -1
- data/lib/solargraph/convention/gemspec.rb +1 -1
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +3 -1
- data/lib/solargraph/convention/struct_definition.rb +36 -13
- data/lib/solargraph/convention.rb +31 -2
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
- data/lib/solargraph/doc_map.rb +44 -13
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/equality.rb +1 -0
- data/lib/solargraph/gem_pins.rb +21 -11
- data/lib/solargraph/language_server/host/dispatch.rb +2 -0
- data/lib/solargraph/language_server/host/message_worker.rb +3 -0
- data/lib/solargraph/language_server/host.rb +12 -5
- data/lib/solargraph/language_server/message/base.rb +2 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +19 -2
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
- data/lib/solargraph/language_server/progress.rb +8 -0
- data/lib/solargraph/language_server/request.rb +4 -1
- data/lib/solargraph/library.rb +11 -18
- data/lib/solargraph/location.rb +3 -0
- data/lib/solargraph/logging.rb +11 -2
- data/lib/solargraph/page.rb +3 -0
- data/lib/solargraph/parser/comment_ripper.rb +8 -1
- data/lib/solargraph/parser/flow_sensitive_typing.rb +33 -5
- data/lib/solargraph/parser/node_processor/base.rb +1 -1
- data/lib/solargraph/parser/node_processor.rb +6 -2
- data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -13
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -16
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -0
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +64 -8
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +36 -16
- data/lib/solargraph/parser/region.rb +3 -0
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/pin/base.rb +77 -14
- data/lib/solargraph/pin/base_variable.rb +6 -5
- data/lib/solargraph/pin/block.rb +3 -2
- data/lib/solargraph/pin/callable.rb +14 -1
- data/lib/solargraph/pin/closure.rb +5 -7
- data/lib/solargraph/pin/common.rb +6 -2
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/local_variable.rb +1 -2
- data/lib/solargraph/pin/method.rb +28 -9
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/parameter.rb +24 -10
- data/lib/solargraph/pin/proxy_type.rb +5 -1
- data/lib/solargraph/pin/reference/override.rb +15 -1
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +17 -0
- data/lib/solargraph/pin/search.rb +6 -1
- data/lib/solargraph/pin/signature.rb +2 -0
- data/lib/solargraph/pin/symbol.rb +5 -0
- data/lib/solargraph/pin_cache.rb +64 -4
- data/lib/solargraph/position.rb +3 -0
- data/lib/solargraph/range.rb +5 -0
- data/lib/solargraph/rbs_map/conversions.rb +29 -6
- data/lib/solargraph/rbs_map/core_fills.rb +18 -0
- data/lib/solargraph/rbs_map/core_map.rb +14 -7
- data/lib/solargraph/rbs_map.rb +14 -1
- data/lib/solargraph/shell.rb +85 -1
- data/lib/solargraph/source/chain/call.rb +7 -3
- data/lib/solargraph/source/chain/constant.rb +3 -66
- data/lib/solargraph/source/chain/if.rb +1 -1
- data/lib/solargraph/source/chain/link.rb +11 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain.rb +11 -2
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/cursor.rb +2 -3
- data/lib/solargraph/source/source_chainer.rb +1 -1
- data/lib/solargraph/source.rb +6 -3
- data/lib/solargraph/source_map/clip.rb +18 -26
- data/lib/solargraph/source_map/data.rb +4 -0
- data/lib/solargraph/source_map/mapper.rb +2 -2
- data/lib/solargraph/source_map.rb +28 -16
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +30 -8
- data/lib/solargraph/type_checker.rb +301 -186
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +21 -5
- data/lib/solargraph/workspace/require_paths.rb +97 -0
- data/lib/solargraph/workspace.rb +30 -67
- data/lib/solargraph/yard_map/mapper/to_method.rb +4 -3
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
- data/lib/solargraph/yard_map/to_method.rb +2 -1
- data/lib/solargraph/yardoc.rb +39 -3
- data/lib/solargraph.rb +2 -0
- data/rbs/fills/bundler/0/bundler.rbs +4271 -0
- data/rbs/fills/open3/0/open3.rbs +172 -0
- data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
- data/rbs/fills/rubygems/0/errors.rbs +364 -0
- data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
- data/rbs/fills/rubygems/0/specification.rbs +1753 -0
- data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
- data/rbs_collection.yaml +4 -4
- data/sig/shims/ast/0/node.rbs +5 -0
- data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
- data/sig/shims/ast/2.4/ast.rbs +73 -0
- data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
- data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
- data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
- data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
- data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
- data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
- data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
- data/solargraph.gemspec +26 -5
- metadata +181 -13
- data/lib/.rubocop.yml +0 -22
- data/lib/solargraph/parser/node_methods.rb +0 -97
data/lib/solargraph/bench.rb
CHANGED
|
@@ -43,6 +43,10 @@ module Solargraph
|
|
|
43
43
|
@rooted_tag ||= rooted_name + rooted_substring
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
def interface?
|
|
47
|
+
name.start_with?('_')
|
|
48
|
+
end
|
|
49
|
+
|
|
46
50
|
# @return [Boolean]
|
|
47
51
|
def duck_type?
|
|
48
52
|
@duck_type ||= name.start_with?('#')
|
|
@@ -130,6 +134,7 @@ module Solargraph
|
|
|
130
134
|
end.call
|
|
131
135
|
end
|
|
132
136
|
|
|
137
|
+
# @return [self]
|
|
133
138
|
def namespace_type
|
|
134
139
|
return ComplexType.parse('::Object') if duck_type?
|
|
135
140
|
return ComplexType.parse('::NilClass') if nil_type?
|
|
@@ -189,6 +194,7 @@ module Solargraph
|
|
|
189
194
|
# @param other [Object]
|
|
190
195
|
def == other
|
|
191
196
|
return false unless self.class == other.class
|
|
197
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
192
198
|
tag == other.tag
|
|
193
199
|
end
|
|
194
200
|
|
|
@@ -49,11 +49,7 @@ module Solargraph
|
|
|
49
49
|
parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
|
|
50
50
|
if parameters_type == :hash
|
|
51
51
|
raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring}" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
|
|
52
|
-
# @todo should be able to resolve map; both types have it
|
|
53
|
-
# with same return type
|
|
54
|
-
# @sg-ignore
|
|
55
52
|
key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
|
|
56
|
-
# @sg-ignore
|
|
57
53
|
subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
|
|
58
54
|
elsif parameters_type == :list && name == 'Hash'
|
|
59
55
|
# Treat Hash<A, B> as Hash{A => B}
|
|
@@ -105,6 +101,7 @@ module Solargraph
|
|
|
105
101
|
tag
|
|
106
102
|
end
|
|
107
103
|
|
|
104
|
+
# @return [self]
|
|
108
105
|
def simplify_literals
|
|
109
106
|
transform do |t|
|
|
110
107
|
next t unless t.literal?
|
|
@@ -116,10 +113,12 @@ module Solargraph
|
|
|
116
113
|
non_literal_name != name
|
|
117
114
|
end
|
|
118
115
|
|
|
116
|
+
# @return [String]
|
|
119
117
|
def non_literal_name
|
|
120
118
|
@non_literal_name ||= determine_non_literal_name
|
|
121
119
|
end
|
|
122
120
|
|
|
121
|
+
# @return [String]
|
|
123
122
|
def determine_non_literal_name
|
|
124
123
|
# https://github.com/ruby/rbs/blob/master/docs/syntax.md
|
|
125
124
|
#
|
|
@@ -139,11 +138,17 @@ module Solargraph
|
|
|
139
138
|
|
|
140
139
|
def eql?(other)
|
|
141
140
|
self.class == other.class &&
|
|
141
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
142
142
|
@name == other.name &&
|
|
143
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
143
144
|
@key_types == other.key_types &&
|
|
145
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
144
146
|
@subtypes == other.subtypes &&
|
|
147
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
145
148
|
@rooted == other.rooted? &&
|
|
149
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
146
150
|
@all_params == other.all_params &&
|
|
151
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
147
152
|
@parameters_type == other.parameters_type
|
|
148
153
|
end
|
|
149
154
|
|
|
@@ -171,6 +176,7 @@ module Solargraph
|
|
|
171
176
|
end
|
|
172
177
|
end
|
|
173
178
|
|
|
179
|
+
# @return [String]
|
|
174
180
|
def desc
|
|
175
181
|
rooted_tags
|
|
176
182
|
end
|
|
@@ -255,7 +261,7 @@ module Solargraph
|
|
|
255
261
|
|
|
256
262
|
# @param generics_to_resolve [Enumerable<String>]
|
|
257
263
|
# @param context_type [UniqueType, nil]
|
|
258
|
-
# @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
|
|
264
|
+
# @param resolved_generic_values [Hash{String => ComplexType, ComplexType::UniqueType}] Added to as types are encountered or resolved
|
|
259
265
|
# @return [UniqueType, ComplexType]
|
|
260
266
|
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
|
261
267
|
if name == ComplexType::GENERIC_TAG_NAME
|
|
@@ -280,7 +286,7 @@ module Solargraph
|
|
|
280
286
|
end
|
|
281
287
|
|
|
282
288
|
# @param generics_to_resolve [Enumerable<String>]
|
|
283
|
-
# @param context_type [UniqueType]
|
|
289
|
+
# @param context_type [UniqueType, nil]
|
|
284
290
|
# @param resolved_generic_values [Hash{String => ComplexType}]
|
|
285
291
|
# @yieldreturn [Array<ComplexType>]
|
|
286
292
|
# @return [Array<ComplexType>]
|
|
@@ -353,9 +359,9 @@ module Solargraph
|
|
|
353
359
|
|
|
354
360
|
# @param new_name [String, nil]
|
|
355
361
|
# @param make_rooted [Boolean, nil]
|
|
356
|
-
# @param new_key_types [Array<
|
|
362
|
+
# @param new_key_types [Array<ComplexType>, nil]
|
|
357
363
|
# @param rooted [Boolean, nil]
|
|
358
|
-
# @param new_subtypes [Array<
|
|
364
|
+
# @param new_subtypes [Array<ComplexType>, nil]
|
|
359
365
|
# @return [self]
|
|
360
366
|
def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
|
|
361
367
|
raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
|
|
@@ -409,12 +415,12 @@ module Solargraph
|
|
|
409
415
|
# @param api_map [ApiMap] The ApiMap that performs qualification
|
|
410
416
|
# @param context [String] The namespace from which to resolve names
|
|
411
417
|
# @return [self, ComplexType, UniqueType] The generated ComplexType
|
|
412
|
-
def qualify api_map,
|
|
418
|
+
def qualify api_map, *gates
|
|
413
419
|
transform do |t|
|
|
414
420
|
next t if t.name == GENERIC_TAG_NAME
|
|
415
|
-
next t if t.duck_type? || t.void? || t.undefined?
|
|
416
|
-
|
|
417
|
-
fqns = api_map.qualify(t.
|
|
421
|
+
next t if t.duck_type? || t.void? || t.undefined? || t.literal?
|
|
422
|
+
open = t.rooted? ? [''] : gates
|
|
423
|
+
fqns = api_map.qualify(t.non_literal_name, *open)
|
|
418
424
|
if fqns.nil?
|
|
419
425
|
next UniqueType::BOOLEAN if t.tag == 'Boolean'
|
|
420
426
|
next UniqueType::UNDEFINED
|
|
@@ -446,6 +452,7 @@ module Solargraph
|
|
|
446
452
|
!can_root_name? || @rooted
|
|
447
453
|
end
|
|
448
454
|
|
|
455
|
+
# @param name_to_check [String]
|
|
449
456
|
def can_root_name?(name_to_check = name)
|
|
450
457
|
self.class.can_root_name?(name_to_check)
|
|
451
458
|
end
|
|
@@ -33,12 +33,12 @@ module Solargraph
|
|
|
33
33
|
# @param api_map [ApiMap]
|
|
34
34
|
# @param context [String]
|
|
35
35
|
# @return [ComplexType]
|
|
36
|
-
def qualify api_map,
|
|
36
|
+
def qualify api_map, *gates
|
|
37
37
|
red = reduce_object
|
|
38
38
|
types = red.items.map do |t|
|
|
39
39
|
next t if ['nil', 'void', 'undefined'].include?(t.name)
|
|
40
40
|
next t if ['::Boolean'].include?(t.rooted_name)
|
|
41
|
-
t.qualify api_map,
|
|
41
|
+
t.qualify api_map, *gates
|
|
42
42
|
end
|
|
43
43
|
ComplexType.new(types).reduce_object
|
|
44
44
|
end
|
|
@@ -105,6 +105,21 @@ module Solargraph
|
|
|
105
105
|
any? { |ut| ut.can_assign?(api_map, atype) }
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
+
# @param new_name [String, nil]
|
|
109
|
+
# @param make_rooted [Boolean, nil]
|
|
110
|
+
# @param new_key_types [Array<ComplexType>, nil]
|
|
111
|
+
# @param rooted [Boolean, nil]
|
|
112
|
+
# @param new_subtypes [Array<ComplexType>, nil]
|
|
113
|
+
# @return [self]
|
|
114
|
+
def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
|
|
115
|
+
ComplexType.new(map do |ut|
|
|
116
|
+
ut.recreate(new_name: new_name,
|
|
117
|
+
make_rooted: make_rooted,
|
|
118
|
+
new_key_types: new_key_types,
|
|
119
|
+
new_subtypes: new_subtypes)
|
|
120
|
+
end)
|
|
121
|
+
end
|
|
122
|
+
|
|
108
123
|
# @return [Integer]
|
|
109
124
|
def length
|
|
110
125
|
@items.length
|
|
@@ -155,10 +170,12 @@ module Solargraph
|
|
|
155
170
|
map(&:tag).join(', ')
|
|
156
171
|
end
|
|
157
172
|
|
|
173
|
+
# @return [String]
|
|
158
174
|
def tags
|
|
159
175
|
map(&:tag).join(', ')
|
|
160
176
|
end
|
|
161
177
|
|
|
178
|
+
# @return [String]
|
|
162
179
|
def simple_tags
|
|
163
180
|
simplify_literals.tags
|
|
164
181
|
end
|
|
@@ -172,10 +189,12 @@ module Solargraph
|
|
|
172
189
|
ComplexType.new(items.map(&:downcast_to_literal_if_possible))
|
|
173
190
|
end
|
|
174
191
|
|
|
192
|
+
# @return [String]
|
|
175
193
|
def desc
|
|
176
194
|
rooted_tags
|
|
177
195
|
end
|
|
178
196
|
|
|
197
|
+
# @return [String]
|
|
179
198
|
def rooted_tags
|
|
180
199
|
map(&:rooted_tag).join(', ')
|
|
181
200
|
end
|
|
@@ -200,6 +219,7 @@ module Solargraph
|
|
|
200
219
|
any?(&:generic?)
|
|
201
220
|
end
|
|
202
221
|
|
|
222
|
+
# @return [self]
|
|
203
223
|
def simplify_literals
|
|
204
224
|
ComplexType.new(map(&:simplify_literals))
|
|
205
225
|
end
|
|
@@ -241,6 +261,7 @@ module Solargraph
|
|
|
241
261
|
def reduce_class_type
|
|
242
262
|
new_items = items.flat_map do |type|
|
|
243
263
|
next type unless ['Module', 'Class'].include?(type.name)
|
|
264
|
+
next type if type.all_params.empty?
|
|
244
265
|
|
|
245
266
|
type.all_params
|
|
246
267
|
end
|
|
@@ -299,7 +320,6 @@ module Solargraph
|
|
|
299
320
|
# # @todo Need ability to use a literal true as a type below
|
|
300
321
|
# # @param partial [Boolean] True if the string is part of a another type
|
|
301
322
|
# # @return [Array<UniqueType>]
|
|
302
|
-
# @sg-ignore
|
|
303
323
|
# @todo To be able to select the right signature above,
|
|
304
324
|
# Chain::Call needs to know the decl type (:arg, :optarg,
|
|
305
325
|
# :kwarg, etc) of the arguments given, instead of just having
|
|
@@ -319,6 +339,7 @@ module Solargraph
|
|
|
319
339
|
paren_stack = 0
|
|
320
340
|
base = String.new
|
|
321
341
|
subtype_string = String.new
|
|
342
|
+
# @param char [String]
|
|
322
343
|
type_string&.each_char do |char|
|
|
323
344
|
if char == '='
|
|
324
345
|
#raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Convention
|
|
5
|
+
# ActiveSupport::Concern is syntactic sugar for a common
|
|
6
|
+
# pattern to include class methods while mixing-in a Module
|
|
7
|
+
# See https://api.rubyonrails.org/classes/ActiveSupport/Concern.html
|
|
8
|
+
class ActiveSupportConcern < Base
|
|
9
|
+
include Logging
|
|
10
|
+
|
|
11
|
+
# @return [Array<Pin::Base>]
|
|
12
|
+
attr_reader :pins
|
|
13
|
+
|
|
14
|
+
# @param api_map [ApiMap]
|
|
15
|
+
# @param rooted_tag [String]
|
|
16
|
+
# @param scope [Symbol] :class or :instance
|
|
17
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
|
18
|
+
# @param deep [Boolean] whether to include methods from included modules
|
|
19
|
+
# @param skip [Set<String>]
|
|
20
|
+
# @param _no_core [Boolean]n whether to skip core methods
|
|
21
|
+
def object api_map, rooted_tag, scope, visibility, deep, skip, _no_core
|
|
22
|
+
moo = ObjectProcessor.new(api_map, rooted_tag, scope, visibility, deep, skip)
|
|
23
|
+
moo.environ
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# yard-activesupport-concern pulls methods inside
|
|
27
|
+
# 'class_methods' blocks into main class visible from YARD
|
|
28
|
+
#
|
|
29
|
+
# @param _doc_map [DocMap]
|
|
30
|
+
def global _doc_map
|
|
31
|
+
Environ.new(yard_plugins: ['activesupport-concern'])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Process an object to add any class methods brought in via
|
|
35
|
+
# ActiveSupport::Concern
|
|
36
|
+
class ObjectProcessor
|
|
37
|
+
include Logging
|
|
38
|
+
|
|
39
|
+
attr_reader :environ
|
|
40
|
+
|
|
41
|
+
# @param api_map [ApiMap]
|
|
42
|
+
# @param rooted_tag [String] the tag of the class or module being processed
|
|
43
|
+
# @param scope [Symbol] :class or :instance
|
|
44
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
|
45
|
+
# @param deep [Boolean] whether to include methods from included modules
|
|
46
|
+
# @param skip [Set<String>] a set of tags to skip
|
|
47
|
+
def initialize api_map, rooted_tag, scope, visibility, deep, skip
|
|
48
|
+
@api_map = api_map
|
|
49
|
+
@rooted_tag = rooted_tag
|
|
50
|
+
@scope = scope
|
|
51
|
+
@visibility = visibility
|
|
52
|
+
@deep = deep
|
|
53
|
+
@skip = skip
|
|
54
|
+
|
|
55
|
+
@environ = Environ.new
|
|
56
|
+
return unless scope == :class
|
|
57
|
+
|
|
58
|
+
@rooted_type = ComplexType.parse(rooted_tag).force_rooted
|
|
59
|
+
@fqns = rooted_type.namespace
|
|
60
|
+
@namespace_pin = api_map.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
|
61
|
+
|
|
62
|
+
api_map.get_includes(fqns).reverse.each do |include_tag|
|
|
63
|
+
process_include include_tag
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
attr_reader :api_map, :rooted_tag, :rooted_type, :scope,
|
|
70
|
+
:visibility, :deep, :skip, :namespace_pin,
|
|
71
|
+
:fqns
|
|
72
|
+
|
|
73
|
+
# @param include_tag [Pin::Reference::Include] the include reference pin
|
|
74
|
+
#
|
|
75
|
+
# @return [void]
|
|
76
|
+
def process_include include_tag
|
|
77
|
+
rooted_include_tag = api_map.dereference(include_tag)
|
|
78
|
+
return if rooted_include_tag.nil?
|
|
79
|
+
logger.debug do
|
|
80
|
+
"ActiveSupportConcern#object(#{fqns}, #{scope}, #{visibility}, #{deep}) - " \
|
|
81
|
+
"Handling class include include_tag=#{include_tag}"
|
|
82
|
+
end
|
|
83
|
+
module_extends = api_map.get_extends(rooted_include_tag).map(&:type).map(&:to_s)
|
|
84
|
+
logger.debug do
|
|
85
|
+
"ActiveSupportConcern#object(#{fqns}, #{scope}, #{visibility}, #{deep}) - " \
|
|
86
|
+
"found module extends of #{rooted_include_tag}: #{module_extends}"
|
|
87
|
+
end
|
|
88
|
+
return unless module_extends.include? 'ActiveSupport::Concern'
|
|
89
|
+
included_class_pins = api_map.inner_get_methods_from_reference(rooted_include_tag, namespace_pin, rooted_type,
|
|
90
|
+
:class, visibility, deep, skip, true)
|
|
91
|
+
logger.debug do
|
|
92
|
+
"ActiveSupportConcern#object(#{fqns}, #{scope}, #{visibility}, #{deep}) - " \
|
|
93
|
+
"Found #{included_class_pins.length} inluded class methods for #{rooted_include_tag}"
|
|
94
|
+
end
|
|
95
|
+
environ.pins.concat included_class_pins
|
|
96
|
+
# another pattern is to put class methods inside a submodule
|
|
97
|
+
classmethods_include_tag = "#{rooted_include_tag}::ClassMethods"
|
|
98
|
+
included_classmethods_pins =
|
|
99
|
+
api_map.inner_get_methods_from_reference(classmethods_include_tag, namespace_pin, rooted_type,
|
|
100
|
+
:instance, visibility, deep, skip, true)
|
|
101
|
+
logger.debug do
|
|
102
|
+
"ActiveSupportConcern#object(#{fqns}, #{scope}, #{visibility}, #{deep}) - " \
|
|
103
|
+
"Found #{included_classmethods_pins.length} included classmethod " \
|
|
104
|
+
"class methods for #{classmethods_include_tag}"
|
|
105
|
+
end
|
|
106
|
+
environ.pins.concat included_classmethods_pins
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -28,6 +28,23 @@ module Solargraph
|
|
|
28
28
|
def global doc_map
|
|
29
29
|
EMPTY_ENVIRON
|
|
30
30
|
end
|
|
31
|
+
|
|
32
|
+
# Provides any additional method pins based on e the described object.
|
|
33
|
+
#
|
|
34
|
+
# @param api_map [ApiMap]
|
|
35
|
+
# @param rooted_tag [String] A fully qualified namespace, with
|
|
36
|
+
# generic parameter values if applicable
|
|
37
|
+
# @param scope [Symbol] :class or :instance
|
|
38
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
|
39
|
+
# @param deep [Boolean]
|
|
40
|
+
# @param skip [Set<String>]
|
|
41
|
+
# @param no_core [Boolean] Skip core classes if true
|
|
42
|
+
#
|
|
43
|
+
# @return [Environ]
|
|
44
|
+
def object api_map, rooted_tag, scope, visibility,
|
|
45
|
+
deep, skip, no_core
|
|
46
|
+
EMPTY_ENVIRON
|
|
47
|
+
end
|
|
31
48
|
end
|
|
32
49
|
end
|
|
33
50
|
end
|
|
@@ -25,6 +25,8 @@ module Solargraph
|
|
|
25
25
|
# s(:def, :foo,
|
|
26
26
|
# s(:args),
|
|
27
27
|
# s(:send, nil, :bar)))
|
|
28
|
+
#
|
|
29
|
+
# @param node [Parser::AST::Node]
|
|
28
30
|
def match?(node)
|
|
29
31
|
return false unless node&.type == :class
|
|
30
32
|
|
|
@@ -46,7 +48,7 @@ module Solargraph
|
|
|
46
48
|
end
|
|
47
49
|
end
|
|
48
50
|
|
|
49
|
-
# @
|
|
51
|
+
# @param node [Parser::AST::Node]
|
|
50
52
|
def initialize(node)
|
|
51
53
|
@node = node
|
|
52
54
|
end
|
|
@@ -74,7 +76,7 @@ module Solargraph
|
|
|
74
76
|
# @return [Parser::AST::Node]
|
|
75
77
|
attr_reader :node
|
|
76
78
|
|
|
77
|
-
# @return [Parser::AST::Node]
|
|
79
|
+
# @return [Parser::AST::Node, nil]
|
|
78
80
|
def data_node
|
|
79
81
|
node.children[1]
|
|
80
82
|
end
|
|
@@ -35,7 +35,7 @@ module Solargraph
|
|
|
35
35
|
comments: comments_for(node)
|
|
36
36
|
)
|
|
37
37
|
|
|
38
|
-
#
|
|
38
|
+
# @todo Support both arg and kwarg initializers for Data.define
|
|
39
39
|
# Solargraph::SourceMap::Clip#complete_keyword_parameters does not seem to currently take into account [Pin::Method#signatures] hence we only one for :kwarg
|
|
40
40
|
pins.push initialize_method_pin
|
|
41
41
|
|
|
@@ -88,6 +88,7 @@ module Solargraph
|
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
# @param attribute_node [Parser::AST::Node]
|
|
91
|
+
# @param attribute_name [String]
|
|
91
92
|
# @return [String, nil]
|
|
92
93
|
def attribute_comments(attribute_node, attribute_name)
|
|
93
94
|
data_comments = comments_for(attribute_node)
|
|
@@ -4,7 +4,7 @@ module Solargraph
|
|
|
4
4
|
module Convention
|
|
5
5
|
class Gemspec < Base
|
|
6
6
|
def local source_map
|
|
7
|
-
return EMPTY_ENVIRON unless File.basename(source_map.filename).end_with?('.gemspec')
|
|
7
|
+
return Convention::Base::EMPTY_ENVIRON unless File.basename(source_map.filename).end_with?('.gemspec')
|
|
8
8
|
@environ ||= Environ.new(
|
|
9
9
|
requires: ['rubygems'],
|
|
10
10
|
pins: [
|
|
@@ -25,6 +25,8 @@ module Solargraph
|
|
|
25
25
|
# s(:def, :foo,
|
|
26
26
|
# s(:args),
|
|
27
27
|
# s(:send, nil, :bar)))
|
|
28
|
+
#
|
|
29
|
+
# @param node [Parser::AST::Node]
|
|
28
30
|
def match?(node)
|
|
29
31
|
return false unless node&.type == :class
|
|
30
32
|
|
|
@@ -46,7 +48,7 @@ module Solargraph
|
|
|
46
48
|
end
|
|
47
49
|
end
|
|
48
50
|
|
|
49
|
-
# @
|
|
51
|
+
# @param node [Parser::AST::Node]
|
|
50
52
|
def initialize(node)
|
|
51
53
|
@node = node
|
|
52
54
|
end
|
|
@@ -20,7 +20,8 @@ module Solargraph
|
|
|
20
20
|
name: struct_definition_node.class_name,
|
|
21
21
|
docstring: docstring,
|
|
22
22
|
visibility: :public,
|
|
23
|
-
gates: region.closure.gates.freeze
|
|
23
|
+
gates: region.closure.gates.freeze,
|
|
24
|
+
source: :struct_definition
|
|
24
25
|
)
|
|
25
26
|
pins.push nspin
|
|
26
27
|
|
|
@@ -32,7 +33,8 @@ module Solargraph
|
|
|
32
33
|
location: get_node_location(node),
|
|
33
34
|
closure: nspin,
|
|
34
35
|
visibility: :private,
|
|
35
|
-
docstring: docstring
|
|
36
|
+
docstring: docstring,
|
|
37
|
+
source: :struct_definition
|
|
36
38
|
)
|
|
37
39
|
|
|
38
40
|
pins.push initialize_method_pin
|
|
@@ -43,7 +45,8 @@ module Solargraph
|
|
|
43
45
|
name: attribute_name,
|
|
44
46
|
decl: struct_definition_node.keyword_init? ? :kwarg : :arg,
|
|
45
47
|
location: get_node_location(attribute_node),
|
|
46
|
-
closure: initialize_method_pin
|
|
48
|
+
closure: initialize_method_pin,
|
|
49
|
+
source: :struct_definition
|
|
47
50
|
)
|
|
48
51
|
)
|
|
49
52
|
end
|
|
@@ -53,29 +56,40 @@ module Solargraph
|
|
|
53
56
|
[attribute_name, "#{attribute_name}="].each do |name|
|
|
54
57
|
docs = docstring.tags.find { |t| t.tag_name == 'param' && t.name == attribute_name }
|
|
55
58
|
|
|
59
|
+
attribute_type = ComplexType.parse(tag_string(docs))
|
|
60
|
+
return_type_comment = attribute_comment(docs, false)
|
|
61
|
+
param_comment = attribute_comment(docs, true)
|
|
62
|
+
|
|
56
63
|
method_pin = Pin::Method.new(
|
|
57
64
|
name: name,
|
|
58
65
|
parameters: [],
|
|
59
66
|
scope: :instance,
|
|
60
67
|
location: get_node_location(attribute_node),
|
|
61
68
|
closure: nspin,
|
|
69
|
+
docstring: YARD::Docstring.new(return_type_comment),
|
|
62
70
|
# even assignments return the value
|
|
63
|
-
comments:
|
|
64
|
-
|
|
71
|
+
comments: return_type_comment,
|
|
72
|
+
return_type: attribute_type,
|
|
73
|
+
visibility: :public,
|
|
74
|
+
source: :struct_definition
|
|
65
75
|
)
|
|
66
76
|
|
|
67
77
|
if name.end_with?('=')
|
|
68
78
|
method_pin.parameters << Pin::Parameter.new(
|
|
69
79
|
name: attribute_name,
|
|
70
80
|
location: get_node_location(attribute_node),
|
|
71
|
-
closure:
|
|
72
|
-
|
|
81
|
+
closure: method_pin,
|
|
82
|
+
return_type: attribute_type,
|
|
83
|
+
comments: param_comment,
|
|
84
|
+
source: :struct_definition
|
|
73
85
|
)
|
|
74
86
|
|
|
75
87
|
pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
88
|
+
closure: method_pin,
|
|
89
|
+
location: get_node_location(attribute_node),
|
|
90
|
+
return_type: attribute_type,
|
|
91
|
+
comments: "@type [#{attribute_type.rooted_tags}]",
|
|
92
|
+
source: :struct_definition)
|
|
79
93
|
end
|
|
80
94
|
|
|
81
95
|
pins.push method_pin
|
|
@@ -88,7 +102,7 @@ module Solargraph
|
|
|
88
102
|
|
|
89
103
|
private
|
|
90
104
|
|
|
91
|
-
# @return [StructDefintionNode, nil]
|
|
105
|
+
# @return [StructDefintionNode, StructAssignmentNode, nil]
|
|
92
106
|
def struct_definition_node
|
|
93
107
|
@struct_definition_node ||= if StructDefintionNode.match?(node)
|
|
94
108
|
StructDefintionNode.new(node)
|
|
@@ -113,7 +127,7 @@ module Solargraph
|
|
|
113
127
|
|
|
114
128
|
# We should support specific comments for an attribute, and that can be either a @return on an @param
|
|
115
129
|
# But since we merge into the struct_comments, then we should interpret either as a param
|
|
116
|
-
comment =
|
|
130
|
+
comment = "@param #{attr_name}#{comment[7..]}" if comment.start_with?('@return')
|
|
117
131
|
|
|
118
132
|
struct_comments += "\n#{comment}"
|
|
119
133
|
end
|
|
@@ -121,12 +135,21 @@ module Solargraph
|
|
|
121
135
|
Solargraph::Source.parse_docstring(struct_comments).to_docstring
|
|
122
136
|
end
|
|
123
137
|
|
|
138
|
+
# @param tag [YARD::Tags::Tag, nil] The param tag for this attribute.xtract_
|
|
139
|
+
#
|
|
140
|
+
# @return [String]
|
|
141
|
+
def tag_string(tag)
|
|
142
|
+
tag&.types&.join(',') || 'undefined'
|
|
143
|
+
end
|
|
144
|
+
|
|
124
145
|
# @param tag [YARD::Tags::Tag, nil] The param tag for this attribute. If nil, this method is a no-op
|
|
125
146
|
# @param for_setter [Boolean] If true, will return a @param tag instead of a @return tag
|
|
147
|
+
#
|
|
148
|
+
# @return [String] The formatted comment for the attribute
|
|
126
149
|
def attribute_comment(tag, for_setter)
|
|
127
150
|
return "" if tag.nil?
|
|
128
151
|
|
|
129
|
-
suffix = "[#{tag
|
|
152
|
+
suffix = "[#{tag_string(tag)}] #{tag.text}"
|
|
130
153
|
|
|
131
154
|
if for_setter
|
|
132
155
|
"@param #{tag.name} #{suffix}"
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
module Solargraph
|
|
5
4
|
# Conventions provide a way to modify an ApiMap based on expectations about
|
|
6
5
|
# one of its sources.
|
|
@@ -12,6 +11,7 @@ module Solargraph
|
|
|
12
11
|
autoload :Rakefile, 'solargraph/convention/rakefile'
|
|
13
12
|
autoload :StructDefinition, 'solargraph/convention/struct_definition'
|
|
14
13
|
autoload :DataDefinition, 'solargraph/convention/data_definition'
|
|
14
|
+
autoload :ActiveSupportConcern, 'solargraph/convention/active_support_concern'
|
|
15
15
|
|
|
16
16
|
# @type [Set<Convention::Base>]
|
|
17
17
|
@@conventions = Set.new
|
|
@@ -22,6 +22,12 @@ module Solargraph
|
|
|
22
22
|
@@conventions.add convention.new
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
# @param convention [Class<Convention::Base>]
|
|
26
|
+
# @return [void]
|
|
27
|
+
def self.unregister convention
|
|
28
|
+
@@conventions.delete_if { |c| c.is_a?(convention) }
|
|
29
|
+
end
|
|
30
|
+
|
|
25
31
|
# @param source_map [SourceMap]
|
|
26
32
|
# @return [Environ]
|
|
27
33
|
def self.for_local(source_map)
|
|
@@ -32,7 +38,7 @@ module Solargraph
|
|
|
32
38
|
result
|
|
33
39
|
end
|
|
34
40
|
|
|
35
|
-
# @param
|
|
41
|
+
# @param doc_map [DocMap]
|
|
36
42
|
# @return [Environ]
|
|
37
43
|
def self.for_global(doc_map)
|
|
38
44
|
result = Environ.new
|
|
@@ -42,8 +48,31 @@ module Solargraph
|
|
|
42
48
|
result
|
|
43
49
|
end
|
|
44
50
|
|
|
51
|
+
# Provides any additional method pins based on the described object.
|
|
52
|
+
#
|
|
53
|
+
# @param api_map [ApiMap]
|
|
54
|
+
# @param rooted_tag [String] A fully qualified namespace, with
|
|
55
|
+
# generic parameter values if applicable
|
|
56
|
+
# @param scope [Symbol] :class or :instance
|
|
57
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
|
58
|
+
# @param deep [Boolean]
|
|
59
|
+
# @param skip [Set<String>]
|
|
60
|
+
# @param no_core [Boolean] Skip core classes if true
|
|
61
|
+
#
|
|
62
|
+
# @return [Environ]
|
|
63
|
+
def self.for_object api_map, rooted_tag, scope, visibility,
|
|
64
|
+
deep, skip, no_core
|
|
65
|
+
result = Environ.new
|
|
66
|
+
@@conventions.each do |conv|
|
|
67
|
+
result.merge conv.object(api_map, rooted_tag, scope, visibility,
|
|
68
|
+
deep, skip, no_core)
|
|
69
|
+
end
|
|
70
|
+
result
|
|
71
|
+
end
|
|
72
|
+
|
|
45
73
|
register Gemfile
|
|
46
74
|
register Gemspec
|
|
47
75
|
register Rakefile
|
|
76
|
+
register ActiveSupportConcern
|
|
48
77
|
end
|
|
49
78
|
end
|
|
@@ -28,7 +28,12 @@ module Solargraph
|
|
|
28
28
|
options, paths = generate_options(source.filename, source.code)
|
|
29
29
|
store = RuboCop::ConfigStore.new
|
|
30
30
|
runner = RuboCop::Runner.new(options, store)
|
|
31
|
-
|
|
31
|
+
# Ensure only one instance of RuboCop::Runner is running at
|
|
32
|
+
# a time - it uses 'chdir' to read config files with ERB,
|
|
33
|
+
# which can conflict with other chdirs.
|
|
34
|
+
result = Solargraph::CHDIR_MUTEX.synchronize do
|
|
35
|
+
redirect_stdout{ runner.run(paths) }
|
|
36
|
+
end
|
|
32
37
|
|
|
33
38
|
return [] if result.empty?
|
|
34
39
|
|