solargraph 0.54.4 → 0.57.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.
Files changed (178) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +125 -0
  3. data/.github/workflows/plugins.yml +149 -5
  4. data/.github/workflows/rspec.yml +39 -4
  5. data/.github/workflows/typecheck.yml +8 -3
  6. data/.gitignore +7 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +2627 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +104 -0
  13. data/README.md +20 -6
  14. data/Rakefile +125 -13
  15. data/lib/solargraph/api_map/cache.rb +3 -2
  16. data/lib/solargraph/api_map/constants.rb +218 -0
  17. data/lib/solargraph/api_map/index.rb +44 -42
  18. data/lib/solargraph/api_map/source_to_yard.rb +10 -4
  19. data/lib/solargraph/api_map/store.rb +165 -32
  20. data/lib/solargraph/api_map.rb +319 -243
  21. data/lib/solargraph/bench.rb +18 -1
  22. data/lib/solargraph/complex_type/type_methods.rb +7 -1
  23. data/lib/solargraph/complex_type/unique_type.rb +105 -16
  24. data/lib/solargraph/complex_type.rb +40 -7
  25. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  26. data/lib/solargraph/convention/base.rb +20 -3
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  29. data/lib/solargraph/convention/data_definition.rb +105 -0
  30. data/lib/solargraph/convention/gemspec.rb +3 -2
  31. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
  32. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
  33. data/lib/solargraph/convention/struct_definition.rb +164 -0
  34. data/lib/solargraph/convention.rb +35 -4
  35. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  36. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
  37. data/lib/solargraph/doc_map.rb +313 -65
  38. data/lib/solargraph/environ.rb +9 -2
  39. data/lib/solargraph/gem_pins.rb +60 -38
  40. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  41. data/lib/solargraph/language_server/host/message_worker.rb +13 -7
  42. data/lib/solargraph/language_server/host.rb +14 -3
  43. data/lib/solargraph/language_server/message/base.rb +2 -1
  44. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
  45. data/lib/solargraph/language_server/message/extended/document.rb +5 -2
  46. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  47. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/text_document/formatting.rb +16 -2
  49. data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
  50. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  51. data/lib/solargraph/language_server/progress.rb +8 -0
  52. data/lib/solargraph/language_server/request.rb +1 -0
  53. data/lib/solargraph/library.rb +53 -32
  54. data/lib/solargraph/location.rb +23 -0
  55. data/lib/solargraph/logging.rb +12 -2
  56. data/lib/solargraph/page.rb +4 -0
  57. data/lib/solargraph/parser/comment_ripper.rb +20 -7
  58. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
  59. data/lib/solargraph/parser/node_methods.rb +16 -2
  60. data/lib/solargraph/parser/node_processor/base.rb +10 -5
  61. data/lib/solargraph/parser/node_processor.rb +26 -9
  62. data/lib/solargraph/parser/parser_gem/class_methods.rb +17 -15
  63. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  64. data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
  65. data/lib/solargraph/parser/parser_gem/node_methods.rb +8 -4
  66. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  67. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
  68. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
  69. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
  70. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
  71. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  72. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
  73. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
  74. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  75. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
  76. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
  77. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
  78. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
  79. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
  80. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +42 -0
  81. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
  82. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
  83. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
  84. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +63 -30
  85. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
  86. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  87. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  88. data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
  89. data/lib/solargraph/parser/region.rb +4 -1
  90. data/lib/solargraph/parser/snippet.rb +2 -0
  91. data/lib/solargraph/parser.rb +1 -0
  92. data/lib/solargraph/pin/base.rb +360 -30
  93. data/lib/solargraph/pin/base_variable.rb +16 -10
  94. data/lib/solargraph/pin/block.rb +2 -0
  95. data/lib/solargraph/pin/breakable.rb +9 -0
  96. data/lib/solargraph/pin/callable.rb +83 -3
  97. data/lib/solargraph/pin/closure.rb +20 -1
  98. data/lib/solargraph/pin/common.rb +10 -1
  99. data/lib/solargraph/pin/constant.rb +2 -0
  100. data/lib/solargraph/pin/delegated_method.rb +21 -1
  101. data/lib/solargraph/pin/documenting.rb +16 -0
  102. data/lib/solargraph/pin/keyword.rb +7 -2
  103. data/lib/solargraph/pin/local_variable.rb +18 -6
  104. data/lib/solargraph/pin/method.rb +175 -46
  105. data/lib/solargraph/pin/method_alias.rb +3 -0
  106. data/lib/solargraph/pin/namespace.rb +17 -9
  107. data/lib/solargraph/pin/parameter.rb +78 -19
  108. data/lib/solargraph/pin/proxy_type.rb +13 -6
  109. data/lib/solargraph/pin/reference/override.rb +24 -6
  110. data/lib/solargraph/pin/reference/require.rb +2 -2
  111. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  112. data/lib/solargraph/pin/reference.rb +26 -0
  113. data/lib/solargraph/pin/search.rb +3 -1
  114. data/lib/solargraph/pin/signature.rb +44 -0
  115. data/lib/solargraph/pin/singleton.rb +1 -1
  116. data/lib/solargraph/pin/symbol.rb +8 -2
  117. data/lib/solargraph/pin/until.rb +18 -0
  118. data/lib/solargraph/pin/while.rb +18 -0
  119. data/lib/solargraph/pin.rb +4 -1
  120. data/lib/solargraph/pin_cache.rb +245 -0
  121. data/lib/solargraph/position.rb +11 -0
  122. data/lib/solargraph/range.rb +10 -0
  123. data/lib/solargraph/rbs_map/conversions.rb +226 -70
  124. data/lib/solargraph/rbs_map/core_fills.rb +32 -16
  125. data/lib/solargraph/rbs_map/core_map.rb +37 -11
  126. data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
  127. data/lib/solargraph/rbs_map.rb +88 -18
  128. data/lib/solargraph/shell.rb +20 -18
  129. data/lib/solargraph/source/chain/array.rb +11 -7
  130. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  131. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  132. data/lib/solargraph/source/chain/call.rb +53 -23
  133. data/lib/solargraph/source/chain/constant.rb +1 -1
  134. data/lib/solargraph/source/chain/hash.rb +4 -3
  135. data/lib/solargraph/source/chain/head.rb +1 -1
  136. data/lib/solargraph/source/chain/if.rb +1 -1
  137. data/lib/solargraph/source/chain/link.rb +12 -1
  138. data/lib/solargraph/source/chain/literal.rb +22 -2
  139. data/lib/solargraph/source/chain/or.rb +1 -1
  140. data/lib/solargraph/source/chain/z_super.rb +1 -1
  141. data/lib/solargraph/source/chain.rb +84 -47
  142. data/lib/solargraph/source/change.rb +2 -2
  143. data/lib/solargraph/source/cursor.rb +2 -3
  144. data/lib/solargraph/source/source_chainer.rb +3 -3
  145. data/lib/solargraph/source.rb +5 -2
  146. data/lib/solargraph/source_map/clip.rb +4 -2
  147. data/lib/solargraph/source_map/data.rb +4 -0
  148. data/lib/solargraph/source_map/mapper.rb +13 -7
  149. data/lib/solargraph/source_map.rb +21 -31
  150. data/lib/solargraph/type_checker/checks.rb +4 -0
  151. data/lib/solargraph/type_checker/param_def.rb +2 -0
  152. data/lib/solargraph/type_checker/rules.rb +8 -0
  153. data/lib/solargraph/type_checker.rb +208 -128
  154. data/lib/solargraph/version.rb +1 -1
  155. data/lib/solargraph/views/_method.erb +10 -10
  156. data/lib/solargraph/views/_namespace.erb +3 -3
  157. data/lib/solargraph/views/document.erb +10 -10
  158. data/lib/solargraph/workspace/config.rb +1 -3
  159. data/lib/solargraph/workspace/require_paths.rb +98 -0
  160. data/lib/solargraph/workspace.rb +38 -52
  161. data/lib/solargraph/yard_map/helpers.rb +29 -1
  162. data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
  163. data/lib/solargraph/yard_map/mapper/to_method.rb +53 -18
  164. data/lib/solargraph/yard_map/mapper/to_namespace.rb +9 -7
  165. data/lib/solargraph/yard_map/mapper.rb +4 -3
  166. data/lib/solargraph/yard_map/to_method.rb +4 -2
  167. data/lib/solargraph/yardoc.rb +22 -10
  168. data/lib/solargraph.rb +34 -1
  169. data/rbs/fills/tuple.rbs +149 -0
  170. data/rbs_collection.yaml +19 -0
  171. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  172. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  173. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  174. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  175. data/solargraph.gemspec +15 -4
  176. metadata +157 -15
  177. data/lib/.rubocop.yml +0 -22
  178. data/lib/solargraph/cache.rb +0 -77
@@ -3,8 +3,10 @@
3
3
  module Solargraph
4
4
  class ApiMap
5
5
  class Index
6
+ include Logging
7
+
6
8
  # @param pins [Array<Pin::Base>]
7
- def initialize pins
9
+ def initialize pins = []
8
10
  catalog pins
9
11
  end
10
12
 
@@ -13,6 +15,9 @@ module Solargraph
13
15
  @pins ||= []
14
16
  end
15
17
 
18
+ # @return [Set<String>]
19
+ attr_reader :namespaces
20
+
16
21
  # @return [Hash{String => Array<Pin::Namespace>}]
17
22
  def namespace_hash
18
23
  @namespace_hash ||= Hash.new { |h, k| h[k] = [] }
@@ -34,30 +39,37 @@ module Solargraph
34
39
  def pins_by_class klass
35
40
  # @type [Set<Solargraph::Pin::Base>]
36
41
  s = Set.new
42
+ # @sg-ignore need to support destructured args in blocks
37
43
  @pin_select_cache[klass] ||= pin_class_hash.each_with_object(s) { |(key, o), n| n.merge(o) if key <= klass }
38
44
  end
39
45
 
40
- # @return [Hash{String => Array<Pin::Reference::Include>}]
46
+ # @return [Hash{String => Array<String>}]
41
47
  def include_references
42
48
  @include_references ||= Hash.new { |h, k| h[k] = [] }
43
49
  end
44
50
 
45
- # @return [Hash{String => Array<Pin::Reference::Extend>}]
51
+ # @return [Hash{String => Array<Pin::Reference::Include>}]
52
+ def include_reference_pins
53
+ @include_reference_pins ||= Hash.new { |h, k| h[k] = [] }
54
+ end
55
+
56
+ # @return [Hash{String => Array<String>}]
46
57
  def extend_references
47
58
  @extend_references ||= Hash.new { |h, k| h[k] = [] }
48
59
  end
49
60
 
50
- # @return [Hash{String => Array<Pin::Reference::Prepend>}]
61
+ # @return [Hash{String => Array<String>}]
51
62
  def prepend_references
52
63
  @prepend_references ||= Hash.new { |h, k| h[k] = [] }
53
64
  end
54
65
 
55
- # @return [Hash{String => Array<Pin::Reference::Superclass>}]
66
+ # @return [Hash{String => Array<String>}]
56
67
  def superclass_references
57
68
  @superclass_references ||= Hash.new { |h, k| h[k] = [] }
58
69
  end
59
70
 
60
- # @param pins [Array<Pin::Base>]
71
+ # @param pins [Enumerable<Pin::Base>]
72
+ # @return [self]
61
73
  def merge pins
62
74
  deep_clone.catalog pins
63
75
  end
@@ -67,6 +79,7 @@ module Solargraph
67
79
  attr_writer :pins, :pin_select_cache, :namespace_hash, :pin_class_hash, :path_pin_hash, :include_references,
68
80
  :extend_references, :prepend_references, :superclass_references
69
81
 
82
+ # @return [self]
70
83
  def deep_clone
71
84
  Index.allocate.tap do |copy|
72
85
  copy.pin_select_cache = {}
@@ -81,8 +94,10 @@ module Solargraph
81
94
  end
82
95
  end
83
96
 
84
- # @param new_pins [Array<Pin::Base>]
97
+ # @param new_pins [Enumerable<Pin::Base>]
98
+ # @return [self]
85
99
  def catalog new_pins
100
+ # @type [Hash{Class<generic<T>> => Set<generic<T>>}]
86
101
  @pin_select_cache = {}
87
102
  pins.concat new_pins
88
103
  set = new_pins.to_set
@@ -106,47 +121,31 @@ module Solargraph
106
121
  # @return [void]
107
122
  def map_references klass, hash
108
123
  pins_by_class(klass).each do |pin|
109
- store_parametric_reference(hash, pin)
124
+ hash[pin.namespace].push pin
110
125
  end
111
126
  end
112
127
 
113
- # Add references to a map
114
- #
115
- # @param hash [Hash{String => Array<Pin::Reference>}]
116
- # @param reference_pin [Pin::Reference]
117
- #
118
- # @return [void]
119
- def store_parametric_reference(hash, reference_pin)
120
- referenced_ns = reference_pin.name
121
- referenced_tag_params = reference_pin.generic_values
122
- referenced_tag = referenced_ns +
123
- if referenced_tag_params && referenced_tag_params.length > 0
124
- "<" + referenced_tag_params.join(', ') + ">"
125
- else
126
- ''
127
- end
128
- referencing_ns = reference_pin.namespace
129
- hash[referencing_ns].push referenced_tag
130
- end
131
-
132
128
  # @return [void]
133
129
  def map_overrides
134
130
  pins_by_class(Pin::Reference::Override).each do |ovr|
135
- pin = path_pin_hash[ovr.name].first
136
- next if pin.nil?
137
- new_pin = if pin.path.end_with?('#initialize')
138
- path_pin_hash[pin.path.sub(/#initialize/, '.new')].first
139
- end
140
- (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
141
- pin.docstring.delete_tags tag
142
- new_pin.docstring.delete_tags tag if new_pin
143
- end
144
- ovr.tags.each do |tag|
145
- pin.docstring.add_tag(tag)
146
- redefine_return_type pin, tag
147
- if new_pin
148
- new_pin.docstring.add_tag(tag)
149
- redefine_return_type new_pin, tag
131
+ logger.debug { "ApiMap::Index#map_overrides: Looking at override #{ovr} for #{ovr.name}" }
132
+ pins = path_pin_hash[ovr.name]
133
+ logger.debug { "ApiMap::Index#map_overrides: pins for path=#{ovr.name}: #{pins}" }
134
+ pins.each do |pin|
135
+ new_pin = if pin.path.end_with?('#initialize')
136
+ path_pin_hash[pin.path.sub(/#initialize/, '.new')].first
137
+ end
138
+ (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
139
+ pin.docstring.delete_tags tag
140
+ new_pin.docstring.delete_tags tag if new_pin
141
+ end
142
+ ovr.tags.each do |tag|
143
+ pin.docstring.add_tag(tag)
144
+ redefine_return_type pin, tag
145
+ if new_pin
146
+ new_pin.docstring.add_tag(tag)
147
+ redefine_return_type new_pin, tag
148
+ end
150
149
  end
151
150
  end
152
151
  end
@@ -156,11 +155,14 @@ module Solargraph
156
155
  # @param tag [YARD::Tags::Tag]
157
156
  # @return [void]
158
157
  def redefine_return_type pin, tag
158
+ # @todo can this be made to not mutate existing pins and use
159
+ # proxy() / proxy_with_signatures() instead?
159
160
  return unless pin && tag.tag_name == 'return'
160
161
  pin.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
161
162
  pin.signatures.each do |sig|
162
163
  sig.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
163
164
  end
165
+ pin.reset_generated!
164
166
  end
165
167
  end
166
168
  end
@@ -45,12 +45,18 @@ module Solargraph
45
45
  code_object_map[pin.path].docstring = pin.docstring
46
46
  store.get_includes(pin.path).each do |ref|
47
47
  include_object = code_object_at(pin.path, YARD::CodeObjects::ClassObject)
48
- include_object.instance_mixins.push code_object_map[ref] unless include_object.nil? or include_object.nil?
48
+ unless include_object.nil? || include_object.nil?
49
+ include_object.instance_mixins.push code_object_map[ref.parametrized_tag.to_s]
50
+ end
49
51
  end
50
52
  store.get_extends(pin.path).each do |ref|
51
53
  extend_object = code_object_at(pin.path, YARD::CodeObjects::ClassObject)
52
- extend_object.instance_mixins.push code_object_map[ref] unless extend_object.nil? or extend_object.nil?
53
- extend_object.class_mixins.push code_object_map[ref] unless extend_object.nil? or extend_object.nil?
54
+ next unless extend_object
55
+ code_object = code_object_map[ref.parametrized_tag.to_s]
56
+ next unless code_object
57
+ extend_object.class_mixins.push code_object
58
+ # @todo add spec showing why this next line is necessary
59
+ extend_object.instance_mixins.push code_object
54
60
  end
55
61
  end
56
62
  store.method_pins.each do |pin|
@@ -67,7 +73,7 @@ module Solargraph
67
73
  method_object.docstring = pin.docstring
68
74
  method_object.visibility = pin.visibility || :public
69
75
  method_object.parameters = pin.parameters.map do |p|
70
- [p.name, p.asgn_code]
76
+ [p.full_name, p.asgn_code]
71
77
  end
72
78
  end
73
79
  end
@@ -1,18 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
-
4
3
  module Solargraph
5
4
  class ApiMap
6
5
  # Queryable collection of Pins representing a Workspace, gems and the Ruby
7
6
  # core.
8
7
  #
9
8
  class Store
10
- # @param static [Enumerable<Pin::Base>]
11
- # @param dynamic [Enumerable<Pin::Base>]
12
- def initialize static = [], dynamic = []
13
- @static_index = Index.new(static)
14
- @dynamic = dynamic
15
- @index = @static_index.merge(dynamic)
9
+ # @param pinsets [Array<Enumerable<Pin::Base>>]
10
+ def initialize *pinsets
11
+ @pinsets = pinsets
12
+ catalog pinsets
16
13
  end
17
14
 
18
15
  # @return [Array<Solargraph::Pin::Base>]
@@ -20,19 +17,34 @@ module Solargraph
20
17
  index.pins
21
18
  end
22
19
 
23
- # @param static [Enumerable<Pin::Base>]
24
- # @param dynamic [Enumerable<Pin::Base>]
25
- def update! static = [], dynamic = []
20
+ # @param pinsets [Array<Enumerable<Pin::Base>>]
21
+ # - pinsets[0] = core Ruby pins
22
+ # - pinsets[1] = documentation/gem pins
23
+ # - pinsets[2] = convention pins
24
+ # - pinsets[3] = workspace source pins
25
+ # - pinsets[4] = currently open file pins
26
+ # @return [Boolean] True if the index was updated
27
+ def update *pinsets
28
+ return catalog(pinsets) if pinsets.length != @pinsets.length
29
+
30
+ changed = pinsets.find_index.with_index { |pinset, idx| @pinsets[idx] != pinset }
31
+ return false unless changed
32
+
26
33
  # @todo Fix this map
27
34
  @fqns_pins_map = nil
28
- if @static_index.pins == static
29
- return self if @dynamic == dynamic
30
- else
31
- @static_index = Index.new(static)
35
+ return catalog(pinsets) if changed == 0
36
+
37
+ pinsets[changed..].each_with_index do |pins, idx|
38
+ @pinsets[changed + idx] = pins
39
+ @indexes[changed + idx] = if pins.empty?
40
+ @indexes[changed + idx - 1]
41
+ else
42
+ @indexes[changed + idx - 1].merge(pins)
43
+ end
32
44
  end
33
- @dynamic = dynamic
34
- @index = @static_index.merge(dynamic)
35
- self
45
+ constants.clear
46
+ cached_qualify_superclass.clear
47
+ true
36
48
  end
37
49
 
38
50
  def to_s
@@ -57,35 +69,51 @@ module Solargraph
57
69
  # @param visibility [Array<Symbol>]
58
70
  # @return [Enumerable<Solargraph::Pin::Method>]
59
71
  def get_methods fqns, scope: :instance, visibility: [:public]
60
- namespace_children(fqns).select do |pin|
72
+ all_pins = namespace_children(fqns).select do |pin|
61
73
  pin.is_a?(Pin::Method) && pin.scope == scope && visibility.include?(pin.visibility)
62
74
  end
75
+ GemPins.combine_method_pins_by_path(all_pins)
63
76
  end
64
77
 
78
+ BOOLEAN_SUPERCLASS_PIN = Pin::Reference::Superclass.new(name: 'Boolean', closure: Pin::ROOT_PIN, source: :solargraph)
79
+ OBJECT_SUPERCLASS_PIN = Pin::Reference::Superclass.new(name: 'Object', closure: Pin::ROOT_PIN, source: :solargraph)
80
+
65
81
  # @param fqns [String]
66
- # @return [String, nil]
82
+ # @return [Pin::Reference::Superclass]
67
83
  def get_superclass fqns
68
- raise "Do not prefix fully qualified namespaces with '::' - #{fqns.inspect}" if fqns.start_with?('::')
69
- return superclass_references[fqns].first if superclass_references.key?(fqns)
70
- return 'Object' if fqns != 'BasicObject' && namespace_exists?(fqns)
71
- return 'Object' if fqns == 'Boolean'
72
- nil
84
+ return nil if fqns.nil? || fqns.empty?
85
+ return BOOLEAN_SUPERCLASS_PIN if %w[TrueClass FalseClass].include?(fqns)
86
+
87
+ superclass_references[fqns].first || try_special_superclasses(fqns)
88
+ end
89
+
90
+ # @param fq_sub_tag [String]
91
+ # @return [String, nil]
92
+ def qualify_superclass fq_sub_tag
93
+ cached_qualify_superclass[fq_sub_tag] || qualify_and_cache_superclass(fq_sub_tag)
94
+ type = ComplexType.try_parse(fq_sub_tag)
95
+ return type.simplify_literals.to_s if type.literal?
96
+ ref = get_superclass(fq_sub_tag)
97
+ return unless ref
98
+ res = constants.dereference(ref)
99
+ return unless res
100
+ res + type.substring
73
101
  end
74
102
 
75
103
  # @param fqns [String]
76
- # @return [Array<String>]
104
+ # @return [Array<Pin::Reference::Include>]
77
105
  def get_includes fqns
78
106
  include_references[fqns] || []
79
107
  end
80
108
 
81
109
  # @param fqns [String]
82
- # @return [Array<String>]
110
+ # @return [Array<Pin::Reference::Prepend>]
83
111
  def get_prepends fqns
84
112
  prepend_references[fqns] || []
85
113
  end
86
114
 
87
115
  # @param fqns [String]
88
- # @return [Array<String>]
116
+ # @return [Array<Pin::Reference::Extend>]
89
117
  def get_extends fqns
90
118
  extend_references[fqns] || []
91
119
  end
@@ -108,7 +136,7 @@ module Solargraph
108
136
  # @param fqns [String]
109
137
  # @return [Enumerable<Solargraph::Pin::Base>]
110
138
  def get_class_variables(fqns)
111
- namespace_children(fqns).select{|pin| pin.is_a?(Pin::ClassVariable)}
139
+ namespace_children(fqns).select { |pin| pin.is_a?(Pin::ClassVariable)}
112
140
  end
113
141
 
114
142
  # @return [Enumerable<Solargraph::Pin::Base>]
@@ -188,9 +216,74 @@ module Solargraph
188
216
  fqns_pins_map[[base, name]]
189
217
  end
190
218
 
219
+ # Get all ancestors (superclasses, includes, prepends, extends) for a namespace
220
+ # @param fqns [String] The fully qualified namespace
221
+ # @return [Array<String>] Array of ancestor namespaces including the original
222
+ def get_ancestors(fqns)
223
+ return [] if fqns.nil? || fqns.empty?
224
+
225
+ ancestors = [fqns]
226
+ visited = Set.new
227
+ queue = [fqns]
228
+
229
+ until queue.empty?
230
+ current = queue.shift
231
+ next if current.nil? || current.empty? || visited.include?(current)
232
+ visited.add(current)
233
+
234
+ current = current.gsub(/^::/, '')
235
+
236
+ # Add superclass
237
+ ref = get_superclass(current)
238
+ superclass = ref && constants.dereference(ref)
239
+ if superclass && !superclass.empty? && !visited.include?(superclass)
240
+ ancestors << superclass
241
+ queue << superclass
242
+ end
243
+
244
+ # Add includes, prepends, and extends
245
+ [get_includes(current), get_prepends(current), get_extends(current)].each do |refs|
246
+ next if refs.nil?
247
+ refs.map(&:parametrized_tag).map(&:to_s).each do |ref|
248
+ next if ref.nil? || ref.empty? || visited.include?(ref)
249
+ ancestors << ref
250
+ queue << ref
251
+ end
252
+ end
253
+ end
254
+
255
+ ancestors.compact.uniq
256
+ end
257
+
258
+ # @return [Constants]
259
+ def constants
260
+ @constants ||= Constants.new(self)
261
+ end
262
+
191
263
  private
192
264
 
193
- attr_reader :index
265
+ # @return [Index]
266
+ def index
267
+ @indexes.last
268
+ end
269
+
270
+ # @param pinsets [Array<Enumerable<Pin::Base>>]
271
+ # @return [Boolean]
272
+ def catalog pinsets
273
+ @pinsets = pinsets
274
+ # @type [Array<Index>]
275
+ @indexes = []
276
+ pinsets.each do |pins|
277
+ if @indexes.last && pins.empty?
278
+ @indexes.push @indexes.last
279
+ else
280
+ @indexes.push(@indexes.last&.merge(pins) || Solargraph::ApiMap::Index.new(pins))
281
+ end
282
+ end
283
+ constants.clear
284
+ cached_qualify_superclass.clear
285
+ true
286
+ end
194
287
 
195
288
  # @return [Hash{::Array(String, String) => ::Array<Pin::Namespace>}]
196
289
  def fqns_pins_map
@@ -210,17 +303,22 @@ module Solargraph
210
303
  index.superclass_references
211
304
  end
212
305
 
213
- # @return [Hash{String => Array<String>}]
306
+ # @return [Hash{String => Array<Pin::Reference::Include>}]
214
307
  def include_references
215
308
  index.include_references
216
309
  end
217
310
 
218
- # @return [Hash{String => Array<String>}]
311
+ # @return [Hash{String => Array<Solargraph::Pin::Reference::Include>}]
312
+ def include_reference_pins
313
+ index.include_reference_pins
314
+ end
315
+
316
+ # @return [Hash{String => Array<Pin::Reference::Prepend>}]
219
317
  def prepend_references
220
318
  index.prepend_references
221
319
  end
222
320
 
223
- # @return [Hash{String => Array<String>}]
321
+ # @return [Hash{String => Array<Pin::Reference::Extend>}]
224
322
  def extend_references
225
323
  index.extend_references
226
324
  end
@@ -236,6 +334,41 @@ module Solargraph
236
334
  def all_instance_variables
237
335
  index.pins_by_class(Pin::InstanceVariable)
238
336
  end
337
+
338
+ # @param fqns [String]
339
+ # @return [Pin::Reference::Superclass, nil]
340
+ def try_special_superclasses(fqns)
341
+ return OBJECT_SUPERCLASS_PIN if fqns == 'Boolean'
342
+ return OBJECT_SUPERCLASS_PIN if !%w[BasicObject Object].include?(fqns) && namespace_exists?(fqns)
343
+
344
+ sub = ComplexType.try_parse(fqns)
345
+ return get_superclass(sub.simplify_literals.name) if sub.literal?
346
+
347
+ get_superclass(sub.namespace) if sub.namespace != fqns
348
+ end
349
+
350
+ # @param fq_sub_tag [String]
351
+ # @return [String, nil]
352
+ def qualify_and_cache_superclass fq_sub_tag
353
+ cached_qualify_superclass[fq_sub_tag] = uncached_qualify_superclass(fq_sub_tag)
354
+ end
355
+
356
+ # @return [Hash{String => String, nil}]
357
+ def cached_qualify_superclass
358
+ @cached_qualify_superclass ||= {}
359
+ end
360
+
361
+ # @param fq_sub_tag [String]
362
+ # @return [String, nil]
363
+ def uncached_qualify_superclass fq_sub_tag
364
+ type = ComplexType.try_parse(fq_sub_tag)
365
+ return type.simplify_literals.to_s if type.literal?
366
+ ref = get_superclass(fq_sub_tag)
367
+ return unless ref
368
+ res = constants.dereference(ref)
369
+ return unless res
370
+ res + type.substring
371
+ end
239
372
  end
240
373
  end
241
374
  end