solargraph 0.58.0 → 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.
Files changed (166) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.gitattributes +2 -0
  4. data/.github/workflows/linting.yml +4 -5
  5. data/.github/workflows/plugins.yml +40 -36
  6. data/.github/workflows/rspec.yml +45 -13
  7. data/.github/workflows/typecheck.yml +2 -2
  8. data/.rubocop_todo.yml +27 -49
  9. data/CHANGELOG.md +3 -0
  10. data/README.md +3 -3
  11. data/Rakefile +1 -0
  12. data/bin/solargraph +8 -8
  13. data/lib/solargraph/api_map/cache.rb +110 -110
  14. data/lib/solargraph/api_map/constants.rb +289 -279
  15. data/lib/solargraph/api_map/index.rb +204 -193
  16. data/lib/solargraph/api_map/source_to_yard.rb +109 -97
  17. data/lib/solargraph/api_map/store.rb +387 -384
  18. data/lib/solargraph/api_map.rb +1000 -945
  19. data/lib/solargraph/complex_type/conformance.rb +176 -0
  20. data/lib/solargraph/complex_type/type_methods.rb +242 -228
  21. data/lib/solargraph/complex_type/unique_type.rb +632 -482
  22. data/lib/solargraph/complex_type.rb +549 -444
  23. data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
  24. data/lib/solargraph/convention/data_definition.rb +108 -105
  25. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
  26. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
  27. data/lib/solargraph/convention/struct_definition.rb +168 -164
  28. data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
  29. data/lib/solargraph/diagnostics/rubocop.rb +119 -118
  30. data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
  31. data/lib/solargraph/diagnostics/type_check.rb +56 -55
  32. data/lib/solargraph/doc_map.rb +200 -439
  33. data/lib/solargraph/equality.rb +34 -34
  34. data/lib/solargraph/gem_pins.rb +97 -98
  35. data/lib/solargraph/language_server/host/dispatch.rb +131 -130
  36. data/lib/solargraph/language_server/host/message_worker.rb +113 -112
  37. data/lib/solargraph/language_server/host/sources.rb +100 -99
  38. data/lib/solargraph/language_server/host.rb +883 -878
  39. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +109 -114
  40. data/lib/solargraph/language_server/message/extended/document.rb +24 -23
  41. data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
  42. data/lib/solargraph/language_server/message/text_document/definition.rb +42 -40
  43. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +28 -26
  44. data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
  45. data/lib/solargraph/language_server/message/text_document/hover.rb +60 -58
  46. data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
  47. data/lib/solargraph/language_server/message/text_document/type_definition.rb +27 -25
  48. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +25 -23
  49. data/lib/solargraph/library.rb +729 -683
  50. data/lib/solargraph/location.rb +87 -82
  51. data/lib/solargraph/logging.rb +57 -37
  52. data/lib/solargraph/parser/comment_ripper.rb +76 -69
  53. data/lib/solargraph/parser/flow_sensitive_typing.rb +483 -255
  54. data/lib/solargraph/parser/node_processor/base.rb +122 -92
  55. data/lib/solargraph/parser/node_processor.rb +63 -62
  56. data/lib/solargraph/parser/parser_gem/class_methods.rb +167 -149
  57. data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
  58. data/lib/solargraph/parser/parser_gem/node_methods.rb +506 -486
  59. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
  60. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
  61. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
  62. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -46
  63. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
  64. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
  65. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +41 -40
  66. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
  67. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
  68. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
  69. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
  71. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
  72. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +53 -52
  73. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +296 -291
  74. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  75. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
  76. data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
  77. data/lib/solargraph/parser/region.rb +75 -69
  78. data/lib/solargraph/parser/snippet.rb +17 -17
  79. data/lib/solargraph/pin/base.rb +761 -729
  80. data/lib/solargraph/pin/base_variable.rb +418 -126
  81. data/lib/solargraph/pin/block.rb +126 -104
  82. data/lib/solargraph/pin/breakable.rb +13 -9
  83. data/lib/solargraph/pin/callable.rb +278 -231
  84. data/lib/solargraph/pin/closure.rb +68 -72
  85. data/lib/solargraph/pin/common.rb +94 -79
  86. data/lib/solargraph/pin/compound_statement.rb +55 -0
  87. data/lib/solargraph/pin/conversions.rb +124 -123
  88. data/lib/solargraph/pin/delegated_method.rb +131 -120
  89. data/lib/solargraph/pin/documenting.rb +115 -114
  90. data/lib/solargraph/pin/instance_variable.rb +38 -34
  91. data/lib/solargraph/pin/keyword.rb +16 -20
  92. data/lib/solargraph/pin/local_variable.rb +31 -75
  93. data/lib/solargraph/pin/method.rb +720 -672
  94. data/lib/solargraph/pin/method_alias.rb +42 -34
  95. data/lib/solargraph/pin/namespace.rb +121 -115
  96. data/lib/solargraph/pin/parameter.rb +338 -275
  97. data/lib/solargraph/pin/proxy_type.rb +40 -39
  98. data/lib/solargraph/pin/reference/override.rb +47 -47
  99. data/lib/solargraph/pin/reference/superclass.rb +17 -15
  100. data/lib/solargraph/pin/reference.rb +41 -39
  101. data/lib/solargraph/pin/search.rb +62 -61
  102. data/lib/solargraph/pin/signature.rb +69 -61
  103. data/lib/solargraph/pin/symbol.rb +53 -53
  104. data/lib/solargraph/pin/until.rb +18 -18
  105. data/lib/solargraph/pin/while.rb +18 -18
  106. data/lib/solargraph/pin.rb +46 -44
  107. data/lib/solargraph/pin_cache.rb +665 -245
  108. data/lib/solargraph/position.rb +118 -119
  109. data/lib/solargraph/range.rb +112 -112
  110. data/lib/solargraph/rbs_map/conversions.rb +846 -823
  111. data/lib/solargraph/rbs_map/core_map.rb +65 -58
  112. data/lib/solargraph/rbs_map/stdlib_map.rb +72 -43
  113. data/lib/solargraph/rbs_map.rb +217 -163
  114. data/lib/solargraph/shell.rb +397 -352
  115. data/lib/solargraph/source/chain/call.rb +372 -337
  116. data/lib/solargraph/source/chain/constant.rb +28 -26
  117. data/lib/solargraph/source/chain/hash.rb +35 -34
  118. data/lib/solargraph/source/chain/if.rb +29 -28
  119. data/lib/solargraph/source/chain/instance_variable.rb +34 -13
  120. data/lib/solargraph/source/chain/literal.rb +53 -48
  121. data/lib/solargraph/source/chain/or.rb +31 -23
  122. data/lib/solargraph/source/chain.rb +294 -291
  123. data/lib/solargraph/source/change.rb +89 -82
  124. data/lib/solargraph/source/cursor.rb +172 -166
  125. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  126. data/lib/solargraph/source/source_chainer.rb +204 -194
  127. data/lib/solargraph/source/updater.rb +59 -55
  128. data/lib/solargraph/source.rb +524 -498
  129. data/lib/solargraph/source_map/clip.rb +237 -226
  130. data/lib/solargraph/source_map/data.rb +37 -34
  131. data/lib/solargraph/source_map/mapper.rb +282 -259
  132. data/lib/solargraph/source_map.rb +220 -212
  133. data/lib/solargraph/type_checker/problem.rb +34 -32
  134. data/lib/solargraph/type_checker/rules.rb +157 -84
  135. data/lib/solargraph/type_checker.rb +895 -814
  136. data/lib/solargraph/version.rb +5 -5
  137. data/lib/solargraph/workspace/config.rb +257 -255
  138. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  139. data/lib/solargraph/workspace/require_paths.rb +98 -97
  140. data/lib/solargraph/workspace.rb +362 -220
  141. data/lib/solargraph/yard_map/helpers.rb +45 -44
  142. data/lib/solargraph/yard_map/mapper/to_method.rb +134 -130
  143. data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
  144. data/lib/solargraph/yard_map/mapper.rb +84 -79
  145. data/lib/solargraph/yardoc.rb +97 -87
  146. data/lib/solargraph.rb +126 -105
  147. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  148. data/rbs/fills/tuple/tuple.rbs +28 -0
  149. data/rbs/shims/ast/0/node.rbs +5 -0
  150. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  151. data/rbs_collection.yaml +1 -1
  152. data/solargraph.gemspec +2 -1
  153. metadata +23 -17
  154. data/lib/solargraph/type_checker/checks.rb +0 -124
  155. data/lib/solargraph/type_checker/param_def.rb +0 -37
  156. data/lib/solargraph/yard_map/to_method.rb +0 -89
  157. data/sig/shims/ast/0/node.rbs +0 -5
  158. /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
  159. /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
  160. /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
  161. /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
  162. /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
  163. /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
  164. /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
  165. /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
  166. /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
@@ -0,0 +1,176 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class ComplexType
5
+ # Checks whether a type can be used in a given situation
6
+ class Conformance
7
+ # @param api_map [ApiMap]
8
+ # @param inferred [ComplexType::UniqueType]
9
+ # @param expected [ComplexType::UniqueType]
10
+ # @param situation [:method_call, :return_type]
11
+ # @param rules [Array<:allow_subtype_skew, :allow_empty_params, :allow_reverse_match,
12
+ # :allow_any_match, :allow_undefined, :allow_unresolved_generic,
13
+ # :allow_unmatched_interface>]
14
+ # @param variance [:invariant, :covariant, :contravariant]
15
+ def initialize api_map, inferred, expected,
16
+ situation = :method_call, rules = [],
17
+ variance: inferred.erased_variance(situation)
18
+ @api_map = api_map
19
+ @inferred = inferred
20
+ @expected = expected
21
+ @situation = situation
22
+ @rules = rules
23
+ @variance = variance
24
+ # :nocov:
25
+ unless expected.is_a?(UniqueType)
26
+ # @sg-ignore This should never happen and the typechecker is angry about it
27
+ raise "Expected type must be a UniqueType, got #{expected.class} in #{expected.inspect}"
28
+ end
29
+ # :nocov:
30
+ return if inferred.is_a?(UniqueType)
31
+ # :nocov:
32
+ # @sg-ignore This should never happen and the typechecker is angry about it
33
+ raise "Inferred type must be a UniqueType, got #{inferred.class} in #{inferred.inspect}"
34
+ # :nocov:
35
+ end
36
+
37
+ def conforms_to_unique_type?
38
+ unless expected.is_a?(UniqueType)
39
+ # :nocov:
40
+ raise "Expected type must be a UniqueType, got #{expected.class} in #{expected.inspect}"
41
+ # :nocov:
42
+ end
43
+
44
+ return true if ignore_interface?
45
+ return true if conforms_via_reverse_match?
46
+
47
+ downcast_inferred = inferred.downcast_to_literal_if_possible
48
+ downcast_expected = expected.downcast_to_literal_if_possible
49
+ if (downcast_inferred.name != inferred.name) || (downcast_expected.name != expected.name)
50
+ return with_new_types(downcast_inferred, downcast_expected).conforms_to_unique_type?
51
+ end
52
+
53
+ if rules.include?(:allow_subtype_skew) && !expected.all_params.empty?
54
+ # parameters are not considered in this case
55
+ return with_new_types(inferred, expected.erase_parameters).conforms_to_unique_type?
56
+ end
57
+
58
+ return with_new_types(inferred.erase_parameters, expected).conforms_to_unique_type? if only_inferred_parameters?
59
+
60
+ return conforms_via_stripped_expected_parameters? if can_strip_expected_parameters?
61
+
62
+ return true if inferred == expected
63
+
64
+ return false unless erased_type_conforms?
65
+
66
+ return true if inferred.all_params.empty? && rules.include?(:allow_empty_params)
67
+
68
+ # at this point we know the erased type is fine - time to look at parameters
69
+
70
+ # there's an implicit 'any' on the expectation parameters
71
+ # if there are none specified
72
+ return true if expected.all_params.empty?
73
+
74
+ return false unless key_types_conform?
75
+
76
+ subtypes_conform?
77
+ end
78
+
79
+ private
80
+
81
+ def only_inferred_parameters?
82
+ !expected.parameters? && inferred.parameters?
83
+ end
84
+
85
+ def conforms_via_stripped_expected_parameters?
86
+ with_new_types(inferred, expected.erase_parameters).conforms_to_unique_type?
87
+ end
88
+
89
+ def ignore_interface?
90
+ (expected.any?(&:interface?) && rules.include?(:allow_unmatched_interface)) ||
91
+ (inferred.interface? && rules.include?(:allow_unmatched_interface))
92
+ end
93
+
94
+ def can_strip_expected_parameters?
95
+ expected.parameters? && !inferred.parameters? && rules.include?(:allow_empty_params)
96
+ end
97
+
98
+ def conforms_via_reverse_match?
99
+ return false unless rules.include? :allow_reverse_match
100
+
101
+ expected.conforms_to?(api_map, inferred, situation,
102
+ rules - [:allow_reverse_match],
103
+ variance: variance)
104
+ end
105
+
106
+ def erased_type_conforms?
107
+ case variance
108
+ when :invariant
109
+ return false unless inferred.name == expected.name
110
+ when :covariant
111
+ # covariant: we can pass in a more specific type
112
+ # we contain the expected mix-in, or we have a more specific type
113
+ return false unless api_map.type_include?(inferred.name, expected.name) ||
114
+ api_map.super_and_sub?(expected.name, inferred.name) ||
115
+ inferred.name == expected.name
116
+ when :contravariant
117
+ # contravariant: we can pass in a more general type
118
+ # we contain the expected mix-in, or we have a more general type
119
+ return false unless api_map.type_include?(inferred.name, expected.name) ||
120
+ api_map.super_and_sub?(inferred.name, expected.name) ||
121
+ inferred.name == expected.name
122
+ else
123
+ # :nocov:
124
+ raise "Unknown variance: #{variance.inspect}"
125
+ # :nocov:
126
+ end
127
+ true
128
+ end
129
+
130
+ def key_types_conform?
131
+ return true if expected.key_types.empty?
132
+
133
+ return false if inferred.key_types.empty?
134
+
135
+ unless ComplexType.new(inferred.key_types).conforms_to?(api_map,
136
+ ComplexType.new(expected.key_types),
137
+ situation,
138
+ rules,
139
+ variance: inferred.parameter_variance(situation))
140
+ return false
141
+ end
142
+
143
+ true
144
+ end
145
+
146
+ def subtypes_conform?
147
+ return true if expected.subtypes.empty?
148
+
149
+ return true if expected.subtypes.any?(&:undefined?) && rules.include?(:allow_undefined)
150
+
151
+ return true if inferred.subtypes.any?(&:undefined?) && rules.include?(:allow_undefined)
152
+
153
+ return true if inferred.subtypes.all?(&:generic?) && rules.include?(:allow_unresolved_generic)
154
+
155
+ return true if expected.subtypes.all?(&:generic?) && rules.include?(:allow_unresolved_generic)
156
+
157
+ return false if inferred.subtypes.empty?
158
+
159
+ ComplexType.new(inferred.subtypes).conforms_to?(api_map,
160
+ ComplexType.new(expected.subtypes),
161
+ situation,
162
+ rules,
163
+ variance: inferred.parameter_variance(situation))
164
+ end
165
+
166
+ # @return [self]
167
+ # @param inferred [ComplexType::UniqueType]
168
+ # @param expected [ComplexType::UniqueType]
169
+ def with_new_types inferred, expected
170
+ self.class.new(api_map, inferred, expected, situation, rules, variance: variance)
171
+ end
172
+
173
+ attr_reader :api_map, :inferred, :expected, :situation, :rules, :variance
174
+ end
175
+ end
176
+ end
@@ -1,228 +1,242 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class ComplexType
5
- # Methods for accessing type data available from
6
- # both ComplexType and UniqueType.
7
- #
8
- # @abstract This mixin relies on these -
9
- # instance variables:
10
- # @name: String
11
- # @subtypes: Array<ComplexType>
12
- # @rooted: boolish
13
- # methods:
14
- # transform()
15
- # all_params()
16
- # rooted?()
17
- # can_root_name?()
18
- module TypeMethods
19
- # @!method transform(new_name = nil, &transform_type)
20
- # @param new_name [String, nil]
21
- # @yieldparam t [UniqueType]
22
- # @yieldreturn [UniqueType]
23
- # @return [UniqueType, nil]
24
- # @!method all_params
25
- # @return [Array<ComplexType>]
26
- # @!method rooted?
27
- # @!method can_root_name?(name_to_check = nil)
28
- # @param name_to_check [String, nil]
29
-
30
- # @return [String]
31
- attr_reader :name
32
-
33
- # @return [Array<ComplexType>]
34
- attr_reader :subtypes
35
-
36
- # @return [String]
37
- def tag
38
- @tag ||= "#{name}#{substring}"
39
- end
40
-
41
- # @return [String]
42
- def rooted_tag
43
- @rooted_tag ||= rooted_name + rooted_substring
44
- end
45
-
46
- def interface?
47
- name.start_with?('_')
48
- end
49
-
50
- # @return [Boolean]
51
- def duck_type?
52
- @duck_type ||= name.start_with?('#')
53
- end
54
-
55
- # @return [Boolean]
56
- def nil_type?
57
- @nil_type ||= (name.casecmp('nil') == 0)
58
- end
59
-
60
- def tuple?
61
- @tuple_type ||= (name == 'Tuple') || (name == 'Array' && subtypes.length >= 1 && fixed_parameters?)
62
- end
63
-
64
- def void?
65
- name == 'void'
66
- end
67
-
68
- def defined?
69
- !undefined?
70
- end
71
-
72
- def undefined?
73
- name == 'undefined'
74
- end
75
-
76
- # @param generics_to_erase [Enumerable<String>]
77
- # @return [self]
78
- def erase_generics(generics_to_erase)
79
- transform do |type|
80
- if type.name == ComplexType::GENERIC_TAG_NAME
81
- if type.all_params.length == 1 && generics_to_erase.include?(type.all_params.first.to_s)
82
- ComplexType::UNDEFINED
83
- else
84
- type
85
- end
86
- else
87
- type
88
- end
89
- end
90
- end
91
-
92
- # @return [Symbol, nil]
93
- attr_reader :parameters_type
94
-
95
- # @type [Hash{String => Symbol}]
96
- PARAMETERS_TYPE_BY_STARTING_TAG = {
97
- '{' => :hash,
98
- '(' => :fixed,
99
- '<' => :list
100
- }.freeze
101
-
102
- # @return [Boolean]
103
- def list_parameters?
104
- parameters_type == :list
105
- end
106
-
107
- # @return [Boolean]
108
- def fixed_parameters?
109
- parameters_type == :fixed
110
- end
111
-
112
- # @return [Boolean]
113
- def hash_parameters?
114
- parameters_type == :hash
115
- end
116
-
117
- # @return [Array<ComplexType>]
118
- def value_types
119
- @subtypes
120
- end
121
-
122
- # @return [Array<ComplexType>]
123
- def key_types
124
- @key_types
125
- end
126
-
127
- # @return [String]
128
- def namespace
129
- # if priority higher than ||=, old implements cause unnecessary check
130
- @namespace ||= lambda do
131
- return 'Object' if duck_type?
132
- return 'NilClass' if nil_type?
133
- return (name == 'Class' || name == 'Module') && !subtypes.empty? ? subtypes.first.name : name
134
- end.call
135
- end
136
-
137
- # @return [self]
138
- def namespace_type
139
- return ComplexType.parse('::Object') if duck_type?
140
- return ComplexType.parse('::NilClass') if nil_type?
141
- return subtypes.first if (name == 'Class' || name == 'Module') && !subtypes.empty?
142
- self
143
- end
144
-
145
- # @return [String]
146
- def rooted_namespace
147
- return namespace unless rooted? && can_root_name?(namespace)
148
- "::#{namespace}"
149
- end
150
-
151
- # @return [String]
152
- def rooted_name
153
- return name unless @rooted && can_root_name?
154
- "::#{name}"
155
- end
156
-
157
- # @return [String]
158
- def substring
159
- @substring ||= generate_substring_from(&:tags)
160
- end
161
-
162
- # @return [String]
163
- def rooted_substring
164
- @rooted_substring = generate_substring_from(&:rooted_tags)
165
- end
166
-
167
- # @return [String]
168
- def generate_substring_from(&to_str)
169
- key_types_str = key_types.map(&to_str).join(', ')
170
- subtypes_str = subtypes.map(&to_str).join(', ')
171
- if key_types.none?(&:defined?) && subtypes.none?(&:defined?)
172
- ''
173
- elsif key_types.empty? && subtypes.empty?
174
- ''
175
- elsif hash_parameters?
176
- "{#{key_types_str} => #{subtypes_str}}"
177
- elsif fixed_parameters?
178
- "(#{subtypes_str})"
179
- else
180
- if name == 'Hash'
181
- "<#{key_types_str}, #{subtypes_str}>"
182
- else
183
- "<#{key_types_str}#{subtypes_str}>"
184
- end
185
- end
186
- end
187
-
188
- # @return [::Symbol] :class or :instance
189
- def scope
190
- @scope ||= :instance if duck_type? || nil_type?
191
- @scope ||= (name == 'Class' || name == 'Module') && !subtypes.empty? ? :class : :instance
192
- end
193
-
194
- # @param other [Object]
195
- def == other
196
- return false unless self.class == other.class
197
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
198
- tag == other.tag
199
- end
200
-
201
- # Generate a ComplexType that fully qualifies this type's namespaces.
202
- #
203
- # @param api_map [ApiMap] The ApiMap that performs qualification
204
- # @param context [String] The namespace from which to resolve names
205
- # @return [self, ComplexType, UniqueType] The generated ComplexType
206
- def qualify api_map, context = ''
207
- transform do |t|
208
- next t if t.name == GENERIC_TAG_NAME
209
- next t if t.duck_type? || t.void? || t.undefined?
210
- recon = (t.rooted? ? '' : context)
211
- fqns = api_map.qualify(t.name, recon)
212
- if fqns.nil?
213
- next UniqueType::BOOLEAN if t.tag == 'Boolean'
214
- next UniqueType::UNDEFINED
215
- end
216
- t.recreate(new_name: fqns, make_rooted: true)
217
- end
218
- end
219
-
220
- # @yieldparam [UniqueType]
221
- # @return [Enumerator<UniqueType>]
222
- def each_unique_type &block
223
- return enum_for(__method__) unless block_given?
224
- yield self
225
- end
226
- end
227
- end
228
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class ComplexType
5
+ # Methods for accessing type data available from
6
+ # both ComplexType and UniqueType.
7
+ #
8
+ # @abstract This mixin relies on these -
9
+ # instance variables:
10
+ # @name: String
11
+ # @subtypes: Array<ComplexType>
12
+ # @rooted: boolish
13
+ # methods:
14
+ # transform()
15
+ # all_params()
16
+ # rooted?()
17
+ # can_root_name?()
18
+ module TypeMethods
19
+ # @!method transform(new_name = nil, &transform_type)
20
+ # @param new_name [String, nil]
21
+ # @yieldparam t [UniqueType]
22
+ # @yieldreturn [UniqueType]
23
+ # @return [UniqueType, nil]
24
+ # @!method all_params
25
+ # @return [Array<ComplexType>]
26
+ # @!method rooted?
27
+ # @!method can_root_name?(name_to_check = nil)
28
+ # @param name_to_check [String, nil]
29
+
30
+ # @return [String]
31
+ attr_reader :name
32
+
33
+ # @return [Array<ComplexType>]
34
+ attr_reader :subtypes
35
+
36
+ # @return [String]
37
+ def tag
38
+ @tag ||= "#{name}#{substring}"
39
+ end
40
+
41
+ # @return [String]
42
+ def rooted_tag
43
+ @rooted_tag ||= rooted_name + rooted_substring
44
+ end
45
+
46
+ def interface?
47
+ name.start_with?('_')
48
+ end
49
+
50
+ # @return [Boolean]
51
+ def duck_type?
52
+ @duck_type ||= name.start_with?('#')
53
+ end
54
+
55
+ # @return [Boolean]
56
+ def nil_type?
57
+ @nil_type ||= (name.casecmp('nil') == 0)
58
+ end
59
+
60
+ def tuple?
61
+ @tuple_type ||= (name == 'Tuple') || (name == 'Array' && subtypes.length >= 1 && fixed_parameters?)
62
+ end
63
+
64
+ def void?
65
+ name == 'void'
66
+ end
67
+
68
+ def defined?
69
+ !undefined?
70
+ end
71
+
72
+ def undefined?
73
+ name == 'undefined'
74
+ end
75
+
76
+ # Variance of the type ignoring any type parameters
77
+ # @return [Symbol]
78
+ # @param situation [Symbol] The situation in which the variance is being considered.
79
+ def erased_variance situation = :method_call
80
+ # :nocov:
81
+ unless %i[method_call return_type assignment].include?(situation)
82
+ raise "Unknown situation: #{situation.inspect}"
83
+ end
84
+ # :nocov:
85
+ :covariant
86
+ end
87
+
88
+ # @param generics_to_erase [Enumerable<String>]
89
+ # @return [self]
90
+ def erase_generics(generics_to_erase)
91
+ transform do |type|
92
+ if type.name == ComplexType::GENERIC_TAG_NAME
93
+ if type.all_params.length == 1 && generics_to_erase.include?(type.all_params.first.to_s)
94
+ ComplexType::UNDEFINED
95
+ else
96
+ type
97
+ end
98
+ else
99
+ type
100
+ end
101
+ end
102
+ end
103
+
104
+ # @return [Symbol, nil]
105
+ attr_reader :parameters_type
106
+
107
+ # @type [Hash{String => Symbol}]
108
+ PARAMETERS_TYPE_BY_STARTING_TAG = {
109
+ '{' => :hash,
110
+ '(' => :fixed,
111
+ '<' => :list
112
+ }.freeze
113
+
114
+ # @return [Boolean]
115
+ def list_parameters?
116
+ parameters_type == :list
117
+ end
118
+
119
+ # @return [Boolean]
120
+ def fixed_parameters?
121
+ parameters_type == :fixed
122
+ end
123
+
124
+ # @return [Boolean]
125
+ def hash_parameters?
126
+ parameters_type == :hash
127
+ end
128
+
129
+ # @return [Array<ComplexType>]
130
+ def value_types
131
+ @subtypes
132
+ end
133
+
134
+ # @return [Array<ComplexType>]
135
+ def key_types
136
+ @key_types
137
+ end
138
+
139
+ # @return [String]
140
+ def namespace
141
+ # if priority higher than ||=, old implements cause unnecessary check
142
+ @namespace ||= lambda do
143
+ return 'Object' if duck_type?
144
+ return 'NilClass' if nil_type?
145
+ return (name == 'Class' || name == 'Module') && !subtypes.empty? ? subtypes.first.name : name
146
+ end.call
147
+ end
148
+
149
+ # @return [self]
150
+ def namespace_type
151
+ return ComplexType.parse('::Object') if duck_type?
152
+ return ComplexType.parse('::NilClass') if nil_type?
153
+ return subtypes.first if (name == 'Class' || name == 'Module') && !subtypes.empty?
154
+ self
155
+ end
156
+
157
+ # @return [String]
158
+ def rooted_namespace
159
+ return namespace unless rooted? && can_root_name?(namespace)
160
+ "::#{namespace}"
161
+ end
162
+
163
+ # @return [String]
164
+ def rooted_name
165
+ return name unless @rooted && can_root_name?
166
+ "::#{name}"
167
+ end
168
+
169
+ # @return [String]
170
+ def substring
171
+ @substring ||= generate_substring_from(&:tags)
172
+ end
173
+
174
+ # @return [String]
175
+ def rooted_substring
176
+ @rooted_substring = generate_substring_from(&:rooted_tags)
177
+ end
178
+
179
+ # @return [String]
180
+ def generate_substring_from(&to_str)
181
+ key_types_str = key_types.map(&to_str).join(', ')
182
+ subtypes_str = subtypes.map(&to_str).join(', ')
183
+ if key_types.none?(&:defined?) && subtypes.none?(&:defined?)
184
+ ''
185
+ elsif key_types.empty? && subtypes.empty?
186
+ ''
187
+ elsif hash_parameters?
188
+ "{#{key_types_str} => #{subtypes_str}}"
189
+ elsif fixed_parameters?
190
+ "(#{subtypes_str})"
191
+ else
192
+ if name == 'Hash'
193
+ "<#{key_types_str}, #{subtypes_str}>"
194
+ else
195
+ "<#{key_types_str}#{subtypes_str}>"
196
+ end
197
+ end
198
+ end
199
+
200
+ # @return [::Symbol] :class or :instance
201
+ def scope
202
+ @scope ||= :instance if duck_type? || nil_type?
203
+ @scope ||= (name == 'Class' || name == 'Module') && !subtypes.empty? ? :class : :instance
204
+ end
205
+
206
+ # @param other [Object]
207
+ def == other
208
+ return false unless self.class == other.class
209
+ # @sg-ignore flow sensitive typing should support .class == .class
210
+ tag == other.tag
211
+ end
212
+
213
+ # Generate a ComplexType that fully qualifies this type's namespaces.
214
+ #
215
+ # @param api_map [ApiMap] The ApiMap that performs qualification
216
+ # @param context [String] The namespace from which to resolve names
217
+ # @return [self, ComplexType, UniqueType] The generated ComplexType
218
+ def qualify api_map, context = ''
219
+ transform do |t|
220
+ next t if t.name == GENERIC_TAG_NAME
221
+ next t if t.duck_type? || t.void? || t.undefined?
222
+ recon = (t.rooted? ? '' : context)
223
+ fqns = api_map.qualify(t.name, recon)
224
+ if fqns.nil?
225
+ next UniqueType::BOOLEAN if t.tag == 'Boolean'
226
+ next UniqueType::UNDEFINED
227
+ end
228
+ t.recreate(new_name: fqns, make_rooted: true)
229
+ end
230
+ end
231
+
232
+ # @yieldparam [UniqueType]
233
+ # @return [void]
234
+ # @overload each_unique_type()
235
+ # @return [Enumerator<UniqueType>]
236
+ def each_unique_type &block
237
+ return enum_for(__method__) unless block_given?
238
+ yield self
239
+ end
240
+ end
241
+ end
242
+ end