solargraph 0.61.0 → 0.62.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 +24 -2
- data/.github/workflows/plugins.yml +18 -0
- data/.github/workflows/rspec.yml +14 -1
- data/.github/workflows/typecheck.yml +6 -0
- data/CHANGELOG.md +38 -0
- data/lib/solargraph/api_map/index.rb +14 -3
- data/lib/solargraph/api_map/store.rb +6 -0
- data/lib/solargraph/api_map.rb +34 -2
- data/lib/solargraph/collection/gem.rb +12 -10
- data/lib/solargraph/collection.rb +0 -1
- data/lib/solargraph/complex_type/unique_type.rb +13 -0
- data/lib/solargraph/complex_type.rb +23 -3
- data/lib/solargraph/convention.rb +0 -4
- data/lib/solargraph/diagnostics/type_check.rb +0 -1
- data/lib/solargraph/external.rb +56 -28
- data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
- data/lib/solargraph/language_server/host/dispatch.rb +4 -2
- data/lib/solargraph/language_server/host.rb +10 -2
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +10 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +1 -1
- data/lib/solargraph/library.rb +19 -33
- data/lib/solargraph/parser/node_processor/base.rb +6 -0
- data/lib/solargraph/parser/parser_gem/node_methods.rb +29 -6
- data/lib/solargraph/parser/parser_gem/node_processors/class_definition/class_assignment_node.rb +98 -0
- data/lib/solargraph/parser/parser_gem/node_processors/class_definition.rb +54 -0
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/data_definition/data_assignment_node.rb +65 -0
- data/lib/solargraph/parser/parser_gem/node_processors/data_definition/data_definition_node.rb +97 -0
- data/lib/solargraph/parser/parser_gem/node_processors/data_definition.rb +110 -0
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +185 -0
- data/lib/solargraph/parser/parser_gem/node_processors/struct_definition/struct_assignment_node.rb +66 -0
- data/lib/solargraph/parser/parser_gem/node_processors/struct_definition/struct_definition_node.rb +108 -0
- data/lib/solargraph/parser/parser_gem/node_processors/struct_definition.rb +170 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +33 -29
- data/lib/solargraph/pin/base.rb +25 -1
- data/lib/solargraph/pin/base_variable.rb +31 -1
- data/lib/solargraph/pin/callable.rb +11 -2
- data/lib/solargraph/pin/delegated_method.rb +5 -0
- data/lib/solargraph/pin/duck_method.rb +36 -16
- data/lib/solargraph/pin/instance_variable.rb +45 -0
- data/lib/solargraph/pin/method.rb +10 -0
- data/lib/solargraph/pin/method_alias.rb +4 -0
- data/lib/solargraph/pin/parameter.rb +1 -1
- data/lib/solargraph/pin/reference/included_mixin.rb +22 -0
- data/lib/solargraph/pin/reference.rb +1 -0
- data/lib/solargraph/plugin/active_support.rb +100 -0
- data/lib/solargraph/plugin/addon.rb +16 -0
- data/lib/solargraph/plugin/base.rb +25 -0
- data/lib/solargraph/plugin/panel.rb +37 -0
- data/lib/solargraph/plugin.rb +26 -0
- data/lib/solargraph/rbs_collection.rb +119 -0
- data/lib/solargraph/rbs_map/conversions.rb +106 -47
- data/lib/solargraph/rbs_map/gem.rb +4 -1
- data/lib/solargraph/rbs_map/helpers.rb +7 -6
- data/lib/solargraph/rbs_translator.rb +105 -70
- data/lib/solargraph/repo.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +32 -13
- data/lib/solargraph/source/node_map.rb +27 -0
- data/lib/solargraph/source.rb +17 -0
- data/lib/solargraph/source_map/call.rb +18 -0
- data/lib/solargraph/source_map/mapper.rb +1 -1
- data/lib/solargraph/source_map.rb +18 -4
- data/lib/solargraph/type_checker/rules.rb +2 -2
- data/lib/solargraph/type_checker.rb +4 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map/macro.rb +51 -1
- data/lib/solargraph.rb +2 -0
- data/rbs/fills/boolean/0/boolean.rbs +12 -0
- data/solargraph.gemspec +1 -1
- metadata +21 -11
- data/lib/solargraph/collection/rbs.rb +0 -49
- data/lib/solargraph/convention/active_support_concern.rb +0 -111
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +0 -61
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +0 -93
- data/lib/solargraph/convention/data_definition.rb +0 -108
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +0 -62
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +0 -103
- data/lib/solargraph/convention/struct_definition.rb +0 -168
|
@@ -6,31 +6,34 @@ module Solargraph
|
|
|
6
6
|
module Parser
|
|
7
7
|
module ParserGem
|
|
8
8
|
module NodeProcessors
|
|
9
|
-
autoload :BeginNode,
|
|
10
|
-
autoload :DefNode,
|
|
11
|
-
autoload :DefsNode,
|
|
12
|
-
autoload :SendNode,
|
|
13
|
-
autoload :NamespaceNode,
|
|
14
|
-
autoload :SclassNode,
|
|
15
|
-
autoload :IvasgnNode,
|
|
16
|
-
autoload :IfNode,
|
|
17
|
-
autoload :CvasgnNode,
|
|
18
|
-
autoload :LvasgnNode,
|
|
19
|
-
autoload :GvasgnNode,
|
|
20
|
-
autoload :CasgnNode,
|
|
21
|
-
autoload :MasgnNode,
|
|
22
|
-
autoload :AliasNode,
|
|
23
|
-
autoload :ArgsNode,
|
|
24
|
-
autoload :BlockNode,
|
|
25
|
-
autoload :OrasgnNode,
|
|
26
|
-
autoload :OpasgnNode,
|
|
27
|
-
autoload :SymNode,
|
|
28
|
-
autoload :ResbodyNode,
|
|
29
|
-
autoload :UntilNode,
|
|
30
|
-
autoload :WhenNode,
|
|
31
|
-
autoload :WhileNode,
|
|
32
|
-
autoload :AndNode,
|
|
33
|
-
autoload :OrNode,
|
|
9
|
+
autoload :BeginNode, 'solargraph/parser/parser_gem/node_processors/begin_node'
|
|
10
|
+
autoload :DefNode, 'solargraph/parser/parser_gem/node_processors/def_node'
|
|
11
|
+
autoload :DefsNode, 'solargraph/parser/parser_gem/node_processors/defs_node'
|
|
12
|
+
autoload :SendNode, 'solargraph/parser/parser_gem/node_processors/send_node'
|
|
13
|
+
autoload :NamespaceNode, 'solargraph/parser/parser_gem/node_processors/namespace_node'
|
|
14
|
+
autoload :SclassNode, 'solargraph/parser/parser_gem/node_processors/sclass_node'
|
|
15
|
+
autoload :IvasgnNode, 'solargraph/parser/parser_gem/node_processors/ivasgn_node'
|
|
16
|
+
autoload :IfNode, 'solargraph/parser/parser_gem/node_processors/if_node'
|
|
17
|
+
autoload :CvasgnNode, 'solargraph/parser/parser_gem/node_processors/cvasgn_node'
|
|
18
|
+
autoload :LvasgnNode, 'solargraph/parser/parser_gem/node_processors/lvasgn_node'
|
|
19
|
+
autoload :GvasgnNode, 'solargraph/parser/parser_gem/node_processors/gvasgn_node'
|
|
20
|
+
autoload :CasgnNode, 'solargraph/parser/parser_gem/node_processors/casgn_node'
|
|
21
|
+
autoload :MasgnNode, 'solargraph/parser/parser_gem/node_processors/masgn_node'
|
|
22
|
+
autoload :AliasNode, 'solargraph/parser/parser_gem/node_processors/alias_node'
|
|
23
|
+
autoload :ArgsNode, 'solargraph/parser/parser_gem/node_processors/args_node'
|
|
24
|
+
autoload :BlockNode, 'solargraph/parser/parser_gem/node_processors/block_node'
|
|
25
|
+
autoload :OrasgnNode, 'solargraph/parser/parser_gem/node_processors/orasgn_node'
|
|
26
|
+
autoload :OpasgnNode, 'solargraph/parser/parser_gem/node_processors/opasgn_node'
|
|
27
|
+
autoload :SymNode, 'solargraph/parser/parser_gem/node_processors/sym_node'
|
|
28
|
+
autoload :ResbodyNode, 'solargraph/parser/parser_gem/node_processors/resbody_node'
|
|
29
|
+
autoload :UntilNode, 'solargraph/parser/parser_gem/node_processors/until_node'
|
|
30
|
+
autoload :WhenNode, 'solargraph/parser/parser_gem/node_processors/when_node'
|
|
31
|
+
autoload :WhileNode, 'solargraph/parser/parser_gem/node_processors/while_node'
|
|
32
|
+
autoload :AndNode, 'solargraph/parser/parser_gem/node_processors/and_node'
|
|
33
|
+
autoload :OrNode, 'solargraph/parser/parser_gem/node_processors/or_node'
|
|
34
|
+
autoload :ClassDefinition, 'solargraph/parser/parser_gem/node_processors/class_definition'
|
|
35
|
+
autoload :StructDefinition, 'solargraph/parser/parser_gem/node_processors/struct_definition'
|
|
36
|
+
autoload :DataDefinition, 'solargraph/parser/parser_gem/node_processors/data_definition'
|
|
34
37
|
end
|
|
35
38
|
end
|
|
36
39
|
|
|
@@ -44,8 +47,8 @@ module Solargraph
|
|
|
44
47
|
register :defs, ParserGem::NodeProcessors::DefsNode
|
|
45
48
|
register :if, ParserGem::NodeProcessors::IfNode
|
|
46
49
|
register :send, ParserGem::NodeProcessors::SendNode
|
|
47
|
-
register :class,
|
|
48
|
-
register :class,
|
|
50
|
+
register :class, ParserGem::NodeProcessors::StructDefinition::StructNode
|
|
51
|
+
register :class, ParserGem::NodeProcessors::DataDefinition::DataNode
|
|
49
52
|
register :class, ParserGem::NodeProcessors::NamespaceNode
|
|
50
53
|
register :module, ParserGem::NodeProcessors::NamespaceNode
|
|
51
54
|
register :sclass, ParserGem::NodeProcessors::SclassNode
|
|
@@ -53,8 +56,9 @@ module Solargraph
|
|
|
53
56
|
register :cvasgn, ParserGem::NodeProcessors::CvasgnNode
|
|
54
57
|
register :lvasgn, ParserGem::NodeProcessors::LvasgnNode
|
|
55
58
|
register :gvasgn, ParserGem::NodeProcessors::GvasgnNode
|
|
56
|
-
register :casgn,
|
|
57
|
-
register :casgn,
|
|
59
|
+
register :casgn, ParserGem::NodeProcessors::StructDefinition::StructNode
|
|
60
|
+
register :casgn, ParserGem::NodeProcessors::DataDefinition::DataNode
|
|
61
|
+
register :casgn, ParserGem::NodeProcessors::ClassDefinition::ClassNode
|
|
58
62
|
register :casgn, ParserGem::NodeProcessors::CasgnNode
|
|
59
63
|
register :masgn, ParserGem::NodeProcessors::MasgnNode
|
|
60
64
|
register :alias, ParserGem::NodeProcessors::AliasNode
|
data/lib/solargraph/pin/base.rb
CHANGED
|
@@ -158,7 +158,17 @@ module Solargraph
|
|
|
158
158
|
# @param other [self]
|
|
159
159
|
# @return [Pin::Closure, nil]
|
|
160
160
|
def combine_closure other
|
|
161
|
-
choose_pin_attr_with_same_name(other, :closure)
|
|
161
|
+
chosen = choose_pin_attr_with_same_name(other, :closure)
|
|
162
|
+
return chosen unless chosen.is_a?(Pin::Namespace) && chosen.generics.empty?
|
|
163
|
+
|
|
164
|
+
# Combined types may name type parameters only the other closure declares
|
|
165
|
+
own = closure
|
|
166
|
+
return own if own.is_a?(Pin::Namespace) && !own.generics.empty?
|
|
167
|
+
|
|
168
|
+
theirs = other.closure
|
|
169
|
+
return theirs if theirs.is_a?(Pin::Namespace) && !theirs.generics.empty?
|
|
170
|
+
|
|
171
|
+
chosen
|
|
162
172
|
end
|
|
163
173
|
|
|
164
174
|
# @param other [self]
|
|
@@ -435,6 +445,7 @@ module Solargraph
|
|
|
435
445
|
# @param context_type [ComplexType] The receiver type
|
|
436
446
|
# @return [self]
|
|
437
447
|
def resolve_generics definitions, context_type
|
|
448
|
+
definitions = declaring_definitions(definitions)
|
|
438
449
|
transform_types { |t| t&.resolve_generics(definitions, context_type) }
|
|
439
450
|
end
|
|
440
451
|
|
|
@@ -731,6 +742,19 @@ module Solargraph
|
|
|
731
742
|
|
|
732
743
|
private
|
|
733
744
|
|
|
745
|
+
# Declarations of a reopened generic may spell its parameters
|
|
746
|
+
# differently, so bind by position against this pin's own one.
|
|
747
|
+
#
|
|
748
|
+
# @param definitions [Pin::Namespace, nil]
|
|
749
|
+
# @return [Pin::Namespace, nil]
|
|
750
|
+
def declaring_definitions definitions
|
|
751
|
+
own = closure
|
|
752
|
+
return definitions unless definitions.is_a?(Pin::Namespace) && own.is_a?(Pin::Namespace)
|
|
753
|
+
return definitions unless own.path == definitions.path && !own.generics.empty?
|
|
754
|
+
|
|
755
|
+
own
|
|
756
|
+
end
|
|
757
|
+
|
|
734
758
|
# @return [void]
|
|
735
759
|
def parse_comments
|
|
736
760
|
# HACK: Avoid a NoMethodError on nil with empty overload tags
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'rbs'
|
|
4
|
+
|
|
3
5
|
module Solargraph
|
|
4
6
|
module Pin
|
|
5
7
|
class BaseVariable < Base
|
|
@@ -14,6 +16,9 @@ module Solargraph
|
|
|
14
16
|
# @return [Range, nil]
|
|
15
17
|
attr_reader :presence
|
|
16
18
|
|
|
19
|
+
# @return [String, nil]
|
|
20
|
+
attr_reader :type_assertion
|
|
21
|
+
|
|
17
22
|
# @param return_type [ComplexType, nil]
|
|
18
23
|
# @param assignment [Parser::AST::Node, nil] First assignment
|
|
19
24
|
# that was made to this variable
|
|
@@ -45,12 +50,16 @@ module Solargraph
|
|
|
45
50
|
# @see https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types
|
|
46
51
|
# @see https://en.wikipedia.org/wiki/Intersection_type#TypeScript_example
|
|
47
52
|
# @param presence [Range, nil]
|
|
53
|
+
# @param type_assertion [String, nil] RBS type from a trailing
|
|
54
|
+
# rbs-inline `#: TYPE` comment on the assignment
|
|
48
55
|
# @param [Hash{Symbol => Object}] splat
|
|
49
56
|
def initialize assignment: nil, assignments: [], mass_assignment: nil,
|
|
50
57
|
presence: nil, return_type: nil,
|
|
51
58
|
intersection_return_type: nil, exclude_return_type: nil,
|
|
59
|
+
type_assertion: nil,
|
|
52
60
|
**splat
|
|
53
61
|
super(**splat)
|
|
62
|
+
@type_assertion = type_assertion
|
|
54
63
|
@assignments = (assignment.nil? ? [] : [assignment]) + assignments
|
|
55
64
|
# @type [nil, ::Array(Parser::AST::Node, Integer)]
|
|
56
65
|
@mass_assignment = mass_assignment
|
|
@@ -95,7 +104,8 @@ module Solargraph
|
|
|
95
104
|
return_type: combine_return_type(other),
|
|
96
105
|
intersection_return_type: combine_types(other, :intersection_return_type),
|
|
97
106
|
exclude_return_type: combine_types(other, :exclude_return_type),
|
|
98
|
-
presence: combine_presence(other)
|
|
107
|
+
presence: combine_presence(other),
|
|
108
|
+
type_assertion: choose(other, :type_assertion)
|
|
99
109
|
})
|
|
100
110
|
super(other, new_attrs)
|
|
101
111
|
end
|
|
@@ -170,6 +180,9 @@ module Solargraph
|
|
|
170
180
|
end
|
|
171
181
|
end
|
|
172
182
|
types
|
|
183
|
+
rescue FileNotFoundError
|
|
184
|
+
# @todo Necessary for pins from source maps that are not part of the workspace
|
|
185
|
+
[ComplexType::UNDEFINED]
|
|
173
186
|
end
|
|
174
187
|
|
|
175
188
|
# @param api_map [ApiMap]
|
|
@@ -364,12 +377,29 @@ module Solargraph
|
|
|
364
377
|
:instance
|
|
365
378
|
end
|
|
366
379
|
|
|
380
|
+
# An rbs-inline type assertion takes precedence over a @type tag,
|
|
381
|
+
# as inline RBS method signatures do over YARD tags.
|
|
382
|
+
#
|
|
367
383
|
# @return [ComplexType, nil]
|
|
368
384
|
def generate_complex_type
|
|
385
|
+
asserted = type_from_assertion
|
|
386
|
+
return asserted unless asserted.nil?
|
|
369
387
|
tag = docstring.tag(:type)
|
|
370
388
|
return ComplexType.try_parse(*tag.types) unless tag.nil? || tag.types.nil? || tag.types.empty?
|
|
371
389
|
nil
|
|
372
390
|
end
|
|
391
|
+
|
|
392
|
+
# @return [ComplexType, nil]
|
|
393
|
+
def type_from_assertion
|
|
394
|
+
assertion = type_assertion
|
|
395
|
+
return nil if assertion.nil? || assertion.empty?
|
|
396
|
+
@type_from_assertion ||= begin
|
|
397
|
+
rbs_type = RBS::Parser.parse_type(assertion, require_eof: true)
|
|
398
|
+
RbsTranslator.to_complex_type(rbs_type) unless rbs_type.nil?
|
|
399
|
+
rescue RBS::ParsingError
|
|
400
|
+
nil
|
|
401
|
+
end
|
|
402
|
+
end
|
|
373
403
|
end
|
|
374
404
|
end
|
|
375
405
|
end
|
|
@@ -14,12 +14,15 @@ module Solargraph
|
|
|
14
14
|
# @param block [Signature, nil]
|
|
15
15
|
# @param return_type [ComplexType, nil]
|
|
16
16
|
# @param parameters [::Array<Pin::Parameter>]
|
|
17
|
+
# @param block_required [Boolean] Whether callers must pass a block, per
|
|
18
|
+
# an RBS non-optional block (`{ ... }` rather than `?{ ... }`).
|
|
17
19
|
# @param [Hash{Symbol => Object}] splat
|
|
18
|
-
def initialize block: nil, return_type: nil, parameters: [], **splat
|
|
20
|
+
def initialize block: nil, return_type: nil, parameters: [], block_required: false, **splat
|
|
19
21
|
super(**splat)
|
|
20
22
|
@block = block
|
|
21
23
|
@return_type = return_type
|
|
22
24
|
@parameters = parameters
|
|
25
|
+
@block_required = block_required
|
|
23
26
|
end
|
|
24
27
|
|
|
25
28
|
def reset_generated!
|
|
@@ -55,6 +58,7 @@ module Solargraph
|
|
|
55
58
|
def combine_with other, attrs = {}
|
|
56
59
|
new_attrs = {
|
|
57
60
|
block: combine_blocks(other),
|
|
61
|
+
block_required: block_required? || other.block_required?,
|
|
58
62
|
return_type: combine_return_type(other)
|
|
59
63
|
}.merge(attrs)
|
|
60
64
|
new_attrs[:parameters] = choose_parameters(other).clone.freeze unless new_attrs.key?(:parameters)
|
|
@@ -241,7 +245,7 @@ module Solargraph
|
|
|
241
245
|
argcount = arguments.length
|
|
242
246
|
parcount = mandatory_positional_param_count
|
|
243
247
|
parcount -= 1 if !parameters.empty? && parameters.last.block?
|
|
244
|
-
return false if block? && !with_block
|
|
248
|
+
return false if block? && block_required? && !with_block
|
|
245
249
|
# @todo this and its caller should be changed so that this can
|
|
246
250
|
# look at the kwargs provided and check names against what
|
|
247
251
|
# we acccept
|
|
@@ -267,6 +271,11 @@ module Solargraph
|
|
|
267
271
|
!!@block
|
|
268
272
|
end
|
|
269
273
|
|
|
274
|
+
# @return [Boolean]
|
|
275
|
+
def block_required?
|
|
276
|
+
!!@block_required
|
|
277
|
+
end
|
|
278
|
+
|
|
270
279
|
protected
|
|
271
280
|
|
|
272
281
|
attr_writer :block
|
|
@@ -5,6 +5,11 @@ module Solargraph
|
|
|
5
5
|
# A DelegatedMethod is a more complicated version of a MethodAlias that
|
|
6
6
|
# allows aliasing a method from a different closure (class/module etc).
|
|
7
7
|
class DelegatedMethod < Pin::Method
|
|
8
|
+
# @return [Boolean]
|
|
9
|
+
def body?
|
|
10
|
+
false
|
|
11
|
+
end
|
|
12
|
+
|
|
8
13
|
# A DelegatedMethod can be constructed with either a :resolved_method
|
|
9
14
|
# pin, or a :receiver_chain. When a :receiver_chain is supplied, it
|
|
10
15
|
# will be used to *dynamically* resolve a receiver type within the
|
|
@@ -1,16 +1,36 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Solargraph
|
|
4
|
-
module Pin
|
|
5
|
-
# DuckMethod pins are used to add completion items for type tags that
|
|
6
|
-
# use duck typing, e.g., `@param file [#read]`.
|
|
7
|
-
#
|
|
8
|
-
class DuckMethod < Pin::Method
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Pin
|
|
5
|
+
# DuckMethod pins are used to add completion items for type tags that
|
|
6
|
+
# use duck typing, e.g., `@param file [#read]`.
|
|
7
|
+
#
|
|
8
|
+
class DuckMethod < Pin::Method
|
|
9
|
+
# A duck-type tag has no syntax for arguments, so the default empty
|
|
10
|
+
# #parameters would synthesize a zero-arg signature no real call matches.
|
|
11
|
+
#
|
|
12
|
+
# @param splat [Hash{Symbol => Object}]
|
|
13
|
+
def initialize **splat
|
|
14
|
+
super(parameters: accepts_any_arguments, **splat)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @return [::Array<Pin::Parameter>]
|
|
18
|
+
def accepts_any_arguments
|
|
19
|
+
[
|
|
20
|
+
Pin::Parameter.new(decl: :restarg, name: 'args', closure: self, source: :api_map),
|
|
21
|
+
Pin::Parameter.new(decl: :kwrestarg, name: 'kwargs', closure: self, source: :api_map)
|
|
22
|
+
]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# A synthetic pin sits in no ancestor chain and has no closure. Letting
|
|
26
|
+
# the inherited walk find a type sends #typify on to `closure.gates`,
|
|
27
|
+
# which raises.
|
|
28
|
+
#
|
|
29
|
+
# @param _api_map [ApiMap]
|
|
30
|
+
# @return [Array<Pin::Method>]
|
|
31
|
+
def rest_of_stack _api_map
|
|
32
|
+
[]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -33,6 +33,51 @@ module Solargraph
|
|
|
33
33
|
def nearly? other
|
|
34
34
|
super && binder == other.binder
|
|
35
35
|
end
|
|
36
|
+
|
|
37
|
+
# Same-file requirement only applies when +presence+ is set; an
|
|
38
|
+
# unnarrowed ivar has none and can be assigned and read in
|
|
39
|
+
# different files (e.g. ancestor class's method vs. descendant's).
|
|
40
|
+
#
|
|
41
|
+
# @param other_closure [Pin::Closure]
|
|
42
|
+
# @param other_loc [Location]
|
|
43
|
+
def visible_at? other_closure, other_loc
|
|
44
|
+
return false if presence && location&.filename != other_loc.filename
|
|
45
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
46
|
+
return false if presence && !presence.include?(other_loc.range.start)
|
|
47
|
+
|
|
48
|
+
visible_in_closure?(other_closure)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
# Unlike BaseVariable, doesn't stop at a lexically-mismatched
|
|
54
|
+
# Namespace pin: #get_instance_variable_pins already restricts
|
|
55
|
+
# candidates to the reading namespace and its ancestors, so
|
|
56
|
+
# reaching one here means visible via inheritance.
|
|
57
|
+
#
|
|
58
|
+
# @param viewing_closure [Pin::Closure]
|
|
59
|
+
# @return [Boolean]
|
|
60
|
+
def visible_in_closure? viewing_closure
|
|
61
|
+
return false if closure.nil?
|
|
62
|
+
|
|
63
|
+
# top-level ivars aren't visible from within a method
|
|
64
|
+
# @sg-ignore Need to add nil check here
|
|
65
|
+
return false if viewing_closure.is_a?(Pin::Method) && closure.context.tags == 'Class<>'
|
|
66
|
+
|
|
67
|
+
# @sg-ignore Need to add nil check here
|
|
68
|
+
return true if viewing_closure.binder.namespace == closure.binder.namespace
|
|
69
|
+
|
|
70
|
+
# @sg-ignore Need to add nil check here
|
|
71
|
+
return true if viewing_closure.return_type == closure.context
|
|
72
|
+
|
|
73
|
+
return true if viewing_closure.is_a?(Pin::Namespace)
|
|
74
|
+
|
|
75
|
+
parent_of_viewing_closure = viewing_closure.closure
|
|
76
|
+
|
|
77
|
+
return false if parent_of_viewing_closure.nil?
|
|
78
|
+
|
|
79
|
+
visible_in_closure?(parent_of_viewing_closure)
|
|
80
|
+
end
|
|
36
81
|
end
|
|
37
82
|
end
|
|
38
83
|
end
|
|
@@ -370,6 +370,13 @@ module Solargraph
|
|
|
370
370
|
@explicit
|
|
371
371
|
end
|
|
372
372
|
|
|
373
|
+
# False for method pins synthesized from a class-body statement rather than parsed from a def.
|
|
374
|
+
#
|
|
375
|
+
# @return [Boolean]
|
|
376
|
+
def body?
|
|
377
|
+
!attribute?
|
|
378
|
+
end
|
|
379
|
+
|
|
373
380
|
def attribute?
|
|
374
381
|
@attribute
|
|
375
382
|
end
|
|
@@ -387,6 +394,9 @@ module Solargraph
|
|
|
387
394
|
|
|
388
395
|
def probe api_map
|
|
389
396
|
attribute? ? infer_from_iv(api_map) : infer_from_return_nodes(api_map)
|
|
397
|
+
rescue FileNotFoundError
|
|
398
|
+
# @todo Necessary for pins from source maps that are not part of the workspace
|
|
399
|
+
ComplexType::UNDEFINED
|
|
390
400
|
end
|
|
391
401
|
|
|
392
402
|
# @return [::Array<Pin::Signature>]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Pin
|
|
5
|
+
class Reference
|
|
6
|
+
# A mixin that a module's +self.included+ hook applies to every class
|
|
7
|
+
# that includes the module, e.g. +base.extend ClassMethods+. The closure
|
|
8
|
+
# is the hooking module and the name is the mixed-in module.
|
|
9
|
+
class IncludedMixin < Reference
|
|
10
|
+
# @return [::Symbol] :include, :prepend or :extend
|
|
11
|
+
attr_reader :keyword
|
|
12
|
+
|
|
13
|
+
# @param keyword [::Symbol] :include, :prepend or :extend
|
|
14
|
+
# @param splat [Hash{Symbol => Object}]
|
|
15
|
+
def initialize keyword:, **splat
|
|
16
|
+
super(**splat)
|
|
17
|
+
@keyword = keyword
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -8,6 +8,7 @@ module Solargraph
|
|
|
8
8
|
autoload :Include, 'solargraph/pin/reference/include'
|
|
9
9
|
autoload :Prepend, 'solargraph/pin/reference/prepend'
|
|
10
10
|
autoload :Extend, 'solargraph/pin/reference/extend'
|
|
11
|
+
autoload :IncludedMixin, 'solargraph/pin/reference/included_mixin'
|
|
11
12
|
autoload :Override, 'solargraph/pin/reference/override'
|
|
12
13
|
autoload :TypeAlias, 'solargraph/pin/reference/type_alias'
|
|
13
14
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Plugin
|
|
5
|
+
class ActiveSupport < Base
|
|
6
|
+
ATTRIBUTE_NAME = /\A[_A-Za-z]\w*\z/
|
|
7
|
+
|
|
8
|
+
def addon
|
|
9
|
+
return EMPTY_ADDON unless gem_names.include?('activesupport')
|
|
10
|
+
|
|
11
|
+
Addon.new(pins: classmethod_pins + attribute_pins)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def classmethod_pins
|
|
17
|
+
pins_by_class(Pin::Reference::Include).map do |inc|
|
|
18
|
+
Pin::Reference::Extend.new(name: "#{inc.name}::ClassMethods", closure: inc.closure)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def attribute_pins
|
|
23
|
+
source_maps.flat_map { |map| map.calls(:class_attribute, :mattr_accessor, :cattr_accessor, :mattr_reader, :cattr_reader, :mattr_writer, :cattr_writer, :config_accessor) }
|
|
24
|
+
.select { |call| call.closure.is_a?(Pin::Namespace) }
|
|
25
|
+
.flat_map { |call| generate_call_pins(call) }
|
|
26
|
+
.compact
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @param call [SourceMap::Call]
|
|
30
|
+
def generate_call_pins call
|
|
31
|
+
options = option_hash(call.chain.links.last.arguments.last)
|
|
32
|
+
method_names = call.chain.links.last.arguments.select(&:literal?).map { |arg| arg.links.last.value }.compact
|
|
33
|
+
.grep(ATTRIBUTE_NAME)
|
|
34
|
+
case call.chain.links.last.word
|
|
35
|
+
when 'class_attribute'
|
|
36
|
+
class_suffixes = ['', '=']
|
|
37
|
+
class_suffixes.push '?' if options[:instance_predicate]
|
|
38
|
+
instance_suffixes = []
|
|
39
|
+
instance_suffixes.push '' if options[:instance_accessor] && options[:instance_reader]
|
|
40
|
+
instance_suffixes.push '=' if options[:instance_accessor] && options[:instance_writer]
|
|
41
|
+
instance_suffixes.push '?' if options[:instance_accessor] && options[:instance_predicate]
|
|
42
|
+
method_names.flat_map { |name| method_pins(name, class_suffixes, instance_suffixes, call) }
|
|
43
|
+
when 'mattr_accessor', 'cattr_accessor', 'config_accessor'
|
|
44
|
+
class_suffixes = ['', '=']
|
|
45
|
+
instance_suffixes = []
|
|
46
|
+
instance_suffixes.push '' if options[:instance_accessor] && options[:instance_reader]
|
|
47
|
+
instance_suffixes.push '=' if options[:instance_accessor] && options[:instance_writer]
|
|
48
|
+
method_names.flat_map { |name| method_pins(name, class_suffixes, instance_suffixes, call) }
|
|
49
|
+
when 'mattr_reader', 'cattr_reader'
|
|
50
|
+
class_suffixes = ['']
|
|
51
|
+
instance_suffixes = []
|
|
52
|
+
instance_suffixes.push '' if options[:instance_accessor] && options[:instance_reader]
|
|
53
|
+
method_names.flat_map { |name| method_pins(name, class_suffixes, instance_suffixes, call) }
|
|
54
|
+
when 'mattr_writer', 'cattr_writer'
|
|
55
|
+
class_suffixes = ['=']
|
|
56
|
+
instance_suffixes = []
|
|
57
|
+
instance_suffixes.push '=' if options[:instance_accessor] && options[:instance_writer]
|
|
58
|
+
method_names.flat_map { |name| method_pins(name, class_suffixes, instance_suffixes, call) }
|
|
59
|
+
else
|
|
60
|
+
[]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def option_hash args
|
|
65
|
+
defaults = {
|
|
66
|
+
instance_reader: true,
|
|
67
|
+
instance_writer: true,
|
|
68
|
+
instance_accessor: true,
|
|
69
|
+
instance_predicate: true
|
|
70
|
+
}
|
|
71
|
+
kwargs = Parser::ParserGem::NodeMethods.convert_hash(args.node)
|
|
72
|
+
.select { |_, val| val.literal? }
|
|
73
|
+
.transform_values { |val| val.links.last.value }
|
|
74
|
+
return defaults unless kwargs.is_a?(Hash)
|
|
75
|
+
defaults.merge(kwargs)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @param call [SourceMap::Call]
|
|
79
|
+
# @param name [String]
|
|
80
|
+
# @param class_suffixes [Array<String>]
|
|
81
|
+
# @param instance_suffixes [Array<String>]
|
|
82
|
+
def method_pins name, class_suffixes, instance_suffixes, call
|
|
83
|
+
comments = call.source_map.source.comments_for(call.chain.node)
|
|
84
|
+
location = Solargraph::Location.new(call.closure.filename, Solargraph::Range.from_node(call.chain.node))
|
|
85
|
+
class_suffixes.map do |sfx|
|
|
86
|
+
Pin::Method.new(name: "#{name}#{sfx}", closure: call.closure, scope: :class, attribute: true, location: location, comments: comments).tap do |pin|
|
|
87
|
+
next unless sfx == '='
|
|
88
|
+
pin.parameters.push Pin::Parameter.new(name: 'value', closure: pin)
|
|
89
|
+
end
|
|
90
|
+
end +
|
|
91
|
+
instance_suffixes.map do |sfx|
|
|
92
|
+
Pin::Method.new(name: "#{name}#{sfx}", closure: call.closure, scope: :instance, attribute: true, location: location, comments: comments).tap do |pin|
|
|
93
|
+
next unless sfx == '='
|
|
94
|
+
pin.parameters.push Pin::Parameter.new(name: 'value', closure: pin)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Plugin
|
|
5
|
+
class Addon
|
|
6
|
+
attr_reader :gem_names, :pins
|
|
7
|
+
|
|
8
|
+
# @param gem_names [Array<String>]
|
|
9
|
+
# @param pins [Array<Pin::Base>]
|
|
10
|
+
def initialize gem_names: [], pins: []
|
|
11
|
+
@gem_names = gem_names
|
|
12
|
+
@pins = pins
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'forwardable'
|
|
4
|
+
|
|
5
|
+
module Solargraph
|
|
6
|
+
module Plugin
|
|
7
|
+
class Base
|
|
8
|
+
extend Forwardable
|
|
9
|
+
|
|
10
|
+
attr_reader :panel
|
|
11
|
+
|
|
12
|
+
def_delegators :@panel, :pins, :pins_by_class, :pins_by_path, :gem_names, :source_maps
|
|
13
|
+
|
|
14
|
+
# @param panel [Panel]
|
|
15
|
+
def initialize panel
|
|
16
|
+
@panel = panel
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @return [Addon]
|
|
20
|
+
def addon
|
|
21
|
+
EMPTY_ADDON
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Plugin
|
|
5
|
+
class Panel
|
|
6
|
+
attr_reader :source_maps, :live_map, :gem_names
|
|
7
|
+
|
|
8
|
+
def initialize source_maps: [], live_map: nil, gem_names: []
|
|
9
|
+
@source_maps = source_maps
|
|
10
|
+
@live_map = live_map
|
|
11
|
+
@gem_names = gem_names
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def pins
|
|
15
|
+
@pins ||= source_maps.flat_map(&:pins)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def pins_by_class klass
|
|
19
|
+
pin_class_hash[klass] || []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def pins_by_path path
|
|
23
|
+
pin_path_hash[path] || []
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def pin_class_hash
|
|
29
|
+
@pin_class_hash ||= pins.to_set.classify(&:class)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def pin_path_hash
|
|
33
|
+
@pin_path_hash ||= pins.to_set.classify(&:path)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Plugin
|
|
5
|
+
autoload :Addon, 'solargraph/plugin/addon'
|
|
6
|
+
autoload :Base, 'solargraph/plugin/base'
|
|
7
|
+
autoload :Panel, 'solargraph/plugin/panel'
|
|
8
|
+
autoload :ActiveSupport, 'solargraph/plugin/active_support'
|
|
9
|
+
|
|
10
|
+
EMPTY_ADDON = Addon.new.freeze
|
|
11
|
+
|
|
12
|
+
def self.registry
|
|
13
|
+
@registry ||= Set.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.register klass
|
|
17
|
+
registry.add klass
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.unregister klass
|
|
21
|
+
registry.delete klass
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Plugin.register ActiveSupport
|
|
25
|
+
end
|
|
26
|
+
end
|