solargraph 0.60.4 → 0.62.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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +24 -2
  3. data/.github/workflows/plugins.yml +19 -1
  4. data/.github/workflows/rspec.yml +17 -2
  5. data/.github/workflows/typecheck.yml +6 -0
  6. data/CHANGELOG.md +54 -0
  7. data/Gemfile +0 -3
  8. data/lib/solargraph/api_map/index.rb +28 -4
  9. data/lib/solargraph/api_map/store.rb +19 -0
  10. data/lib/solargraph/api_map.rb +91 -80
  11. data/lib/solargraph/cache_dir.rb +58 -0
  12. data/lib/solargraph/collection/base.rb +50 -0
  13. data/lib/solargraph/collection/core.rb +17 -0
  14. data/lib/solargraph/collection/gem.rb +59 -0
  15. data/lib/solargraph/collection/stdlib.rb +25 -0
  16. data/lib/solargraph/collection.rb +30 -0
  17. data/lib/solargraph/complex_type/unique_type.rb +13 -0
  18. data/lib/solargraph/complex_type.rb +23 -3
  19. data/lib/solargraph/convention.rb +5 -7
  20. data/lib/solargraph/diagnostics/require_not_found.rb +0 -4
  21. data/lib/solargraph/diagnostics/type_check.rb +0 -1
  22. data/lib/solargraph/external.rb +187 -0
  23. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  24. data/lib/solargraph/language_server/host/dispatch.rb +4 -2
  25. data/lib/solargraph/language_server/host.rb +10 -2
  26. data/lib/solargraph/language_server/message/completion_item/resolve.rb +10 -3
  27. data/lib/solargraph/language_server/message/text_document/definition.rb +5 -2
  28. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -2
  29. data/lib/solargraph/library.rb +26 -53
  30. data/lib/solargraph/metagem.rb +80 -0
  31. data/lib/solargraph/parser/node_processor/base.rb +6 -0
  32. data/lib/solargraph/parser/parser_gem/node_chainer.rb +22 -3
  33. data/lib/solargraph/parser/parser_gem/node_methods.rb +29 -6
  34. data/lib/solargraph/parser/parser_gem/node_processors/class_definition/class_assignment_node.rb +98 -0
  35. data/lib/solargraph/parser/parser_gem/node_processors/class_definition.rb +54 -0
  36. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +1 -0
  37. data/lib/solargraph/parser/parser_gem/node_processors/data_definition/data_assignment_node.rb +65 -0
  38. data/lib/solargraph/parser/parser_gem/node_processors/data_definition/data_definition_node.rb +97 -0
  39. data/lib/solargraph/parser/parser_gem/node_processors/data_definition.rb +110 -0
  40. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +1 -0
  41. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +2 -0
  42. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  43. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +185 -0
  44. data/lib/solargraph/parser/parser_gem/node_processors/struct_definition/struct_assignment_node.rb +66 -0
  45. data/lib/solargraph/parser/parser_gem/node_processors/struct_definition/struct_definition_node.rb +108 -0
  46. data/lib/solargraph/parser/parser_gem/node_processors/struct_definition.rb +170 -0
  47. data/lib/solargraph/parser/parser_gem/node_processors.rb +33 -29
  48. data/lib/solargraph/pin/base.rb +25 -1
  49. data/lib/solargraph/pin/base_variable.rb +31 -1
  50. data/lib/solargraph/pin/callable.rb +11 -2
  51. data/lib/solargraph/pin/closure.rb +17 -0
  52. data/lib/solargraph/pin/delegated_method.rb +5 -0
  53. data/lib/solargraph/pin/duck_method.rb +36 -16
  54. data/lib/solargraph/pin/factory_parameter.rb +84 -0
  55. data/lib/solargraph/pin/instance_variable.rb +45 -0
  56. data/lib/solargraph/pin/method.rb +10 -0
  57. data/lib/solargraph/pin/method_alias.rb +4 -0
  58. data/lib/solargraph/pin/parameter.rb +1 -1
  59. data/lib/solargraph/pin/reference/included_mixin.rb +22 -0
  60. data/lib/solargraph/pin/reference.rb +1 -0
  61. data/lib/solargraph/pin.rb +1 -0
  62. data/lib/solargraph/plugin/active_support.rb +100 -0
  63. data/lib/solargraph/plugin/addon.rb +16 -0
  64. data/lib/solargraph/plugin/base.rb +25 -0
  65. data/lib/solargraph/plugin/panel.rb +37 -0
  66. data/lib/solargraph/plugin.rb +26 -0
  67. data/lib/solargraph/rbs_collection.rb +119 -0
  68. data/lib/solargraph/rbs_map/base.rb +31 -0
  69. data/lib/solargraph/rbs_map/conversions.rb +109 -48
  70. data/lib/solargraph/rbs_map/{core_map.rb → core.rb} +18 -39
  71. data/lib/solargraph/rbs_map/core_fills.rb +1 -1
  72. data/lib/solargraph/rbs_map/gem.rb +16 -0
  73. data/lib/solargraph/rbs_map/helpers.rb +61 -0
  74. data/lib/solargraph/rbs_map/path.rb +19 -0
  75. data/lib/solargraph/rbs_map/stdlib.rb +24 -0
  76. data/lib/solargraph/rbs_map.rb +7 -198
  77. data/lib/solargraph/rbs_translator.rb +105 -70
  78. data/lib/solargraph/repo.rb +177 -0
  79. data/lib/solargraph/shell.rb +49 -99
  80. data/lib/solargraph/source/chain/call.rb +58 -14
  81. data/lib/solargraph/source/chain/literal.rb +17 -17
  82. data/lib/solargraph/source/chain/parameter.rb +79 -0
  83. data/lib/solargraph/source/chain.rb +8 -0
  84. data/lib/solargraph/source/node_map.rb +27 -0
  85. data/lib/solargraph/source/source_chainer.rb +40 -44
  86. data/lib/solargraph/source.rb +17 -0
  87. data/lib/solargraph/source_map/call.rb +18 -0
  88. data/lib/solargraph/source_map/clip.rb +5 -3
  89. data/lib/solargraph/source_map/mapper.rb +6 -2
  90. data/lib/solargraph/source_map.rb +28 -9
  91. data/lib/solargraph/type_checker/rules.rb +3 -2
  92. data/lib/solargraph/type_checker.rb +4 -1
  93. data/lib/solargraph/version.rb +1 -1
  94. data/lib/solargraph/workspace.rb +0 -1
  95. data/lib/solargraph/yard_map/cache.rb +1 -1
  96. data/lib/solargraph/yard_map/directives/attribute_directive.rb +1 -1
  97. data/lib/solargraph/yard_map/directives/domain_directive.rb +1 -1
  98. data/lib/solargraph/yard_map/directives/method_directive.rb +1 -1
  99. data/lib/solargraph/yard_map/directives/override_directive.rb +1 -1
  100. data/lib/solargraph/yard_map/directives/parse_directive.rb +1 -1
  101. data/lib/solargraph/yard_map/directives/scope_directive.rb +178 -0
  102. data/lib/solargraph/yard_map/directives/visibility_directive.rb +1 -1
  103. data/lib/solargraph/yard_map/directives.rb +5 -2
  104. data/lib/solargraph/yard_map/helpers.rb +1 -1
  105. data/lib/solargraph/yard_map/macro.rb +85 -6
  106. data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -1
  107. data/lib/solargraph/yard_map/mapper/to_method.rb +1 -1
  108. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -1
  109. data/lib/solargraph/yard_map/mapper.rb +2 -2
  110. data/lib/solargraph/yard_map.rb +1 -1
  111. data/lib/solargraph/yardoc.rb +43 -60
  112. data/lib/solargraph.rb +8 -3
  113. data/rbs/fills/boolean/0/boolean.rbs +12 -0
  114. data/solargraph.gemspec +2 -2
  115. metadata +41 -18
  116. data/lib/solargraph/convention/active_support_concern.rb +0 -111
  117. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +0 -61
  118. data/lib/solargraph/convention/data_definition/data_definition_node.rb +0 -93
  119. data/lib/solargraph/convention/data_definition.rb +0 -108
  120. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +0 -62
  121. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +0 -103
  122. data/lib/solargraph/convention/struct_definition.rb +0 -168
  123. data/lib/solargraph/doc_map.rb +0 -439
  124. data/lib/solargraph/gem_pins.rb +0 -87
  125. data/lib/solargraph/pin_cache.rb +0 -248
  126. data/lib/solargraph/rbs_map/stdlib_map.rb +0 -71
  127. data/lib/solargraph/workspace/gemspecs.rb +0 -373
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7c7397d5a9bbee07b12baa9372ce14f61216e5a310aa0f68605acabf8a9430e2
4
- data.tar.gz: aeecf5c5d1ea7b1040fd3ae4bd9d1bff1685e468bd92b30dedfdd8ded2f1cd04
3
+ metadata.gz: 8b2496884d72c8abed7340388dc6bd09f8be728ba93724c6146366b51a12c595
4
+ data.tar.gz: b8f1be6afe684fc5a50349958937a12073dab1b7f5ff4574234e3ffaa57fc164
5
5
  SHA512:
6
- metadata.gz: f4abae37c4fc8b57efe4a7b3550a2edbfc64455e8852f81660220f4a67facf101eafd058805b58cf0be6f9d5b9d16317cd21f6cd3b47f0c666c48418ee0d54c2
7
- data.tar.gz: e14586769600dd63e2a96b8bcb4a5e4aa9bb045948e87e8c06b6606e711fed6816347051505eb756df55fed375a0419431dd02a44c2082d6d1ec0e2b13c6564f
6
+ metadata.gz: 3414b07c09f728a8418bf1fb97d58eeb57a8496819c4a8340595750e6f59d952f77ea0cc3ce2e44705894905f773d3073c793e987d5b0e92aeea8ed4c29e835d
7
+ data.tar.gz: eb38a46cf34401299101a91be9b1c113dd977784e6c17c25aae78e2554a932bb46ac7d822dd303753e353f2b1daba6cf8186d26807b418d2804e725f60dc2a14
@@ -28,6 +28,12 @@ jobs:
28
28
  with:
29
29
  fetch-depth: 0
30
30
 
31
+ - name: Install libjitterentropy.a for rugged
32
+ # Ubuntu 26.04's libcrypto.pc links it statically
33
+ run: |
34
+ if pkg-config --libs --static libcrypto | grep -q jitterentropy; then
35
+ sudo apt-get update && sudo apt-get install -y libjitterentropy3-dev
36
+ fi
31
37
  - uses: ruby/setup-ruby@v1
32
38
  with:
33
39
  ruby-version: 3.4
@@ -66,6 +72,12 @@ jobs:
66
72
  runs-on: ubuntu-latest
67
73
  steps:
68
74
  - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
75
+ - name: Install libjitterentropy.a for rugged
76
+ # Ubuntu 26.04's libcrypto.pc links it statically
77
+ run: |
78
+ if pkg-config --libs --static libcrypto | grep -q jitterentropy; then
79
+ sudo apt-get update && sudo apt-get install -y libjitterentropy3-dev
80
+ fi
69
81
  - uses: ruby/setup-ruby@1a615958ad9d422dd932dc1d5823942ee002799f # v1.227.0
70
82
  with:
71
83
  ruby-version: '3.3'
@@ -86,6 +98,12 @@ jobs:
86
98
 
87
99
  steps:
88
100
  - uses: actions/checkout@v3
101
+ - name: Install libjitterentropy.a for rugged
102
+ # Ubuntu 26.04's libcrypto.pc links it statically
103
+ run: |
104
+ if pkg-config --libs --static libcrypto | grep -q jitterentropy; then
105
+ sudo apt-get update && sudo apt-get install -y libjitterentropy3-dev
106
+ fi
89
107
  - name: Set up Ruby
90
108
  uses: ruby/setup-ruby@v1
91
109
  with:
@@ -97,14 +115,18 @@ jobs:
97
115
 
98
116
  - name: Run rbs validate
99
117
  run: bundle exec rbs validate
100
- # @todo Temporary, expect to revert in 0.60
101
- continue-on-error: true
102
118
  rubocop_todo:
103
119
  name: .rubocop_todo.yml
104
120
  runs-on: ubuntu-latest
105
121
 
106
122
  steps:
107
123
  - uses: actions/checkout@v3
124
+ - name: Install libjitterentropy.a for rugged
125
+ # Ubuntu 26.04's libcrypto.pc links it statically
126
+ run: |
127
+ if pkg-config --libs --static libcrypto | grep -q jitterentropy; then
128
+ sudo apt-get update && sudo apt-get install -y libjitterentropy3-dev
129
+ fi
108
130
  - name: Set up Ruby
109
131
  uses: ruby/setup-ruby@v1
110
132
  with:
@@ -20,6 +20,12 @@ jobs:
20
20
 
21
21
  steps:
22
22
  - uses: actions/checkout@v3
23
+ - name: Install libjitterentropy.a for rugged
24
+ # Ubuntu 26.04's libcrypto.pc links it statically
25
+ run: |
26
+ if pkg-config --libs --static libcrypto | grep -q jitterentropy; then
27
+ sudo apt-get update && sudo apt-get install -y libjitterentropy3-dev
28
+ fi
23
29
  - name: Set up Ruby
24
30
  uses: ruby/setup-ruby@v1
25
31
  with:
@@ -54,6 +60,12 @@ jobs:
54
60
 
55
61
  steps:
56
62
  - uses: actions/checkout@v3
63
+ - name: Install libjitterentropy.a for rugged
64
+ # Ubuntu 26.04's libcrypto.pc links it statically
65
+ run: |
66
+ if pkg-config --libs --static libcrypto | grep -q jitterentropy; then
67
+ sudo apt-get update && sudo apt-get install -y libjitterentropy3-dev
68
+ fi
57
69
  - name: Set up Ruby
58
70
  uses: ruby/setup-ruby@v1
59
71
  with:
@@ -89,6 +101,12 @@ jobs:
89
101
 
90
102
  steps:
91
103
  - uses: actions/checkout@v3
104
+ - name: Install libjitterentropy.a for rugged
105
+ # Ubuntu 26.04's libcrypto.pc links it statically
106
+ run: |
107
+ if pkg-config --libs --static libcrypto | grep -q jitterentropy; then
108
+ sudo apt-get update && sudo apt-get install -y libjitterentropy3-dev
109
+ fi
92
110
  - name: Set up Ruby
93
111
  uses: ruby/setup-ruby@v1
94
112
  with:
@@ -129,7 +147,7 @@ jobs:
129
147
  - name: clone https://github.com/lekemula/solargraph-rspec/
130
148
  run: |
131
149
  cd ..
132
- git clone https://github.com/lekemula/solargraph-rspec.git
150
+ git clone https://github.com/lekemula/solargraph-rspec/
133
151
  cd solargraph-rspec
134
152
  - name: Set up Ruby
135
153
  uses: ruby/setup-ruby@v1
@@ -18,14 +18,15 @@ permissions:
18
18
 
19
19
  jobs:
20
20
  rspec:
21
- runs-on: ubuntu-latest
21
+ # ruby/setup-ruby has no Ruby 3.1 build for Ubuntu 26.04
22
+ runs-on: ${{ matrix.ruby-version == '3.1' && 'ubuntu-24.04' || 'ubuntu-latest' }}
22
23
  strategy:
23
24
  matrix:
24
25
  # @todo Restore 'head' once ruby/setup-ruby publishes it for ubuntu-24.04.
25
26
  # It currently 404s ("Unavailable version head for ruby"), failing CI:
26
27
  # https://github.com/castwide/solargraph/actions/runs/25863741955/job/76000137015?pr=1187
27
28
  ruby-version: ['3.1', '3.2', '3.3', '3.4', '4.0']
28
- rbs-version: ['3.10.0', '4.0.0', '4.0.1', '4.0.2']
29
+ rbs-version: ['3.10.4', '4.0.0', '4.0.1', '4.0.2']
29
30
  exclude:
30
31
  - ruby-version: '3.1'
31
32
  rbs-version: '4.0.0'
@@ -35,6 +36,12 @@ jobs:
35
36
  rbs-version: '4.0.2'
36
37
  steps:
37
38
  - uses: actions/checkout@v3
39
+ - name: Install libjitterentropy.a for rugged
40
+ # Ubuntu 26.04's libcrypto.pc links it statically
41
+ run: |
42
+ if pkg-config --libs --static libcrypto | grep -q jitterentropy; then
43
+ sudo apt-get update && sudo apt-get install -y libjitterentropy3-dev
44
+ fi
38
45
  - name: Set up Ruby
39
46
  uses: ruby/setup-ruby@v1
40
47
  with:
@@ -48,6 +55,8 @@ jobs:
48
55
  # starting from Ruby 3.6.0
49
56
  - name: Work around legacy rbs deprecation on ruby > 3.4
50
57
  run: echo "gem 'tsort'" >> .Gemfile
58
+ - name: Install bundle
59
+ run: bundle install
51
60
  - name: Update gems
52
61
  run: |
53
62
  bundle update rbs # use latest available for this Ruby version
@@ -63,6 +72,12 @@ jobs:
63
72
  # fetch all history for all branches and tags so we can
64
73
  # compare against origin/master
65
74
  fetch-depth: 0
75
+ - name: Install libjitterentropy.a for rugged
76
+ # Ubuntu 26.04's libcrypto.pc links it statically
77
+ run: |
78
+ if pkg-config --libs --static libcrypto | grep -q jitterentropy; then
79
+ sudo apt-get update && sudo apt-get install -y libjitterentropy3-dev
80
+ fi
66
81
  - name: Set up Ruby
67
82
  uses: ruby/setup-ruby@v1
68
83
  with:
@@ -24,6 +24,12 @@ jobs:
24
24
 
25
25
  steps:
26
26
  - uses: actions/checkout@v3
27
+ - name: Install libjitterentropy.a for rugged
28
+ # Ubuntu 26.04's libcrypto.pc links it statically
29
+ run: |
30
+ if pkg-config --libs --static libcrypto | grep -q jitterentropy; then
31
+ sudo apt-get update && sudo apt-get install -y libjitterentropy3-dev
32
+ fi
27
33
  - name: Set up Ruby
28
34
  uses: ruby/setup-ruby@v1
29
35
  with:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,57 @@
1
+ ## 0.62.0 - October 30, 2026
2
+ - Fix false positive: Struct.new(keyword_init: true) members are optional (#1269)
3
+ - Strip nil from or-expression fallbacks in conditional branch values (#1309)
4
+ - Map Forwardable delegations to method pins (#1311)
5
+ - Resolve a self return type per union member (#1314)
6
+ - Read implicitly-returns-nil per RBS overload, not from the first one (#1316)
7
+ - Make `rbs validate` a blocking CI check again (#1317)
8
+ - Add nil protection to definition (#1427)
9
+ - Index `X = Class.new(Super)` constant assignments as classes (#1306)
10
+ - Map gems without YARD (#1378)
11
+ - Loosen the Rubocop development dependency (#1428)
12
+ - [regression fix] Build rugged on Ubuntu 26.04 CI runners (#1436)
13
+ - Skip Diagnoser#tick when the queue is drained (#1426)
14
+ - Stop flagging anonymous argument forwarding (#1400)
15
+ - Resolve instance variable type when assigned only in an ancestor class's method (#1345)
16
+ - Apply @!override to constants instead of crashing (#1305)
17
+ - Resolve generic type variables against union @param types (#1299)
18
+ - ensure clause breaks return type inference (#1285)
19
+ - Improved RBS type alias support (#1281)
20
+ - Bind reopened generic parameters by position (#1411)
21
+ - Apply mixins from self.included hooks to includers (#1405)
22
+ - Define Boolean so its operators resolve (#1351)
23
+ - Stop reporting a duck type's own method as unresolved (#1280)
24
+ - Keep the generic return type when a method takes a block (#1274)
25
+ - [regression fix] Stop rerunning a gem cache command that failed (#1442)
26
+ - Remove Dispatch#update's hidden assumption that self is a Host (#1440)
27
+ - Default anonymous type shorthand names (#1454)
28
+ - New Plugin architecture with ActiveSupport implementation (#1435)
29
+ - Keep the adapter spec from hanging in Backport.run (#1449)
30
+ - Stop mapping a gem's non-sig RBS as its API (#1453)
31
+ - Type variables from rbs-inline #: assertions on assignments (#1444)
32
+ - Resolve inline RBS names in enclosing namespace (#1447)
33
+ - Enable pending clip spec (#1462)
34
+ - Remove Convention::ActiveSupportConcern (#1469)
35
+ - Move Class, Struct, and Data definition processors to NodeProcessors (#1468)
36
+ - Preserve immutable completion item properties during resolve (#1471)
37
+ - [regression fix] Cache gems that have a leftover YARD lock (#1465)
38
+
39
+ ## 0.61.0 - October 7, 2026
40
+ - Clips qualify constant pins for completion (#1368)
41
+ - Unused spec tags (#1370)
42
+ - External gem dependency management (#1369)
43
+ - Use a development branch of Solargraph::RSpec for plugin tests (#1371)
44
+ - Pin::Base spec changes (#1372)
45
+ - Consolidate cache and gems commands (#1373)
46
+ - Sleep timeouts (#1375)
47
+ - RbsMap loads minimal pins (#1377)
48
+ - Fix 10x slowdown when analyzing projects with many gems (#1374)
49
+ - Clone main solargraph-rspec repo in plugins workflow (#1388)
50
+ - Add new Pin::FactoryParameter (#1063)
51
+ - Support YARD `@!scope` directive (#1387)
52
+ - Add nil guard to Hover (#1389)
53
+ - Stop dropping union members that differ only by type parameter (#1273)
54
+
1
55
  ## 0.60.4 - August 30, 2026
2
56
  - Fix @yieldparam type lost on multi-overload block-form methods (#1289) (#1290)
3
57
  - Read inline RBS superclass params only on the class line (#1301)
data/Gemfile CHANGED
@@ -4,9 +4,6 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec name: 'solargraph'
6
6
 
7
- # Test fixture gems
8
- gem 'gem-with-yard-macros', path: 'spec/fixtures/gem-with-yard-macros'
9
-
10
7
  # Local gemfile for development tools, etc.
11
8
  local_gemfile = File.expand_path('.Gemfile', __dir__)
12
9
  instance_eval File.read local_gemfile if File.exist? local_gemfile
@@ -85,6 +85,13 @@ module Solargraph
85
85
  @prepend_references ||= Hash.new { |h, k| h[k] = [] }
86
86
  end
87
87
 
88
+ # @return [Hash{String => Array<Pin::Reference::IncludedMixin>}]
89
+ def included_mixin_references
90
+ # @param h [String]
91
+ # @param k [Array<Pin::Reference::IncludedMixin>]
92
+ @included_mixin_references ||= Hash.new { |h, k| h[k] = [] }
93
+ end
94
+
88
95
  # @return [Hash{String => Array<Pin::Reference::Superclass>}]
89
96
  def superclass_references
90
97
  # @param h [String]
@@ -92,6 +99,11 @@ module Solargraph
92
99
  @superclass_references ||= Hash.new { |h, k| h[k] = [] }
93
100
  end
94
101
 
102
+ # @return [Hash{String => Array<Pin::FactoryParameter>}]
103
+ def factory_parameter_hash
104
+ @factory_parameter_hash ||= Hash.new { |h, k| h[k] = [] }
105
+ end
106
+
95
107
  # @param pins [Enumerable<Pin::Base>]
96
108
  # @return [self]
97
109
  def merge pins
@@ -101,8 +113,8 @@ module Solargraph
101
113
  protected
102
114
 
103
115
  attr_writer :pins, :pin_select_cache, :namespace_hash, :pin_class_hash, :path_pin_hash, :include_references,
104
- :extend_references, :prepend_references, :superclass_references, :macro_method_names,
105
- :macro_method_name_pins
116
+ :extend_references, :prepend_references, :superclass_references, :factory_parameter_hash,
117
+ :macro_method_names, :macro_method_name_pins, :included_mixin_references
106
118
 
107
119
  # @return [self]
108
120
  def deep_clone
@@ -112,7 +124,7 @@ module Solargraph
112
124
  copy.macro_method_names = macro_method_names
113
125
  %i[
114
126
  namespace_hash pin_class_hash path_pin_hash include_references extend_references prepend_references
115
- superclass_references macro_method_name_pins
127
+ superclass_references macro_method_name_pins included_mixin_references
116
128
  ].each do |sym|
117
129
  copy.send("#{sym}=", send(sym).clone)
118
130
  copy.send(sym)&.transform_values!(&:clone)
@@ -145,9 +157,11 @@ module Solargraph
145
157
  map_references Pin::Reference::Prepend, prepend_references
146
158
  map_references Pin::Reference::Extend, extend_references
147
159
  map_references Pin::Reference::Superclass, superclass_references
160
+ map_references Pin::Reference::IncludedMixin, included_mixin_references
148
161
  macro_pins = pins_by_class(Pin::Method).select { |pin| pin.macros.any? }
149
162
  @macro_method_names = macro_pins.to_set(&:name)
150
163
  @macro_method_name_pins = macro_pins.to_set.classify(&:name)
164
+ map_factory_parameters
151
165
  map_overrides
152
166
  pins_by_class(Pin::Reference::TypeAlias).each { |pin| alias_hash[pin.name] = pin.return_type }
153
167
  self
@@ -198,7 +212,7 @@ module Solargraph
198
212
  end
199
213
  end
200
214
 
201
- # @param pin [Pin::Method]
215
+ # @param pin [Pin::Base]
202
216
  # @param tag [YARD::Tags::Tag]
203
217
  # @return [void]
204
218
  def redefine_return_type pin, tag
@@ -206,10 +220,20 @@ module Solargraph
206
220
  # proxy() / proxy_with_signatures() instead?
207
221
  return unless pin && tag.tag_name == 'return'
208
222
  pin.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
223
+ # Only methods carry signatures; constants and other pins have
224
+ # just the one return type set above.
225
+ return unless pin.is_a?(Pin::Method)
209
226
  pin.signatures.each do |sig|
210
227
  sig.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
211
228
  end
212
229
  end
230
+
231
+ # @return [void]
232
+ def map_factory_parameters
233
+ pins_by_class(Pin::FactoryParameter).each do |fp|
234
+ factory_parameter_hash[fp.method_path] << fp
235
+ end
236
+ end
213
237
  end
214
238
  end
215
239
  end
@@ -124,6 +124,12 @@ module Solargraph
124
124
  extend_references[fqns] || []
125
125
  end
126
126
 
127
+ # @param fqns [String]
128
+ # @return [Array<Pin::Reference::IncludedMixin>]
129
+ def get_included_mixins fqns
130
+ index.included_mixin_references[fqns] || []
131
+ end
132
+
127
133
  # @param path [String]
128
134
  # @return [Array<Solargraph::Pin::Base>]
129
135
  def get_path_pins path
@@ -261,6 +267,14 @@ module Solargraph
261
267
  ancestors.compact.uniq
262
268
  end
263
269
 
270
+ # Get factory parameters for a method pin.
271
+ #
272
+ # @param method_pin [Pin::Method]
273
+ # @return [Array<Pin::FactoryParameter>]
274
+ def factory_parameters_for_method method_pin
275
+ factory_parameter_hash[method_pin.path] || []
276
+ end
277
+
264
278
  # @param fqns [String]
265
279
  #
266
280
  # @return [Array<Solargraph::Pin::Reference>]
@@ -358,6 +372,11 @@ module Solargraph
358
372
  index.extend_references
359
373
  end
360
374
 
375
+ # @return [Hash{String => Array<Pin::FactoryParameter>}]
376
+ def factory_parameter_hash
377
+ index.factory_parameter_hash
378
+ end
379
+
361
380
  # @param name [String]
362
381
  # @return [Enumerable<Solargraph::Pin::Base>]
363
382
  def namespace_children name
@@ -15,13 +15,9 @@ module Solargraph
15
15
  autoload :Index, 'solargraph/api_map/index'
16
16
  autoload :Constants, 'solargraph/api_map/constants'
17
17
 
18
- # @return [Array<String>]
19
- attr_reader :unresolved_requires
20
-
21
- @@core_map = RbsMap::CoreMap.new
18
+ include Equality
22
19
 
23
- # @return [Array<String>]
24
- attr_reader :missing_docs
20
+ @@core_pins = Collection::Core.load
25
21
 
26
22
  # @param pins [Array<Solargraph::Pin::Base>]
27
23
  # @param loose_unions [Boolean] if true, a potential type can be
@@ -38,12 +34,6 @@ module Solargraph
38
34
  index pins
39
35
  end
40
36
 
41
- # @param out [StringIO, IO, nil] output stream for logging
42
- # @return [void]
43
- def self.reset_core out: nil
44
- @@core_map = RbsMap::CoreMap.new
45
- end
46
-
47
37
  #
48
38
  # This is a mutable object, which is cached in the Chain class -
49
39
  # if you add any fields which change the results of calls (not
@@ -86,7 +76,7 @@ module Solargraph
86
76
  @source_map_hash = {}
87
77
  conventions_environ.clear
88
78
  cache.clear
89
- store.update @@core_map.pins, pins
79
+ store.update @@core_pins, pins
90
80
  self
91
81
  end
92
82
 
@@ -106,6 +96,8 @@ module Solargraph
106
96
  # @param bench [Bench]
107
97
  # @return [self]
108
98
  def catalog bench
99
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
100
+ @workspace = bench.workspace
109
101
  @source_map_hash = bench.source_map_hash
110
102
  # @type [Array<Pin::Base>]
111
103
  iced_pins = bench.icebox.flat_map(&:pins)
@@ -114,24 +106,37 @@ module Solargraph
114
106
  source_map_hash.each_value do |map|
115
107
  conventions_environ.merge map.conventions_environ
116
108
  end
117
- unresolved_requires = (bench.external_requires + conventions_environ.requires + bench.workspace.config.required).to_a.compact.uniq
118
- recreate_docmap = @unresolved_requires != unresolved_requires ||
119
- # @sg-ignore Unresolved call to rbs_collection_path on Solargraph::Workspace, nil
120
- workspace.rbs_collection_path != bench.workspace.rbs_collection_path ||
121
- @doc_map.uncached_gemspecs.any?
122
-
123
- if recreate_docmap
124
- @doc_map = DocMap.new(unresolved_requires, bench.workspace, out: nil) # @todo Implement gem preferences
125
- @unresolved_requires = @doc_map.unresolved_requires
109
+ addon = Plugin::Addon.new
110
+ Plugin.registry.each do |plugin|
111
+ panel ||= Plugin::Panel.new(source_maps: bench.source_maps, live_map: bench.live_map, gem_names: external.configured_gem_names)
112
+ added = plugin.new(panel).addon
113
+ addon.gem_names.concat added.gem_names
114
+ addon.pins.concat added.pins
115
+ rescue StandardError => e
116
+ Solargraph.logger.warn "#{plugin} failed - [#{e.class}] #{e.message}"
126
117
  end
127
- start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
128
- Solargraph.logger.info 'Cataloging ApiMap started'
129
- @cache.clear if store.update(@@core_map.pins, @doc_map.pins, conventions_environ.pins, iced_pins, live_pins) { process_macros }
130
- @missing_docs = [] # @todo Implement missing docs
118
+
119
+ # @todo Determine what needs to be sent to global conventions
120
+ conventions_environ.merge Convention.for_global(nil)
121
+ external_changed = external.update(bench.external_requires.to_a + conventions_environ.requires, addon.gem_names)
122
+ store_changed = store.update(@@core_pins, external.pins.clone, conventions_environ.pins, addon.pins, iced_pins, live_pins) { process_macros }
123
+ @cache.clear if external_changed || store_changed
131
124
  Solargraph.logger.info "Cataloging ApiMap finished in #{Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time} seconds"
132
125
  self
133
126
  end
134
127
 
128
+ def external
129
+ @external ||= External.new(workspace&.directory, [])
130
+ end
131
+
132
+ def unresolved_requires
133
+ external.unresolved_requires
134
+ end
135
+
136
+ def unloaded_gems
137
+ external.unloaded_gems
138
+ end
139
+
135
140
  # @return [Array<Pin::Base>]
136
141
  def process_macros
137
142
  macro_pins = []
@@ -144,45 +149,23 @@ module Solargraph
144
149
  method_candidates.each do |node|
145
150
  closure = source_map.locate_closure_pin(node.location.line, node.location.column)
146
151
  chain = Solargraph::Parser::ParserGem::NodeChainer.chain(node)
147
- if node.children[0].nil? && store.macro_method_name_pins.key?(node.children[1].to_s)
148
- match = store.macro_method_name_pins[node.children[1].to_s].find do |pin|
149
- get_complex_type_methods(closure.return_type).include?(pin)
150
- end
151
- if match
152
- match.macros.each do |macro|
153
- macro_pins.concat macro.generate_pins_from(chain, match, source_map)
154
- end
155
- next
156
- end
152
+ next unless node.children[0].nil? && store.macro_method_name_pins.key?(node.children[1].to_s)
153
+ match = store.macro_method_name_pins[node.children[1].to_s].find do |pin|
154
+ get_complex_type_methods(closure.return_type).include?(pin)
155
+ end
156
+ next unless match
157
+ match.macros.each do |macro|
158
+ macro_pins.concat macro.generate_pins_from(chain, match, source_map)
157
159
  end
160
+ next
158
161
  end
159
162
  end
160
163
  macro_pins
161
164
  end
162
165
 
163
- # @return [DocMap]
164
- def doc_map
165
- @doc_map ||= DocMap.new([], Workspace.new('.'))
166
- end
167
-
168
- # @return [::Array<Gem::Specification>]
169
- def uncached_gemspecs
170
- doc_map.uncached_gemspecs || []
171
- end
172
-
173
- # @return [::Array<Gem::Specification>]
174
- def uncached_rbs_collection_gemspecs
175
- @doc_map.uncached_rbs_collection_gemspecs
176
- end
177
-
178
- # @return [::Array<Gem::Specification>]
179
- def uncached_yard_gemspecs
180
- @doc_map.uncached_yard_gemspecs
181
- end
182
-
183
166
  # @return [Enumerable<Pin::Base>]
184
167
  def core_pins
185
- @@core_map.pins
168
+ @@core_pins
186
169
  end
187
170
 
188
171
  # @param name [String, nil]
@@ -237,21 +220,6 @@ module Solargraph
237
220
  api_map
238
221
  end
239
222
 
240
- # @param out [StringIO, IO, nil]
241
- # @param rebuild [Boolean] whether to rebuild the pins even if they are cached
242
- # @return [void]
243
- def cache_all_for_doc_map! out: $stderr, rebuild: false
244
- doc_map.cache_all!(out, rebuild: rebuild)
245
- end
246
-
247
- # @param gemspec [Gem::Specification]
248
- # @param rebuild [Boolean]
249
- # @param out [StringIO, IO, nil]
250
- # @return [void]
251
- def cache_gem gemspec, rebuild: false, out: nil
252
- doc_map.cache(gemspec, rebuild: rebuild, out: out)
253
- end
254
-
255
223
  class << self
256
224
  include Logging
257
225
  end
@@ -267,12 +235,12 @@ module Solargraph
267
235
  # @return [ApiMap]
268
236
  def self.load_with_cache directory, out = $stderr, loose_unions: true
269
237
  api_map = load(directory, loose_unions: loose_unions)
270
- if api_map.uncached_gemspecs.empty?
271
- logger.info { "All gems cached for #{directory}" }
272
- return api_map
273
- end
238
+ return api_map if api_map.external.unloaded_gems.empty?
274
239
 
275
- api_map.cache_all_for_doc_map!(out: out)
240
+ api_map.external.unloaded_gems.each do |metagem|
241
+ out&.puts "Caching gem #{metagem.name} (#{metagem.cache_name})"
242
+ Collection::Gem.load metagem
243
+ end
276
244
  load(directory, loose_unions: loose_unions)
277
245
  end
278
246
 
@@ -288,6 +256,21 @@ module Solargraph
288
256
  store.pins_by_class(Pin::Keyword)
289
257
  end
290
258
 
259
+ # An array of pins based on factory parameters.
260
+ #
261
+ # @return [Enumerable<Solargraph::Pin::FactoryParameter>]
262
+ def factory_parameter_pins
263
+ store.pins_by_class(Pin::FactoryParameter)
264
+ end
265
+
266
+ # Get factory parameters for a method pin.
267
+ #
268
+ # @param method_pin [Solargraph::Pin::Method]
269
+ # @return [Array<Solargraph::Pin::FactoryParameter>]
270
+ def factory_parameters_for_method method_pin
271
+ store.factory_parameters_for_method(method_pin)
272
+ end
273
+
291
274
  # @param name [String]
292
275
  # @return [ComplexType, nil]
293
276
  def unalias name
@@ -609,6 +592,9 @@ module Solargraph
609
592
 
610
593
  # Get an array of pins that match the specified path.
611
594
  #
595
+ # @example
596
+ # api_map.get_pins_by_path('String#split')
597
+ #
612
598
  # @param path [String]
613
599
  # @return [Array<Pin::Base>]
614
600
  def get_path_pins path
@@ -755,7 +741,7 @@ module Solargraph
755
741
 
756
742
  # @return [Workspace, nil]
757
743
  def workspace
758
- doc_map.workspace
744
+ @workspace
759
745
  end
760
746
 
761
747
  # @param fq_reference_tag [String] A fully qualified whose method should be pulled in
@@ -793,6 +779,22 @@ module Solargraph
793
779
  methods
794
780
  end
795
781
 
782
+ # Mixins that +self.included+ hooks of the modules included in fqns apply
783
+ # to it, e.g. +base.extend ClassMethods+
784
+ #
785
+ # @param fqns [String]
786
+ # @param keywords [Array<::Symbol>] which of :include, :prepend and :extend
787
+ # @return [Array<String>]
788
+ def included_hook_mixins fqns, keywords
789
+ store.get_includes(fqns).flat_map do |ref|
790
+ included = dereference(ref)
791
+ next [] if included.nil?
792
+ store.get_included_mixins(ComplexType.parse(included).namespace)
793
+ .select { |mixin| keywords.include?(mixin.keyword) }
794
+ .filter_map { |mixin| dereference(mixin) }
795
+ end
796
+ end
797
+
796
798
  # @param fq_sub_tag [String]
797
799
  # @return [String, nil]
798
800
  def qualify_superclass fq_sub_tag
@@ -865,6 +867,9 @@ module Solargraph
865
867
  result.concat inner_get_methods_from_reference(in_tag, namespace_pin, rooted_type, scope, visibility, deep,
866
868
  skip, true)
867
869
  end
870
+ included_hook_mixins(fqns, %i[include prepend]).each do |mixin|
871
+ result.concat inner_get_methods(mixin, scope, visibility, deep, skip, true)
872
+ end
868
873
  rooted_sc_tag = qualify_superclass(rooted_tag)
869
874
  unless rooted_sc_tag.nil?
870
875
  result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope,
@@ -878,6 +883,9 @@ module Solargraph
878
883
  fqem = dereference(em)
879
884
  result.concat inner_get_methods(fqem, :instance, visibility, deep, skip, true) unless fqem.nil?
880
885
  end
886
+ included_hook_mixins(fqns, [:extend]).each do |mixin|
887
+ result.concat inner_get_methods(mixin, :instance, visibility, deep, skip, true)
888
+ end
881
889
  rooted_sc_tag = qualify_superclass(rooted_tag)
882
890
  unless rooted_sc_tag.nil?
883
891
  result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope,
@@ -1051,8 +1059,11 @@ module Solargraph
1051
1059
  # that this overload of 'protected' will typecheck @sg-ignore
1052
1060
  # @sg-ignore
1053
1061
  def equality_fields
1054
- [self.class, @source_map_hash, conventions_environ, @doc_map, @unresolved_requires, @missing_docs,
1055
- @loose_unions]
1062
+ # External is compared by identity and generation instead of by its pins:
1063
+ # Chain#infer hashes the ApiMap on every inference, and Array#hash would
1064
+ # walk every gem pin on each of those calls.
1065
+ [@source_map_hash, conventions_environ, @external, @external&.generation,
1066
+ @unresolved_requires, @loose_unions]
1056
1067
  end
1057
1068
  end
1058
1069
  end