solargraph 0.56.2 → 0.58.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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +127 -0
  3. data/.github/workflows/plugins.yml +183 -7
  4. data/.github/workflows/rspec.yml +55 -5
  5. data/.github/workflows/typecheck.yml +6 -3
  6. data/.gitignore +5 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +1279 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +69 -0
  13. data/README.md +8 -4
  14. data/Rakefile +125 -13
  15. data/bin/solargraph +8 -5
  16. data/lib/solargraph/api_map/cache.rb +3 -2
  17. data/lib/solargraph/api_map/constants.rb +279 -0
  18. data/lib/solargraph/api_map/index.rb +49 -31
  19. data/lib/solargraph/api_map/source_to_yard.rb +13 -4
  20. data/lib/solargraph/api_map/store.rb +144 -26
  21. data/lib/solargraph/api_map.rb +217 -245
  22. data/lib/solargraph/bench.rb +1 -0
  23. data/lib/solargraph/complex_type/type_methods.rb +6 -0
  24. data/lib/solargraph/complex_type/unique_type.rb +19 -12
  25. data/lib/solargraph/complex_type.rb +24 -3
  26. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  27. data/lib/solargraph/convention/base.rb +17 -0
  28. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -0
  29. data/lib/solargraph/convention/data_definition/data_definition_node.rb +4 -2
  30. data/lib/solargraph/convention/data_definition.rb +2 -1
  31. data/lib/solargraph/convention/gemspec.rb +1 -1
  32. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  33. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +3 -1
  34. data/lib/solargraph/convention/struct_definition.rb +36 -13
  35. data/lib/solargraph/convention.rb +31 -2
  36. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  37. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  38. data/lib/solargraph/doc_map.rb +44 -13
  39. data/lib/solargraph/environ.rb +9 -2
  40. data/lib/solargraph/equality.rb +1 -0
  41. data/lib/solargraph/gem_pins.rb +21 -11
  42. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  43. data/lib/solargraph/language_server/host/message_worker.rb +3 -0
  44. data/lib/solargraph/language_server/host.rb +12 -5
  45. data/lib/solargraph/language_server/message/base.rb +2 -1
  46. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
  47. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/text_document/formatting.rb +19 -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 +4 -1
  53. data/lib/solargraph/library.rb +11 -18
  54. data/lib/solargraph/location.rb +3 -0
  55. data/lib/solargraph/logging.rb +11 -2
  56. data/lib/solargraph/page.rb +3 -0
  57. data/lib/solargraph/parser/comment_ripper.rb +8 -1
  58. data/lib/solargraph/parser/flow_sensitive_typing.rb +33 -5
  59. data/lib/solargraph/parser/node_processor/base.rb +1 -1
  60. data/lib/solargraph/parser/node_processor.rb +6 -2
  61. data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -13
  62. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  63. data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
  64. data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -16
  65. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
  66. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
  67. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
  68. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -0
  69. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +64 -8
  70. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
  71. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +36 -16
  72. data/lib/solargraph/parser/region.rb +3 -0
  73. data/lib/solargraph/parser/snippet.rb +2 -0
  74. data/lib/solargraph/pin/base.rb +77 -14
  75. data/lib/solargraph/pin/base_variable.rb +6 -5
  76. data/lib/solargraph/pin/block.rb +3 -2
  77. data/lib/solargraph/pin/callable.rb +14 -1
  78. data/lib/solargraph/pin/closure.rb +5 -7
  79. data/lib/solargraph/pin/common.rb +6 -2
  80. data/lib/solargraph/pin/constant.rb +2 -0
  81. data/lib/solargraph/pin/local_variable.rb +1 -2
  82. data/lib/solargraph/pin/method.rb +28 -9
  83. data/lib/solargraph/pin/method_alias.rb +3 -0
  84. data/lib/solargraph/pin/parameter.rb +24 -10
  85. data/lib/solargraph/pin/proxy_type.rb +5 -1
  86. data/lib/solargraph/pin/reference/override.rb +15 -1
  87. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  88. data/lib/solargraph/pin/reference.rb +17 -0
  89. data/lib/solargraph/pin/search.rb +6 -1
  90. data/lib/solargraph/pin/signature.rb +2 -0
  91. data/lib/solargraph/pin/symbol.rb +5 -0
  92. data/lib/solargraph/pin_cache.rb +64 -4
  93. data/lib/solargraph/position.rb +3 -0
  94. data/lib/solargraph/range.rb +5 -0
  95. data/lib/solargraph/rbs_map/conversions.rb +29 -6
  96. data/lib/solargraph/rbs_map/core_fills.rb +18 -0
  97. data/lib/solargraph/rbs_map/core_map.rb +14 -7
  98. data/lib/solargraph/rbs_map.rb +14 -1
  99. data/lib/solargraph/shell.rb +85 -1
  100. data/lib/solargraph/source/chain/call.rb +7 -3
  101. data/lib/solargraph/source/chain/constant.rb +3 -66
  102. data/lib/solargraph/source/chain/if.rb +1 -1
  103. data/lib/solargraph/source/chain/link.rb +11 -2
  104. data/lib/solargraph/source/chain/or.rb +1 -1
  105. data/lib/solargraph/source/chain.rb +11 -2
  106. data/lib/solargraph/source/change.rb +2 -2
  107. data/lib/solargraph/source/cursor.rb +2 -3
  108. data/lib/solargraph/source/source_chainer.rb +1 -1
  109. data/lib/solargraph/source.rb +6 -3
  110. data/lib/solargraph/source_map/clip.rb +18 -26
  111. data/lib/solargraph/source_map/data.rb +4 -0
  112. data/lib/solargraph/source_map/mapper.rb +2 -2
  113. data/lib/solargraph/source_map.rb +28 -16
  114. data/lib/solargraph/type_checker/param_def.rb +2 -0
  115. data/lib/solargraph/type_checker/rules.rb +30 -8
  116. data/lib/solargraph/type_checker.rb +301 -186
  117. data/lib/solargraph/version.rb +1 -1
  118. data/lib/solargraph/workspace/config.rb +21 -5
  119. data/lib/solargraph/workspace/require_paths.rb +97 -0
  120. data/lib/solargraph/workspace.rb +30 -67
  121. data/lib/solargraph/yard_map/mapper/to_method.rb +4 -3
  122. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  123. data/lib/solargraph/yard_map/to_method.rb +2 -1
  124. data/lib/solargraph/yardoc.rb +39 -3
  125. data/lib/solargraph.rb +2 -0
  126. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  127. data/rbs/fills/open3/0/open3.rbs +172 -0
  128. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  129. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  130. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  131. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  132. data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
  133. data/rbs_collection.yaml +4 -4
  134. data/sig/shims/ast/0/node.rbs +5 -0
  135. data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
  136. data/sig/shims/ast/2.4/ast.rbs +73 -0
  137. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  138. data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
  139. data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
  140. data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  141. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  142. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  143. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  144. data/solargraph.gemspec +26 -5
  145. metadata +181 -13
  146. data/lib/.rubocop.yml +0 -22
  147. data/lib/solargraph/parser/node_methods.rb +0 -97
@@ -17,16 +17,22 @@ module Solargraph
17
17
 
18
18
  # @return [Hash{String => Array<Pin::Namespace>}]
19
19
  def namespace_hash
20
+ # @param h [String]
21
+ # @param k [Array<Pin::Namespace>]
20
22
  @namespace_hash ||= Hash.new { |h, k| h[k] = [] }
21
23
  end
22
24
 
23
25
  # @return [Hash{String => Array<Pin::Base>}]
24
26
  def pin_class_hash
27
+ # @param h [String]
28
+ # @param k [Array<Pin::Base>]
25
29
  @pin_class_hash ||= Hash.new { |h, k| h[k] = [] }
26
30
  end
27
31
 
28
32
  # @return [Hash{String => Array<Pin::Base>}]
29
33
  def path_pin_hash
34
+ # @param h [String]
35
+ # @param k [Array<Pin::Base>]
30
36
  @path_pin_hash ||= Hash.new { |h, k| h[k] = [] }
31
37
  end
32
38
 
@@ -36,30 +42,47 @@ module Solargraph
36
42
  def pins_by_class klass
37
43
  # @type [Set<Solargraph::Pin::Base>]
38
44
  s = Set.new
45
+ # @sg-ignore need to support destructured args in blocks
39
46
  @pin_select_cache[klass] ||= pin_class_hash.each_with_object(s) { |(key, o), n| n.merge(o) if key <= klass }
40
47
  end
41
48
 
42
- # @return [Hash{String => Array<Pin::Reference::Include>}]
49
+ # @return [Hash{String => Array<String>}]
43
50
  def include_references
51
+ # @param h [String]
52
+ # @param k [Array<String>]
44
53
  @include_references ||= Hash.new { |h, k| h[k] = [] }
45
54
  end
46
55
 
47
- # @return [Hash{String => Array<Pin::Reference::Extend>}]
56
+ # @return [Hash{String => Array<Pin::Reference::Include>}]
57
+ def include_reference_pins
58
+ # @param h [String]
59
+ # @param k [Array<Pin::Reference::Include>]
60
+ @include_reference_pins ||= Hash.new { |h, k| h[k] = [] }
61
+ end
62
+
63
+ # @return [Hash{String => Array<String>}]
48
64
  def extend_references
65
+ # @param h [String]
66
+ # @param k [Array<String>]
49
67
  @extend_references ||= Hash.new { |h, k| h[k] = [] }
50
68
  end
51
69
 
52
- # @return [Hash{String => Array<Pin::Reference::Prepend>}]
70
+ # @return [Hash{String => Array<String>}]
53
71
  def prepend_references
72
+ # @param h [String]
73
+ # @param k [Array<String>]
54
74
  @prepend_references ||= Hash.new { |h, k| h[k] = [] }
55
75
  end
56
76
 
57
- # @return [Hash{String => Array<Pin::Reference::Superclass>}]
77
+ # @return [Hash{String => Array<String>}]
58
78
  def superclass_references
79
+ # @param h [String]
80
+ # @param k [Array<String>]
59
81
  @superclass_references ||= Hash.new { |h, k| h[k] = [] }
60
82
  end
61
83
 
62
- # @param pins [Array<Pin::Base>]
84
+ # @param pins [Enumerable<Pin::Base>]
85
+ # @return [self]
63
86
  def merge pins
64
87
  deep_clone.catalog pins
65
88
  end
@@ -69,6 +92,7 @@ module Solargraph
69
92
  attr_writer :pins, :pin_select_cache, :namespace_hash, :pin_class_hash, :path_pin_hash, :include_references,
70
93
  :extend_references, :prepend_references, :superclass_references
71
94
 
95
+ # @return [self]
72
96
  def deep_clone
73
97
  Index.allocate.tap do |copy|
74
98
  copy.pin_select_cache = {}
@@ -83,17 +107,26 @@ module Solargraph
83
107
  end
84
108
  end
85
109
 
86
- # @param new_pins [Array<Pin::Base>]
110
+ # @param new_pins [Enumerable<Pin::Base>]
111
+ #
112
+ # @return [self]
87
113
  def catalog new_pins
114
+ # @type [Hash{Class<generic<T>> => Set<generic<T>>}]
88
115
  @pin_select_cache = {}
89
116
  pins.concat new_pins
90
117
  set = new_pins.to_set
118
+ # @param k [String]
119
+ # @param v [Set<Pin::Base>]
91
120
  set.classify(&:class)
92
- .map { |k, v| pin_class_hash[k].concat v.to_a }
121
+ .map { |k, v| pin_class_hash[k].concat v.to_a }
122
+ # @param k [String]
123
+ # @param v [Set<Pin::Namespace>]
93
124
  set.classify(&:namespace)
94
- .map { |k, v| namespace_hash[k].concat v.to_a }
125
+ .map { |k, v| namespace_hash[k].concat v.to_a }
126
+ # @param k [String]
127
+ # @param v [Set<Pin::Base>]
95
128
  set.classify(&:path)
96
- .map { |k, v| path_pin_hash[k].concat v.to_a }
129
+ .map { |k, v| path_pin_hash[k].concat v.to_a }
97
130
  @namespaces = path_pin_hash.keys.compact.to_set
98
131
  map_references Pin::Reference::Include, include_references
99
132
  map_references Pin::Reference::Prepend, prepend_references
@@ -103,36 +136,21 @@ module Solargraph
103
136
  self
104
137
  end
105
138
 
106
- # @param klass [Class<Pin::Reference>]
107
- # @param hash [Hash{String => Array<Pin::Reference>}]
139
+ # @generic T
140
+ # @param klass [Class<generic<T>>]
141
+ # @param hash [Hash{String => generic<T>}]
142
+ #
108
143
  # @return [void]
109
144
  def map_references klass, hash
145
+ # @param pin [generic<T>]
110
146
  pins_by_class(klass).each do |pin|
111
- store_parametric_reference(hash, pin)
147
+ hash[pin.namespace].push pin
112
148
  end
113
149
  end
114
150
 
115
- # Add references to a map
116
- #
117
- # @param hash [Hash{String => Array<Pin::Reference>}]
118
- # @param reference_pin [Pin::Reference]
119
- #
120
- # @return [void]
121
- def store_parametric_reference(hash, reference_pin)
122
- referenced_ns = reference_pin.name
123
- referenced_tag_params = reference_pin.generic_values
124
- referenced_tag = referenced_ns +
125
- if referenced_tag_params && referenced_tag_params.length > 0
126
- "<" + referenced_tag_params.join(', ') + ">"
127
- else
128
- ''
129
- end
130
- referencing_ns = reference_pin.namespace
131
- hash[referencing_ns].push referenced_tag
132
- end
133
-
134
151
  # @return [void]
135
152
  def map_overrides
153
+ # @param ovr [Pin::Reference::Override]
136
154
  pins_by_class(Pin::Reference::Override).each do |ovr|
137
155
  logger.debug { "ApiMap::Index#map_overrides: Looking at override #{ovr} for #{ovr.name}" }
138
156
  pins = path_pin_hash[ovr.name]
@@ -32,11 +32,13 @@ module Solargraph
32
32
  next
33
33
  end
34
34
  if pin.type == :class
35
+ # @param obj [YARD::CodeObjects::RootObject]
35
36
  code_object_map[pin.path] ||= YARD::CodeObjects::ClassObject.new(root_code_object, pin.path) { |obj|
36
37
  next if pin.location.nil? || pin.location.filename.nil?
37
38
  obj.add_file(pin.location.filename, pin.location.range.start.line, !pin.comments.empty?)
38
39
  }
39
40
  else
41
+ # @param obj [YARD::CodeObjects::RootObject]
40
42
  code_object_map[pin.path] ||= YARD::CodeObjects::ModuleObject.new(root_code_object, pin.path) { |obj|
41
43
  next if pin.location.nil? || pin.location.filename.nil?
42
44
  obj.add_file(pin.location.filename, pin.location.range.start.line, !pin.comments.empty?)
@@ -45,12 +47,18 @@ module Solargraph
45
47
  code_object_map[pin.path].docstring = pin.docstring
46
48
  store.get_includes(pin.path).each do |ref|
47
49
  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?
50
+ unless include_object.nil? || include_object.nil?
51
+ include_object.instance_mixins.push code_object_map[ref.type.to_s]
52
+ end
49
53
  end
50
54
  store.get_extends(pin.path).each do |ref|
51
55
  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?
56
+ next unless extend_object
57
+ code_object = code_object_map[ref.type.to_s]
58
+ next unless code_object
59
+ extend_object.class_mixins.push code_object
60
+ # @todo add spec showing why this next line is necessary
61
+ extend_object.instance_mixins.push code_object
54
62
  end
55
63
  end
56
64
  store.method_pins.each do |pin|
@@ -59,6 +67,7 @@ module Solargraph
59
67
  next
60
68
  end
61
69
 
70
+ # @param obj [YARD::CodeObjects::RootObject]
62
71
  code_object_map[pin.path] ||= YARD::CodeObjects::MethodObject.new(code_object_at(pin.namespace, YARD::CodeObjects::NamespaceObject), pin.name, pin.scope) { |obj|
63
72
  next if pin.location.nil? || pin.location.filename.nil?
64
73
  obj.add_file pin.location.filename, pin.location.range.start.line
@@ -67,7 +76,7 @@ module Solargraph
67
76
  method_object.docstring = pin.docstring
68
77
  method_object.visibility = pin.visibility || :public
69
78
  method_object.parameters = pin.parameters.map do |p|
70
- [p.name, p.asgn_code]
79
+ [p.full_name, p.asgn_code]
71
80
  end
72
81
  end
73
82
  end
@@ -8,6 +8,7 @@ module Solargraph
8
8
  class Store
9
9
  # @param pinsets [Array<Enumerable<Pin::Base>>]
10
10
  def initialize *pinsets
11
+ @pinsets = pinsets
11
12
  catalog pinsets
12
13
  end
13
14
 
@@ -16,7 +17,12 @@ module Solargraph
16
17
  index.pins
17
18
  end
18
19
 
19
- # @param pinsets [Array<Enumerable<Pin::Base>>]
20
+ # @param pinsets [Array<Array<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
20
26
  # @return [Boolean] True if the index was updated
21
27
  def update *pinsets
22
28
  return catalog(pinsets) if pinsets.length != @pinsets.length
@@ -36,6 +42,8 @@ module Solargraph
36
42
  @indexes[changed + idx - 1].merge(pins)
37
43
  end
38
44
  end
45
+ constants.clear
46
+ cached_qualify_superclass.clear
39
47
  true
40
48
  end
41
49
 
@@ -49,9 +57,10 @@ module Solargraph
49
57
 
50
58
  # @param fqns [String]
51
59
  # @param visibility [Array<Symbol>]
52
- # @return [Enumerable<Solargraph::Pin::Base>]
60
+ # @return [Enumerable<Solargraph::Pin::Namespace, Solargraph::Pin::Constant>]
53
61
  def get_constants fqns, visibility = [:public]
54
62
  namespace_children(fqns).select { |pin|
63
+ # @sg-ignore flow-sensitive typing not smart enough to handle this case
55
64
  !pin.name.empty? && (pin.is_a?(Pin::Namespace) || pin.is_a?(Pin::Constant)) && visibility.include?(pin.visibility)
56
65
  }
57
66
  end
@@ -62,40 +71,51 @@ module Solargraph
62
71
  # @return [Enumerable<Solargraph::Pin::Method>]
63
72
  def get_methods fqns, scope: :instance, visibility: [:public]
64
73
  all_pins = namespace_children(fqns).select do |pin|
74
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
65
75
  pin.is_a?(Pin::Method) && pin.scope == scope && visibility.include?(pin.visibility)
66
76
  end
67
77
  GemPins.combine_method_pins_by_path(all_pins)
68
78
  end
69
79
 
70
- # @param fq_tag [String]
80
+ BOOLEAN_SUPERCLASS_PIN = Pin::Reference::Superclass.new(name: 'Boolean', closure: Pin::ROOT_PIN, source: :solargraph)
81
+ OBJECT_SUPERCLASS_PIN = Pin::Reference::Superclass.new(name: 'Object', closure: Pin::ROOT_PIN, source: :solargraph)
82
+
83
+ # @param fqns [String]
84
+ # @return [Pin::Reference::Superclass]
85
+ def get_superclass fqns
86
+ return nil if fqns.nil? || fqns.empty?
87
+ return BOOLEAN_SUPERCLASS_PIN if %w[TrueClass FalseClass].include?(fqns)
88
+
89
+ superclass_references[fqns].first || try_special_superclasses(fqns)
90
+ end
91
+
92
+ # @param fq_sub_tag [String]
71
93
  # @return [String, nil]
72
- def get_superclass fq_tag
73
- raise "Do not prefix fully qualified tags with '::' - #{fq_tag.inspect}" if fq_tag.start_with?('::')
74
- sub = ComplexType.parse(fq_tag)
75
- fqns = sub.namespace
76
- return superclass_references[fq_tag].first if superclass_references.key?(fq_tag)
77
- return superclass_references[fqns].first if superclass_references.key?(fqns)
78
- return 'Object' if fqns != 'BasicObject' && namespace_exists?(fqns)
79
- return 'Object' if fqns == 'Boolean'
80
- simplified_literal_name = ComplexType.parse("#{fqns}").simplify_literals.name
81
- return simplified_literal_name if simplified_literal_name != fqns
82
- nil
94
+ def qualify_superclass fq_sub_tag
95
+ cached_qualify_superclass[fq_sub_tag] || qualify_and_cache_superclass(fq_sub_tag)
96
+ type = ComplexType.try_parse(fq_sub_tag)
97
+ return type.simplify_literals.to_s if type.literal?
98
+ ref = get_superclass(fq_sub_tag)
99
+ return unless ref
100
+ res = constants.dereference(ref)
101
+ return unless res
102
+ res
83
103
  end
84
104
 
85
105
  # @param fqns [String]
86
- # @return [Array<String>]
106
+ # @return [Array<Pin::Reference::Include>]
87
107
  def get_includes fqns
88
108
  include_references[fqns] || []
89
109
  end
90
110
 
91
111
  # @param fqns [String]
92
- # @return [Array<String>]
112
+ # @return [Array<Pin::Reference::Prepend>]
93
113
  def get_prepends fqns
94
114
  prepend_references[fqns] || []
95
115
  end
96
116
 
97
117
  # @param fqns [String]
98
- # @return [Array<String>]
118
+ # @return [Array<Pin::Reference::Extend>]
99
119
  def get_extends fqns
100
120
  extend_references[fqns] || []
101
121
  end
@@ -116,7 +136,8 @@ module Solargraph
116
136
  end
117
137
 
118
138
  # @param fqns [String]
119
- # @return [Enumerable<Solargraph::Pin::Base>]
139
+ #
140
+ # @return [Enumerable<Solargraph::Pin::ClassVariable>]
120
141
  def get_class_variables(fqns)
121
142
  namespace_children(fqns).select { |pin| pin.is_a?(Pin::ClassVariable)}
122
143
  end
@@ -132,11 +153,6 @@ module Solargraph
132
153
  fqns_pins(fqns).any?
133
154
  end
134
155
 
135
- # @return [Set<String>]
136
- def namespaces
137
- index.namespaces
138
- end
139
-
140
156
  # @return [Enumerable<Solargraph::Pin::Namespace>]
141
157
  def namespace_pins
142
158
  pins_by_class(Solargraph::Pin::Namespace)
@@ -198,14 +214,71 @@ module Solargraph
198
214
  fqns_pins_map[[base, name]]
199
215
  end
200
216
 
217
+ # Get all ancestors (superclasses, includes, prepends, extends) for a namespace
218
+ # @param fqns [String] The fully qualified namespace
219
+ # @return [Array<String>] Array of ancestor namespaces including the original
220
+ def get_ancestors(fqns)
221
+ return [] if fqns.nil? || fqns.empty?
222
+
223
+ ancestors = [fqns]
224
+ visited = Set.new
225
+ queue = [fqns]
226
+
227
+ until queue.empty?
228
+ current = queue.shift
229
+ next if current.nil? || current.empty? || visited.include?(current)
230
+ visited.add(current)
231
+
232
+ current = current.gsub(/^::/, '')
233
+
234
+ # Add superclass
235
+ ref = get_superclass(current)
236
+ superclass = ref && constants.dereference(ref)
237
+ if superclass && !superclass.empty? && !visited.include?(superclass)
238
+ ancestors << superclass
239
+ queue << superclass
240
+ end
241
+
242
+ # Add includes, prepends, and extends
243
+ [get_includes(current), get_prepends(current), get_extends(current)].each do |refs|
244
+ next if refs.nil?
245
+ # @param ref [String]
246
+ refs.map(&:type).map(&:to_s).each do |ref|
247
+ next if ref.nil? || ref.empty? || visited.include?(ref)
248
+ ancestors << ref
249
+ queue << ref
250
+ end
251
+ end
252
+ end
253
+
254
+ ancestors.compact.uniq
255
+ end
256
+
257
+ # @param fqns [String]
258
+ #
259
+ # @return [Array<Solargraph::Pin::Reference>]
260
+ def get_ancestor_references(fqns)
261
+ (get_prepends(fqns) + get_includes(fqns) + [get_superclass(fqns)]).compact
262
+ end
263
+
264
+ # @return [Constants]
265
+ def constants
266
+ @constants ||= Constants.new(self)
267
+ end
268
+
201
269
  private
202
270
 
271
+ # @return [Index]
203
272
  def index
204
273
  @indexes.last
205
274
  end
206
275
 
276
+ # @param pinsets [Array<Array<Pin::Base>>]
277
+ #
278
+ # @return [void]
207
279
  def catalog pinsets
208
280
  @pinsets = pinsets
281
+ # @type [Array<Index>]
209
282
  @indexes = []
210
283
  pinsets.each do |pins|
211
284
  if @indexes.last && pins.empty?
@@ -214,11 +287,16 @@ module Solargraph
214
287
  @indexes.push(@indexes.last&.merge(pins) || Solargraph::ApiMap::Index.new(pins))
215
288
  end
216
289
  end
290
+ constants.clear
291
+ cached_qualify_superclass.clear
217
292
  true
218
293
  end
219
294
 
220
295
  # @return [Hash{::Array(String, String) => ::Array<Pin::Namespace>}]
221
296
  def fqns_pins_map
297
+ # @param h [Hash{::Array(String, String) => ::Array<Pin::Namespace>}]
298
+ # @param base [String]
299
+ # @param name [String]
222
300
  @fqns_pins_map ||= Hash.new do |h, (base, name)|
223
301
  value = namespace_children(base).select { |pin| pin.name == name && pin.is_a?(Pin::Namespace) }
224
302
  h[[base, name]] = value
@@ -235,17 +313,22 @@ module Solargraph
235
313
  index.superclass_references
236
314
  end
237
315
 
238
- # @return [Hash{String => Array<String>}]
316
+ # @return [Hash{String => Array<Pin::Reference::Include>}]
239
317
  def include_references
240
318
  index.include_references
241
319
  end
242
320
 
243
- # @return [Hash{String => Array<String>}]
321
+ # @return [Hash{String => Array<Solargraph::Pin::Reference::Include>}]
322
+ def include_reference_pins
323
+ index.include_reference_pins
324
+ end
325
+
326
+ # @return [Hash{String => Array<Pin::Reference::Prepend>}]
244
327
  def prepend_references
245
328
  index.prepend_references
246
329
  end
247
330
 
248
- # @return [Hash{String => Array<String>}]
331
+ # @return [Hash{String => Array<Pin::Reference::Extend>}]
249
332
  def extend_references
250
333
  index.extend_references
251
334
  end
@@ -261,6 +344,41 @@ module Solargraph
261
344
  def all_instance_variables
262
345
  index.pins_by_class(Pin::InstanceVariable)
263
346
  end
347
+
348
+ # @param fqns [String]
349
+ # @return [Pin::Reference::Superclass, nil]
350
+ def try_special_superclasses(fqns)
351
+ return OBJECT_SUPERCLASS_PIN if fqns == 'Boolean'
352
+ return OBJECT_SUPERCLASS_PIN if !%w[BasicObject Object].include?(fqns) && namespace_exists?(fqns)
353
+
354
+ sub = ComplexType.try_parse(fqns)
355
+ return get_superclass(sub.simplify_literals.name) if sub.literal?
356
+
357
+ get_superclass(sub.namespace) if sub.namespace != fqns
358
+ end
359
+
360
+ # @param fq_sub_tag [String]
361
+ # @return [String, nil]
362
+ def qualify_and_cache_superclass fq_sub_tag
363
+ cached_qualify_superclass[fq_sub_tag] = uncached_qualify_superclass(fq_sub_tag)
364
+ end
365
+
366
+ # @return [Hash{String => String, nil}]
367
+ def cached_qualify_superclass
368
+ @cached_qualify_superclass ||= {}
369
+ end
370
+
371
+ # @param fq_sub_tag [String]
372
+ # @return [String, nil]
373
+ def uncached_qualify_superclass fq_sub_tag
374
+ type = ComplexType.try_parse(fq_sub_tag)
375
+ return type.simplify_literals.to_s if type.literal?
376
+ ref = get_superclass(fq_sub_tag)
377
+ return unless ref
378
+ res = constants.dereference(ref)
379
+ return unless res
380
+ res + type.substring
381
+ end
264
382
  end
265
383
  end
266
384
  end