solargraph 0.51.2 → 0.54.2
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/plugins.yml +40 -0
- data/.github/workflows/rspec.yml +1 -3
- data/.github/workflows/typecheck.yml +34 -0
- data/.yardopts +2 -2
- data/CHANGELOG.md +127 -5
- data/README.md +13 -16
- data/SPONSORS.md +1 -7
- data/lib/solargraph/api_map/cache.rb +50 -20
- data/lib/solargraph/api_map/source_to_yard.rb +17 -10
- data/lib/solargraph/api_map/store.rb +60 -15
- data/lib/solargraph/api_map.rb +282 -123
- data/lib/solargraph/bench.rb +3 -2
- data/lib/solargraph/cache.rb +29 -5
- data/lib/solargraph/complex_type/type_methods.rb +122 -39
- data/lib/solargraph/complex_type/unique_type.rb +310 -76
- data/lib/solargraph/complex_type.rb +166 -44
- data/lib/solargraph/convention.rb +0 -1
- data/lib/solargraph/converters/dd.rb +5 -0
- data/lib/solargraph/converters/dl.rb +3 -0
- data/lib/solargraph/converters/dt.rb +3 -0
- data/lib/solargraph/diagnostics/rubocop.rb +8 -7
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/diagnostics.rb +2 -2
- data/lib/solargraph/doc_map.rb +187 -0
- data/lib/solargraph/gem_pins.rb +72 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
- data/lib/solargraph/language_server/host/dispatch.rb +22 -5
- data/lib/solargraph/language_server/host/message_worker.rb +49 -5
- data/lib/solargraph/language_server/host/sources.rb +8 -65
- data/lib/solargraph/language_server/host.rb +65 -84
- data/lib/solargraph/language_server/message/base.rb +19 -12
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
- data/lib/solargraph/language_server/message/initialize.rb +19 -2
- data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +3 -1
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +3 -3
- data/lib/solargraph/language_server/message/text_document.rb +0 -1
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
- data/lib/solargraph/language_server/progress.rb +135 -0
- data/lib/solargraph/language_server/transport/adapter.rb +16 -1
- data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
- data/lib/solargraph/language_server.rb +1 -0
- data/lib/solargraph/library.rb +207 -111
- data/lib/solargraph/location.rb +15 -1
- data/lib/solargraph/page.rb +6 -0
- data/lib/solargraph/parser/comment_ripper.rb +4 -0
- data/lib/solargraph/parser/node_methods.rb +47 -7
- data/lib/solargraph/parser/node_processor/base.rb +11 -1
- data/lib/solargraph/parser/node_processor.rb +1 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
- data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +62 -43
- data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +57 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +7 -20
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +4 -4
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +8 -6
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
- data/lib/solargraph/parser/parser_gem.rb +12 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +8 -12
- data/lib/solargraph/pin/base.rb +78 -10
- data/lib/solargraph/pin/base_variable.rb +40 -7
- data/lib/solargraph/pin/block.rb +69 -46
- data/lib/solargraph/pin/callable.rb +147 -0
- data/lib/solargraph/pin/closure.rb +23 -3
- data/lib/solargraph/pin/common.rb +6 -6
- data/lib/solargraph/pin/conversions.rb +36 -5
- data/lib/solargraph/pin/delegated_method.rb +6 -2
- data/lib/solargraph/pin/documenting.rb +25 -32
- data/lib/solargraph/pin/instance_variable.rb +6 -2
- data/lib/solargraph/pin/local_variable.rb +13 -1
- data/lib/solargraph/pin/method.rb +205 -32
- data/lib/solargraph/pin/namespace.rb +20 -7
- data/lib/solargraph/pin/parameter.rb +41 -36
- data/lib/solargraph/pin/proxy_type.rb +1 -1
- data/lib/solargraph/pin/reference/override.rb +2 -2
- data/lib/solargraph/pin/reference.rb +8 -0
- data/lib/solargraph/pin/search.rb +3 -3
- data/lib/solargraph/pin/signature.rb +8 -14
- data/lib/solargraph/pin.rb +4 -2
- data/lib/solargraph/range.rb +4 -6
- data/lib/solargraph/rbs_map/conversions.rb +326 -76
- data/lib/solargraph/rbs_map/core_fills.rb +16 -33
- data/lib/solargraph/rbs_map/core_map.rb +3 -13
- data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
- data/lib/solargraph/rbs_map.rb +32 -13
- data/lib/solargraph/shell.rb +95 -72
- data/lib/solargraph/source/chain/array.rb +33 -0
- data/lib/solargraph/source/chain/block_symbol.rb +13 -0
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +152 -69
- data/lib/solargraph/source/chain/constant.rb +15 -1
- data/lib/solargraph/source/chain/if.rb +23 -0
- data/lib/solargraph/source/chain/link.rb +17 -2
- data/lib/solargraph/source/chain/or.rb +2 -2
- data/lib/solargraph/source/chain/z_super.rb +3 -3
- data/lib/solargraph/source/chain.rb +85 -26
- data/lib/solargraph/source/change.rb +3 -0
- data/lib/solargraph/source/cursor.rb +16 -2
- data/lib/solargraph/source/source_chainer.rb +8 -5
- data/lib/solargraph/source/updater.rb +1 -0
- data/lib/solargraph/source.rb +120 -148
- data/lib/solargraph/source_map/clip.rb +16 -27
- data/lib/solargraph/source_map/data.rb +30 -0
- data/lib/solargraph/source_map/mapper.rb +15 -3
- data/lib/solargraph/source_map.rb +48 -24
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker/rules.rb +6 -1
- data/lib/solargraph/type_checker.rb +150 -39
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +3 -5
- data/lib/solargraph/workspace/config.rb +9 -6
- data/lib/solargraph/workspace.rb +30 -3
- data/lib/solargraph/yard_map/cache.rb +6 -0
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +16 -3
- data/lib/solargraph/yard_map/mapper.rb +1 -1
- data/lib/solargraph/yard_map/to_method.rb +11 -4
- data/lib/solargraph/yard_map.rb +1 -292
- data/lib/solargraph/yard_tags.rb +20 -0
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +6 -4
- data/solargraph.gemspec +7 -6
- metadata +71 -82
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- data/lib/solargraph/documentor.rb +0 -76
- data/lib/solargraph/language_server/host/cataloger.rb +0 -56
- data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -50
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
- data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
- data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
- data/lib/solargraph/parser/legacy.rb +0 -12
- data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -153
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
- data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -51
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
- data/lib/solargraph/parser/rubyvm.rb +0 -40
- data/lib/solargraph/rbs_map/core_signs.rb +0 -33
- data/lib/yard-solargraph.rb +0 -33
@@ -4,15 +4,31 @@ module Solargraph
|
|
4
4
|
# A container for type data based on YARD type tags.
|
5
5
|
#
|
6
6
|
class ComplexType
|
7
|
+
GENERIC_TAG_NAME = 'generic'.freeze
|
7
8
|
# @!parse
|
8
9
|
# include TypeMethods
|
9
10
|
|
10
11
|
autoload :TypeMethods, 'solargraph/complex_type/type_methods'
|
11
12
|
autoload :UniqueType, 'solargraph/complex_type/unique_type'
|
12
13
|
|
13
|
-
# @param types [Array<UniqueType>]
|
14
|
+
# @param types [Array<UniqueType, ComplexType>]
|
14
15
|
def initialize types = [UniqueType::UNDEFINED]
|
15
|
-
@items
|
16
|
+
# @todo @items here should not need an annotation
|
17
|
+
# @type [Array<UniqueType>]
|
18
|
+
@items = types.flat_map(&:items).uniq(&:to_s)
|
19
|
+
end
|
20
|
+
|
21
|
+
def eql?(other)
|
22
|
+
self.class == other.class &&
|
23
|
+
@items == other.items
|
24
|
+
end
|
25
|
+
|
26
|
+
def ==(other)
|
27
|
+
self.eql?(other)
|
28
|
+
end
|
29
|
+
|
30
|
+
def hash
|
31
|
+
[self.class, @items].hash
|
16
32
|
end
|
17
33
|
|
18
34
|
# @param api_map [ApiMap]
|
@@ -21,34 +37,61 @@ module Solargraph
|
|
21
37
|
def qualify api_map, context = ''
|
22
38
|
red = reduce_object
|
23
39
|
types = red.items.map do |t|
|
24
|
-
next t if ['
|
40
|
+
next t if ['nil', 'void', 'undefined'].include?(t.name)
|
41
|
+
next t if ['::Boolean'].include?(t.rooted_name)
|
25
42
|
t.qualify api_map, context
|
26
43
|
end
|
27
44
|
ComplexType.new(types).reduce_object
|
28
45
|
end
|
29
46
|
|
47
|
+
# @param generics_to_resolve [Enumerable<String>]]
|
48
|
+
# @param context_type [UniqueType, nil]
|
49
|
+
# @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
|
50
|
+
# @return [self]
|
51
|
+
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
52
|
+
return self unless generic?
|
53
|
+
|
54
|
+
ComplexType.new(@items.map { |i| i.resolve_generics_from_context(generics_to_resolve, context_type, resolved_generic_values: resolved_generic_values) })
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [UniqueType]
|
30
58
|
def first
|
31
59
|
@items.first
|
32
60
|
end
|
33
61
|
|
62
|
+
# @return [String]
|
34
63
|
def to_rbs
|
35
|
-
((@items.length > 1 ? '(' : '') +
|
36
|
-
|
37
|
-
|
64
|
+
((@items.length > 1 ? '(' : '') +
|
65
|
+
@items.map(&:to_rbs).join(' | ') +
|
66
|
+
(@items.length > 1 ? ')' : ''))
|
67
|
+
end
|
68
|
+
|
69
|
+
# @param dst [ComplexType]
|
70
|
+
# @return [ComplexType]
|
71
|
+
def self_to_type dst
|
72
|
+
object_type_dst = dst.reduce_class_type
|
73
|
+
transform do |t|
|
74
|
+
next t if t.name != 'self'
|
75
|
+
object_type_dst
|
76
|
+
end
|
38
77
|
end
|
39
78
|
|
79
|
+
# @yieldparam [UniqueType]
|
80
|
+
# @return [Array]
|
40
81
|
def map &block
|
41
82
|
@items.map &block
|
42
83
|
end
|
43
84
|
|
44
85
|
# @yieldparam [UniqueType]
|
45
|
-
# @return [
|
86
|
+
# @return [Enumerable<UniqueType>]
|
46
87
|
def each &block
|
47
88
|
@items.each &block
|
48
89
|
end
|
49
90
|
|
50
91
|
# @yieldparam [UniqueType]
|
51
|
-
# @return [
|
92
|
+
# @return [void]
|
93
|
+
# @overload each_unique_type()
|
94
|
+
# @return [Enumerator<UniqueType>]
|
52
95
|
def each_unique_type &block
|
53
96
|
return enum_for(__method__) unless block_given?
|
54
97
|
|
@@ -57,14 +100,27 @@ module Solargraph
|
|
57
100
|
end
|
58
101
|
end
|
59
102
|
|
103
|
+
# @return [Integer]
|
60
104
|
def length
|
61
105
|
@items.length
|
62
106
|
end
|
63
107
|
|
108
|
+
# @return [Array<UniqueType>]
|
109
|
+
def to_a
|
110
|
+
@items
|
111
|
+
end
|
112
|
+
|
113
|
+
def tags
|
114
|
+
@items.map(&:tag).join(', ')
|
115
|
+
end
|
116
|
+
|
117
|
+
# @param index [Integer]
|
118
|
+
# @return [UniqueType]
|
64
119
|
def [](index)
|
65
120
|
@items[index]
|
66
121
|
end
|
67
122
|
|
123
|
+
# @return [Array<UniqueType>]
|
68
124
|
def select &block
|
69
125
|
@items.select &block
|
70
126
|
end
|
@@ -80,12 +136,16 @@ module Solargraph
|
|
80
136
|
@items.map(&:namespace)
|
81
137
|
end
|
82
138
|
|
139
|
+
# @param name [Symbol]
|
140
|
+
# @return [Object, nil]
|
83
141
|
def method_missing name, *args, &block
|
84
142
|
return if @items.first.nil?
|
85
143
|
return @items.first.send(name, *args, &block) if respond_to_missing?(name)
|
86
144
|
super
|
87
145
|
end
|
88
146
|
|
147
|
+
# @param name [Symbol]
|
148
|
+
# @param include_private [Boolean]
|
89
149
|
def respond_to_missing?(name, include_private = false)
|
90
150
|
TypeMethods.public_instance_methods.include?(name) || super
|
91
151
|
end
|
@@ -94,6 +154,10 @@ module Solargraph
|
|
94
154
|
map(&:tag).join(', ')
|
95
155
|
end
|
96
156
|
|
157
|
+
def rooted_tags
|
158
|
+
map(&:rooted_tag).join(', ')
|
159
|
+
end
|
160
|
+
|
97
161
|
def all? &block
|
98
162
|
@items.all? &block
|
99
163
|
end
|
@@ -106,54 +170,84 @@ module Solargraph
|
|
106
170
|
@items.any?(&:selfy?)
|
107
171
|
end
|
108
172
|
|
109
|
-
def
|
110
|
-
any?(&:
|
173
|
+
def generic?
|
174
|
+
any?(&:generic?)
|
111
175
|
end
|
112
176
|
|
113
|
-
|
114
|
-
|
115
|
-
|
177
|
+
# @param new_name [String, nil]
|
178
|
+
# @yieldparam t [UniqueType]
|
179
|
+
# @yieldreturn [UniqueType]
|
180
|
+
# @return [ComplexType]
|
181
|
+
def transform(new_name = nil, &transform_type)
|
182
|
+
raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::')
|
183
|
+
ComplexType.new(map { |ut| ut.transform(new_name, &transform_type) })
|
116
184
|
end
|
117
185
|
|
118
|
-
# @
|
186
|
+
# @return [self]
|
187
|
+
def force_rooted
|
188
|
+
transform do |t|
|
189
|
+
t.recreate(make_rooted: true)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# @param definitions [Pin::Namespace, Pin::Method]
|
194
|
+
# @param context_type [ComplexType]
|
119
195
|
# @return [ComplexType]
|
120
|
-
def
|
121
|
-
|
122
|
-
|
123
|
-
result = @items.map { |i| i.self_to red }
|
124
|
-
ComplexType.parse(*result.map(&:tag))
|
196
|
+
def resolve_generics definitions, context_type
|
197
|
+
result = @items.map { |i| i.resolve_generics(definitions, context_type) }
|
198
|
+
ComplexType.new(result)
|
125
199
|
end
|
126
200
|
|
127
201
|
def nullable?
|
128
202
|
@items.any?(&:nil_type?)
|
129
203
|
end
|
130
204
|
|
205
|
+
# @return [Array<ComplexType>]
|
131
206
|
def all_params
|
132
207
|
@items.first.all_params || []
|
133
208
|
end
|
134
209
|
|
135
|
-
|
210
|
+
# @return [ComplexType]
|
211
|
+
def reduce_class_type
|
212
|
+
new_items = items.flat_map do |type|
|
213
|
+
next type unless ['Module', 'Class'].include?(type.name)
|
214
|
+
|
215
|
+
type.all_params
|
216
|
+
end
|
217
|
+
ComplexType.new(new_items)
|
218
|
+
end
|
219
|
+
|
220
|
+
# every type and subtype in this union have been resolved to be
|
221
|
+
# fully qualified
|
222
|
+
def all_rooted?
|
223
|
+
all?(&:all_rooted?)
|
224
|
+
end
|
225
|
+
|
226
|
+
# every top-level type has resolved to be fully qualified; see
|
227
|
+
# #all_rooted? to check their subtypes as well
|
228
|
+
def rooted?
|
229
|
+
all?(&:rooted?)
|
230
|
+
end
|
136
231
|
|
137
232
|
attr_reader :items
|
138
233
|
|
139
|
-
def
|
140
|
-
|
141
|
-
ComplexType.try_parse(reduce_class(subtypes.join(', ')))
|
234
|
+
def rooted?
|
235
|
+
@items.all?(&:rooted?)
|
142
236
|
end
|
143
237
|
|
144
|
-
|
238
|
+
protected
|
145
239
|
|
146
|
-
# @
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
# @return [String]
|
152
|
-
def reduce_class dst
|
153
|
-
while dst =~ /^(Class|Module)\<(.*?)\>$/
|
154
|
-
dst = dst.sub(/^(Class|Module)\</, '').sub(/\>$/, '')
|
240
|
+
# @return [ComplexType]
|
241
|
+
def reduce_object
|
242
|
+
new_items = items.flat_map do |ut|
|
243
|
+
next [ut] if ut.name != 'Object' || ut.subtypes.empty?
|
244
|
+
ut.subtypes
|
155
245
|
end
|
156
|
-
|
246
|
+
ComplexType.new(new_items)
|
247
|
+
end
|
248
|
+
|
249
|
+
def bottom?
|
250
|
+
@items.all?(&:bot?)
|
157
251
|
end
|
158
252
|
|
159
253
|
class << self
|
@@ -170,9 +264,18 @@ module Solargraph
|
|
170
264
|
# used internally.
|
171
265
|
#
|
172
266
|
# @param *strings [Array<String>] The type definitions to parse
|
173
|
-
# @
|
174
|
-
# @
|
267
|
+
# @return [ComplexType]
|
268
|
+
# # @overload parse(*strings, partial: false)
|
269
|
+
# # @todo Need ability to use a literal true as a type below
|
270
|
+
# # @param partial [Boolean] True if the string is part of a another type
|
271
|
+
# # @return [Array<UniqueType>]
|
272
|
+
# @sg-ignore
|
273
|
+
# @todo To be able to select the right signature above,
|
274
|
+
# Chain::Call needs to know the decl type (:arg, :optarg,
|
275
|
+
# :kwarg, etc) of the arguments given, instead of just having
|
276
|
+
# an array of Chains as the arguments.
|
175
277
|
def parse *strings, partial: false
|
278
|
+
# @type [Hash{Array<String> => ComplexType}]
|
176
279
|
@cache ||= {}
|
177
280
|
unless partial
|
178
281
|
cached = @cache[strings]
|
@@ -197,7 +300,10 @@ module Solargraph
|
|
197
300
|
elsif base.end_with?('=')
|
198
301
|
raise ComplexTypeError, "Invalid hash thing" unless key_types.nil?
|
199
302
|
# types.push ComplexType.new([UniqueType.new(base[0..-2].strip)])
|
200
|
-
types.push UniqueType.
|
303
|
+
types.push UniqueType.parse(base[0..-2].strip, subtype_string)
|
304
|
+
# @todo this should either expand key_type's type
|
305
|
+
# automatically or complain about not being
|
306
|
+
# compatible with key_type's type in type checking
|
201
307
|
key_types = types
|
202
308
|
types = []
|
203
309
|
base.clear
|
@@ -220,12 +326,12 @@ module Solargraph
|
|
220
326
|
paren_stack += 1
|
221
327
|
elsif char == ')'
|
222
328
|
paren_stack -= 1
|
223
|
-
subtype_string += char
|
329
|
+
subtype_string += char
|
224
330
|
raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack < 0
|
225
331
|
next
|
226
332
|
elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0
|
227
333
|
# types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)])
|
228
|
-
types.push UniqueType.
|
334
|
+
types.push UniqueType.parse(base.strip, subtype_string.strip)
|
229
335
|
base.clear
|
230
336
|
subtype_string.clear
|
231
337
|
next
|
@@ -238,7 +344,7 @@ module Solargraph
|
|
238
344
|
end
|
239
345
|
raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 || curly_stack != 0 || paren_stack != 0
|
240
346
|
# types.push ComplexType.new([UniqueType.new(base, subtype_string)])
|
241
|
-
types.push UniqueType.
|
347
|
+
types.push UniqueType.parse(base.strip, subtype_string.strip)
|
242
348
|
end
|
243
349
|
unless key_types.nil?
|
244
350
|
raise ComplexTypeError, "Invalid use of key/value parameters" unless partial
|
@@ -255,17 +361,33 @@ module Solargraph
|
|
255
361
|
def try_parse *strings
|
256
362
|
parse *strings
|
257
363
|
rescue ComplexTypeError => e
|
258
|
-
Solargraph.logger.info "Error parsing complex type
|
364
|
+
Solargraph.logger.info "Error parsing complex type `#{strings.join(', ')}`: #{e.message}"
|
259
365
|
ComplexType::UNDEFINED
|
260
366
|
end
|
261
367
|
end
|
262
368
|
|
263
369
|
VOID = ComplexType.parse('void')
|
264
370
|
UNDEFINED = ComplexType.parse('undefined')
|
265
|
-
SYMBOL = ComplexType.parse('Symbol')
|
266
|
-
ROOT = ComplexType.parse('Class<>')
|
371
|
+
SYMBOL = ComplexType.parse('::Symbol')
|
372
|
+
ROOT = ComplexType.parse('::Class<>')
|
267
373
|
NIL = ComplexType.parse('nil')
|
268
374
|
SELF = ComplexType.parse('self')
|
269
|
-
BOOLEAN = ComplexType.parse('Boolean')
|
375
|
+
BOOLEAN = ComplexType.parse('::Boolean')
|
376
|
+
BOT = ComplexType.parse('bot')
|
377
|
+
|
378
|
+
private
|
379
|
+
|
380
|
+
# @todo This is a quick and dirty hack that forces `self` keywords
|
381
|
+
# to reference an instance of their class and never the class itself.
|
382
|
+
# This behavior may change depending on which result is expected
|
383
|
+
# from YARD conventions. See https://github.com/lsegal/yard/issues/1257
|
384
|
+
# @param dst [String]
|
385
|
+
# @return [String]
|
386
|
+
def reduce_class dst
|
387
|
+
while dst =~ /^(Class|Module)\<(.*?)\>$/
|
388
|
+
dst = dst.sub(/^(Class|Module)\</, '').sub(/\>$/, '')
|
389
|
+
end
|
390
|
+
dst
|
391
|
+
end
|
270
392
|
end
|
271
393
|
end
|
@@ -1,6 +1,11 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
1
3
|
module ReverseMarkdown
|
2
4
|
module Converters
|
3
5
|
class Dd < Base
|
6
|
+
# @return [String]
|
7
|
+
# @param node [Nokogiri::XML::Element]
|
8
|
+
# @param state [Hash]
|
4
9
|
def convert node, state = {}
|
5
10
|
content = treat_children(node, state)
|
6
11
|
": #{content.strip}\n"
|
@@ -29,9 +29,9 @@ module Solargraph
|
|
29
29
|
store = RuboCop::ConfigStore.new
|
30
30
|
runner = RuboCop::Runner.new(options, store)
|
31
31
|
result = redirect_stdout{ runner.run(paths) }
|
32
|
-
|
32
|
+
|
33
33
|
return [] if result.empty?
|
34
|
-
|
34
|
+
|
35
35
|
make_array JSON.parse(result)
|
36
36
|
rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
|
37
37
|
raise DiagnosticsError, "Error in RuboCop configuration: #{e.message}"
|
@@ -48,7 +48,7 @@ module Solargraph
|
|
48
48
|
args.find { |a| a =~ /version=/ }.to_s.split('=').last
|
49
49
|
end
|
50
50
|
|
51
|
-
# @param resp [Hash]
|
51
|
+
# @param resp [Hash{String => Array<Hash{String => Array<Hash{String => undefined}>}>}]
|
52
52
|
# @return [Array<Hash>]
|
53
53
|
def make_array resp
|
54
54
|
diagnostics = []
|
@@ -62,8 +62,8 @@ module Solargraph
|
|
62
62
|
|
63
63
|
# Convert a RuboCop offense to an LSP diagnostic
|
64
64
|
#
|
65
|
-
# @param off [Hash] Offense received from Rubocop
|
66
|
-
# @return [Hash] LSP diagnostic
|
65
|
+
# @param off [Hash{String => unknown}] Offense received from Rubocop
|
66
|
+
# @return [Hash{Symbol => Hash, String, Integer}] LSP diagnostic
|
67
67
|
def offense_to_diagnostic off
|
68
68
|
{
|
69
69
|
range: offense_range(off).to_hash,
|
@@ -81,19 +81,20 @@ module Solargraph
|
|
81
81
|
Range.new(offense_start_position(off), offense_ending_position(off))
|
82
82
|
end
|
83
83
|
|
84
|
-
# @param off [Hash]
|
84
|
+
# @param off [Hash{String => Hash{String => Integer}}]
|
85
85
|
# @return [Position]
|
86
86
|
def offense_start_position off
|
87
87
|
Position.new(off['location']['start_line'] - 1, off['location']['start_column'] - 1)
|
88
88
|
end
|
89
89
|
|
90
|
-
# @param off [Hash]
|
90
|
+
# @param off [Hash{String => Hash{String => Integer}}]
|
91
91
|
# @return [Position]
|
92
92
|
def offense_ending_position off
|
93
93
|
if off['location']['start_line'] != off['location']['last_line']
|
94
94
|
Position.new(off['location']['start_line'], 0)
|
95
95
|
else
|
96
96
|
start_line = off['location']['start_line'] - 1
|
97
|
+
# @type [Integer]
|
97
98
|
last_column = off['location']['last_column']
|
98
99
|
line = @source.code.lines[start_line]
|
99
100
|
col_off = if line.nil? || line.empty?
|
@@ -12,6 +12,7 @@ module Solargraph
|
|
12
12
|
#
|
13
13
|
# @param version [String, nil]
|
14
14
|
# @raise [InvalidRubocopVersionError] if _version_ is not installed
|
15
|
+
# @return [void]
|
15
16
|
def require_rubocop(version = nil)
|
16
17
|
begin
|
17
18
|
gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path
|
@@ -6,6 +6,7 @@ module Solargraph
|
|
6
6
|
# parameters, and invalid param tags.
|
7
7
|
#
|
8
8
|
class TypeCheck < Base
|
9
|
+
# @return [Array<Hash>]
|
9
10
|
def diagnose source, api_map
|
10
11
|
# return [] unless args.include?('always') || api_map.workspaced?(source.filename)
|
11
12
|
severity = Diagnostics::Severities::ERROR
|
@@ -33,14 +33,14 @@ module Solargraph
|
|
33
33
|
# Find a reporter by name.
|
34
34
|
#
|
35
35
|
# @param name [String] The name with which the reporter was registered
|
36
|
-
# @return [Class<Solargraph::Diagnostics::Base
|
36
|
+
# @return [Class<Solargraph::Diagnostics::Base>, nil]
|
37
37
|
def reporter name
|
38
38
|
reporter_hash[name]
|
39
39
|
end
|
40
40
|
|
41
41
|
private
|
42
42
|
|
43
|
-
# @return [Hash]
|
43
|
+
# @return [Hash{String => Class<Solargraph::Diagnostics::Base>}]
|
44
44
|
def reporter_hash
|
45
45
|
@reporter_hash ||= {}
|
46
46
|
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
# A collection of pins generated from required gems.
|
5
|
+
#
|
6
|
+
class DocMap
|
7
|
+
# @return [Array<String>]
|
8
|
+
attr_reader :requires
|
9
|
+
|
10
|
+
# @return [Array<Gem::Specification>]
|
11
|
+
attr_reader :preferences
|
12
|
+
|
13
|
+
# @return [Array<Pin::Base>]
|
14
|
+
attr_reader :pins
|
15
|
+
|
16
|
+
# @return [Array<Gem::Specification>]
|
17
|
+
attr_reader :uncached_gemspecs
|
18
|
+
|
19
|
+
# @param requires [Array<String>]
|
20
|
+
# @param preferences [Array<Gem::Specification>]
|
21
|
+
# @param rbs_path [String, Pathname, nil]
|
22
|
+
def initialize(requires, preferences, rbs_path = nil)
|
23
|
+
@requires = requires.compact
|
24
|
+
@preferences = preferences.compact
|
25
|
+
@rbs_path = rbs_path
|
26
|
+
generate
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Array<Gem::Specification>]
|
30
|
+
def gemspecs
|
31
|
+
@gemspecs ||= required_gem_map.values.compact
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Array<String>]
|
35
|
+
def unresolved_requires
|
36
|
+
@unresolved_requires ||= required_gem_map.select { |_, gemspec| gemspec.nil? }.keys
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Hash{Gem::Specification => Array[Pin::Base]}]
|
40
|
+
def self.gems_in_memory
|
41
|
+
@gems_in_memory ||= {}
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Set<Gem::Specification>]
|
45
|
+
def dependencies
|
46
|
+
@dependencies ||= (gemspecs.flat_map { |spec| fetch_dependencies(spec) } - gemspecs).to_set
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
# @return [void]
|
52
|
+
def generate
|
53
|
+
@pins = []
|
54
|
+
@uncached_gemspecs = []
|
55
|
+
required_gem_map.each do |path, gemspec|
|
56
|
+
if gemspec
|
57
|
+
try_cache gemspec
|
58
|
+
else
|
59
|
+
try_stdlib_map path
|
60
|
+
end
|
61
|
+
end
|
62
|
+
dependencies.each { |dep| try_cache dep }
|
63
|
+
@uncached_gemspecs.uniq!
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [Hash{String => Gem::Specification, nil}]
|
67
|
+
def required_gem_map
|
68
|
+
@required_gem_map ||= requires.to_h { |path| [path, resolve_path_to_gemspec(path)] }
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Hash{String => Gem::Specification}]
|
72
|
+
def preference_map
|
73
|
+
@preference_map ||= preferences.to_h { |gemspec| [gemspec.name, gemspec] }
|
74
|
+
end
|
75
|
+
|
76
|
+
# @param gemspec [Gem::Specification]
|
77
|
+
# @return [void]
|
78
|
+
def try_cache gemspec
|
79
|
+
return if try_gem_in_memory(gemspec)
|
80
|
+
cache_file = File.join('gems', "#{gemspec.name}-#{gemspec.version}.ser")
|
81
|
+
if Cache.exist?(cache_file)
|
82
|
+
cached = Cache.load(cache_file)
|
83
|
+
gempins = update_from_collection(gemspec, cached)
|
84
|
+
self.class.gems_in_memory[gemspec] = gempins
|
85
|
+
@pins.concat gempins
|
86
|
+
else
|
87
|
+
Solargraph.logger.debug "No pin cache for #{gemspec.name} #{gemspec.version}"
|
88
|
+
@uncached_gemspecs.push gemspec
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# @param path [String] require path that might be in the RBS stdlib collection
|
93
|
+
# @return [void]
|
94
|
+
def try_stdlib_map path
|
95
|
+
map = RbsMap::StdlibMap.load(path)
|
96
|
+
if map.resolved?
|
97
|
+
Solargraph.logger.debug "Loading stdlib pins for #{path}"
|
98
|
+
@pins.concat map.pins
|
99
|
+
else
|
100
|
+
# @todo Temporarily ignoring unresolved `require 'set'`
|
101
|
+
Solargraph.logger.debug "Require path #{path} could not be resolved" unless path == 'set'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# @param gemspec [Gem::Specification]
|
106
|
+
# @return [Boolean]
|
107
|
+
def try_gem_in_memory gemspec
|
108
|
+
gempins = DocMap.gems_in_memory[gemspec]
|
109
|
+
return false unless gempins
|
110
|
+
Solargraph.logger.debug "Found #{gemspec.name} #{gemspec.version} in memory"
|
111
|
+
@pins.concat gempins
|
112
|
+
true
|
113
|
+
end
|
114
|
+
|
115
|
+
def update_from_collection gemspec, gempins
|
116
|
+
return gempins unless @rbs_path && File.directory?(@rbs_path)
|
117
|
+
return gempins if RbsMap.new(gemspec.name, gemspec.version).resolved?
|
118
|
+
|
119
|
+
rbs_map = RbsMap.new(gemspec.name, gemspec.version, directories: [@rbs_path])
|
120
|
+
return gempins unless rbs_map.resolved?
|
121
|
+
|
122
|
+
Solargraph.logger.info "Updating #{gemspec.name} #{gemspec.version} from collection"
|
123
|
+
GemPins.combine(gempins, rbs_map)
|
124
|
+
end
|
125
|
+
|
126
|
+
# @param path [String]
|
127
|
+
# @return [Gem::Specification, nil]
|
128
|
+
def resolve_path_to_gemspec path
|
129
|
+
return nil if path.empty?
|
130
|
+
|
131
|
+
gemspec = Gem::Specification.find_by_path(path)
|
132
|
+
if gemspec.nil?
|
133
|
+
gem_name_guess = path.split('/').first
|
134
|
+
begin
|
135
|
+
# this can happen when the gem is included via a local path in
|
136
|
+
# a Gemfile; Gem doesn't try to index the paths in that case.
|
137
|
+
#
|
138
|
+
# See if we can make a good guess:
|
139
|
+
potential_gemspec = Gem::Specification.find_by_name(gem_name_guess)
|
140
|
+
file = "lib/#{path}.rb"
|
141
|
+
gemspec = potential_gemspec if potential_gemspec.files.any? { |gemspec_file| file == gemspec_file }
|
142
|
+
rescue Gem::MissingSpecError
|
143
|
+
Solargraph.logger.debug "Require path #{path} could not be resolved to a gem via find_by_path or guess of #{gem_name_guess}"
|
144
|
+
nil
|
145
|
+
end
|
146
|
+
end
|
147
|
+
gemspec_or_preference gemspec
|
148
|
+
end
|
149
|
+
|
150
|
+
# @param gemspec [Gem::Specification, nil]
|
151
|
+
# @return [Gem::Specification, nil]
|
152
|
+
def gemspec_or_preference gemspec
|
153
|
+
return gemspec unless gemspec && preference_map.key?(gemspec.name)
|
154
|
+
return gemspec if gemspec.version == preference_map[gemspec.name].version
|
155
|
+
|
156
|
+
change_gemspec_version gemspec, preference_map[by_path.name].version
|
157
|
+
end
|
158
|
+
|
159
|
+
# @param gemspec [Gem::Specification]
|
160
|
+
# @param version [Gem::Version]
|
161
|
+
# @return [Gem::Specification]
|
162
|
+
def change_gemspec_version gemspec, version
|
163
|
+
Gem::Specification.find_by_name(gemspec.name, "= #{version}")
|
164
|
+
rescue Gem::MissingSpecError
|
165
|
+
Solargraph.logger.info "Gem #{gemspec.name} version #{version} not found. Using #{gemspec.version} instead"
|
166
|
+
gemspec
|
167
|
+
end
|
168
|
+
|
169
|
+
# @param gemspec [Gem::Specification]
|
170
|
+
# @return [Array<Gem::Specification>]
|
171
|
+
def fetch_dependencies gemspec
|
172
|
+
only_runtime_dependencies(gemspec).each_with_object(Set.new) do |spec, deps|
|
173
|
+
Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}"
|
174
|
+
dep = Gem::Specification.find_by_name(spec.name, spec.requirement)
|
175
|
+
deps.merge fetch_dependencies(dep) if deps.add?(dep)
|
176
|
+
rescue Gem::MissingSpecError
|
177
|
+
Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirements} for #{gemspec.name} not found."
|
178
|
+
end.to_a
|
179
|
+
end
|
180
|
+
|
181
|
+
# @param gemspec [Gem::Specification]
|
182
|
+
# @return [Array<Gem::Dependency>]
|
183
|
+
def only_runtime_dependencies gemspec
|
184
|
+
gemspec.dependencies - gemspec.development_dependencies
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|