solargraph 0.58.2 → 0.59.0.dev.1
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/.envrc +3 -0
- data/.github/workflows/linting.yml +4 -5
- data/.github/workflows/plugins.yml +40 -36
- data/.github/workflows/rspec.yml +45 -13
- data/.github/workflows/typecheck.yml +2 -2
- data/.gitignore +0 -1
- data/.rubocop_todo.yml +27 -49
- data/CHANGELOG.md +1 -7
- data/README.md +3 -3
- data/Rakefile +1 -0
- data/lib/solargraph/api_map/cache.rb +3 -3
- data/lib/solargraph/api_map/constants.rb +13 -3
- data/lib/solargraph/api_map/index.rb +22 -11
- data/lib/solargraph/api_map/source_to_yard.rb +13 -1
- data/lib/solargraph/api_map/store.rb +11 -8
- data/lib/solargraph/api_map.rb +105 -50
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +16 -2
- data/lib/solargraph/complex_type/unique_type.rb +170 -20
- data/lib/solargraph/complex_type.rb +119 -14
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
- data/lib/solargraph/convention/data_definition.rb +4 -1
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +1 -0
- data/lib/solargraph/convention/struct_definition.rb +5 -1
- data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
- data/lib/solargraph/diagnostics/rubocop.rb +1 -0
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +2 -0
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/doc_map.rb +134 -373
- data/lib/solargraph/equality.rb +1 -1
- data/lib/solargraph/gem_pins.rb +14 -15
- data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
- data/lib/solargraph/language_server/host/dispatch.rb +1 -0
- data/lib/solargraph/language_server/host/message_worker.rb +2 -1
- data/lib/solargraph/language_server/host/sources.rb +1 -0
- data/lib/solargraph/language_server/host.rb +6 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -7
- data/lib/solargraph/language_server/message/extended/document.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +2 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -0
- data/lib/solargraph/library.rb +59 -13
- data/lib/solargraph/location.rb +9 -4
- data/lib/solargraph/logging.rb +21 -1
- data/lib/solargraph/parser/comment_ripper.rb +7 -0
- data/lib/solargraph/parser/flow_sensitive_typing.rb +330 -102
- data/lib/solargraph/parser/node_processor/base.rb +32 -2
- data/lib/solargraph/parser/node_processor.rb +7 -6
- data/lib/solargraph/parser/parser_gem/class_methods.rb +28 -10
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +31 -6
- data/lib/solargraph/parser/parser_gem/node_methods.rb +27 -7
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -11
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +7 -0
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +3 -2
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +2 -2
- data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +12 -7
- data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +5 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
- data/lib/solargraph/parser/region.rb +9 -3
- data/lib/solargraph/parser/snippet.rb +1 -1
- data/lib/solargraph/pin/base.rb +53 -21
- data/lib/solargraph/pin/base_variable.rb +312 -20
- data/lib/solargraph/pin/block.rb +26 -4
- data/lib/solargraph/pin/breakable.rb +5 -1
- data/lib/solargraph/pin/callable.rb +50 -3
- data/lib/solargraph/pin/closure.rb +2 -6
- data/lib/solargraph/pin/common.rb +20 -5
- data/lib/solargraph/pin/compound_statement.rb +55 -0
- data/lib/solargraph/pin/conversions.rb +2 -1
- data/lib/solargraph/pin/delegated_method.rb +15 -4
- data/lib/solargraph/pin/documenting.rb +1 -0
- data/lib/solargraph/pin/instance_variable.rb +5 -1
- data/lib/solargraph/pin/keyword.rb +0 -4
- data/lib/solargraph/pin/local_variable.rb +13 -57
- data/lib/solargraph/pin/method.rb +90 -42
- data/lib/solargraph/pin/method_alias.rb +8 -0
- data/lib/solargraph/pin/namespace.rb +7 -1
- data/lib/solargraph/pin/parameter.rb +76 -13
- data/lib/solargraph/pin/proxy_type.rb +2 -1
- data/lib/solargraph/pin/reference/override.rb +1 -1
- data/lib/solargraph/pin/reference/superclass.rb +2 -0
- data/lib/solargraph/pin/reference.rb +2 -0
- data/lib/solargraph/pin/search.rb +1 -0
- data/lib/solargraph/pin/signature.rb +8 -0
- data/lib/solargraph/pin/symbol.rb +1 -1
- data/lib/solargraph/pin/until.rb +1 -1
- data/lib/solargraph/pin/while.rb +1 -1
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/pin_cache.rb +477 -57
- data/lib/solargraph/position.rb +12 -26
- data/lib/solargraph/range.rb +6 -6
- data/lib/solargraph/rbs_map/conversions.rb +33 -10
- data/lib/solargraph/rbs_map/core_map.rb +24 -17
- data/lib/solargraph/rbs_map/stdlib_map.rb +34 -5
- data/lib/solargraph/rbs_map.rb +74 -20
- data/lib/solargraph/shell.rb +73 -28
- data/lib/solargraph/source/chain/call.rb +52 -17
- data/lib/solargraph/source/chain/constant.rb +2 -0
- data/lib/solargraph/source/chain/hash.rb +1 -0
- data/lib/solargraph/source/chain/if.rb +1 -0
- data/lib/solargraph/source/chain/instance_variable.rb +22 -1
- data/lib/solargraph/source/chain/literal.rb +5 -0
- data/lib/solargraph/source/chain/or.rb +9 -1
- data/lib/solargraph/source/chain.rb +25 -22
- data/lib/solargraph/source/change.rb +9 -2
- data/lib/solargraph/source/cursor.rb +7 -1
- data/lib/solargraph/source/source_chainer.rb +13 -3
- data/lib/solargraph/source/updater.rb +4 -0
- data/lib/solargraph/source.rb +33 -7
- data/lib/solargraph/source_map/clip.rb +13 -2
- data/lib/solargraph/source_map/data.rb +4 -1
- data/lib/solargraph/source_map/mapper.rb +24 -1
- data/lib/solargraph/source_map.rb +14 -6
- data/lib/solargraph/type_checker/problem.rb +3 -1
- data/lib/solargraph/type_checker/rules.rb +75 -2
- data/lib/solargraph/type_checker.rb +111 -30
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +3 -1
- data/lib/solargraph/workspace/gemspecs.rb +367 -0
- data/lib/solargraph/workspace/require_paths.rb +1 -0
- data/lib/solargraph/workspace.rb +158 -16
- data/lib/solargraph/yard_map/helpers.rb +2 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +5 -1
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
- data/lib/solargraph/yard_map/mapper.rb +5 -0
- data/lib/solargraph/yardoc.rb +33 -23
- data/lib/solargraph.rb +24 -3
- data/rbs/fills/rubygems/0/dependency.rbs +193 -0
- data/rbs/fills/tuple/tuple.rbs +28 -0
- data/rbs/shims/ast/0/node.rbs +1 -1
- data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
- data/solargraph.gemspec +2 -1
- metadata +12 -7
- data/lib/solargraph/type_checker/checks.rb +0 -124
- data/lib/solargraph/type_checker/param_def.rb +0 -37
- data/lib/solargraph/yard_map/to_method.rb +0 -89
|
@@ -6,12 +6,24 @@ module Solargraph
|
|
|
6
6
|
# @!method source
|
|
7
7
|
# @abstract
|
|
8
8
|
# @return [Source, nil]
|
|
9
|
+
# @!method reset_generated!
|
|
10
|
+
# @abstract
|
|
11
|
+
# @return [void]
|
|
9
12
|
# @type @closure [Pin::Closure, nil]
|
|
13
|
+
# @type @binder [ComplexType, ComplexType::UniqueType, nil]
|
|
14
|
+
|
|
15
|
+
# @todo Missed nil violation
|
|
16
|
+
# @return [Location, nil]
|
|
17
|
+
attr_accessor :location
|
|
10
18
|
|
|
11
|
-
# @
|
|
12
|
-
|
|
19
|
+
# @param value [Pin::Closure]
|
|
20
|
+
# @return [void]
|
|
21
|
+
def closure=(value)
|
|
22
|
+
@closure = value
|
|
23
|
+
# remove cached values generated from closure
|
|
24
|
+
reset_generated!
|
|
25
|
+
end
|
|
13
26
|
|
|
14
|
-
# @sg-ignore Solargraph::Pin::Common#closure return type could not be inferred
|
|
15
27
|
# @return [Pin::Closure, nil]
|
|
16
28
|
def closure
|
|
17
29
|
Solargraph.assert_or_log(:closure, "Closure not set on #{self.class} #{name.inspect} from #{source.inspect}") unless @closure
|
|
@@ -23,12 +35,13 @@ module Solargraph
|
|
|
23
35
|
@name ||= ''
|
|
24
36
|
end
|
|
25
37
|
|
|
38
|
+
# @todo redundant with Base#return_type?
|
|
26
39
|
# @return [ComplexType]
|
|
27
40
|
def return_type
|
|
28
41
|
@return_type ||= ComplexType::UNDEFINED
|
|
29
42
|
end
|
|
30
43
|
|
|
31
|
-
# @return [ComplexType]
|
|
44
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
32
45
|
def context
|
|
33
46
|
# Get the static context from the nearest namespace
|
|
34
47
|
@context ||= find_context
|
|
@@ -40,7 +53,8 @@ module Solargraph
|
|
|
40
53
|
context.namespace.to_s
|
|
41
54
|
end
|
|
42
55
|
|
|
43
|
-
# @return [ComplexType]
|
|
56
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
57
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1100
|
|
44
58
|
def binder
|
|
45
59
|
@binder || context
|
|
46
60
|
end
|
|
@@ -70,6 +84,7 @@ module Solargraph
|
|
|
70
84
|
elsif here.is_a?(Pin::Method)
|
|
71
85
|
return here.context
|
|
72
86
|
end
|
|
87
|
+
# @sg-ignore Need to add nil check here
|
|
73
88
|
here = here.closure
|
|
74
89
|
end
|
|
75
90
|
ComplexType::ROOT
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Solargraph
|
|
2
|
+
module Pin
|
|
3
|
+
# A series of statements where if a given statement executes, /all
|
|
4
|
+
# of the previous statements in the sequence must have executed as
|
|
5
|
+
# well/. In other words, the statements are run from the top in
|
|
6
|
+
# sequence, until interrupted by something like a
|
|
7
|
+
# return/break/next/raise/etc.
|
|
8
|
+
#
|
|
9
|
+
# This mix-in is used in flow sensitive typing to determine how
|
|
10
|
+
# far we can assume a given assertion about a type can be trusted
|
|
11
|
+
# to be true.
|
|
12
|
+
#
|
|
13
|
+
# Some examples in Ruby:
|
|
14
|
+
#
|
|
15
|
+
# * Bodies of methods and Ruby blocks
|
|
16
|
+
# * Branches of conditionals and loops - if/elsif/else,
|
|
17
|
+
# unless/else, when, until, ||=, ?:, switch/case/else
|
|
18
|
+
# * The body of begin-end/try/rescue/ensure statements
|
|
19
|
+
#
|
|
20
|
+
# Compare/contrast with:
|
|
21
|
+
#
|
|
22
|
+
# * Scope - a sequence where variables declared are not available
|
|
23
|
+
# after the end of the scope. Note that this is not necessarily
|
|
24
|
+
# true for a compound statement.
|
|
25
|
+
# * Compound statement - synonym
|
|
26
|
+
# * Block - in Ruby this has a special meaning (a closure passed to a method), but
|
|
27
|
+
# in general parlance this is also a synonym.
|
|
28
|
+
# * Closure - a sequence which is also a scope
|
|
29
|
+
# * Namespace - a named sequence which is also a scope and a
|
|
30
|
+
# closure
|
|
31
|
+
#
|
|
32
|
+
# See:
|
|
33
|
+
# https://cse.buffalo.edu/~regan/cse305/RubyBNF.pdf
|
|
34
|
+
# https://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html
|
|
35
|
+
# https://en.wikipedia.org/wiki/Block_(programming)
|
|
36
|
+
#
|
|
37
|
+
# Note:
|
|
38
|
+
#
|
|
39
|
+
# Just because statement #1 in a sequence is executed, it doesn't
|
|
40
|
+
# mean that future ones will. Consider the effect of
|
|
41
|
+
# break/next/return/raise/etc. on control flow.
|
|
42
|
+
class CompoundStatement < Pin::Base
|
|
43
|
+
attr_reader :node
|
|
44
|
+
|
|
45
|
+
# @param receiver [Parser::AST::Node, nil]
|
|
46
|
+
# @param node [Parser::AST::Node, nil]
|
|
47
|
+
# @param context [ComplexType, nil]
|
|
48
|
+
# @param args [::Array<Parameter>]
|
|
49
|
+
def initialize node: nil, **splat
|
|
50
|
+
super(**splat)
|
|
51
|
+
@node = node
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -43,6 +43,7 @@ module Solargraph
|
|
|
43
43
|
data: {
|
|
44
44
|
path: path,
|
|
45
45
|
return_type: return_type.tag,
|
|
46
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
46
47
|
location: (location ? location.to_hash : nil),
|
|
47
48
|
deprecated: deprecated?
|
|
48
49
|
}
|
|
@@ -80,7 +81,7 @@ module Solargraph
|
|
|
80
81
|
|
|
81
82
|
# Get a markdown-flavored link to a documentation page.
|
|
82
83
|
#
|
|
83
|
-
# @return [String]
|
|
84
|
+
# @return [String, nil]
|
|
84
85
|
def link_documentation
|
|
85
86
|
@link_documentation ||= generate_link
|
|
86
87
|
end
|
|
@@ -13,10 +13,11 @@ module Solargraph
|
|
|
13
13
|
#
|
|
14
14
|
# @param method [Method, nil] an already resolved method pin.
|
|
15
15
|
# @param receiver [Source::Chain, nil] the source code used to resolve the receiver for this delegated method.
|
|
16
|
-
# @param name [String]
|
|
17
|
-
# @param receiver_method_name [String] the method name that will be called on the receiver (defaults to :name).
|
|
16
|
+
# @param name [String, nil]
|
|
17
|
+
# @param receiver_method_name [String, nil] the method name that will be called on the receiver (defaults to :name).
|
|
18
18
|
def initialize(method: nil, receiver: nil, name: method&.name, receiver_method_name: name, **splat)
|
|
19
19
|
raise ArgumentError, 'either :method or :receiver is required' if (method && receiver) || (!method && !receiver)
|
|
20
|
+
# @sg-ignore Need to add nil check here
|
|
20
21
|
super(name: name, **splat)
|
|
21
22
|
|
|
22
23
|
@receiver_chain = receiver
|
|
@@ -69,30 +70,40 @@ module Solargraph
|
|
|
69
70
|
#
|
|
70
71
|
# @param api_map [ApiMap]
|
|
71
72
|
# @return [Pin::Method, nil]
|
|
73
|
+
# @sg-ignore Declared return type ::Solargraph::Pin::Method, nil
|
|
74
|
+
# does not match inferred type nil, false for
|
|
75
|
+
# Solargraph::Pin::DelegatedMethod#resolve_method
|
|
72
76
|
def resolve_method api_map
|
|
73
77
|
return if @resolved_method
|
|
74
78
|
|
|
79
|
+
# @sg-ignore Need to add nil check here
|
|
75
80
|
resolver = @receiver_chain.define(api_map, self, []).first
|
|
76
81
|
|
|
77
82
|
unless resolver
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
# @sg-ignore Need to add nil check here
|
|
84
|
+
Solargraph.logger.warn "Delegated receiver for #{path} was resolved to nil from `#{print_chain(@receiver_chain)}'"
|
|
80
85
|
return
|
|
81
86
|
end
|
|
82
87
|
|
|
88
|
+
# @sg-ignore Need to add nil check here
|
|
83
89
|
receiver_type = resolver.return_type
|
|
84
90
|
|
|
91
|
+
# @sg-ignore Need to add nil check here
|
|
85
92
|
return if receiver_type.undefined?
|
|
86
93
|
|
|
87
94
|
receiver_path, method_scope =
|
|
95
|
+
# @sg-ignore Need to add nil check here
|
|
88
96
|
if @receiver_chain.constant?
|
|
89
97
|
# HACK: the `return_type` of a constant is Class<Whatever>, but looking up a method expects
|
|
90
98
|
# the arguments `"Whatever"` and `scope: :class`.
|
|
99
|
+
# @sg-ignore Need to add nil check here
|
|
91
100
|
[receiver_type.to_s.sub(/^Class<(.+)>$/, '\1'), :class]
|
|
92
101
|
else
|
|
102
|
+
# @sg-ignore Need to add nil check here
|
|
93
103
|
[receiver_type.to_s, :instance]
|
|
94
104
|
end
|
|
95
105
|
|
|
106
|
+
# @sg-ignore Need to add nil check here
|
|
96
107
|
method_stack = api_map.get_method_stack(receiver_path, @receiver_method_name, scope: method_scope)
|
|
97
108
|
@resolved_method = method_stack.first
|
|
98
109
|
end
|
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
module Solargraph
|
|
4
4
|
module Pin
|
|
5
5
|
class InstanceVariable < BaseVariable
|
|
6
|
-
# @
|
|
6
|
+
# @sg-ignore Need to add nil check here
|
|
7
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
7
8
|
def binder
|
|
9
|
+
# @sg-ignore Need to add nil check here
|
|
8
10
|
closure.binder
|
|
9
11
|
end
|
|
10
12
|
|
|
13
|
+
# @sg-ignore Need to add nil check here
|
|
11
14
|
# @return [::Symbol]
|
|
12
15
|
def scope
|
|
16
|
+
# @sg-ignore Need to add nil check here
|
|
13
17
|
closure.binder.scope
|
|
14
18
|
end
|
|
15
19
|
|
|
@@ -3,73 +3,29 @@
|
|
|
3
3
|
module Solargraph
|
|
4
4
|
module Pin
|
|
5
5
|
class LocalVariable < BaseVariable
|
|
6
|
-
# @
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
# @param api_map [ApiMap]
|
|
7
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
8
|
+
def probe api_map
|
|
9
|
+
if presence_certain? && return_type && return_type&.defined?
|
|
10
|
+
# flow sensitive typing has already figured out this type
|
|
11
|
+
# has been downcast - use the type it figured out
|
|
12
|
+
# @sg-ignore flow sensitive typing should support ivars
|
|
13
|
+
return adjust_type api_map, return_type.qualify(api_map, *gates)
|
|
14
|
+
end
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
# @param presence [Range, nil]
|
|
15
|
-
# @param presence_certain [Boolean]
|
|
16
|
-
# @param splat [Hash]
|
|
17
|
-
def initialize assignment: nil, presence: nil, presence_certain: false, **splat
|
|
18
|
-
super(**splat)
|
|
19
|
-
@assignment = assignment
|
|
20
|
-
@presence = presence
|
|
21
|
-
@presence_certain = presence_certain
|
|
16
|
+
super
|
|
22
17
|
end
|
|
23
18
|
|
|
24
19
|
def combine_with(other, attrs={})
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
presence_certain: assert_same(other, :presence_certain?),
|
|
28
|
-
}.merge(attrs)
|
|
29
|
-
new_attrs[:presence] = assert_same(other, :presence) unless attrs.key?(:presence)
|
|
20
|
+
# keep this as a parameter
|
|
21
|
+
return other.combine_with(self, attrs) if other.is_a?(Parameter) && !self.is_a?(Parameter)
|
|
30
22
|
|
|
31
|
-
super
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# @param other_closure [Pin::Closure]
|
|
35
|
-
# @param other_loc [Location]
|
|
36
|
-
def visible_at?(other_closure, other_loc)
|
|
37
|
-
location.filename == other_loc.filename &&
|
|
38
|
-
presence.include?(other_loc.range.start) &&
|
|
39
|
-
match_named_closure(other_closure, closure)
|
|
23
|
+
super
|
|
40
24
|
end
|
|
41
25
|
|
|
42
26
|
def to_rbs
|
|
43
27
|
(name || '(anon)') + ' ' + (return_type&.to_rbs || 'untyped')
|
|
44
28
|
end
|
|
45
|
-
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
# @param tag1 [String]
|
|
49
|
-
# @param tag2 [String]
|
|
50
|
-
# @return [Boolean]
|
|
51
|
-
def match_tags tag1, tag2
|
|
52
|
-
# @todo This is an unfortunate hack made necessary by a discrepancy in
|
|
53
|
-
# how tags indicate the root namespace. The long-term solution is to
|
|
54
|
-
# standardize it, whether it's `Class<>`, an empty string, or
|
|
55
|
-
# something else.
|
|
56
|
-
tag1 == tag2 ||
|
|
57
|
-
(['', 'Class<>'].include?(tag1) && ['', 'Class<>'].include?(tag2))
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# @param needle [Pin::Base]
|
|
61
|
-
# @param haystack [Pin::Base]
|
|
62
|
-
# @return [Boolean]
|
|
63
|
-
def match_named_closure needle, haystack
|
|
64
|
-
return true if needle == haystack || haystack.is_a?(Pin::Block)
|
|
65
|
-
cursor = haystack
|
|
66
|
-
until cursor.nil?
|
|
67
|
-
return true if needle.path == cursor.path
|
|
68
|
-
return false if cursor.path && !cursor.path.empty?
|
|
69
|
-
cursor = cursor.closure
|
|
70
|
-
end
|
|
71
|
-
false
|
|
72
|
-
end
|
|
73
29
|
end
|
|
74
30
|
end
|
|
75
31
|
end
|
|
@@ -22,8 +22,9 @@ module Solargraph
|
|
|
22
22
|
# @param attribute [Boolean]
|
|
23
23
|
# @param signatures [::Array<Signature>, nil]
|
|
24
24
|
# @param anon_splat [Boolean]
|
|
25
|
+
# @param context [ComplexType, ComplexType::UniqueType, nil]
|
|
25
26
|
def initialize visibility: :public, explicit: true, block: :undefined, node: nil, attribute: false, signatures: nil, anon_splat: false,
|
|
26
|
-
**splat
|
|
27
|
+
context: nil, **splat
|
|
27
28
|
super(**splat)
|
|
28
29
|
@visibility = visibility
|
|
29
30
|
@explicit = explicit
|
|
@@ -32,26 +33,7 @@ module Solargraph
|
|
|
32
33
|
@attribute = attribute
|
|
33
34
|
@signatures = signatures
|
|
34
35
|
@anon_splat = anon_splat
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
# @param signature_pins [Array<Pin::Signature>]
|
|
38
|
-
# @return [Array<Pin::Signature>]
|
|
39
|
-
def combine_all_signature_pins(*signature_pins)
|
|
40
|
-
# @type [Hash{Array => Array<Pin::Signature>}]
|
|
41
|
-
by_arity = {}
|
|
42
|
-
signature_pins.each do |signature_pin|
|
|
43
|
-
by_arity[signature_pin.arity] ||= []
|
|
44
|
-
by_arity[signature_pin.arity] << signature_pin
|
|
45
|
-
end
|
|
46
|
-
by_arity.transform_values! do |same_arity_pins|
|
|
47
|
-
# @param memo [Pin::Signature, nil]
|
|
48
|
-
# @param signature [Pin::Signature]
|
|
49
|
-
same_arity_pins.reduce(nil) do |memo, signature|
|
|
50
|
-
next signature if memo.nil?
|
|
51
|
-
memo.combine_with(signature)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
by_arity.values.flatten
|
|
36
|
+
@context = context if context
|
|
55
37
|
end
|
|
56
38
|
|
|
57
39
|
# @param other [Pin::Method]
|
|
@@ -66,20 +48,6 @@ module Solargraph
|
|
|
66
48
|
end
|
|
67
49
|
end
|
|
68
50
|
|
|
69
|
-
# @param other [Pin::Method]
|
|
70
|
-
# @return [Array<Pin::Signature>]
|
|
71
|
-
def combine_signatures(other)
|
|
72
|
-
all_undefined = signatures.all? { |sig| sig.return_type.undefined? }
|
|
73
|
-
other_all_undefined = other.signatures.all? { |sig| sig.return_type.undefined? }
|
|
74
|
-
if all_undefined && !other_all_undefined
|
|
75
|
-
other.signatures
|
|
76
|
-
elsif other_all_undefined && !all_undefined
|
|
77
|
-
signatures
|
|
78
|
-
else
|
|
79
|
-
combine_all_signature_pins(*signatures, *other.signatures)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
51
|
def combine_with(other, attrs = {})
|
|
84
52
|
priority_choice = choose_priority(other)
|
|
85
53
|
return priority_choice unless priority_choice.nil?
|
|
@@ -92,7 +60,6 @@ module Solargraph
|
|
|
92
60
|
end
|
|
93
61
|
new_attrs = {
|
|
94
62
|
visibility: combine_visibility(other),
|
|
95
|
-
# @sg-ignore https://github.com/castwide/solargraph/pull/1050
|
|
96
63
|
explicit: explicit? || other.explicit?,
|
|
97
64
|
block: combine_blocks(other),
|
|
98
65
|
node: choose_node(other, :node),
|
|
@@ -160,6 +127,8 @@ module Solargraph
|
|
|
160
127
|
!block.nil?
|
|
161
128
|
end
|
|
162
129
|
|
|
130
|
+
# @sg-ignore flow sensitive typing needs to remove literal with
|
|
131
|
+
# this unless block
|
|
163
132
|
# @return [Pin::Signature, nil]
|
|
164
133
|
def block
|
|
165
134
|
return @block unless @block == :undefined
|
|
@@ -179,9 +148,10 @@ module Solargraph
|
|
|
179
148
|
end
|
|
180
149
|
|
|
181
150
|
# @param parameters [::Array<Parameter>]
|
|
182
|
-
# @param return_type [ComplexType]
|
|
151
|
+
# @param return_type [ComplexType, nil]
|
|
183
152
|
# @return [Signature]
|
|
184
153
|
def generate_signature(parameters, return_type)
|
|
154
|
+
# @type [Pin::Signature, nil]
|
|
185
155
|
block = nil
|
|
186
156
|
yieldparam_tags = docstring.tags(:yieldparam)
|
|
187
157
|
yieldreturn_tags = docstring.tags(:yieldreturn)
|
|
@@ -202,6 +172,7 @@ module Solargraph
|
|
|
202
172
|
comments: p.text,
|
|
203
173
|
name: name,
|
|
204
174
|
decl: decl,
|
|
175
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
205
176
|
presence: location ? location.range : nil,
|
|
206
177
|
return_type: ComplexType.try_parse(*p.types),
|
|
207
178
|
source: source
|
|
@@ -247,6 +218,7 @@ module Solargraph
|
|
|
247
218
|
else
|
|
248
219
|
"(#{signatures.first.parameters.map(&:full).join(', ')}) " unless signatures.first.parameters.empty?
|
|
249
220
|
end.to_s
|
|
221
|
+
# @sg-ignore Need to add nil check here
|
|
250
222
|
detail += "=#{probed? ? '~' : (proxied? ? '^' : '>')} #{return_type.to_s}" unless return_type.undefined?
|
|
251
223
|
detail.strip!
|
|
252
224
|
return nil if detail.empty?
|
|
@@ -276,6 +248,7 @@ module Solargraph
|
|
|
276
248
|
return nil if signatures.empty?
|
|
277
249
|
|
|
278
250
|
rbs = "def #{name}: #{signatures.first.to_rbs}"
|
|
251
|
+
# @sg-ignore Need to add nil check here
|
|
279
252
|
signatures[1..].each do |sig|
|
|
280
253
|
rbs += "\n"
|
|
281
254
|
rbs += (' ' * (4 + name.length))
|
|
@@ -294,6 +267,7 @@ module Solargraph
|
|
|
294
267
|
end
|
|
295
268
|
|
|
296
269
|
def typify api_map
|
|
270
|
+
# @sg-ignore Need to add nil check here
|
|
297
271
|
logger.debug { "Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context.rooted_tags}, return_type=#{return_type.rooted_tags}) - starting" }
|
|
298
272
|
decl = super
|
|
299
273
|
unless decl.undefined?
|
|
@@ -303,6 +277,7 @@ module Solargraph
|
|
|
303
277
|
type = see_reference(api_map) || typify_from_super(api_map)
|
|
304
278
|
logger.debug { "Method#typify(self=#{self}) - type=#{type&.rooted_tags.inspect}" }
|
|
305
279
|
unless type.nil?
|
|
280
|
+
# @sg-ignore Need to add nil check here
|
|
306
281
|
qualified = type.qualify(api_map, *closure.gates)
|
|
307
282
|
logger.debug { "Method#typify(self=#{self}) => #{qualified.rooted_tags.inspect}" }
|
|
308
283
|
return qualified
|
|
@@ -396,7 +371,7 @@ module Solargraph
|
|
|
396
371
|
attribute? ? infer_from_iv(api_map) : infer_from_return_nodes(api_map)
|
|
397
372
|
end
|
|
398
373
|
|
|
399
|
-
# @return [::Array<Pin::
|
|
374
|
+
# @return [::Array<Pin::Signature>]
|
|
400
375
|
def overloads
|
|
401
376
|
# Ignore overload tags with nil parameters. If it's not an array, the
|
|
402
377
|
# tag's source is likely malformed.
|
|
@@ -414,6 +389,7 @@ module Solargraph
|
|
|
414
389
|
comments: tag.docstring.all.to_s,
|
|
415
390
|
name: name,
|
|
416
391
|
decl: decl,
|
|
392
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
417
393
|
presence: location ? location.range : nil,
|
|
418
394
|
return_type: param_type_from_name(tag, src.first),
|
|
419
395
|
source: :overloads
|
|
@@ -468,10 +444,12 @@ module Solargraph
|
|
|
468
444
|
|
|
469
445
|
attr_writer :documentation
|
|
470
446
|
|
|
447
|
+
# @sg-ignore Need to add nil check here
|
|
471
448
|
def dodgy_visibility_source?
|
|
472
449
|
# as of 2025-03-12, the RBS generator used for
|
|
473
450
|
# e.g. activesupport did not understand 'private' markings
|
|
474
451
|
# inside 'class << self' blocks, but YARD did OK at it
|
|
452
|
+
# @sg-ignore Need to add nil check here
|
|
475
453
|
source == :rbs && scope == :class && type_location&.filename&.include?('generated') && return_type.undefined? ||
|
|
476
454
|
# YARD's RBS generator seems to miss a lot of should-be protected instance methods
|
|
477
455
|
source == :rbs && scope == :instance && namespace.start_with?('YARD::') ||
|
|
@@ -485,6 +463,71 @@ module Solargraph
|
|
|
485
463
|
|
|
486
464
|
private
|
|
487
465
|
|
|
466
|
+
# @param other [Pin::Method]
|
|
467
|
+
# @return [Array<Pin::Signature>]
|
|
468
|
+
def combine_signatures(other)
|
|
469
|
+
all_undefined = signatures.all? { |sig| !sig.return_type&.defined? }
|
|
470
|
+
other_all_undefined = other.signatures.all? { |sig| !sig.return_type&.defined? }
|
|
471
|
+
if all_undefined && !other_all_undefined
|
|
472
|
+
other.signatures
|
|
473
|
+
elsif other_all_undefined && !all_undefined
|
|
474
|
+
signatures
|
|
475
|
+
else
|
|
476
|
+
combine_signatures_by_type_arity(*signatures, *other.signatures)
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
# @param signature_pins [Array<Pin::Signature>]
|
|
481
|
+
#
|
|
482
|
+
# @return [Array<Pin::Signature>]
|
|
483
|
+
def combine_signatures_by_type_arity(*signature_pins)
|
|
484
|
+
# @type [Hash{Array => Array<Pin::Signature>}]
|
|
485
|
+
by_type_arity = {}
|
|
486
|
+
signature_pins.each do |signature_pin|
|
|
487
|
+
by_type_arity[signature_pin.type_arity] ||= []
|
|
488
|
+
by_type_arity[signature_pin.type_arity] << signature_pin
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
by_type_arity.transform_values! do |same_type_arity_signatures|
|
|
492
|
+
combine_same_type_arity_signatures same_type_arity_signatures
|
|
493
|
+
end
|
|
494
|
+
by_type_arity.values.flatten
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
# @param same_type_arity_signatures [Array<Pin::Signature>]
|
|
498
|
+
#
|
|
499
|
+
# @return [Array<Pin::Signature>]
|
|
500
|
+
def combine_same_type_arity_signatures(same_type_arity_signatures)
|
|
501
|
+
# This is an O(n^2) operation, so bail out if n is not small
|
|
502
|
+
return same_type_arity_signatures if same_type_arity_signatures.length > 10
|
|
503
|
+
|
|
504
|
+
# @param old_signatures [Array<Pin::Signature>]
|
|
505
|
+
# @param new_signature [Pin::Signature]
|
|
506
|
+
same_type_arity_signatures.reduce([]) do |old_signatures, new_signature|
|
|
507
|
+
next [new_signature] if old_signatures.empty?
|
|
508
|
+
|
|
509
|
+
found_merge = false
|
|
510
|
+
old_signatures.flat_map do |old_signature|
|
|
511
|
+
potential_new_signature = old_signature.combine_with(new_signature)
|
|
512
|
+
|
|
513
|
+
if potential_new_signature.type_arity == old_signature.type_arity
|
|
514
|
+
# the number of types in each parameter and return type
|
|
515
|
+
# match, so we found compatible signatures to merge. If
|
|
516
|
+
# we increased the number of types, we'd potentially
|
|
517
|
+
# have taken away the ability to use parameter types to
|
|
518
|
+
# choose the correct return type (while Ruby doesn't
|
|
519
|
+
# dispatch based on type, RBS does distinguish overloads
|
|
520
|
+
# based on types, not just arity, allowing for type
|
|
521
|
+
# information describing how methods behave based on
|
|
522
|
+
# their input types)
|
|
523
|
+
old_signatures - [old_signature] + [potential_new_signature]
|
|
524
|
+
else
|
|
525
|
+
old_signatures + [new_signature]
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
end
|
|
529
|
+
end
|
|
530
|
+
|
|
488
531
|
# @param name [String]
|
|
489
532
|
# @param asgn [Boolean]
|
|
490
533
|
#
|
|
@@ -532,19 +575,20 @@ module Solargraph
|
|
|
532
575
|
end
|
|
533
576
|
|
|
534
577
|
# @param api_map [ApiMap]
|
|
535
|
-
# @return [ComplexType, nil]
|
|
578
|
+
# @return [ComplexType, ComplexType::UniqueType, nil]
|
|
536
579
|
def see_reference api_map
|
|
537
580
|
# This should actually be an intersection type
|
|
538
|
-
# @param ref [YARD::Tags::Tag,
|
|
581
|
+
# @param ref [YARD::Tags::Tag, YARD::Tags::RefTag]
|
|
539
582
|
docstring.ref_tags.each do |ref|
|
|
540
583
|
# @sg-ignore ref should actually be an intersection type
|
|
541
584
|
next unless ref.tag_name == 'return' && ref.owner
|
|
542
|
-
# @sg-ignore
|
|
585
|
+
# @sg-ignore should actually be an intersection type
|
|
543
586
|
result = resolve_reference(ref.owner.to_s, api_map)
|
|
544
587
|
return result unless result.nil?
|
|
545
588
|
end
|
|
546
589
|
match = comments.match(/^[ \t]*\(see (.*)\)/m)
|
|
547
590
|
return nil if match.nil?
|
|
591
|
+
# @sg-ignore Need to add nil check here
|
|
548
592
|
resolve_reference match[1], api_map
|
|
549
593
|
end
|
|
550
594
|
|
|
@@ -559,6 +603,7 @@ module Solargraph
|
|
|
559
603
|
stack = rest_of_stack api_map
|
|
560
604
|
return nil if stack.empty?
|
|
561
605
|
stack.each do |pin|
|
|
606
|
+
# @sg-ignore Need to add nil check here
|
|
562
607
|
return pin.return_type unless pin.return_type.undefined?
|
|
563
608
|
end
|
|
564
609
|
nil
|
|
@@ -566,7 +611,7 @@ module Solargraph
|
|
|
566
611
|
|
|
567
612
|
# @param ref [String]
|
|
568
613
|
# @param api_map [ApiMap]
|
|
569
|
-
# @return [ComplexType, nil]
|
|
614
|
+
# @return [ComplexType, ComplexType::UniqueType, nil]
|
|
570
615
|
def resolve_reference ref, api_map
|
|
571
616
|
parts = ref.split(/[.#]/)
|
|
572
617
|
if parts.first.empty? || parts.one?
|
|
@@ -574,6 +619,7 @@ module Solargraph
|
|
|
574
619
|
else
|
|
575
620
|
fqns = api_map.qualify(parts.first, *gates)
|
|
576
621
|
return ComplexType::UNDEFINED if fqns.nil?
|
|
622
|
+
# @sg-ignore Need to add nil check here
|
|
577
623
|
path = fqns + ref[parts.first.length] + parts.last
|
|
578
624
|
end
|
|
579
625
|
pins = api_map.get_path_pins(path)
|
|
@@ -609,9 +655,11 @@ module Solargraph
|
|
|
609
655
|
rng = Range.from_node(n)
|
|
610
656
|
next unless rng
|
|
611
657
|
clip = api_map.clip_at(
|
|
658
|
+
# @sg-ignore Need to add nil check here
|
|
612
659
|
location.filename,
|
|
613
660
|
rng.ending
|
|
614
661
|
)
|
|
662
|
+
# @sg-ignore Need to add nil check here
|
|
615
663
|
chain = Solargraph::Parser.chain(n, location.filename)
|
|
616
664
|
type = chain.infer(api_map, self, clip.locals)
|
|
617
665
|
result.push type unless type.undefined?
|
|
@@ -26,6 +26,14 @@ module Solargraph
|
|
|
26
26
|
:public
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
def to_rbs
|
|
30
|
+
if scope == :class
|
|
31
|
+
"alias self.#{name} self.#{original}"
|
|
32
|
+
else
|
|
33
|
+
"alias #{name} #{original}"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
29
37
|
def path
|
|
30
38
|
@path ||= namespace + (scope == :instance ? '#' : '.') + name
|
|
31
39
|
end
|
|
@@ -26,7 +26,6 @@ module Solargraph
|
|
|
26
26
|
@type = type
|
|
27
27
|
@visibility = visibility
|
|
28
28
|
if name.start_with?('::')
|
|
29
|
-
# @type [String]
|
|
30
29
|
name = name[2..-1] || ''
|
|
31
30
|
@closure = Solargraph::Pin::ROOT_PIN
|
|
32
31
|
end
|
|
@@ -39,6 +38,7 @@ module Solargraph
|
|
|
39
38
|
closure_name = if [Solargraph::Pin::ROOT_PIN, nil].include?(closure)
|
|
40
39
|
''
|
|
41
40
|
else
|
|
41
|
+
# @sg-ignore Need to add nil check here
|
|
42
42
|
closure.full_context.namespace + '::'
|
|
43
43
|
end
|
|
44
44
|
closure_name += parts.join('::')
|
|
@@ -48,6 +48,12 @@ module Solargraph
|
|
|
48
48
|
@name = name
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
+
def reset_generated!
|
|
52
|
+
@return_type = nil
|
|
53
|
+
@full_context = nil
|
|
54
|
+
@path = nil
|
|
55
|
+
end
|
|
56
|
+
|
|
51
57
|
def to_rbs
|
|
52
58
|
"#{@type.to_s} #{return_type.all_params.first.to_rbs}#{rbs_generics}".strip
|
|
53
59
|
end
|