solargraph 0.58.3 → 0.60.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 (238) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +12 -5
  4. data/.github/workflows/plugins.yml +54 -34
  5. data/.github/workflows/rspec.yml +18 -28
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.rubocop.yml +39 -6
  8. data/.rubocop_todo.yml +53 -966
  9. data/CHANGELOG.md +35 -0
  10. data/Gemfile +6 -1
  11. data/README.md +3 -3
  12. data/Rakefile +26 -23
  13. data/bin/solargraph +2 -1
  14. data/lib/solargraph/api_map/cache.rb +3 -3
  15. data/lib/solargraph/api_map/constants.rb +12 -3
  16. data/lib/solargraph/api_map/index.rb +42 -20
  17. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  18. data/lib/solargraph/api_map/store.rb +61 -36
  19. data/lib/solargraph/api_map.rb +192 -78
  20. data/lib/solargraph/bench.rb +2 -3
  21. data/lib/solargraph/complex_type/conformance.rb +176 -0
  22. data/lib/solargraph/complex_type/type_methods.rb +31 -18
  23. data/lib/solargraph/complex_type/unique_type.rb +225 -63
  24. data/lib/solargraph/complex_type.rb +177 -59
  25. data/lib/solargraph/convention/active_support_concern.rb +111 -111
  26. data/lib/solargraph/convention/base.rb +50 -50
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -1
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  29. data/lib/solargraph/convention/data_definition.rb +5 -2
  30. data/lib/solargraph/convention/gemfile.rb +1 -1
  31. data/lib/solargraph/convention/gemspec.rb +1 -1
  32. data/lib/solargraph/convention/rakefile.rb +1 -1
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  35. data/lib/solargraph/convention/struct_definition.rb +8 -4
  36. data/lib/solargraph/convention.rb +2 -2
  37. data/lib/solargraph/converters/dd.rb +2 -0
  38. data/lib/solargraph/converters/dl.rb +2 -0
  39. data/lib/solargraph/converters/dt.rb +2 -0
  40. data/lib/solargraph/converters/misc.rb +2 -0
  41. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  42. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  44. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  45. data/lib/solargraph/diagnostics/update_errors.rb +4 -8
  46. data/lib/solargraph/diagnostics.rb +55 -55
  47. data/lib/solargraph/doc_map.rb +39 -39
  48. data/lib/solargraph/environ.rb +52 -52
  49. data/lib/solargraph/equality.rb +4 -4
  50. data/lib/solargraph/gem_pins.rb +4 -15
  51. data/lib/solargraph/language_server/error_codes.rb +10 -10
  52. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  53. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  54. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  55. data/lib/solargraph/language_server/host/sources.rb +2 -1
  56. data/lib/solargraph/language_server/host.rb +35 -28
  57. data/lib/solargraph/language_server/message/base.rb +1 -1
  58. data/lib/solargraph/language_server/message/client/register_capability.rb +1 -3
  59. data/lib/solargraph/language_server/message/completion_item/resolve.rb +6 -8
  60. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  61. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  62. data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -7
  63. data/lib/solargraph/language_server/message/extended/download_core.rb +2 -1
  64. data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
  65. data/lib/solargraph/language_server/message/extended/search.rb +1 -1
  66. data/lib/solargraph/language_server/message/initialize.rb +20 -14
  67. data/lib/solargraph/language_server/message/initialized.rb +28 -28
  68. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  69. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  70. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +17 -10
  71. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  72. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  73. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  74. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +13 -6
  75. data/lib/solargraph/language_server/message/text_document/references.rb +17 -10
  76. data/lib/solargraph/language_server/message/text_document/rename.rb +20 -13
  77. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  78. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  79. data/lib/solargraph/language_server/message/text_document.rb +28 -28
  80. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +34 -28
  81. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +38 -30
  82. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +23 -17
  83. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  84. data/lib/solargraph/language_server/message.rb +1 -1
  85. data/lib/solargraph/language_server/progress.rb +143 -143
  86. data/lib/solargraph/language_server/request.rb +4 -2
  87. data/lib/solargraph/language_server/transport/adapter.rb +68 -68
  88. data/lib/solargraph/language_server/transport/data_reader.rb +11 -13
  89. data/lib/solargraph/language_server/uri_helpers.rb +2 -2
  90. data/lib/solargraph/language_server.rb +20 -20
  91. data/lib/solargraph/library.rb +57 -38
  92. data/lib/solargraph/location.rb +17 -14
  93. data/lib/solargraph/logging.rb +22 -4
  94. data/lib/solargraph/page.rb +1 -1
  95. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  96. data/lib/solargraph/parser/flow_sensitive_typing.rb +324 -108
  97. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  98. data/lib/solargraph/parser/node_processor.rb +8 -7
  99. data/lib/solargraph/parser/parser_gem/class_methods.rb +30 -14
  100. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -1
  101. data/lib/solargraph/parser/parser_gem/node_chainer.rb +51 -25
  102. data/lib/solargraph/parser/parser_gem/node_methods.rb +222 -72
  103. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +24 -24
  104. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  105. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  106. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  107. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -12
  108. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +36 -36
  109. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +24 -24
  110. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  111. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +9 -8
  112. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +24 -24
  113. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  114. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  115. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  116. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  117. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +64 -40
  118. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  119. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  120. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  121. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  122. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  123. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  124. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +20 -20
  125. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -1
  126. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  127. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  128. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  129. data/lib/solargraph/parser/parser_gem.rb +2 -0
  130. data/lib/solargraph/parser/region.rb +9 -3
  131. data/lib/solargraph/parser/snippet.rb +3 -1
  132. data/lib/solargraph/parser.rb +2 -0
  133. data/lib/solargraph/pin/base.rb +156 -84
  134. data/lib/solargraph/pin/base_variable.rb +273 -24
  135. data/lib/solargraph/pin/block.rb +29 -6
  136. data/lib/solargraph/pin/breakable.rb +7 -1
  137. data/lib/solargraph/pin/callable.rb +67 -23
  138. data/lib/solargraph/pin/closure.rb +7 -10
  139. data/lib/solargraph/pin/common.rb +36 -6
  140. data/lib/solargraph/pin/compound_statement.rb +55 -0
  141. data/lib/solargraph/pin/constant.rb +3 -5
  142. data/lib/solargraph/pin/conversions.rb +10 -4
  143. data/lib/solargraph/pin/delegated_method.rb +19 -8
  144. data/lib/solargraph/pin/documenting.rb +4 -2
  145. data/lib/solargraph/pin/instance_variable.rb +5 -1
  146. data/lib/solargraph/pin/keyword.rb +0 -4
  147. data/lib/solargraph/pin/local_variable.rb +15 -59
  148. data/lib/solargraph/pin/method.rb +205 -111
  149. data/lib/solargraph/pin/method_alias.rb +8 -0
  150. data/lib/solargraph/pin/namespace.rb +19 -12
  151. data/lib/solargraph/pin/parameter.rb +102 -36
  152. data/lib/solargraph/pin/proxy_type.rb +4 -1
  153. data/lib/solargraph/pin/reference/override.rb +1 -1
  154. data/lib/solargraph/pin/reference/require.rb +14 -14
  155. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  156. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  157. data/lib/solargraph/pin/reference.rb +20 -0
  158. data/lib/solargraph/pin/search.rb +8 -7
  159. data/lib/solargraph/pin/signature.rb +15 -12
  160. data/lib/solargraph/pin/singleton.rb +11 -11
  161. data/lib/solargraph/pin/symbol.rb +2 -1
  162. data/lib/solargraph/pin/until.rb +2 -4
  163. data/lib/solargraph/pin/while.rb +2 -4
  164. data/lib/solargraph/pin.rb +2 -0
  165. data/lib/solargraph/pin_cache.rb +22 -19
  166. data/lib/solargraph/position.rb +17 -10
  167. data/lib/solargraph/range.rb +16 -15
  168. data/lib/solargraph/rbs_map/conversions.rb +278 -191
  169. data/lib/solargraph/rbs_map/core_fills.rb +18 -11
  170. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  171. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  172. data/lib/solargraph/rbs_map.rb +76 -32
  173. data/lib/solargraph/rbs_translator.rb +206 -0
  174. data/lib/solargraph/server_methods.rb +1 -1
  175. data/lib/solargraph/shell.rb +330 -71
  176. data/lib/solargraph/source/chain/array.rb +3 -12
  177. data/lib/solargraph/source/chain/block_symbol.rb +13 -13
  178. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  179. data/lib/solargraph/source/chain/call.rb +91 -119
  180. data/lib/solargraph/source/chain/class_variable.rb +1 -1
  181. data/lib/solargraph/source/chain/constant.rb +5 -1
  182. data/lib/solargraph/source/chain/global_variable.rb +1 -1
  183. data/lib/solargraph/source/chain/hash.rb +8 -5
  184. data/lib/solargraph/source/chain/head.rb +19 -19
  185. data/lib/solargraph/source/chain/if.rb +12 -10
  186. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  187. data/lib/solargraph/source/chain/link.rb +12 -22
  188. data/lib/solargraph/source/chain/literal.rb +22 -15
  189. data/lib/solargraph/source/chain/or.rb +10 -4
  190. data/lib/solargraph/source/chain/q_call.rb +2 -0
  191. data/lib/solargraph/source/chain/variable.rb +3 -1
  192. data/lib/solargraph/source/chain/z_super.rb +1 -3
  193. data/lib/solargraph/source/chain.rb +51 -38
  194. data/lib/solargraph/source/change.rb +12 -5
  195. data/lib/solargraph/source/cursor.rb +33 -18
  196. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  197. data/lib/solargraph/source/source_chainer.rb +56 -32
  198. data/lib/solargraph/source/updater.rb +5 -1
  199. data/lib/solargraph/source.rb +59 -35
  200. data/lib/solargraph/source_map/clip.rb +54 -30
  201. data/lib/solargraph/source_map/data.rb +4 -1
  202. data/lib/solargraph/source_map/mapper.rb +28 -131
  203. data/lib/solargraph/source_map.rb +35 -9
  204. data/lib/solargraph/type_checker/problem.rb +3 -1
  205. data/lib/solargraph/type_checker/rules.rb +81 -8
  206. data/lib/solargraph/type_checker.rb +196 -122
  207. data/lib/solargraph/version.rb +19 -1
  208. data/lib/solargraph/workspace/config.rb +14 -11
  209. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  210. data/lib/solargraph/workspace/require_paths.rb +1 -0
  211. data/lib/solargraph/workspace.rb +50 -28
  212. data/lib/solargraph/yard_map/cache.rb +25 -25
  213. data/lib/solargraph/yard_map/directives/attribute_directive.rb +65 -0
  214. data/lib/solargraph/yard_map/directives/domain_directive.rb +30 -0
  215. data/lib/solargraph/yard_map/directives/method_directive.rb +51 -0
  216. data/lib/solargraph/yard_map/directives/override_directive.rb +30 -0
  217. data/lib/solargraph/yard_map/directives/parse_directive.rb +53 -0
  218. data/lib/solargraph/yard_map/directives/visibility_directive.rb +70 -0
  219. data/lib/solargraph/yard_map/directives.rb +35 -0
  220. data/lib/solargraph/yard_map/helpers.rb +8 -3
  221. data/lib/solargraph/yard_map/macro.rb +113 -0
  222. data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
  223. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  224. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  225. data/lib/solargraph/yard_map/mapper.rb +31 -8
  226. data/lib/solargraph/yard_map.rb +19 -18
  227. data/lib/solargraph/yard_tags.rb +2 -2
  228. data/lib/solargraph/yardoc.rb +7 -4
  229. data/lib/solargraph.rb +34 -10
  230. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  231. data/rbs/shims/ast/0/node.rbs +1 -1
  232. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  233. data/solargraph.gemspec +38 -35
  234. metadata +64 -42
  235. data/lib/solargraph/type_checker/checks.rb +0 -124
  236. data/lib/solargraph/type_checker/param_def.rb +0 -37
  237. data/lib/solargraph/yard_map/to_method.rb +0 -89
  238. data/rbs/fills/tuple/tuple.rbs +0 -149
@@ -19,7 +19,7 @@ module Solargraph
19
19
  Solargraph::Pin::Method.new(name: 'class', scope: :instance,
20
20
  closure: Solargraph::Pin::Namespace.new(name: 'Object', source: :core_fill), comments: '@return [::Class<self>]',
21
21
  source: :core_fill)
22
- ]
22
+ ].freeze
23
23
 
24
24
  OVERRIDES = [
25
25
  Override.from_comment('BasicObject#instance_eval', '@yieldreceiver [self]',
@@ -38,43 +38,50 @@ module Solargraph
38
38
  source: :core_fill),
39
39
  # RBS does not define Class with a generic, so all calls to
40
40
  # generic() return an 'untyped'. We can do better:
41
- Override.method_return('Class#allocate', 'self', source: :core_fill),
42
- ]
41
+ Override.method_return('Class#allocate', 'self', source: :core_fill)
42
+ ].freeze
43
43
 
44
44
  # @todo I don't see any direct link in RBS to build this from -
45
45
  # presumably RBS is using duck typing to match interfaces
46
46
  # against concrete classes
47
47
  INCLUDES = [
48
48
  Solargraph::Pin::Reference::Include.new(name: '_ToAry',
49
- closure: Solargraph::Pin::Namespace.new(name: 'Array', source: :core_fill),
49
+ closure: Solargraph::Pin::Namespace.new(name: 'Array',
50
+ source: :core_fill),
50
51
  generic_values: ['generic<Elem>'],
51
52
  source: :core_fill),
52
53
  Solargraph::Pin::Reference::Include.new(name: '_ToAry',
53
- closure: Solargraph::Pin::Namespace.new(name: 'Set', source: :core_fill),
54
+ closure: Solargraph::Pin::Namespace.new(name: 'Set',
55
+ source: :core_fill),
54
56
  generic_values: ['generic<Elem>'],
55
57
  source: :core_fill),
56
58
  Solargraph::Pin::Reference::Include.new(name: '_Each',
57
- closure: Solargraph::Pin::Namespace.new(name: 'Array', source: :core_fill),
59
+ closure: Solargraph::Pin::Namespace.new(name: 'Array',
60
+ source: :core_fill),
58
61
  generic_values: ['generic<Elem>'],
59
62
  source: :core_fill),
60
63
  Solargraph::Pin::Reference::Include.new(name: '_Each',
61
- closure: Solargraph::Pin::Namespace.new(name: 'Set', source: :core_fill),
64
+ closure: Solargraph::Pin::Namespace.new(name: 'Set',
65
+ source: :core_fill),
62
66
  generic_values: ['generic<Elem>'],
63
67
  source: :core_fill),
64
68
  Solargraph::Pin::Reference::Include.new(name: '_ToS',
65
- closure: Solargraph::Pin::Namespace.new(name: 'Object', source: :core_fill),
69
+ closure: Solargraph::Pin::Namespace.new(name: 'Object',
70
+ source: :core_fill),
66
71
  source: :core_fill),
67
72
  Solargraph::Pin::Reference::Include.new(name: '_ToS',
68
- closure: Solargraph::Pin::Namespace.new(name: 'String', source: :core_fill),
73
+ closure: Solargraph::Pin::Namespace.new(name: 'String',
74
+ source: :core_fill),
69
75
  source: :core_fill)
70
- ]
76
+ ].freeze
71
77
 
72
78
  # HACK: Add Errno exception classes
73
79
  errno = Solargraph::Pin::Namespace.new(name: 'Errno', source: :core_fill)
74
80
  errnos = []
75
81
  Errno.constants.each do |const|
76
82
  errnos.push Solargraph::Pin::Namespace.new(type: :class, name: const.to_s, closure: errno, source: :core_fill)
77
- errnos.push Solargraph::Pin::Reference::Superclass.new(closure: errnos.last, name: 'SystemCallError', source: :core_fill)
83
+ errnos.push Solargraph::Pin::Reference::Superclass.new(closure: errnos.last, name: 'SystemCallError',
84
+ source: :core_fill)
78
85
  end
79
86
  ERRNOS = errnos
80
87
 
@@ -15,31 +15,38 @@ module Solargraph
15
15
 
16
16
  def initialize; end
17
17
 
18
+ # @param out [IO, nil] output stream for logging
18
19
  # @return [Enumerable<Pin::Base>]
19
- def pins
20
+ def pins out: $stderr
20
21
  return @pins if @pins
22
+ @pins = cache_core(out: out)
23
+ end
21
24
 
22
- @pins = []
25
+ # @param out [StringIO, IO, nil] output stream for logging
26
+ # @return [Array<Pin::Base>]
27
+ def cache_core out: $stderr
28
+ new_pins = []
23
29
  cache = PinCache.deserialize_core
24
- if cache
25
- @pins.replace cache
26
- else
27
- @pins.concat conversions.pins
30
+ return cache if cache
31
+ new_pins.concat conversions.pins
32
+
33
+ # Avoid RBS::DuplicatedDeclarationError by loading in a different EnvironmentLoader
34
+ fill_loader = RBS::EnvironmentLoader.new(core_root: nil, repository: RBS::Repository.new(no_stdlib: false))
35
+ fill_loader.add(path: Pathname(FILLS_DIRECTORY))
36
+ out&.puts 'Caching RBS pins for Ruby core'
37
+ fill_conversions = Conversions.new(loader: fill_loader)
38
+ new_pins.concat fill_conversions.pins
28
39
 
29
- # Avoid RBS::DuplicatedDeclarationError by loading in a different EnvironmentLoader
30
- fill_loader = RBS::EnvironmentLoader.new(core_root: nil, repository: RBS::Repository.new(no_stdlib: false))
31
- fill_loader.add(path: Pathname(FILLS_DIRECTORY))
32
- fill_conversions = Conversions.new(loader: fill_loader)
33
- @pins.concat fill_conversions.pins
40
+ # add some overrides
41
+ new_pins.concat RbsMap::CoreFills::ALL
34
42
 
35
- @pins.concat RbsMap::CoreFills::ALL
43
+ # process overrides, then remove any which couldn't be resolved
44
+ processed = ApiMap::Store.new(new_pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
45
+ new_pins.replace processed
36
46
 
37
- processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
38
- @pins.replace processed
47
+ PinCache.serialize_core new_pins
39
48
 
40
- PinCache.serialize_core @pins
41
- end
42
- @pins
49
+ new_pins
43
50
  end
44
51
 
45
52
  private
@@ -12,19 +12,22 @@ module Solargraph
12
12
  # @type [Hash{String => RbsMap}]
13
13
  @stdlib_maps_hash = {}
14
14
 
15
+ # @param rebuild [Boolean] build pins regardless of whether we
16
+ # have cached them already
15
17
  # @param library [String]
16
- def initialize library
18
+ # @param out [StringIO, IO, nil] where to log messages
19
+ def initialize library, rebuild: false, out: $stderr
17
20
  cached_pins = PinCache.deserialize_stdlib_require library
18
- if cached_pins
21
+ if cached_pins && !rebuild
19
22
  @pins = cached_pins
20
23
  @resolved = true
21
24
  @loaded = true
22
25
  logger.debug { "Deserialized #{cached_pins.length} cached pins for stdlib require #{library.inspect}" }
23
- else
24
- super
26
+ elsif self.class.source.has? library, nil
27
+ super(library, out: out)
25
28
  unless resolved?
26
29
  @pins = []
27
- logger.info { "Could not resolve #{library.inspect}" }
30
+ logger.debug { "StdlibMap could not resolve #{library.inspect}" }
28
31
  return
29
32
  end
30
33
  generated_pins = pins
@@ -33,6 +36,31 @@ module Solargraph
33
36
  end
34
37
  end
35
38
 
39
+ # @return [RBS::Collection::Sources::Stdlib]
40
+ def self.source
41
+ @source ||= RBS::Collection::Sources::Stdlib.instance
42
+ end
43
+
44
+ # @param name [String]
45
+ # @param version [String, nil]
46
+ # @return [Array<Hash{String => String}>, nil]
47
+ def self.stdlib_dependencies name, version = nil
48
+ if source.has?(name, version)
49
+ # @sg-ignore we are relying on undocumented behavior where
50
+ # passing version=nil gives the latest version it has
51
+ source.dependencies_of(name, version)
52
+ else
53
+ []
54
+ end
55
+ end
56
+
57
+ def resolve_dependencies?
58
+ # there are 'virtual' dependencies for stdlib gems in RBS that
59
+ # aren't represented in the actual gemspecs that we'd
60
+ # otherwise use
61
+ true
62
+ end
63
+
36
64
  # @param library [String]
37
65
  # @return [StdlibMap]
38
66
  def self.load library
@@ -16,17 +16,14 @@ module Solargraph
16
16
  # @type [Hash{String => RbsMap}]
17
17
  @@rbs_maps_hash = {}
18
18
 
19
- attr_reader :library
20
-
21
- attr_reader :rbs_collection_paths
22
-
23
- attr_reader :rbs_collection_config_path
19
+ attr_reader :library, :rbs_collection_paths, :rbs_collection_config_path
24
20
 
25
21
  # @param library [String]
26
22
  # @param version [String, nil]
27
23
  # @param rbs_collection_config_path [String, Pathname, nil]
28
24
  # @param rbs_collection_paths [Array<Pathname, String>]
29
- def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: []
25
+ # @param out [StringIO, IO, nil] where to log messages
26
+ def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: [], out: $stderr
30
27
  if rbs_collection_config_path.nil? && !rbs_collection_paths.empty?
31
28
  raise 'Please provide rbs_collection_config_path if you provide rbs_collection_paths'
32
29
  end
@@ -37,6 +34,28 @@ module Solargraph
37
34
  add_library loader, library, version
38
35
  end
39
36
 
37
+ CACHE_KEY_GEM_EXPORT = 'gem-export'
38
+ CACHE_KEY_UNRESOLVED = 'unresolved'
39
+ CACHE_KEY_STDLIB = 'stdlib'
40
+ CACHE_KEY_LOCAL = 'local'
41
+
42
+ # @param cache_key [String, nil]
43
+ # @return [String, nil] a description of the source of the RBS info
44
+ def self.rbs_source_desc cache_key
45
+ case cache_key
46
+ when CACHE_KEY_GEM_EXPORT
47
+ 'RBS gem export'
48
+ when CACHE_KEY_UNRESOLVED
49
+ nil
50
+ when CACHE_KEY_STDLIB
51
+ 'RBS standard library'
52
+ when CACHE_KEY_LOCAL
53
+ 'local RBS shims'
54
+ else
55
+ 'RBS collection'
56
+ end
57
+ end
58
+
40
59
  # @return [RBS::EnvironmentLoader]
41
60
  def loader
42
61
  @loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
@@ -47,10 +66,15 @@ module Solargraph
47
66
  # updated upstream for the same library and version. May change
48
67
  # if the config for where information comes form changes.
49
68
  def cache_key
50
- @hextdigest ||= begin
69
+ return CACHE_KEY_UNRESOLVED unless resolved?
70
+
71
+ @cache_key ||= begin
51
72
  # @type [String, nil]
52
73
  data = nil
74
+ # @type gem_config [nil, Hash{String => Hash{String => String}}]
75
+ gem_config = nil
53
76
  if rbs_collection_config_path
77
+ # @sg-ignore rbs_collection_config_path is not nil here
54
78
  lockfile_path = RBS::Collection::Config.to_lockfile_path(Pathname.new(rbs_collection_config_path))
55
79
  if lockfile_path.exist?
56
80
  collection_config = RBS::Collection::Config.from_path lockfile_path
@@ -58,16 +82,21 @@ module Solargraph
58
82
  data = gem_config&.to_s
59
83
  end
60
84
  end
61
- if data.nil? || data.empty?
62
- if resolved?
63
- # definitely came from the gem itself and not elsewhere -
64
- # only one version per gem
65
- 'gem-export'
85
+ if gem_config.nil?
86
+ CACHE_KEY_STDLIB
87
+ else
88
+ # @type [String]
89
+ source = gem_config.dig('source', 'type')
90
+ case source
91
+ when 'rubygems'
92
+ CACHE_KEY_GEM_EXPORT
93
+ when 'local'
94
+ CACHE_KEY_LOCAL
95
+ when 'stdlib'
96
+ CACHE_KEY_STDLIB
66
97
  else
67
- 'unresolved'
98
+ Digest::SHA1.hexdigest(data || '')
68
99
  end
69
- else
70
- Digest::SHA1.hexdigest(data)
71
100
  end
72
101
  end
73
102
  end
@@ -77,6 +106,10 @@ module Solargraph
77
106
  # @param rbs_collection_config_path [String, Pathname, nil]
78
107
  # @return [RbsMap]
79
108
  def self.from_gemspec gemspec, rbs_collection_path, rbs_collection_config_path
109
+ # prefers stdlib RBS if available
110
+ rbs_map = RbsMap::StdlibMap.new(gemspec.name)
111
+ return rbs_map if rbs_map.resolved?
112
+
80
113
  rbs_map = RbsMap.new(gemspec.name, gemspec.version,
81
114
  rbs_collection_paths: [rbs_collection_path].compact,
82
115
  rbs_collection_config_path: rbs_collection_config_path)
@@ -88,18 +121,26 @@ module Solargraph
88
121
  rbs_collection_config_path: rbs_collection_config_path)
89
122
  end
90
123
 
124
+ # @param out [IO, nil] where to log messages
91
125
  # @return [Array<Pin::Base>]
92
- def pins
93
- @pins ||= resolved? ? conversions.pins : []
126
+ def pins out: $stderr
127
+ @pins ||= if resolved?
128
+ conversions.pins
129
+ else
130
+ []
131
+ end
94
132
  end
95
133
 
96
134
  # @generic T
97
135
  # @param path [String]
98
136
  # @param klass [Class<generic<T>>]
137
+ #
138
+ # @sg-ignore Need to be able to resolve generics based on a
139
+ # Class<generic<T>> param
99
140
  # @return [generic<T>, nil]
100
141
  def path_pin path, klass = Pin::Base
101
142
  pin = pins.find { |p| p.path == path }
102
- pin if pin&.is_a?(klass)
143
+ pin if pin.is_a?(klass)
103
144
  end
104
145
 
105
146
  # @param path [String]
@@ -130,29 +171,32 @@ module Solargraph
130
171
 
131
172
  private
132
173
 
133
- # @return [RBS::EnvironmentLoader]
134
- def loader
135
- @loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
136
- end
137
-
138
174
  # @return [Conversions]
139
175
  def conversions
140
176
  @conversions ||= Conversions.new(loader: loader)
141
177
  end
142
178
 
179
+ def resolve_dependencies?
180
+ # we need to resolve dependencies via gemfile.lock manually for
181
+ # YARD regardless, so use same mechanism here so we don't
182
+ # duplicate work generating pins from dependencies
183
+ false
184
+ end
185
+
143
186
  # @param loader [RBS::EnvironmentLoader]
144
187
  # @param library [String]
145
- # @param version [String, nil]
188
+ # @param version [String, nil] the version of the library to load, or nil for any
189
+ # @param out [StringIO, IO, nil] where to log messages
146
190
  # @return [Boolean] true if adding the library succeeded
147
- def add_library loader, library, version
191
+ def add_library loader, library, version, out: $stderr
148
192
  @resolved = if loader.has_library?(library: library, version: version)
149
- loader.add library: library, version: version
150
- logger.debug { "#{short_name} successfully loaded library #{library}:#{version}" }
151
- true
152
- else
153
- logger.info { "#{short_name} did not find data for library #{library}:#{version}" }
154
- false
155
- end
193
+ loader.add library: library, version: version, resolve_dependencies: resolve_dependencies?
194
+ logger.debug { "#{short_name} successfully loaded library #{library}:#{version}" }
195
+ true
196
+ else
197
+ logger.info { "#{short_name} did not find data for library #{library}:#{version}" }
198
+ false
199
+ end
156
200
  end
157
201
 
158
202
  # @return [String]
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ # Convert RBS types to complex types and pins.
5
+ #
6
+ module RbsTranslator
7
+ RBS_TO_YARD_TYPE = {
8
+ 'bool' => 'Boolean',
9
+ 'string' => 'String',
10
+ 'int' => 'Integer',
11
+ 'untyped' => '',
12
+ 'NilClass' => 'nil'
13
+ }
14
+
15
+ # @param type [RBS::Types::Bases::Base]
16
+ # @return [ComplexType]
17
+ def self.to_complex_type(type)
18
+ tag = type_to_tag(type)
19
+ ComplexType.try_parse(tag).force_rooted
20
+ end
21
+
22
+ # @param param_type [RBS::Types::Function::Param]
23
+ # @param name [String]
24
+ # @param decl [Symbol]
25
+ # @param closure [Pin::Closure]
26
+ # @return [Pin::Parameter]
27
+ def self.to_parameter_pin(param_type, name, decl, closure)
28
+ return_type = if decl == :restarg
29
+ ComplexType.parse('Array')
30
+ elsif decl == :kwrestarg
31
+ ComplexType.parse('Hash{Symbol => Object}')
32
+ else
33
+ RbsTranslator.to_complex_type(param_type.type)
34
+ end
35
+ Solargraph::Pin::Parameter.new(decl: decl, name: name, closure: closure, return_type: return_type, source: :rbs, type_location: to_sg_location(param_type.location) || closure.type_location)
36
+ end
37
+
38
+ # @param method_type [RBS::MethodType]
39
+ # @param closure [Pin::Closure]
40
+ # @param parameter_names [Array<String>]
41
+ # @return [Array<Pin::Parameter>]
42
+ def self.to_parameter_pins method_type, closure, parameter_names = []
43
+ if defined?(RBS::Types::UntypedFunction) && method_type.type.is_a?(RBS::Types::UntypedFunction)
44
+ return [
45
+ Solargraph::Pin::Parameter.new(decl: :restarg, name: 'arg', closure: closure, source: :rbs)
46
+ ]
47
+ end
48
+
49
+ arg_num = 0
50
+ params = []
51
+ method_type.type.required_positionals.each do |param|
52
+ params.push RbsTranslator.to_parameter_pin(param, param.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :arg, closure)
53
+ arg_num += 1
54
+ end
55
+ method_type.type.optional_positionals.each do |param|
56
+ params.push RbsTranslator.to_parameter_pin(param, param.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :optarg, closure)
57
+ arg_num += 1
58
+ end
59
+ if method_type.type.rest_positionals
60
+ params.push RbsTranslator.to_parameter_pin(method_type.type.rest_positionals, method_type.type.rest_positionals.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :restarg, closure)
61
+ arg_num += 1
62
+ end
63
+ method_type.type.required_keywords.each do |param|
64
+ params.push RbsTranslator.to_parameter_pin(param.last, param.first.to_s, :kwarg, closure)
65
+ arg_num += 1
66
+ end
67
+ method_type.type.optional_keywords.each do |param|
68
+ params.push RbsTranslator.to_parameter_pin(param.last, param.first.to_s, :kwoptarg, closure)
69
+ arg_num += 1
70
+ end
71
+ if method_type.type.rest_keywords
72
+ params.push RbsTranslator.to_parameter_pin(method_type.type.rest_keywords, method_type.type.rest_keywords.name&.to_s || parameter_names[arg_num] || "arg_#{arg_num}", :kwrestarg, closure)
73
+ end
74
+ params
75
+ end
76
+
77
+ # @param method_type [RBS::MethodType]
78
+ # @param closure [Pin::Closure]
79
+ # @param parameter_names [Array<String>]
80
+ # @return [Pin::Signature]
81
+ def self.to_signature method_type, closure, parameter_names = []
82
+ # There may be edge cases here around different signatures
83
+ # having different type params / orders - we may need to match
84
+ # this data model and have generics live in signatures to
85
+ # handle those correctly
86
+ generics = method_type.type_params.map(&:name).map(&:to_s).uniq
87
+ parameters = to_parameter_pins(method_type, closure, parameter_names)
88
+ return_type = to_complex_type(method_type.type.return_type)
89
+ block = if method_type.block
90
+ block_parameters = to_parameter_pins(method_type.block, closure)
91
+ block_return_type = to_complex_type(method_type.block.type.return_type)
92
+ Pin::Signature.new(generics: generics, parameters: block_parameters, return_type: block_return_type, source: :rbs, type_location: closure.location, closure: closure)
93
+ end
94
+ Pin::Signature.new(generics: generics, parameters: parameters, return_type: return_type, block: block, source: :rbs, type_location: closure.location, closure: closure)
95
+ end
96
+
97
+ # @param type_name [RBS::TypeName]
98
+ # @param type_args [Enumerable<RBS::Types::Bases::Base>]
99
+ # @return [ComplexType::UniqueType]
100
+ def self.build_unique_type(type_name, type_args = [])
101
+ base = RBS_TO_YARD_TYPE[type_name.relative!.to_s] || type_name.relative!.to_s
102
+ params = type_args.map do |a|
103
+ RbsTranslator.to_complex_type(a)
104
+ end
105
+ if base == 'Hash' && params.length == 2
106
+ ComplexType::UniqueType.new(base, [params.first], [params.last], rooted: true, parameters_type: :hash)
107
+ else
108
+ ComplexType::UniqueType.new(base, [], params.reject(&:undefined?), rooted: true, parameters_type: :list)
109
+ end
110
+ end
111
+
112
+ # @param location [RBS::Location, nil]
113
+ # @return [Solargraph::Location, nil]
114
+ def self.to_sg_location(location)
115
+ return nil if location&.name.nil?
116
+
117
+ start_pos = Position.new(location.start_line - 1, location.start_column)
118
+ end_pos = Position.new(location.end_line - 1, location.end_column)
119
+ range = Range.new(start_pos, end_pos)
120
+ Location.new(location.name.to_s, range)
121
+ end
122
+
123
+ class << self
124
+ private
125
+
126
+ # @param type [RBS::Types::Bases::Base]
127
+ # @return [String]
128
+ def type_to_tag type
129
+ case type
130
+ when RBS::Types::Optional
131
+ "#{type_to_tag(type.type)}, nil"
132
+ when RBS::Types::Bases::Bool
133
+ 'Boolean'
134
+ when RBS::Types::Tuple
135
+ "Array(#{type.types.map { |t| type_to_tag(t) }.join(', ')})"
136
+ when RBS::Types::Literal
137
+ type.literal.inspect
138
+ when RBS::Types::Union
139
+ type.types.map { |t| type_to_tag(t) }.join(', ')
140
+ when RBS::Types::Record
141
+ # @todo Better record support
142
+ 'Hash'
143
+ when RBS::Types::Bases::Nil
144
+ 'nil'
145
+ when RBS::Types::Bases::Void
146
+ 'void'
147
+ when RBS::Types::Variable
148
+ "#{Solargraph::ComplexType::GENERIC_TAG_NAME}<#{type.name}>"
149
+ when RBS::Types::Bases::Self, RBS::Types::Bases::Instance
150
+ 'self'
151
+ when RBS::Types::Bases::Top
152
+ # `Top` is the most super superclass
153
+ 'BasicObject'
154
+ when RBS::Types::Intersection
155
+ type.types.map { |member| type_to_tag(member) }.join(', ')
156
+ when RBS::Types::Proc
157
+ 'Proc'
158
+ when RBS::Types::ClassInstance, RBS::Types::Alias, RBS::Types::Interface
159
+ # `Alias` is a top-level type alias, e.g., 'bool' in "type bool = true | false"
160
+ # @todo ensure these get resolved after processing all aliases
161
+ # @todo handle recursive aliases
162
+ #
163
+ # `Interface represents a mix-in module which can be considered a
164
+ # subtype of a consumer of it
165
+ #
166
+ type_tag(type.name, type.args)
167
+ when RBS::Types::ClassSingleton
168
+ # e.g., singleton(String)
169
+ type_tag(type.name)
170
+ when RBS::Types::Bases::Any, RBS::Types::Bases::Bottom
171
+ # `Bottom`` is used in contexts where nothing will ever return
172
+ # - e.g., it could be the return type of 'exit()' or 'raise'
173
+ # @todo define a specific bottom type and use it to
174
+ # determine dead code
175
+ #
176
+ 'undefined'
177
+ else
178
+ Solargraph.logger.warn "Unrecognized RBS type: #{type.class} at #{type.location}"
179
+ 'undefined'
180
+ end
181
+ end
182
+
183
+ # @param type_name [RBS::TypeName]
184
+ # @param type_args [Enumerable<RBS::Types::Bases::Base>]
185
+ # @return [String]
186
+ def type_tag(type_name, type_args = [])
187
+ build_type(type_name, type_args).tags
188
+ end
189
+
190
+ # @param type_name [RBS::TypeName]
191
+ # @param type_args [Enumerable<RBS::Types::Bases::Base>]
192
+ # @return [ComplexType::UniqueType]
193
+ def build_type(type_name, type_args = [])
194
+ base = RBS_TO_YARD_TYPE[type_name.relative!.to_s] || type_name.relative!.to_s
195
+ params = type_args.map { |a| type_to_tag(a) }.map do |t|
196
+ ComplexType.try_parse(t)
197
+ end
198
+ if base == 'Hash' && params.length == 2
199
+ ComplexType::UniqueType.new(base, [params.first], [params.last], rooted: true, parameters_type: :hash)
200
+ else
201
+ ComplexType::UniqueType.new(base, [], params.reject(&:undefined?), rooted: true, parameters_type: :list)
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
@@ -7,7 +7,7 @@ module Solargraph
7
7
  # @return [Integer]
8
8
  def available_port
9
9
  socket = Socket.new(:INET, :STREAM, 0)
10
- socket.bind(Addrinfo.tcp("127.0.0.1", 0))
10
+ socket.bind(Addrinfo.tcp('127.0.0.1', 0))
11
11
  port = socket.local_address.ip_port
12
12
  socket.close
13
13
  port