solargraph 0.39.13 → 0.40.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/.travis.yml +2 -7
- data/CHANGELOG.md +984 -0
- data/Rakefile +12 -1
- data/SPONSORS.md +1 -0
- data/lib/solargraph.rb +2 -4
- data/lib/solargraph/api_map.rb +75 -74
- data/lib/solargraph/api_map/cache.rb +2 -2
- data/lib/solargraph/api_map/store.rb +4 -8
- data/lib/solargraph/{bundle.rb → bench.rb} +6 -2
- data/lib/solargraph/compat.rb +14 -0
- data/lib/solargraph/complex_type.rb +2 -2
- data/lib/solargraph/convention.rb +14 -5
- data/lib/solargraph/convention/base.rb +16 -8
- data/lib/solargraph/convention/gemfile.rb +2 -5
- data/lib/solargraph/convention/gemspec.rb +3 -6
- data/lib/solargraph/convention/rspec.rb +3 -6
- data/lib/solargraph/documentor.rb +2 -0
- data/lib/solargraph/environ.rb +11 -6
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +6 -1
- data/lib/solargraph/language_server/message/text_document/definition.rb +1 -1
- data/lib/solargraph/library.rb +7 -7
- data/lib/solargraph/parser/legacy/node_chainer.rb +7 -7
- data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +1 -1
- data/lib/solargraph/parser/legacy/node_processors/send_node.rb +36 -23
- data/lib/solargraph/parser/node_processor/base.rb +3 -0
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +9 -9
- data/lib/solargraph/parser/rubyvm/node_methods.rb +1 -1
- data/lib/solargraph/parser/rubyvm/node_processors.rb +1 -0
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +35 -11
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +1 -1
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +40 -29
- data/lib/solargraph/pin.rb +0 -3
- data/lib/solargraph/pin/common.rb +1 -1
- data/lib/solargraph/pin/conversions.rb +3 -4
- data/lib/solargraph/pin/documenting.rb +3 -9
- data/lib/solargraph/pin/method.rb +141 -7
- data/lib/solargraph/pin/method_alias.rb +1 -1
- data/lib/solargraph/position.rb +2 -14
- data/lib/solargraph/shell.rb +1 -0
- data/lib/solargraph/source.rb +10 -6
- data/lib/solargraph/source/chain.rb +18 -5
- data/lib/solargraph/source_map.rb +4 -1
- data/lib/solargraph/source_map/clip.rb +3 -2
- data/lib/solargraph/source_map/mapper.rb +10 -6
- data/lib/solargraph/type_checker.rb +35 -39
- data/lib/solargraph/type_checker/param_def.rb +1 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map.rb +40 -47
- data/lib/solargraph/yard_map/core_fills.rb +185 -0
- data/lib/solargraph/yard_map/helpers.rb +16 -0
- data/lib/solargraph/yard_map/mapper.rb +14 -8
- data/lib/solargraph/{pin/yard_pin/constant.rb → yard_map/mapper/to_constant.rb} +6 -6
- data/lib/solargraph/yard_map/mapper/to_method.rb +78 -0
- data/lib/solargraph/{pin/yard_pin/namespace.rb → yard_map/mapper/to_namespace.rb} +6 -6
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +1 -1
- data/lib/solargraph/yard_map/stdlib_fills.rb +43 -0
- data/lib/solargraph/yard_map/to_method.rb +79 -0
- data/solargraph.gemspec +4 -4
- metadata +20 -34
- data/lib/solargraph/core_fills.rb +0 -159
- data/lib/solargraph/pin/attribute.rb +0 -49
- data/lib/solargraph/pin/base_method.rb +0 -141
- data/lib/solargraph/pin/yard_pin.rb +0 -12
- data/lib/solargraph/pin/yard_pin/method.rb +0 -80
- data/lib/solargraph/pin/yard_pin/yard_mixin.rb +0 -20
- data/lib/solargraph/stdlib_fills.rb +0 -40
- data/travis-bundler.rb +0 -11
data/lib/solargraph/position.rb
CHANGED
@@ -40,20 +40,8 @@ module Solargraph
|
|
40
40
|
# @param position [Position]
|
41
41
|
# @return [Integer]
|
42
42
|
def self.to_offset text, position
|
43
|
-
|
44
|
-
|
45
|
-
line = position.line
|
46
|
-
column = position.character
|
47
|
-
text.lines.each do |l|
|
48
|
-
line_length = l.length
|
49
|
-
if feed == line
|
50
|
-
result += column
|
51
|
-
break
|
52
|
-
end
|
53
|
-
result += line_length
|
54
|
-
feed += 1
|
55
|
-
end
|
56
|
-
result
|
43
|
+
return 0 if text.empty?
|
44
|
+
text.lines[0...position.line].sum(&:length) + position.character
|
57
45
|
end
|
58
46
|
|
59
47
|
# Get a numeric offset for the specified text and a position identified
|
data/lib/solargraph/shell.rb
CHANGED
@@ -153,6 +153,7 @@ module Solargraph
|
|
153
153
|
probcount += problems.length
|
154
154
|
end
|
155
155
|
puts "#{probcount} problem#{probcount != 1 ? 's' : ''} found#{files.length != 1 ? " in #{filecount} of #{files.length} files" : ''}."
|
156
|
+
exit 1 if probcount > 0
|
156
157
|
end
|
157
158
|
|
158
159
|
desc 'scan', 'Test the workspace for problems'
|
data/lib/solargraph/source.rb
CHANGED
@@ -284,7 +284,7 @@ module Solargraph
|
|
284
284
|
|
285
285
|
FOLDING_NODE_TYPES = if Parser.rubyvm?
|
286
286
|
%i[
|
287
|
-
CLASS SCLASS MODULE DEFN DEFS IF WHILE UNLESS ITER STR
|
287
|
+
CLASS SCLASS MODULE DEFN DEFS IF WHILE UNLESS ITER STR HASH ARRAY LIST
|
288
288
|
].freeze
|
289
289
|
else
|
290
290
|
%i[
|
@@ -345,18 +345,22 @@ module Solargraph
|
|
345
345
|
|
346
346
|
# @param top [Parser::AST::Node]
|
347
347
|
# @param result [Array<Range>]
|
348
|
+
# @param parent [Symbol]
|
348
349
|
# @return [void]
|
349
|
-
def inner_folding_ranges top, result = []
|
350
|
+
def inner_folding_ranges top, result = [], parent = nil
|
350
351
|
# return unless top.is_a?(::Parser::AST::Node)
|
351
352
|
return unless Parser.is_ast_node?(top)
|
352
353
|
if FOLDING_NODE_TYPES.include?(top.type)
|
353
|
-
|
354
|
-
|
355
|
-
|
354
|
+
# @todo Smelly exception for hash's first-level array in RubyVM
|
355
|
+
unless [:ARRAY, :LIST].include?(top.type) && parent == :HASH
|
356
|
+
range = Range.from_node(top)
|
357
|
+
if result.empty? || range.start.line > result.last.start.line
|
358
|
+
result.push range unless range.ending.line - range.start.line < 2
|
359
|
+
end
|
356
360
|
end
|
357
361
|
end
|
358
362
|
top.children.each do |child|
|
359
|
-
inner_folding_ranges(child, result)
|
363
|
+
inner_folding_ranges(child, result, top.type)
|
360
364
|
end
|
361
365
|
end
|
362
366
|
|
@@ -110,18 +110,21 @@ module Solargraph
|
|
110
110
|
# @param api_map [ApiMap]
|
111
111
|
# @return [ComplexType]
|
112
112
|
def infer_first_defined pins, context, api_map
|
113
|
-
|
113
|
+
possibles = []
|
114
114
|
pins.each do |pin|
|
115
115
|
# Avoid infinite recursion
|
116
116
|
next if @@inference_stack.include?(pin.identity)
|
117
117
|
@@inference_stack.push pin.identity
|
118
118
|
type = pin.typify(api_map)
|
119
119
|
@@inference_stack.pop
|
120
|
-
|
120
|
+
if type.defined?
|
121
|
+
possibles.push type
|
122
|
+
break if pin.is_a?(Pin::Method)
|
123
|
+
end
|
121
124
|
end
|
122
|
-
if
|
125
|
+
if possibles.empty?
|
123
126
|
# Limit method inference recursion
|
124
|
-
return
|
127
|
+
return ComplexType::UNDEFINED if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
|
125
128
|
@@inference_depth += 1
|
126
129
|
pins.each do |pin|
|
127
130
|
# Avoid infinite recursion
|
@@ -129,10 +132,20 @@ module Solargraph
|
|
129
132
|
@@inference_stack.push pin.identity
|
130
133
|
type = pin.probe(api_map)
|
131
134
|
@@inference_stack.pop
|
132
|
-
|
135
|
+
if type.defined?
|
136
|
+
possibles.push type
|
137
|
+
break if pin.is_a?(Pin::Method)
|
138
|
+
end
|
133
139
|
end
|
134
140
|
@@inference_depth -= 1
|
135
141
|
end
|
142
|
+
return ComplexType::UNDEFINED if possibles.empty?
|
143
|
+
type = if possibles.length > 1
|
144
|
+
sorted = possibles.map { |t| t.rooted? ? "::#{t}" : t.to_s }.sort { |a, _| a == 'nil' ? 1 : 0 }
|
145
|
+
ComplexType.parse(*sorted)
|
146
|
+
else
|
147
|
+
possibles.first
|
148
|
+
end
|
136
149
|
return type if context.nil? || context.return_type.undefined?
|
137
150
|
type.self_to(context.return_type.namespace)
|
138
151
|
end
|
@@ -30,7 +30,7 @@ module Solargraph
|
|
30
30
|
@source = source.dup
|
31
31
|
@pins = pins
|
32
32
|
@locals = locals
|
33
|
-
environ.merge Convention.
|
33
|
+
environ.merge Convention.for_local(self) unless filename.nil?
|
34
34
|
@pin_class_hash = pins.to_set.classify(&:class).transform_values(&:to_a)
|
35
35
|
@pin_select_cache = {}
|
36
36
|
end
|
@@ -168,6 +168,9 @@ module Solargraph
|
|
168
168
|
position = Position.new(line, character)
|
169
169
|
found = nil
|
170
170
|
pins.each do |pin|
|
171
|
+
# @todo Attribute pins should not be treated like closures, but
|
172
|
+
# there's probably a better way to handle it
|
173
|
+
next if pin.is_a?(Pin::Method) && pin.attribute?
|
171
174
|
found = pin if (klasses.empty? || klasses.any? { |kls| pin.is_a?(kls) } ) && pin.location.range.contain?(position)
|
172
175
|
break if pin.location.range.start.line > line
|
173
176
|
end
|
@@ -149,7 +149,7 @@ module Solargraph
|
|
149
149
|
frag_start = cursor.start_of_word.to_s.downcase
|
150
150
|
filtered = result.uniq(&:name).select { |s|
|
151
151
|
s.name.downcase.start_with?(frag_start) &&
|
152
|
-
(!s.is_a?(Pin::
|
152
|
+
(!s.is_a?(Pin::Method) || s.name.match(/^[a-z0-9_]+(\!|\?|=)?$/i))
|
153
153
|
}
|
154
154
|
Completion.new(filtered, cursor.range)
|
155
155
|
end
|
@@ -212,7 +212,8 @@ module Solargraph
|
|
212
212
|
result.concat api_map.get_constants(context_pin.context.namespace, *gates)
|
213
213
|
result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
|
214
214
|
result.concat api_map.get_methods('Kernel')
|
215
|
-
result.concat ApiMap.keywords
|
215
|
+
# result.concat ApiMap.keywords
|
216
|
+
result.concat api_map.keyword_pins
|
216
217
|
result.concat yielded_self_pins
|
217
218
|
end
|
218
219
|
end
|
@@ -126,27 +126,31 @@ module Solargraph
|
|
126
126
|
namespace = closure_at(source_position)
|
127
127
|
t = (directive.tag.types.nil? || directive.tag.types.empty?) ? nil : directive.tag.types.flatten.join('')
|
128
128
|
if t.nil? || t.include?('r')
|
129
|
-
pins.push Solargraph::Pin::
|
129
|
+
pins.push Solargraph::Pin::Method.new(
|
130
130
|
location: location,
|
131
131
|
closure: namespace,
|
132
132
|
name: directive.tag.name,
|
133
133
|
comments: docstring.all.to_s,
|
134
|
-
access: :reader,
|
135
134
|
scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
|
136
135
|
visibility: :public,
|
137
|
-
explicit: false
|
136
|
+
explicit: false,
|
137
|
+
attribute: true
|
138
138
|
)
|
139
139
|
end
|
140
140
|
if t.nil? || t.include?('w')
|
141
|
-
pins.push Solargraph::Pin::
|
141
|
+
pins.push Solargraph::Pin::Method.new(
|
142
142
|
location: location,
|
143
143
|
closure: namespace,
|
144
144
|
name: "#{directive.tag.name}=",
|
145
145
|
comments: docstring.all.to_s,
|
146
|
-
access: :writer,
|
147
146
|
scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
|
148
|
-
visibility: :public
|
147
|
+
visibility: :public,
|
148
|
+
attribute: true
|
149
149
|
)
|
150
|
+
pins.last.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
|
151
|
+
if pins.last.return_type.defined?
|
152
|
+
pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
|
153
|
+
end
|
150
154
|
end
|
151
155
|
when 'parse'
|
152
156
|
begin
|
@@ -73,15 +73,15 @@ module Solargraph
|
|
73
73
|
# @return [Array<Problem>]
|
74
74
|
def method_tag_problems
|
75
75
|
result = []
|
76
|
-
# @param pin [Pin::
|
77
|
-
source_map.pins_by_class(Pin::
|
76
|
+
# @param pin [Pin::Method]
|
77
|
+
source_map.pins_by_class(Pin::Method).each do |pin|
|
78
78
|
result.concat method_return_type_problems_for(pin)
|
79
79
|
result.concat method_param_type_problems_for(pin)
|
80
80
|
end
|
81
81
|
result
|
82
82
|
end
|
83
83
|
|
84
|
-
# @param pin [Pin::
|
84
|
+
# @param pin [Pin::Method]
|
85
85
|
# @return [Array<Problem>]
|
86
86
|
def method_return_type_problems_for pin
|
87
87
|
result = []
|
@@ -115,7 +115,7 @@ module Solargraph
|
|
115
115
|
pin.location && source_map.source.comment_at?(pin.location.range.ending)
|
116
116
|
end
|
117
117
|
|
118
|
-
# @param pin [Pin::
|
118
|
+
# @param pin [Pin::Method]
|
119
119
|
# @return [Array<Problem>]
|
120
120
|
def method_param_type_problems_for pin
|
121
121
|
stack = api_map.get_method_stack(pin.namespace, pin.name, scope: pin.scope)
|
@@ -147,14 +147,12 @@ module Solargraph
|
|
147
147
|
result = []
|
148
148
|
all_variables.each do |pin|
|
149
149
|
if pin.return_type.defined?
|
150
|
-
# @todo Somwhere in here we still need to determine if the variable is defined by an external call
|
151
150
|
declared = pin.typify(api_map)
|
152
151
|
if declared.defined?
|
153
152
|
if rules.validate_tags?
|
154
153
|
inferred = pin.probe(api_map)
|
155
154
|
if inferred.undefined?
|
156
155
|
next if rules.ignore_all_undefined?
|
157
|
-
# next unless internal?(pin) # @todo This might be redundant for variables
|
158
156
|
if declared_externally?(pin)
|
159
157
|
ignored_pins.push pin
|
160
158
|
else
|
@@ -172,7 +170,6 @@ module Solargraph
|
|
172
170
|
result.push Problem.new(pin.location, "Unresolved type #{pin.return_type} for variable #{pin.name}", pin: pin)
|
173
171
|
end
|
174
172
|
else
|
175
|
-
# @todo Check if the variable is defined by an external call
|
176
173
|
inferred = pin.probe(api_map)
|
177
174
|
if inferred.undefined? && declared_externally?(pin)
|
178
175
|
ignored_pins.push pin
|
@@ -227,7 +224,7 @@ module Solargraph
|
|
227
224
|
base = base.base
|
228
225
|
end
|
229
226
|
closest = found.typify(api_map) if found
|
230
|
-
if !found || closest.defined?
|
227
|
+
if !found || (closest.defined? && internal_or_core?(found))
|
231
228
|
unless ignored_pins.include?(found)
|
232
229
|
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
|
233
230
|
@marked_ranges.push rng
|
@@ -244,8 +241,8 @@ module Solargraph
|
|
244
241
|
base = chain
|
245
242
|
until base.links.length == 1 && base.undefined?
|
246
243
|
pins = base.define(api_map, block_pin, locals)
|
247
|
-
if pins.first.is_a?(Pin::
|
248
|
-
# @type [Pin::
|
244
|
+
if pins.first.is_a?(Pin::Method)
|
245
|
+
# @type [Pin::Method]
|
249
246
|
pin = pins.first
|
250
247
|
ap = if base.links.last.is_a?(Solargraph::Source::Chain::ZSuper)
|
251
248
|
arity_problems_for(pin, fake_args_for(block_pin), location)
|
@@ -313,7 +310,6 @@ module Solargraph
|
|
313
310
|
end
|
314
311
|
else
|
315
312
|
if par.decl == :kwarg
|
316
|
-
# @todo Problem: missing required keyword argument
|
317
313
|
result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
318
314
|
end
|
319
315
|
end
|
@@ -360,9 +356,14 @@ module Solargraph
|
|
360
356
|
|
361
357
|
# @param pin [Pin::Base]
|
362
358
|
def internal? pin
|
359
|
+
return false if pin.nil?
|
363
360
|
pin.location && api_map.bundled?(pin.location.filename)
|
364
361
|
end
|
365
362
|
|
363
|
+
def internal_or_core? pin
|
364
|
+
internal?(pin) || api_map.yard_map.core_pins.include?(pin) || api_map.yard_map.stdlib_pins.include?(pin)
|
365
|
+
end
|
366
|
+
|
366
367
|
# @param pin [Pin::Base]
|
367
368
|
def external? pin
|
368
369
|
!internal? pin
|
@@ -395,7 +396,7 @@ module Solargraph
|
|
395
396
|
true
|
396
397
|
end
|
397
398
|
|
398
|
-
# @param pin [Pin::
|
399
|
+
# @param pin [Pin::Method]
|
399
400
|
def arity_problems_for(pin, arguments, location)
|
400
401
|
return [] unless pin.explicit?
|
401
402
|
return [] if pin.parameters.empty? && arguments.empty?
|
@@ -410,29 +411,29 @@ module Solargraph
|
|
410
411
|
if unchecked.empty? && pin.parameters.any? { |param| param.decl == :kwarg }
|
411
412
|
return [Problem.new(location, "Missing keyword arguments to #{pin.path}")]
|
412
413
|
end
|
414
|
+
settled_kwargs = 0
|
413
415
|
unless unchecked.empty?
|
414
416
|
kwargs = convert_hash(unchecked.last.node)
|
415
|
-
|
416
|
-
if
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
end
|
428
|
-
end
|
429
|
-
kwargs.clear if pin.parameters.any?(&:kwrestarg?)
|
430
|
-
unless kwargs.empty?
|
431
|
-
return [Problem.new(location, "Unrecognized keyword argument #{kwargs.keys.first} to #{pin.path}")]
|
417
|
+
if pin.parameters.any? { |param| [:kwarg, :kwoptarg].include?(param.decl) || param.kwrestarg? }
|
418
|
+
if kwargs.empty?
|
419
|
+
add_params += 1
|
420
|
+
else
|
421
|
+
unchecked.pop
|
422
|
+
pin.parameters.each do |param|
|
423
|
+
next unless param.keyword?
|
424
|
+
if kwargs.key?(param.name.to_sym)
|
425
|
+
kwargs.delete param.name.to_sym
|
426
|
+
settled_kwargs += 1
|
427
|
+
elsif param.decl == :kwarg
|
428
|
+
return [Problem.new(location, "Missing keyword argument #{param.name} to #{pin.path}")]
|
432
429
|
end
|
433
430
|
end
|
431
|
+
kwargs.clear if pin.parameters.any?(&:kwrestarg?)
|
432
|
+
unless kwargs.empty?
|
433
|
+
return [Problem.new(location, "Unrecognized keyword argument #{kwargs.keys.first} to #{pin.path}")]
|
434
|
+
end
|
434
435
|
end
|
435
|
-
|
436
|
+
end
|
436
437
|
end
|
437
438
|
req = required_param_count(pin)
|
438
439
|
if req + add_params < unchecked.length
|
@@ -443,23 +444,18 @@ module Solargraph
|
|
443
444
|
return []
|
444
445
|
end
|
445
446
|
return [Problem.new(location, "Too many arguments to #{pin.path}")]
|
446
|
-
elsif unchecked.length < req && (arguments.empty? || !arguments.last.splat?)
|
447
|
+
elsif unchecked.length < req - settled_kwargs && (arguments.empty? || !arguments.last.splat?)
|
447
448
|
return [Problem.new(location, "Not enough arguments to #{pin.path}")]
|
448
449
|
end
|
449
450
|
[]
|
450
451
|
end
|
451
452
|
|
452
|
-
# @param pin [Pin::
|
453
|
+
# @param pin [Pin::Method]
|
453
454
|
def required_param_count(pin)
|
454
|
-
|
455
|
-
pin.parameters.each do |param|
|
456
|
-
break unless param.decl == :arg
|
457
|
-
count += 1
|
458
|
-
end
|
459
|
-
count
|
455
|
+
pin.parameters.sum { |param| %i[arg kwarg].include?(param.decl) ? 1 : 0 }
|
460
456
|
end
|
461
457
|
|
462
|
-
# @param pin [Pin::
|
458
|
+
# @param pin [Pin::Method]
|
463
459
|
def optional_param_count(pin)
|
464
460
|
count = 0
|
465
461
|
pin.parameters.each do |param|
|
data/lib/solargraph/version.rb
CHANGED
data/lib/solargraph/yard_map.rb
CHANGED
@@ -10,11 +10,15 @@ module Solargraph
|
|
10
10
|
# stdlib, and gems.
|
11
11
|
#
|
12
12
|
class YardMap
|
13
|
-
autoload :Cache,
|
14
|
-
autoload :CoreDocs,
|
15
|
-
autoload :CoreGen,
|
16
|
-
autoload :Mapper,
|
17
|
-
autoload :RdocToYard,
|
13
|
+
autoload :Cache, 'solargraph/yard_map/cache'
|
14
|
+
autoload :CoreDocs, 'solargraph/yard_map/core_docs'
|
15
|
+
autoload :CoreGen, 'solargraph/yard_map/core_gen'
|
16
|
+
autoload :Mapper, 'solargraph/yard_map/mapper'
|
17
|
+
autoload :RdocToYard, 'solargraph/yard_map/rdoc_to_yard'
|
18
|
+
autoload :CoreFills, 'solargraph/yard_map/core_fills'
|
19
|
+
autoload :StdlibFills, 'solargraph/yard_map/stdlib_fills'
|
20
|
+
autoload :Helpers, 'solargraph/yard_map/helpers'
|
21
|
+
autoload :ToMethod, 'solargraph/yard_map/to_method'
|
18
22
|
|
19
23
|
CoreDocs.require_minimum
|
20
24
|
|
@@ -50,6 +54,8 @@ module Solargraph
|
|
50
54
|
def initialize(required: [], gemset: {}, with_dependencies: true)
|
51
55
|
# HACK: YardMap needs its own copy of this array
|
52
56
|
@required = required.clone
|
57
|
+
# HACK: Hardcoded YAML handling
|
58
|
+
@required.push 'psych' if @required.include?('yaml')
|
53
59
|
@with_dependencies = with_dependencies
|
54
60
|
@gem_paths = {}
|
55
61
|
@stdlib_namespaces = []
|
@@ -74,6 +80,8 @@ module Solargraph
|
|
74
80
|
# @param new_gemset [Hash{String => String}]
|
75
81
|
# @return [Boolean]
|
76
82
|
def change new_requires, new_gemset, source_gems = []
|
83
|
+
# HACK: Hardcoded YAML handling
|
84
|
+
new_requires.push 'psych' if new_requires.include?('yaml')
|
77
85
|
if new_requires.uniq.sort == required.uniq.sort && new_gemset == gemset && @source_gems.uniq.sort == source_gems.uniq.sort
|
78
86
|
false
|
79
87
|
else
|
@@ -131,7 +139,7 @@ module Solargraph
|
|
131
139
|
# @param path [String]
|
132
140
|
# @return [Pin::Base]
|
133
141
|
def path_pin path
|
134
|
-
pins.select{ |p| p.path == path }.first
|
142
|
+
pins.select { |p| p.path == path }.first
|
135
143
|
end
|
136
144
|
|
137
145
|
# Get the location of a file referenced by a require path.
|
@@ -151,6 +159,10 @@ module Solargraph
|
|
151
159
|
nil
|
152
160
|
end
|
153
161
|
|
162
|
+
def stdlib_pins
|
163
|
+
@stdlib_pins ||= []
|
164
|
+
end
|
165
|
+
|
154
166
|
private
|
155
167
|
|
156
168
|
# @return [YardMap::Cache]
|
@@ -158,10 +170,12 @@ module Solargraph
|
|
158
170
|
@cache ||= YardMap::Cache.new
|
159
171
|
end
|
160
172
|
|
173
|
+
# @return [Hash]
|
161
174
|
def pin_class_hash
|
162
175
|
@pin_class_hash ||= pins.to_set.classify(&:class).transform_values(&:to_a)
|
163
176
|
end
|
164
177
|
|
178
|
+
# @return [Array<Pin::Base>]
|
165
179
|
def pins_by_class klass
|
166
180
|
@pin_select_cache[klass] ||= pin_class_hash.select { |key, _| key <= klass }.values.flatten
|
167
181
|
end
|
@@ -179,12 +193,13 @@ module Solargraph
|
|
179
193
|
|
180
194
|
# @return [void]
|
181
195
|
def process_requires
|
182
|
-
pins.
|
196
|
+
pins.replace core_pins
|
183
197
|
unresolved_requires.clear
|
184
|
-
|
198
|
+
stdlib_pins.clear
|
199
|
+
environ = Convention.for_global(self)
|
185
200
|
done = []
|
186
201
|
from_std = []
|
187
|
-
required.each do |r|
|
202
|
+
(required + environ.requires).each do |r|
|
188
203
|
next if r.nil? || r.empty? || done.include?(r)
|
189
204
|
done.push r
|
190
205
|
cached = cache.get_path_pins(r)
|
@@ -209,7 +224,6 @@ module Solargraph
|
|
209
224
|
yardocs.unshift yd
|
210
225
|
result.concat process_yardoc yd, spec
|
211
226
|
result.concat add_gem_dependencies(spec) if with_dependencies?
|
212
|
-
stdlib_fill r, result
|
213
227
|
end
|
214
228
|
rescue Gem::LoadError => e
|
215
229
|
base = r.split('/').first
|
@@ -219,7 +233,7 @@ module Solargraph
|
|
219
233
|
if stdtmp.empty?
|
220
234
|
unresolved_requires.push r
|
221
235
|
else
|
222
|
-
|
236
|
+
stdlib_pins.concat stdtmp
|
223
237
|
result.concat stdtmp
|
224
238
|
end
|
225
239
|
end
|
@@ -229,7 +243,13 @@ module Solargraph
|
|
229
243
|
pins.concat result
|
230
244
|
end
|
231
245
|
end
|
232
|
-
|
246
|
+
if required.include?('yaml') && required.include?('psych')
|
247
|
+
# HACK: Hardcoded YAML handling
|
248
|
+
# @todo Why can't this be handled with an override or a virtual pin?
|
249
|
+
pin = path_pin('YAML')
|
250
|
+
pin.instance_variable_set(:@return_type, ComplexType.parse('Module<Psych>')) unless pin.nil?
|
251
|
+
end
|
252
|
+
pins.concat environ.pins
|
233
253
|
end
|
234
254
|
|
235
255
|
# @param spec [Gem::Specification]
|
@@ -327,22 +347,6 @@ module Solargraph
|
|
327
347
|
spec
|
328
348
|
end
|
329
349
|
|
330
|
-
# @param path [String]
|
331
|
-
# @param pins [Array<Pin::Base>]
|
332
|
-
# @return [void]
|
333
|
-
def stdlib_fill path, pins
|
334
|
-
StdlibFills.get(path).each do |ovr|
|
335
|
-
pin = pins.select { |p| p.path == ovr.name }.first
|
336
|
-
next if pin.nil?
|
337
|
-
(ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
|
338
|
-
pin.docstring.delete_tags tag.to_sym
|
339
|
-
end
|
340
|
-
ovr.tags.each do |tag|
|
341
|
-
pin.docstring.add_tag(tag)
|
342
|
-
end
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
350
|
def load_core_pins
|
347
351
|
yd = CoreDocs.yardoc_file
|
348
352
|
ser = File.join(File.dirname(yd), 'core.ser')
|
@@ -360,23 +364,7 @@ module Solargraph
|
|
360
364
|
else
|
361
365
|
read_core_and_save_cache(yd, ser)
|
362
366
|
end
|
363
|
-
|
364
|
-
errno = result.select{ |pin| pin.path == 'Errno' }.first
|
365
|
-
Errno.constants.each do |const|
|
366
|
-
result.push Solargraph::Pin::Namespace.new(type: :class, name: const.to_s, closure: errno)
|
367
|
-
result.push Solargraph::Pin::Reference::Superclass.new(closure: result.last, name: 'SystemCallError')
|
368
|
-
end
|
369
|
-
CoreFills::OVERRIDES.each do |ovr|
|
370
|
-
pin = result.select { |p| p.path == ovr.name }.first
|
371
|
-
next if pin.nil?
|
372
|
-
(ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
|
373
|
-
pin.docstring.delete_tags tag.to_sym
|
374
|
-
end
|
375
|
-
ovr.tags.each do |tag|
|
376
|
-
pin.docstring.add_tag(tag)
|
377
|
-
end
|
378
|
-
end
|
379
|
-
result
|
367
|
+
ApiMap::Store.new(result + CoreFills::ALL).pins.reject { |pin| pin.is_a?(Pin::Reference::Override) }
|
380
368
|
end
|
381
369
|
|
382
370
|
def read_core_and_save_cache yd, ser
|
@@ -384,7 +372,7 @@ module Solargraph
|
|
384
372
|
load_yardoc yd
|
385
373
|
result.concat Mapper.new(YARD::Registry.all).map
|
386
374
|
# HACK: Assume core methods with a single `args` parameter accept restarg
|
387
|
-
result.select { |pin| pin.is_a?(Solargraph::Pin::
|
375
|
+
result.select { |pin| pin.is_a?(Solargraph::Pin::Method )}.each do |pin|
|
388
376
|
if pin.parameters.length == 1 && pin.parameters.first.name == 'args' && pin.parameters.first.decl == :arg
|
389
377
|
# @todo Smelly instance variable access
|
390
378
|
pin.parameters.first.instance_variable_set(:@decl, :restarg)
|
@@ -403,7 +391,7 @@ module Solargraph
|
|
403
391
|
|
404
392
|
def load_stdlib_pins base
|
405
393
|
ser = File.join(File.dirname(CoreDocs.yardoc_stdlib_file), "#{base}.ser")
|
406
|
-
if File.file?(ser)
|
394
|
+
result = if File.file?(ser)
|
407
395
|
Solargraph.logger.info "Loading #{base} stdlib from cache"
|
408
396
|
file = File.open(ser, 'rb')
|
409
397
|
dump = file.read
|
@@ -418,6 +406,11 @@ module Solargraph
|
|
418
406
|
else
|
419
407
|
read_stdlib_and_save_cache(base, ser)
|
420
408
|
end
|
409
|
+
fills = StdlibFills.get(base)
|
410
|
+
unless fills.empty?
|
411
|
+
result = ApiMap::Store.new(result + fills).pins.reject { |pin| pin.is_a?(Pin::Reference::Override) }
|
412
|
+
end
|
413
|
+
result
|
421
414
|
end
|
422
415
|
|
423
416
|
def read_stdlib_and_save_cache base, ser
|