solargraph 0.54.1 → 0.56.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 (135) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/plugins.yml +2 -0
  3. data/.github/workflows/typecheck.yml +3 -1
  4. data/.gitignore +2 -0
  5. data/CHANGELOG.md +70 -0
  6. data/README.md +13 -3
  7. data/lib/solargraph/api_map/cache.rb +10 -1
  8. data/lib/solargraph/api_map/index.rb +175 -0
  9. data/lib/solargraph/api_map/store.rb +79 -126
  10. data/lib/solargraph/api_map.rb +247 -93
  11. data/lib/solargraph/bench.rb +17 -1
  12. data/lib/solargraph/complex_type/type_methods.rb +13 -1
  13. data/lib/solargraph/complex_type/unique_type.rb +118 -9
  14. data/lib/solargraph/complex_type.rb +48 -18
  15. data/lib/solargraph/convention/base.rb +3 -3
  16. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +60 -0
  17. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +100 -0
  18. data/lib/solargraph/convention/struct_definition.rb +101 -0
  19. data/lib/solargraph/convention.rb +5 -3
  20. data/lib/solargraph/doc_map.rb +274 -56
  21. data/lib/solargraph/equality.rb +33 -0
  22. data/lib/solargraph/gem_pins.rb +53 -37
  23. data/lib/solargraph/language_server/host/message_worker.rb +31 -11
  24. data/lib/solargraph/language_server/host.rb +24 -13
  25. data/lib/solargraph/language_server/message/base.rb +19 -12
  26. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
  27. data/lib/solargraph/language_server/message/extended/document.rb +5 -2
  28. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  29. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  30. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  31. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -0
  32. data/lib/solargraph/library.rb +13 -11
  33. data/lib/solargraph/location.rb +28 -0
  34. data/lib/solargraph/logging.rb +1 -0
  35. data/lib/solargraph/parser/comment_ripper.rb +12 -6
  36. data/lib/solargraph/parser/flow_sensitive_typing.rb +227 -0
  37. data/lib/solargraph/parser/node_methods.rb +15 -1
  38. data/lib/solargraph/parser/node_processor.rb +3 -1
  39. data/lib/solargraph/parser/parser_gem/class_methods.rb +16 -14
  40. data/lib/solargraph/parser/parser_gem/node_chainer.rb +17 -23
  41. data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -3
  42. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  43. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
  44. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
  45. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +4 -2
  46. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +23 -2
  47. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  48. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
  49. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
  50. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  51. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +21 -0
  52. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
  53. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +4 -3
  54. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +29 -6
  55. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +41 -0
  56. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  57. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
  58. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +28 -16
  59. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +2 -1
  60. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  61. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  62. data/lib/solargraph/parser/parser_gem/node_processors.rb +10 -0
  63. data/lib/solargraph/parser/region.rb +1 -1
  64. data/lib/solargraph/parser.rb +1 -0
  65. data/lib/solargraph/pin/base.rb +326 -43
  66. data/lib/solargraph/pin/base_variable.rb +18 -10
  67. data/lib/solargraph/pin/block.rb +3 -3
  68. data/lib/solargraph/pin/breakable.rb +9 -0
  69. data/lib/solargraph/pin/callable.rb +77 -6
  70. data/lib/solargraph/pin/closure.rb +18 -1
  71. data/lib/solargraph/pin/common.rb +5 -0
  72. data/lib/solargraph/pin/delegated_method.rb +20 -1
  73. data/lib/solargraph/pin/documenting.rb +16 -0
  74. data/lib/solargraph/pin/keyword.rb +7 -2
  75. data/lib/solargraph/pin/local_variable.rb +15 -6
  76. data/lib/solargraph/pin/method.rb +172 -42
  77. data/lib/solargraph/pin/namespace.rb +17 -9
  78. data/lib/solargraph/pin/parameter.rb +61 -11
  79. data/lib/solargraph/pin/proxy_type.rb +12 -6
  80. data/lib/solargraph/pin/reference/override.rb +10 -6
  81. data/lib/solargraph/pin/reference/require.rb +2 -2
  82. data/lib/solargraph/pin/signature.rb +42 -0
  83. data/lib/solargraph/pin/singleton.rb +1 -1
  84. data/lib/solargraph/pin/symbol.rb +3 -2
  85. data/lib/solargraph/pin/until.rb +18 -0
  86. data/lib/solargraph/pin/while.rb +18 -0
  87. data/lib/solargraph/pin.rb +4 -1
  88. data/lib/solargraph/pin_cache.rb +185 -0
  89. data/lib/solargraph/position.rb +16 -0
  90. data/lib/solargraph/range.rb +16 -0
  91. data/lib/solargraph/rbs_map/conversions.rb +199 -66
  92. data/lib/solargraph/rbs_map/core_fills.rb +32 -16
  93. data/lib/solargraph/rbs_map/core_map.rb +34 -11
  94. data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
  95. data/lib/solargraph/rbs_map.rb +74 -16
  96. data/lib/solargraph/shell.rb +19 -18
  97. data/lib/solargraph/source/chain/array.rb +12 -8
  98. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  99. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  100. data/lib/solargraph/source/chain/call.rb +62 -25
  101. data/lib/solargraph/source/chain/constant.rb +1 -1
  102. data/lib/solargraph/source/chain/hash.rb +9 -3
  103. data/lib/solargraph/source/chain/head.rb +1 -1
  104. data/lib/solargraph/source/chain/if.rb +6 -1
  105. data/lib/solargraph/source/chain/link.rb +19 -5
  106. data/lib/solargraph/source/chain/literal.rb +27 -2
  107. data/lib/solargraph/source/chain/or.rb +1 -1
  108. data/lib/solargraph/source/chain/z_super.rb +1 -1
  109. data/lib/solargraph/source/chain.rb +106 -62
  110. data/lib/solargraph/source/cursor.rb +1 -11
  111. data/lib/solargraph/source/source_chainer.rb +2 -2
  112. data/lib/solargraph/source.rb +2 -1
  113. data/lib/solargraph/source_map/clip.rb +4 -2
  114. data/lib/solargraph/source_map/mapper.rb +9 -5
  115. data/lib/solargraph/source_map.rb +0 -17
  116. data/lib/solargraph/type_checker/checks.rb +4 -0
  117. data/lib/solargraph/type_checker.rb +41 -14
  118. data/lib/solargraph/version.rb +1 -1
  119. data/lib/solargraph/views/_method.erb +10 -10
  120. data/lib/solargraph/views/_namespace.erb +3 -3
  121. data/lib/solargraph/views/document.erb +10 -10
  122. data/lib/solargraph/workspace/config.rb +7 -3
  123. data/lib/solargraph/workspace.rb +16 -6
  124. data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -2
  125. data/lib/solargraph/yard_map/mapper/to_method.rb +55 -15
  126. data/lib/solargraph/yard_map/mapper/to_namespace.rb +5 -2
  127. data/lib/solargraph/yard_map/mapper.rb +5 -3
  128. data/lib/solargraph/yard_map/to_method.rb +4 -2
  129. data/lib/solargraph/yardoc.rb +6 -9
  130. data/lib/solargraph.rb +20 -1
  131. data/rbs/fills/tuple.rbs +150 -0
  132. data/rbs_collection.yaml +19 -0
  133. data/solargraph.gemspec +6 -5
  134. metadata +56 -29
  135. data/lib/solargraph/cache.rb +0 -77
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d6619265fc1ba2cab9154e70c5f4a6626999b685d58e26a805ec606d6804f17b
4
- data.tar.gz: cfac32a13734ba9b392d27fcb8da7c76b180f0bf64189d17698b2246ce6e3773
3
+ metadata.gz: 6f8c351394fab745041193e5d33cd582f0131e6d0f2d30f210767bd273376f24
4
+ data.tar.gz: 9d7a3c46740bd9fa040190d00f0e17cab638bde681da5998337dd41e6a924ff6
5
5
  SHA512:
6
- metadata.gz: 8d1d40bf5d19b37f6a2ee8cce73e36027140ae402d27326c15e39a961217153e8b269722503ca0a8a3b592bee50cb6227fffcd812f62a1ec8a1bf94219270eea
7
- data.tar.gz: 627df7fb0bd23b641f0b1a40434a6384def8f32bf318b4f92d243266ee0c3145059adc29ea487dcdc30c914045e5737bca92bff6bd67fd06527f97c2e4690fb8
6
+ metadata.gz: 0fefbe369014891f339463c19a198ab0b9c1d918fb70662b496d90f79871e7ab03d3b4e7bf853fee19f7bbd467817690b29e506ca340518156667e986685c92e
7
+ data.tar.gz: e92af09e57129e47e6c4b685642460c514bc7c26a015f93c7eb81d917b12717cfac0621181fc36dcc481770ce6b3d93a611f5acd5aee64b1730c8dde4b63b949
@@ -34,6 +34,8 @@ jobs:
34
34
  bundle exec solargraph config
35
35
  yq -yi '.plugins += ["solargraph-rails"]' .solargraph.yml
36
36
  yq -yi '.plugins += ["solargraph-rspec"]' .solargraph.yml
37
+ - name: Install gem types
38
+ run: bundle exec rbs collection install
37
39
  - name: Ensure typechecking still works
38
40
  run: bundle exec solargraph typecheck --level typed
39
41
  - name: Ensure specs still run
@@ -30,5 +30,7 @@ jobs:
30
30
  bundler-cache: false
31
31
  - name: Install gems
32
32
  run: bundle install
33
+ - name: Install gem types
34
+ run: bundle exec rbs collection install
33
35
  - name: Typecheck self
34
- run: bundle exec solargraph typecheck --level typed
36
+ run: SOLARGRAPH_ASSERTS=on bundle exec solargraph typecheck --level typed
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
+ /.gem_rbs_collection
2
+ /rbs_collection.lock.yaml
1
3
  /Gemfile.lock
2
4
  .Gemfile
3
5
  .idea
data/CHANGELOG.md CHANGED
@@ -1,3 +1,73 @@
1
+ ## 0.56.0 - July 1, 2025
2
+ - [regression] Gem caching perf and logging fixes #983
3
+
4
+ ## 0.55.5 - July 1, 2025
5
+ - Flatten results of DocMap external bundle query (#981)
6
+ - [breaking] Reimplement global conventions (#877)
7
+ - GemPins pin merging improvements (#946)
8
+ - Support class-scoped aliases and attributes from RBS (#952)
9
+ - Restructure ComplexType specs towards YARD doc compliance (#969)
10
+ - Use Prism (#974)
11
+ - Document pages (#977)
12
+ - Enable disabled-but-working specs (#978)
13
+ - Map RBS 'untyped' type (RBS::Types::Bases::Any) to 'undefined' (#979)
14
+ - Re-enable support for .gem_rbs_collection directories (#942)
15
+ - [breaking] Comply with YARD documentation on Hash tag format (#968)
16
+ - Ignore directory paths in Workspace#would_require? (#988)
17
+
18
+ ## 0.55.4 - June 27, 2025
19
+ - Flatten results of DocMap external bundle query (#981)
20
+
21
+ ## 0.55.3 - June 25, 2025
22
+ - Nil guards in flow-sensitive typing (patch release) (#980)
23
+
24
+ ## 0.55.2 - June 21, 2025
25
+ - Require external bundle (#972)
26
+
27
+ ## 0.55.1 - June 8, 2025
28
+ - Fix inline Struct definition (#962)
29
+ - Ensure DocMap requires bundler when loading gemspecs (#963)
30
+ - DelegatedMethod improvements (#953)
31
+
32
+ ## 0.55.0 - June 3, 2025
33
+ - Flow-sensitive typing - automatically downcast from is_a? calls (#856)
34
+ - Tuple enabler: infer literal types and use them for signature selection (#836)
35
+ - Signature selection improvements (#907)
36
+ - Add support for Ruby Structs (#939)
37
+ - [regression] Fix interface change breaking solargraph-rails (#940)
38
+ - [regression] Add back bundler/require support for solargraph-rails (#941)
39
+ - Add specs for initialize capabilities (#955)
40
+ - Create MethodAlias pins from YARD (#945)
41
+ - MessageWorker prioritizes synchronization (#956)
42
+ - initialize/new method pin cleanups (#949)
43
+ - Clip rebinds blocks when cursor is not part of receiver (#958)
44
+
45
+ ## 0.54.5 - May 17, 2025
46
+ - Repair unknown encoding errors (#936, #935)
47
+ - Index arbitrary pinsets (#937)
48
+ - Separate YARD cache from doc map cache (#938)
49
+
50
+ ## 0.54.4 - May 14, 2025
51
+ - Delete files from Library hash (#932)
52
+ - Clip#define returns variable pins (#934, #933)
53
+
54
+ ## 0.54.3 - May 13, 2025
55
+ - Improve inspect()/desc()/to_s() methods for better debugging output (#913)
56
+ - Fix generic resolution in Hash types (#906)
57
+ - Stop parsing RBS type parameter constraints as the type name (#918)
58
+ - Fix pin inference stack (#922)
59
+ - Refactor pin equality for performance (#925)
60
+ - Improve ApiMap catalog speed by preserving static pin indexes (#930)
61
+ - Update jaro_winkler dependency (#931)
62
+
63
+ ## 0.54.2 - April 28, 2025
64
+ - Resolve generics correctly on mixin inclusion (#898)
65
+ - Pick correct String#split overload (#905)
66
+ - Fix type sent into YARD method (#912)
67
+ - Early CancelRequest handling (#914)
68
+ - Destructure partial yield types (#915)
69
+ - Dependency versions (#916)
70
+
1
71
  ## 0.54.1 - April 26, 2025
2
72
  - Retire more RubyVM-specific code (#797)
3
73
  - Add additional docs for key classes, modules and methods (#802)
data/README.md CHANGED
@@ -63,12 +63,22 @@ The RSpec framework is supported via [solargraph-rspec](https://github.com/lekem
63
63
 
64
64
  **Note: Before version 0.53.0, it was recommended to run `yard gems` periodically or automate it with `yard config` to ensure that Solargraph had access to gem documentation. These steps are no longer necessary. Solargraph maintains its own gem documentation cache independent of the yardocs in your gem installations.**
65
65
 
66
- Solargraph automatically generates code maps from installed gems. You can also manage your cached gem documentation with the `solargraph gems` command.
67
-
68
- When editing code, a `require` call that references a gem will pull the documentation into the code maps and include the gem's API in code completion and intellisense.
66
+ When editing code, a `require` call that references a gem will pull the documentation into the code maps and include the gem's API in code completion and intellisense. Solargraph automatically generates code maps from installed gems, based on the YARD or RBS type information inside the gem. You can also eagerly cache gem documentation with the `solargraph gems` command.
69
67
 
70
68
  If your project automatically requires bundled gems (e.g., `require 'bundler/require'`), Solargraph will add all of the Gemfile's default dependencies to the map.
71
69
 
70
+ To ensure you have types for gems which contain neither RBS nor YARD
71
+ information, use
72
+ [gem\_rbs\_collection](https://github.com/ruby/gem_rbs_collection) to
73
+ install a community-supported set of RBS types for various gems:
74
+
75
+ ```sh
76
+ bundle exec rbs collection init
77
+ bundle exec rbs collection install
78
+ ```
79
+
80
+ Once installed, you can also insert your own local overrides and definitions in RBS in a directory configured in the `rbs_collection.yaml` that the above commands create.
81
+
72
82
  ### Type Checking
73
83
 
74
84
  As of version 0.33.0, Solargraph includes a [type checker](https://github.com/castwide/solargraph/issues/192) that uses a combination of YARD tags and code analysis to report missing type definitions. In strict mode, it performs type inference to determine whether the tags match the types it detects from code.
@@ -8,7 +8,7 @@ module Solargraph
8
8
  @methods = {}
9
9
  # @type [Hash{(String, Array<String>) => Array<Pin::Base>}]
10
10
  @constants = {}
11
- # @type [Hash{(String, String) => String}]
11
+ # @type [Hash{String => String}]
12
12
  @qualified_namespaces = {}
13
13
  # @type [Hash{String => Pin::Method}]
14
14
  @receiver_definitions = {}
@@ -16,6 +16,15 @@ module Solargraph
16
16
  @clips = {}
17
17
  end
18
18
 
19
+ def to_s
20
+ self.class.to_s
21
+ end
22
+
23
+ # avoid enormous dump
24
+ def inspect
25
+ to_s
26
+ end
27
+
19
28
  # @param fqns [String]
20
29
  # @param scope [Symbol]
21
30
  # @param visibility [Array<Symbol>]
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class ApiMap
5
+ class Index
6
+ include Logging
7
+
8
+ # @param pins [Array<Pin::Base>]
9
+ def initialize pins = []
10
+ catalog pins
11
+ end
12
+
13
+ # @return [Array<Pin::Base>]
14
+ def pins
15
+ @pins ||= []
16
+ end
17
+
18
+ # @return [Hash{String => Array<Pin::Namespace>}]
19
+ def namespace_hash
20
+ @namespace_hash ||= Hash.new { |h, k| h[k] = [] }
21
+ end
22
+
23
+ # @return [Hash{String => Array<Pin::Base>}]
24
+ def pin_class_hash
25
+ @pin_class_hash ||= Hash.new { |h, k| h[k] = [] }
26
+ end
27
+
28
+ # @return [Hash{String => Array<Pin::Base>}]
29
+ def path_pin_hash
30
+ @path_pin_hash ||= Hash.new { |h, k| h[k] = [] }
31
+ end
32
+
33
+ # @generic T
34
+ # @param klass [Class<generic<T>>]
35
+ # @return [Set<generic<T>>]
36
+ def pins_by_class klass
37
+ # @type [Set<Solargraph::Pin::Base>]
38
+ s = Set.new
39
+ @pin_select_cache[klass] ||= pin_class_hash.each_with_object(s) { |(key, o), n| n.merge(o) if key <= klass }
40
+ end
41
+
42
+ # @return [Hash{String => Array<Pin::Reference::Include>}]
43
+ def include_references
44
+ @include_references ||= Hash.new { |h, k| h[k] = [] }
45
+ end
46
+
47
+ # @return [Hash{String => Array<Pin::Reference::Extend>}]
48
+ def extend_references
49
+ @extend_references ||= Hash.new { |h, k| h[k] = [] }
50
+ end
51
+
52
+ # @return [Hash{String => Array<Pin::Reference::Prepend>}]
53
+ def prepend_references
54
+ @prepend_references ||= Hash.new { |h, k| h[k] = [] }
55
+ end
56
+
57
+ # @return [Hash{String => Array<Pin::Reference::Superclass>}]
58
+ def superclass_references
59
+ @superclass_references ||= Hash.new { |h, k| h[k] = [] }
60
+ end
61
+
62
+ # @param pins [Array<Pin::Base>]
63
+ def merge pins
64
+ deep_clone.catalog pins
65
+ end
66
+
67
+ protected
68
+
69
+ attr_writer :pins, :pin_select_cache, :namespace_hash, :pin_class_hash, :path_pin_hash, :include_references,
70
+ :extend_references, :prepend_references, :superclass_references
71
+
72
+ def deep_clone
73
+ Index.allocate.tap do |copy|
74
+ copy.pin_select_cache = {}
75
+ copy.pins = pins.clone
76
+ %i[
77
+ namespace_hash pin_class_hash path_pin_hash include_references extend_references prepend_references
78
+ superclass_references
79
+ ].each do |sym|
80
+ copy.send("#{sym}=", send(sym).clone)
81
+ copy.send(sym)&.transform_values!(&:clone)
82
+ end
83
+ end
84
+ end
85
+
86
+ # @param new_pins [Array<Pin::Base>]
87
+ def catalog new_pins
88
+ @pin_select_cache = {}
89
+ pins.concat new_pins
90
+ set = new_pins.to_set
91
+ set.classify(&:class)
92
+ .map { |k, v| pin_class_hash[k].concat v.to_a }
93
+ set.classify(&:namespace)
94
+ .map { |k, v| namespace_hash[k].concat v.to_a }
95
+ set.classify(&:path)
96
+ .map { |k, v| path_pin_hash[k].concat v.to_a }
97
+ @namespaces = path_pin_hash.keys.compact.to_set
98
+ map_references Pin::Reference::Include, include_references
99
+ map_references Pin::Reference::Prepend, prepend_references
100
+ map_references Pin::Reference::Extend, extend_references
101
+ map_references Pin::Reference::Superclass, superclass_references
102
+ map_overrides
103
+ self
104
+ end
105
+
106
+ # @param klass [Class<Pin::Reference>]
107
+ # @param hash [Hash{String => Array<Pin::Reference>}]
108
+ # @return [void]
109
+ def map_references klass, hash
110
+ pins_by_class(klass).each do |pin|
111
+ store_parametric_reference(hash, pin)
112
+ end
113
+ end
114
+
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
+ # @return [void]
135
+ def map_overrides
136
+ pins_by_class(Pin::Reference::Override).each do |ovr|
137
+ logger.debug { "ApiMap::Index#map_overrides: Looking at override #{ovr} for #{ovr.name}" }
138
+ pins = path_pin_hash[ovr.name]
139
+ logger.debug { "ApiMap::Index#map_overrides: pins for path=#{ovr.name}: #{pins}" }
140
+ pins.each do |pin|
141
+ new_pin = if pin.path.end_with?('#initialize')
142
+ path_pin_hash[pin.path.sub(/#initialize/, '.new')].first
143
+ end
144
+ (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
145
+ pin.docstring.delete_tags tag
146
+ new_pin.docstring.delete_tags tag if new_pin
147
+ end
148
+ ovr.tags.each do |tag|
149
+ pin.docstring.add_tag(tag)
150
+ redefine_return_type pin, tag
151
+ if new_pin
152
+ new_pin.docstring.add_tag(tag)
153
+ redefine_return_type new_pin, tag
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+
160
+ # @param pin [Pin::Method]
161
+ # @param tag [YARD::Tags::Tag]
162
+ # @return [void]
163
+ def redefine_return_type pin, tag
164
+ # @todo can this be made to not mutate existing pins and use
165
+ # proxy() / proxy_with_signatures() instead?
166
+ return unless pin && tag.tag_name == 'return'
167
+ pin.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
168
+ pin.signatures.each do |sig|
169
+ sig.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
170
+ end
171
+ pin.reset_generated!
172
+ end
173
+ end
174
+ end
175
+ end
@@ -1,19 +1,50 @@
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
9
+ # @param pinsets [Array<Enumerable<Pin::Base>>]
10
+ def initialize *pinsets
11
+ catalog pinsets
12
+ end
13
+
10
14
  # @return [Array<Solargraph::Pin::Base>]
11
- attr_reader :pins
15
+ def pins
16
+ index.pins
17
+ end
18
+
19
+ # @param pinsets [Array<Enumerable<Pin::Base>>]
20
+ # @return [Boolean] True if the index was updated
21
+ def update *pinsets
22
+ return catalog(pinsets) if pinsets.length != @pinsets.length
23
+
24
+ changed = pinsets.find_index.with_index { |pinset, idx| @pinsets[idx] != pinset }
25
+ return false unless changed
12
26
 
13
- # @param pins [Enumerable<Solargraph::Pin::Base>]
14
- def initialize pins = []
15
- @pins = pins
16
- index
27
+ # @todo Fix this map
28
+ @fqns_pins_map = nil
29
+ return catalog(pinsets) if changed == 0
30
+
31
+ pinsets[changed..].each_with_index do |pins, idx|
32
+ @pinsets[changed + idx] = pins
33
+ @indexes[changed + idx] = if pins.empty?
34
+ @indexes[changed + idx - 1]
35
+ else
36
+ @indexes[changed + idx - 1].merge(pins)
37
+ end
38
+ end
39
+ true
40
+ end
41
+
42
+ def to_s
43
+ self.class.to_s
44
+ end
45
+
46
+ def inspect
47
+ to_s
17
48
  end
18
49
 
19
50
  # @param fqns [String]
@@ -30,18 +61,24 @@ module Solargraph
30
61
  # @param visibility [Array<Symbol>]
31
62
  # @return [Enumerable<Solargraph::Pin::Method>]
32
63
  def get_methods fqns, scope: :instance, visibility: [:public]
33
- namespace_children(fqns).select do |pin|
64
+ all_pins = namespace_children(fqns).select do |pin|
34
65
  pin.is_a?(Pin::Method) && pin.scope == scope && visibility.include?(pin.visibility)
35
66
  end
67
+ GemPins.combine_method_pins_by_path(all_pins)
36
68
  end
37
69
 
38
- # @param fqns [String]
70
+ # @param fq_tag [String]
39
71
  # @return [String, nil]
40
- def get_superclass fqns
41
- raise "Do not prefix fully qualified namespaces with '::' - #{fqns.inspect}" if fqns.start_with?('::')
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)
42
77
  return superclass_references[fqns].first if superclass_references.key?(fqns)
43
78
  return 'Object' if fqns != 'BasicObject' && namespace_exists?(fqns)
44
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
45
82
  nil
46
83
  end
47
84
 
@@ -66,11 +103,7 @@ module Solargraph
66
103
  # @param path [String]
67
104
  # @return [Array<Solargraph::Pin::Base>]
68
105
  def get_path_pins path
69
- path_pin_hash[path] || []
70
- end
71
-
72
- def cacheable_pins
73
- @cacheable_pins ||= pins_by_class(Pin::Namespace) + pins_by_class(Pin::Constant) + pins_by_class(Pin::Method) + pins_by_class(Pin::Reference)
106
+ index.path_pin_hash[path]
74
107
  end
75
108
 
76
109
  # @param fqns [String]
@@ -85,7 +118,7 @@ module Solargraph
85
118
  # @param fqns [String]
86
119
  # @return [Enumerable<Solargraph::Pin::Base>]
87
120
  def get_class_variables(fqns)
88
- namespace_children(fqns).select{|pin| pin.is_a?(Pin::ClassVariable)}
121
+ namespace_children(fqns).select { |pin| pin.is_a?(Pin::ClassVariable)}
89
122
  end
90
123
 
91
124
  # @return [Enumerable<Solargraph::Pin::Base>]
@@ -101,10 +134,10 @@ module Solargraph
101
134
 
102
135
  # @return [Set<String>]
103
136
  def namespaces
104
- @namespaces ||= Set.new
137
+ index.namespaces
105
138
  end
106
139
 
107
- # @return [Enumerable<Solargraph::Pin::Base>]
140
+ # @return [Enumerable<Solargraph::Pin::Namespace>]
108
141
  def namespace_pins
109
142
  pins_by_class(Solargraph::Pin::Namespace)
110
143
  end
@@ -143,18 +176,11 @@ module Solargraph
143
176
  pins_by_class(Pin::Block)
144
177
  end
145
178
 
146
- def inspect
147
- # Avoid insane dumps in specs
148
- to_s
149
- end
150
-
151
179
  # @generic T
152
- # @param klass [Class<T>]
153
- # @return [Set<T>]
180
+ # @param klass [Class<generic<T>>]
181
+ # @return [Set<generic<T>>]
154
182
  def pins_by_class klass
155
- # @type [Set<Solargraph::Pin::Base>]
156
- s = Set.new
157
- @pin_select_cache[klass] ||= @pin_class_hash.each_with_object(s) { |(key, o), n| n.merge(o) if key <= klass }
183
+ index.pins_by_class klass
158
184
  end
159
185
 
160
186
  # @param fqns [String]
@@ -174,6 +200,23 @@ module Solargraph
174
200
 
175
201
  private
176
202
 
203
+ def index
204
+ @indexes.last
205
+ end
206
+
207
+ def catalog pinsets
208
+ @pinsets = pinsets
209
+ @indexes = []
210
+ pinsets.each do |pins|
211
+ if @indexes.last && pins.empty?
212
+ @indexes.push @indexes.last
213
+ else
214
+ @indexes.push(@indexes.last&.merge(pins) || Solargraph::ApiMap::Index.new(pins))
215
+ end
216
+ end
217
+ true
218
+ end
219
+
177
220
  # @return [Hash{::Array(String, String) => ::Array<Pin::Namespace>}]
178
221
  def fqns_pins_map
179
222
  @fqns_pins_map ||= Hash.new do |h, (base, name)|
@@ -184,129 +227,39 @@ module Solargraph
184
227
 
185
228
  # @return [Enumerable<Solargraph::Pin::Symbol>]
186
229
  def symbols
187
- pins_by_class(Pin::Symbol)
230
+ index.pins_by_class(Pin::Symbol)
188
231
  end
189
232
 
190
233
  # @return [Hash{String => Array<String>}]
191
234
  def superclass_references
192
- @superclass_references ||= {}
235
+ index.superclass_references
193
236
  end
194
237
 
195
238
  # @return [Hash{String => Array<String>}]
196
239
  def include_references
197
- @include_references ||= {}
240
+ index.include_references
198
241
  end
199
242
 
200
243
  # @return [Hash{String => Array<String>}]
201
244
  def prepend_references
202
- @prepend_references ||= {}
245
+ index.prepend_references
203
246
  end
204
247
 
205
248
  # @return [Hash{String => Array<String>}]
206
249
  def extend_references
207
- @extend_references ||= {}
250
+ index.extend_references
208
251
  end
209
252
 
210
253
  # @param name [String]
211
254
  # @return [Enumerable<Solargraph::Pin::Base>]
212
255
  def namespace_children name
213
- namespace_map[name] || []
214
- end
215
-
216
- # @return [Hash{String => Enumerable<Pin::Base>}
217
- def namespace_map
218
- @namespace_map ||= {}
256
+ return [] unless index.namespace_hash.key?(name)
257
+ index.namespace_hash[name]
219
258
  end
220
259
 
221
260
  # @return [Enumerable<Pin::InstanceVariable>]
222
261
  def all_instance_variables
223
- pins_by_class(Pin::InstanceVariable)
224
- end
225
-
226
- # @return [Hash{String => Array<Pin::Base>}]
227
- def path_pin_hash
228
- @path_pin_hash ||= {}
229
- end
230
-
231
- # Add references to a map
232
- #
233
- # @param h [Hash{String => Pin:Base}]
234
- # @param reference_pin [Pin::Reference]
235
- #
236
- # @return [void]
237
- def store_parametric_reference(h, reference_pin)
238
- referenced_ns = reference_pin.name
239
- referenced_tag_params = reference_pin.generic_values
240
- referenced_tag = referenced_ns +
241
- if referenced_tag_params && referenced_tag_params.length > 0
242
- "<" + referenced_tag_params.join(', ') + ">"
243
- else
244
- ''
245
- end
246
- referencing_ns = reference_pin.namespace
247
- h[referencing_ns] ||= []
248
- h[referencing_ns].push referenced_tag
249
- end
250
-
251
- # @return [void]
252
- def index
253
- set = pins.to_set
254
- @pin_class_hash = set.classify(&:class).transform_values(&:to_a)
255
- # @type [Hash{Class => ::Array<Solargraph::Pin::Base>}]
256
- @pin_select_cache = {}
257
- @namespace_map = set.classify(&:namespace)
258
- @path_pin_hash = set.classify(&:path)
259
- @namespaces = @path_pin_hash.keys.compact.to_set
260
- pins_by_class(Pin::Reference::Include).each do |pin|
261
- store_parametric_reference(include_references, pin)
262
- end
263
- # @todo move the rest of these reference pins over to use
264
- # generic types, adding rbs_map/conversions.rb code to
265
- # populate type parameters and adding related specs ensuring
266
- # the generics get resolved, along with any api_map.rb
267
- # changes needed in
268
- pins_by_class(Pin::Reference::Prepend).each do |pin|
269
- prepend_references[pin.namespace] ||= []
270
- prepend_references[pin.namespace].push pin.name
271
- end
272
- pins_by_class(Pin::Reference::Extend).each do |pin|
273
- extend_references[pin.namespace] ||= []
274
- extend_references[pin.namespace].push pin.name
275
- end
276
- pins_by_class(Pin::Reference::Superclass).each do |pin|
277
- superclass_references[pin.namespace] ||= []
278
- superclass_references[pin.namespace].push pin.name
279
- end
280
- pins_by_class(Pin::Reference::Override).each do |ovr|
281
- pin = get_path_pins(ovr.name).first
282
- next if pin.nil?
283
- new_pin = if pin.path.end_with?('#initialize')
284
- get_path_pins(pin.path.sub(/#initialize/, '.new')).first
285
- end
286
- (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
287
- pin.docstring.delete_tags tag.to_sym
288
- new_pin.docstring.delete_tags tag.to_sym if new_pin
289
- end
290
- ovr.tags.each do |tag|
291
- pin.docstring.add_tag(tag)
292
- redefine_return_type pin, tag
293
- if new_pin
294
- new_pin.docstring.add_tag(tag)
295
- redefine_return_type new_pin, tag
296
- end
297
- end
298
- end
299
- end
300
-
301
- # @param pin [Pin::Base]
302
- # @param tag [String]
303
- # @return [void]
304
- def redefine_return_type pin, tag
305
- return unless pin && tag.tag_name == 'return'
306
- pin.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
307
- pin.signatures.each do |sig|
308
- sig.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
309
- end
262
+ index.pins_by_class(Pin::InstanceVariable)
310
263
  end
311
264
  end
312
265
  end