solargraph 0.54.4 → 0.57.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 +125 -0
- data/.github/workflows/plugins.yml +149 -5
- data/.github/workflows/rspec.yml +39 -4
- data/.github/workflows/typecheck.yml +8 -3
- data/.gitignore +7 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +2627 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +104 -0
- data/README.md +20 -6
- data/Rakefile +125 -13
- data/lib/solargraph/api_map/cache.rb +3 -2
- data/lib/solargraph/api_map/constants.rb +218 -0
- data/lib/solargraph/api_map/index.rb +44 -42
- data/lib/solargraph/api_map/source_to_yard.rb +10 -4
- data/lib/solargraph/api_map/store.rb +165 -32
- data/lib/solargraph/api_map.rb +319 -243
- data/lib/solargraph/bench.rb +18 -1
- data/lib/solargraph/complex_type/type_methods.rb +7 -1
- data/lib/solargraph/complex_type/unique_type.rb +105 -16
- data/lib/solargraph/complex_type.rb +40 -7
- data/lib/solargraph/convention/active_support_concern.rb +111 -0
- data/lib/solargraph/convention/base.rb +20 -3
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
- data/lib/solargraph/convention/data_definition.rb +105 -0
- data/lib/solargraph/convention/gemspec.rb +3 -2
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
- data/lib/solargraph/convention/struct_definition.rb +164 -0
- data/lib/solargraph/convention.rb +35 -4
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
- data/lib/solargraph/doc_map.rb +313 -65
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/gem_pins.rb +60 -38
- data/lib/solargraph/language_server/host/dispatch.rb +2 -0
- data/lib/solargraph/language_server/host/message_worker.rb +13 -7
- data/lib/solargraph/language_server/host.rb +14 -3
- data/lib/solargraph/language_server/message/base.rb +2 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
- data/lib/solargraph/language_server/message/extended/document.rb +5 -2
- data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +16 -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 +1 -0
- data/lib/solargraph/library.rb +53 -32
- data/lib/solargraph/location.rb +23 -0
- data/lib/solargraph/logging.rb +12 -2
- data/lib/solargraph/page.rb +4 -0
- data/lib/solargraph/parser/comment_ripper.rb +20 -7
- data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
- data/lib/solargraph/parser/node_methods.rb +16 -2
- data/lib/solargraph/parser/node_processor/base.rb +10 -5
- data/lib/solargraph/parser/node_processor.rb +26 -9
- data/lib/solargraph/parser/parser_gem/class_methods.rb +17 -15
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
- data/lib/solargraph/parser/parser_gem/node_methods.rb +8 -4
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +42 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +63 -30
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
- data/lib/solargraph/parser/region.rb +4 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +1 -0
- data/lib/solargraph/pin/base.rb +360 -30
- data/lib/solargraph/pin/base_variable.rb +16 -10
- data/lib/solargraph/pin/block.rb +2 -0
- data/lib/solargraph/pin/breakable.rb +9 -0
- data/lib/solargraph/pin/callable.rb +83 -3
- data/lib/solargraph/pin/closure.rb +20 -1
- data/lib/solargraph/pin/common.rb +10 -1
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/delegated_method.rb +21 -1
- data/lib/solargraph/pin/documenting.rb +16 -0
- data/lib/solargraph/pin/keyword.rb +7 -2
- data/lib/solargraph/pin/local_variable.rb +18 -6
- data/lib/solargraph/pin/method.rb +175 -46
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/namespace.rb +17 -9
- data/lib/solargraph/pin/parameter.rb +78 -19
- data/lib/solargraph/pin/proxy_type.rb +13 -6
- data/lib/solargraph/pin/reference/override.rb +24 -6
- data/lib/solargraph/pin/reference/require.rb +2 -2
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +26 -0
- data/lib/solargraph/pin/search.rb +3 -1
- data/lib/solargraph/pin/signature.rb +44 -0
- data/lib/solargraph/pin/singleton.rb +1 -1
- data/lib/solargraph/pin/symbol.rb +8 -2
- data/lib/solargraph/pin/until.rb +18 -0
- data/lib/solargraph/pin/while.rb +18 -0
- data/lib/solargraph/pin.rb +4 -1
- data/lib/solargraph/pin_cache.rb +245 -0
- data/lib/solargraph/position.rb +11 -0
- data/lib/solargraph/range.rb +10 -0
- data/lib/solargraph/rbs_map/conversions.rb +226 -70
- data/lib/solargraph/rbs_map/core_fills.rb +32 -16
- data/lib/solargraph/rbs_map/core_map.rb +37 -11
- data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
- data/lib/solargraph/rbs_map.rb +88 -18
- data/lib/solargraph/shell.rb +20 -18
- data/lib/solargraph/source/chain/array.rb +11 -7
- data/lib/solargraph/source/chain/block_symbol.rb +1 -1
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +53 -23
- data/lib/solargraph/source/chain/constant.rb +1 -1
- data/lib/solargraph/source/chain/hash.rb +4 -3
- data/lib/solargraph/source/chain/head.rb +1 -1
- data/lib/solargraph/source/chain/if.rb +1 -1
- data/lib/solargraph/source/chain/link.rb +12 -1
- data/lib/solargraph/source/chain/literal.rb +22 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +1 -1
- data/lib/solargraph/source/chain.rb +84 -47
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/cursor.rb +2 -3
- data/lib/solargraph/source/source_chainer.rb +3 -3
- data/lib/solargraph/source.rb +5 -2
- data/lib/solargraph/source_map/clip.rb +4 -2
- data/lib/solargraph/source_map/data.rb +4 -0
- data/lib/solargraph/source_map/mapper.rb +13 -7
- data/lib/solargraph/source_map.rb +21 -31
- data/lib/solargraph/type_checker/checks.rb +4 -0
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +8 -0
- data/lib/solargraph/type_checker.rb +208 -128
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/_method.erb +10 -10
- data/lib/solargraph/views/_namespace.erb +3 -3
- data/lib/solargraph/views/document.erb +10 -10
- data/lib/solargraph/workspace/config.rb +1 -3
- data/lib/solargraph/workspace/require_paths.rb +98 -0
- data/lib/solargraph/workspace.rb +38 -52
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +53 -18
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +9 -7
- data/lib/solargraph/yard_map/mapper.rb +4 -3
- data/lib/solargraph/yard_map/to_method.rb +4 -2
- data/lib/solargraph/yardoc.rb +22 -10
- data/lib/solargraph.rb +34 -1
- data/rbs/fills/tuple.rbs +149 -0
- data/rbs_collection.yaml +19 -0
- data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -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 +15 -4
- metadata +157 -15
- data/lib/.rubocop.yml +0 -22
- data/lib/solargraph/cache.rb +0 -77
data/lib/solargraph/bench.rb
CHANGED
@@ -11,18 +11,35 @@ module Solargraph
|
|
11
11
|
# @return [Workspace]
|
12
12
|
attr_reader :workspace
|
13
13
|
|
14
|
+
# @return [SourceMap]
|
15
|
+
attr_reader :live_map
|
16
|
+
|
14
17
|
# @return [Set<String>]
|
15
18
|
attr_reader :external_requires
|
16
19
|
|
17
20
|
# @param source_maps [Array<SourceMap>, Set<SourceMap>]
|
18
21
|
# @param workspace [Workspace]
|
22
|
+
# @param live_map [SourceMap, nil]
|
19
23
|
# @param external_requires [Array<String>, Set<String>]
|
20
|
-
def initialize source_maps: [], workspace: Workspace.new, external_requires: []
|
24
|
+
def initialize source_maps: [], workspace: Workspace.new, live_map: nil, external_requires: []
|
21
25
|
@source_maps = source_maps.to_set
|
22
26
|
@workspace = workspace
|
27
|
+
@live_map = live_map
|
23
28
|
@external_requires = external_requires.reject { |path| workspace.would_require?(path) }
|
24
29
|
.compact
|
25
30
|
.to_set
|
26
31
|
end
|
32
|
+
|
33
|
+
# @return [Hash{String => SourceMap}]
|
34
|
+
def source_map_hash
|
35
|
+
# @todo Work around #to_h bug in current Ruby head (3.5) with #map#to_h
|
36
|
+
@source_map_hash ||= source_maps.map { |s| [s.filename, s] }
|
37
|
+
.to_h
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Set<SourceMap>]
|
41
|
+
def icebox
|
42
|
+
@icebox ||= (source_maps - [live_map])
|
43
|
+
end
|
27
44
|
end
|
28
45
|
end
|
@@ -88,6 +88,7 @@ module Solargraph
|
|
88
88
|
# @return [Symbol, nil]
|
89
89
|
attr_reader :parameters_type
|
90
90
|
|
91
|
+
# @type [Hash{String => Symbol}]
|
91
92
|
PARAMETERS_TYPE_BY_STARTING_TAG = {
|
92
93
|
'{' => :hash,
|
93
94
|
'(' => :fixed,
|
@@ -129,6 +130,7 @@ module Solargraph
|
|
129
130
|
end.call
|
130
131
|
end
|
131
132
|
|
133
|
+
# @return [self]
|
132
134
|
def namespace_type
|
133
135
|
return ComplexType.parse('::Object') if duck_type?
|
134
136
|
return ComplexType.parse('::NilClass') if nil_type?
|
@@ -171,7 +173,11 @@ module Solargraph
|
|
171
173
|
elsif fixed_parameters?
|
172
174
|
"(#{subtypes_str})"
|
173
175
|
else
|
174
|
-
|
176
|
+
if name == 'Hash'
|
177
|
+
"<#{key_types_str}, #{subtypes_str}>"
|
178
|
+
else
|
179
|
+
"<#{key_types_str}#{subtypes_str}>"
|
180
|
+
end
|
175
181
|
end
|
176
182
|
end
|
177
183
|
|
@@ -27,7 +27,7 @@ module Solargraph
|
|
27
27
|
# @return [UniqueType]
|
28
28
|
def self.parse name, substring = '', make_rooted: nil
|
29
29
|
if name.start_with?(':::')
|
30
|
-
raise "Illegal prefix: #{name}"
|
30
|
+
raise ComplexTypeError, "Illegal prefix: #{name}"
|
31
31
|
end
|
32
32
|
if name.start_with?('::')
|
33
33
|
name = name[2..-1]
|
@@ -48,12 +48,15 @@ module Solargraph
|
|
48
48
|
subs = ComplexType.parse(substring[1..-2], partial: true)
|
49
49
|
parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
|
50
50
|
if parameters_type == :hash
|
51
|
-
raise ComplexTypeError, "Bad hash type" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
+
key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
|
53
|
+
subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
|
54
|
+
elsif parameters_type == :list && name == 'Hash'
|
55
|
+
# Treat Hash<A, B> as Hash{A => B}
|
56
|
+
if subs.length != 2
|
57
|
+
raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring} - must have exactly two parameters"
|
58
|
+
end
|
55
59
|
key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
|
56
|
-
# @sg-ignore
|
57
60
|
subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
|
58
61
|
else
|
59
62
|
subtypes.concat subs
|
@@ -73,19 +76,66 @@ module Solargraph
|
|
73
76
|
end
|
74
77
|
raise "Please remove leading :: and set rooted instead - #{name.inspect}" if name.start_with?('::')
|
75
78
|
@name = name
|
76
|
-
@
|
77
|
-
|
79
|
+
@parameters_type = parameters_type
|
80
|
+
if implicit_union?
|
81
|
+
@key_types = key_types.uniq
|
82
|
+
@subtypes = subtypes.uniq
|
83
|
+
else
|
84
|
+
@key_types = key_types
|
85
|
+
@subtypes = subtypes
|
86
|
+
end
|
78
87
|
@rooted = rooted
|
79
88
|
@all_params = []
|
80
|
-
@all_params.concat key_types
|
81
|
-
@all_params.concat subtypes
|
82
|
-
|
89
|
+
@all_params.concat @key_types
|
90
|
+
@all_params.concat @subtypes
|
91
|
+
end
|
92
|
+
|
93
|
+
def implicit_union?
|
94
|
+
# @todo use api_map to establish number of generics in type;
|
95
|
+
# if only one is allowed but multiple are passed in, treat
|
96
|
+
# those as implicit unions
|
97
|
+
['Hash', 'Array', 'Set', '_ToAry', 'Enumerable', '_Each'].include?(name) && parameters_type != :fixed
|
83
98
|
end
|
84
99
|
|
85
100
|
def to_s
|
86
101
|
tag
|
87
102
|
end
|
88
103
|
|
104
|
+
# @return [self]
|
105
|
+
def simplify_literals
|
106
|
+
transform do |t|
|
107
|
+
next t unless t.literal?
|
108
|
+
t.recreate(new_name: t.non_literal_name)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def literal?
|
113
|
+
non_literal_name != name
|
114
|
+
end
|
115
|
+
|
116
|
+
# @return [String]
|
117
|
+
def non_literal_name
|
118
|
+
@non_literal_name ||= determine_non_literal_name
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return [String]
|
122
|
+
def determine_non_literal_name
|
123
|
+
# https://github.com/ruby/rbs/blob/master/docs/syntax.md
|
124
|
+
#
|
125
|
+
# _literal_ ::= _string-literal_
|
126
|
+
# | _symbol-literal_
|
127
|
+
# | _integer-literal_
|
128
|
+
# | `true`
|
129
|
+
# | `false`
|
130
|
+
return name if name.empty?
|
131
|
+
return 'NilClass' if name == 'nil'
|
132
|
+
return 'Boolean' if ['true', 'false'].include?(name)
|
133
|
+
return 'Symbol' if name[0] == ':'
|
134
|
+
return 'String' if ['"', "'"].include?(name[0])
|
135
|
+
return 'Integer' if name.match?(/^-?\d+$/)
|
136
|
+
name
|
137
|
+
end
|
138
|
+
|
89
139
|
def eql?(other)
|
90
140
|
self.class == other.class &&
|
91
141
|
@name == other.name &&
|
@@ -113,11 +163,14 @@ module Solargraph
|
|
113
163
|
def rbs_name
|
114
164
|
if name == 'undefined'
|
115
165
|
'untyped'
|
166
|
+
elsif literal?
|
167
|
+
name
|
116
168
|
else
|
117
169
|
rooted_name
|
118
170
|
end
|
119
171
|
end
|
120
172
|
|
173
|
+
# @return [String]
|
121
174
|
def desc
|
122
175
|
rooted_tags
|
123
176
|
end
|
@@ -183,9 +236,26 @@ module Solargraph
|
|
183
236
|
name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
|
184
237
|
end
|
185
238
|
|
239
|
+
# @param api_map [ApiMap] The ApiMap that performs qualification
|
240
|
+
# @param atype [ComplexType] type which may be assigned to this type
|
241
|
+
def can_assign?(api_map, atype)
|
242
|
+
logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect})" }
|
243
|
+
downcasted_atype = atype.downcast_to_literal_if_possible
|
244
|
+
out = downcasted_atype.all? do |autype|
|
245
|
+
autype.name == name || api_map.super_and_sub?(name, autype.name)
|
246
|
+
end
|
247
|
+
logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect}) => #{out}" }
|
248
|
+
out
|
249
|
+
end
|
250
|
+
|
251
|
+
# @return [UniqueType]
|
252
|
+
def downcast_to_literal_if_possible
|
253
|
+
SINGLE_SUBTYPE.fetch(rooted_tag, self)
|
254
|
+
end
|
255
|
+
|
186
256
|
# @param generics_to_resolve [Enumerable<String>]
|
187
257
|
# @param context_type [UniqueType, nil]
|
188
|
-
# @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
|
258
|
+
# @param resolved_generic_values [Hash{String => ComplexType, ComplexType::UniqueType}] Added to as types are encountered or resolved
|
189
259
|
# @return [UniqueType, ComplexType]
|
190
260
|
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
191
261
|
if name == ComplexType::GENERIC_TAG_NAME
|
@@ -243,7 +313,8 @@ module Solargraph
|
|
243
313
|
|
244
314
|
transform(name) do |t|
|
245
315
|
if t.name == GENERIC_TAG_NAME
|
246
|
-
|
316
|
+
generic_name = t.subtypes.first&.name
|
317
|
+
idx = definitions.generics.index(generic_name)
|
247
318
|
next t if idx.nil?
|
248
319
|
if context_type.parameters_type == :hash
|
249
320
|
if idx == 0
|
@@ -253,8 +324,14 @@ module Solargraph
|
|
253
324
|
else
|
254
325
|
next ComplexType::UNDEFINED
|
255
326
|
end
|
327
|
+
elsif context_type.all?(&:implicit_union?)
|
328
|
+
if idx == 0 && !context_type.all_params.empty?
|
329
|
+
ComplexType.new(context_type.all_params)
|
330
|
+
else
|
331
|
+
ComplexType::UNDEFINED
|
332
|
+
end
|
256
333
|
else
|
257
|
-
context_type.all_params[idx] || ComplexType::UNDEFINED
|
334
|
+
context_type.all_params[idx] || definitions.generic_defaults[generic_name] || ComplexType::UNDEFINED
|
258
335
|
end
|
259
336
|
else
|
260
337
|
t
|
@@ -276,9 +353,9 @@ module Solargraph
|
|
276
353
|
|
277
354
|
# @param new_name [String, nil]
|
278
355
|
# @param make_rooted [Boolean, nil]
|
279
|
-
# @param new_key_types [Array<
|
356
|
+
# @param new_key_types [Array<ComplexType>, nil]
|
280
357
|
# @param rooted [Boolean, nil]
|
281
|
-
# @param new_subtypes [Array<
|
358
|
+
# @param new_subtypes [Array<ComplexType>, nil]
|
282
359
|
# @return [self]
|
283
360
|
def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
|
284
361
|
raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
|
@@ -381,6 +458,18 @@ module Solargraph
|
|
381
458
|
|
382
459
|
UNDEFINED = UniqueType.new('undefined', rooted: false)
|
383
460
|
BOOLEAN = UniqueType.new('Boolean', rooted: true)
|
461
|
+
TRUE = UniqueType.new('true', rooted: true)
|
462
|
+
FALSE = UniqueType.new('false', rooted: true)
|
463
|
+
NIL = UniqueType.new('nil', rooted: true)
|
464
|
+
# @type [Hash{String => UniqueType}]
|
465
|
+
SINGLE_SUBTYPE = {
|
466
|
+
'::TrueClass' => UniqueType::TRUE,
|
467
|
+
'::FalseClass' => UniqueType::FALSE,
|
468
|
+
'::NilClass' => UniqueType::NIL
|
469
|
+
}.freeze
|
470
|
+
|
471
|
+
|
472
|
+
include Logging
|
384
473
|
end
|
385
474
|
end
|
386
475
|
end
|
@@ -16,7 +16,13 @@ module Solargraph
|
|
16
16
|
def initialize types = [UniqueType::UNDEFINED]
|
17
17
|
# @todo @items here should not need an annotation
|
18
18
|
# @type [Array<UniqueType>]
|
19
|
-
|
19
|
+
items = types.flat_map(&:items).uniq(&:to_s)
|
20
|
+
if items.any? { |i| i.name == 'false' } && items.any? { |i| i.name == 'true' }
|
21
|
+
items.delete_if { |i| i.name == 'false' || i.name == 'true' }
|
22
|
+
items.unshift(ComplexType::BOOLEAN)
|
23
|
+
end
|
24
|
+
items = [UniqueType::UNDEFINED] if items.any?(&:undefined?)
|
25
|
+
@items = items
|
20
26
|
end
|
21
27
|
|
22
28
|
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
@@ -70,7 +76,7 @@ module Solargraph
|
|
70
76
|
end
|
71
77
|
|
72
78
|
# @yieldparam [UniqueType]
|
73
|
-
# @return [Array]
|
79
|
+
# @return [Array<UniqueType>]
|
74
80
|
def map &block
|
75
81
|
@items.map &block
|
76
82
|
end
|
@@ -93,6 +99,12 @@ module Solargraph
|
|
93
99
|
end
|
94
100
|
end
|
95
101
|
|
102
|
+
# @param atype [ComplexType] type which may be assigned to this type
|
103
|
+
# @param api_map [ApiMap] The ApiMap that performs qualification
|
104
|
+
def can_assign?(api_map, atype)
|
105
|
+
any? { |ut| ut.can_assign?(api_map, atype) }
|
106
|
+
end
|
107
|
+
|
96
108
|
# @return [Integer]
|
97
109
|
def length
|
98
110
|
@items.length
|
@@ -103,10 +115,6 @@ module Solargraph
|
|
103
115
|
@items
|
104
116
|
end
|
105
117
|
|
106
|
-
def tags
|
107
|
-
@items.map(&:tag).join(', ')
|
108
|
-
end
|
109
|
-
|
110
118
|
# @param index [Integer]
|
111
119
|
# @return [UniqueType]
|
112
120
|
def [](index)
|
@@ -147,10 +155,31 @@ module Solargraph
|
|
147
155
|
map(&:tag).join(', ')
|
148
156
|
end
|
149
157
|
|
158
|
+
# @return [String]
|
159
|
+
def tags
|
160
|
+
map(&:tag).join(', ')
|
161
|
+
end
|
162
|
+
|
163
|
+
# @return [String]
|
164
|
+
def simple_tags
|
165
|
+
simplify_literals.tags
|
166
|
+
end
|
167
|
+
|
168
|
+
def literal?
|
169
|
+
@items.any?(&:literal?)
|
170
|
+
end
|
171
|
+
|
172
|
+
# @return [ComplexType]
|
173
|
+
def downcast_to_literal_if_possible
|
174
|
+
ComplexType.new(items.map(&:downcast_to_literal_if_possible))
|
175
|
+
end
|
176
|
+
|
177
|
+
# @return [String]
|
150
178
|
def desc
|
151
179
|
rooted_tags
|
152
180
|
end
|
153
181
|
|
182
|
+
# @return [String]
|
154
183
|
def rooted_tags
|
155
184
|
map(&:rooted_tag).join(', ')
|
156
185
|
end
|
@@ -175,6 +204,11 @@ module Solargraph
|
|
175
204
|
any?(&:generic?)
|
176
205
|
end
|
177
206
|
|
207
|
+
# @return [self]
|
208
|
+
def simplify_literals
|
209
|
+
ComplexType.new(map(&:simplify_literals))
|
210
|
+
end
|
211
|
+
|
178
212
|
# @param new_name [String, nil]
|
179
213
|
# @yieldparam t [UniqueType]
|
180
214
|
# @yieldreturn [UniqueType]
|
@@ -270,7 +304,6 @@ module Solargraph
|
|
270
304
|
# # @todo Need ability to use a literal true as a type below
|
271
305
|
# # @param partial [Boolean] True if the string is part of a another type
|
272
306
|
# # @return [Array<UniqueType>]
|
273
|
-
# @sg-ignore
|
274
307
|
# @todo To be able to select the right signature above,
|
275
308
|
# Chain::Call needs to know the decl type (:arg, :optarg,
|
276
309
|
# :kwarg, etc) of the arguments given, instead of just having
|
@@ -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(&:parametrized_tag).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
|
@@ -20,12 +20,29 @@ module Solargraph
|
|
20
20
|
EMPTY_ENVIRON
|
21
21
|
end
|
22
22
|
|
23
|
-
# The Environ for a
|
23
|
+
# The Environ for a DocMap.
|
24
24
|
# Subclasses can override this method.
|
25
25
|
#
|
26
|
-
# @param
|
26
|
+
# @param doc_map [DocMap]
|
27
27
|
# @return [Environ]
|
28
|
-
def global
|
28
|
+
def global doc_map
|
29
|
+
EMPTY_ENVIRON
|
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
|
29
46
|
EMPTY_ENVIRON
|
30
47
|
end
|
31
48
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module Convention
|
5
|
+
module DataDefinition
|
6
|
+
# A node wrapper for a Data definition via const assignment.
|
7
|
+
# @example
|
8
|
+
# MyData = Data.new(:bar, :baz) do
|
9
|
+
# def foo
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
class DataAssignmentNode < DataDefintionNode
|
13
|
+
class << self
|
14
|
+
# @example
|
15
|
+
# s(:casgn, nil, :Foo,
|
16
|
+
# s(:block,
|
17
|
+
# s(:send,
|
18
|
+
# s(:const, nil, :Data), :define,
|
19
|
+
# s(:sym, :bar),
|
20
|
+
# s(:sym, :baz)),
|
21
|
+
# s(:args),
|
22
|
+
# s(:def, :foo,
|
23
|
+
# s(:args),
|
24
|
+
# s(:send, nil, :bar))))
|
25
|
+
# @param node [::Parser::AST::Node]
|
26
|
+
def match?(node)
|
27
|
+
return false unless node&.type == :casgn
|
28
|
+
return false if node.children[2].nil?
|
29
|
+
|
30
|
+
data_node = if node.children[2].type == :block
|
31
|
+
node.children[2].children[0]
|
32
|
+
else
|
33
|
+
node.children[2]
|
34
|
+
end
|
35
|
+
|
36
|
+
data_definition_node?(data_node)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def class_name
|
41
|
+
if node.children[0]
|
42
|
+
Parser::NodeMethods.unpack_name(node.children[0]) + "::#{node.children[1]}"
|
43
|
+
else
|
44
|
+
node.children[1].to_s
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# @return [Parser::AST::Node]
|
51
|
+
def data_node
|
52
|
+
if node.children[2].type == :block
|
53
|
+
node.children[2].children[0]
|
54
|
+
else
|
55
|
+
node.children[2]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module Convention
|
5
|
+
module DataDefinition
|
6
|
+
# A node wrapper for a Data definition via inheritance.
|
7
|
+
# @example
|
8
|
+
# class MyData < Data.new(:bar, :baz)
|
9
|
+
# def foo
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
class DataDefintionNode
|
13
|
+
class << self
|
14
|
+
# @example
|
15
|
+
# s(:class,
|
16
|
+
# s(:const, nil, :Foo),
|
17
|
+
# s(:send,
|
18
|
+
# s(:const, nil, :Data), :define,
|
19
|
+
# s(:sym, :bar),
|
20
|
+
# s(:sym, :baz)),
|
21
|
+
# s(:hash,
|
22
|
+
# s(:pair,
|
23
|
+
# s(:sym, :keyword_init),
|
24
|
+
# s(:true)))),
|
25
|
+
# s(:def, :foo,
|
26
|
+
# s(:args),
|
27
|
+
# s(:send, nil, :bar)))
|
28
|
+
#
|
29
|
+
# @param node [Parser::AST::Node]
|
30
|
+
def match?(node)
|
31
|
+
return false unless node&.type == :class
|
32
|
+
|
33
|
+
data_definition_node?(node.children[1])
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# @param data_node [Parser::AST::Node]
|
39
|
+
# @return [Boolean]
|
40
|
+
def data_definition_node?(data_node)
|
41
|
+
return false unless data_node.is_a?(::Parser::AST::Node)
|
42
|
+
return false unless data_node&.type == :send
|
43
|
+
return false unless data_node.children[0]&.type == :const
|
44
|
+
return false unless data_node.children[0].children[1] == :Data
|
45
|
+
return false unless data_node.children[1] == :define
|
46
|
+
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param node [Parser::AST::Node]
|
52
|
+
def initialize(node)
|
53
|
+
@node = node
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [String]
|
57
|
+
def class_name
|
58
|
+
Parser::NodeMethods.unpack_name(node)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [Array<Array(Parser::AST::Node, String)>]
|
62
|
+
def attributes
|
63
|
+
data_attribute_nodes.map do |data_def_param|
|
64
|
+
next unless data_def_param.type == :sym
|
65
|
+
[data_def_param, data_def_param.children[0].to_s]
|
66
|
+
end.compact
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Parser::AST::Node]
|
70
|
+
def body_node
|
71
|
+
node.children[2]
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# @return [Parser::AST::Node]
|
77
|
+
attr_reader :node
|
78
|
+
|
79
|
+
# @return [Parser::AST::Node]
|
80
|
+
def data_node
|
81
|
+
node.children[1]
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return [Array<Parser::AST::Node>]
|
85
|
+
def data_attribute_nodes
|
86
|
+
data_node.children[2..-1]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|