solargraph 0.50.0 → 0.53.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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/plugins.yml +40 -0
  3. data/.github/workflows/rspec.yml +4 -8
  4. data/.github/workflows/typecheck.yml +34 -0
  5. data/.yardopts +2 -2
  6. data/CHANGELOG.md +81 -3
  7. data/README.md +13 -16
  8. data/SPONSORS.md +2 -9
  9. data/lib/solargraph/api_map/cache.rb +60 -20
  10. data/lib/solargraph/api_map/store.rb +47 -11
  11. data/lib/solargraph/api_map.rb +161 -95
  12. data/lib/solargraph/bench.rb +2 -2
  13. data/lib/solargraph/cache.rb +30 -6
  14. data/lib/solargraph/complex_type/type_methods.rb +54 -9
  15. data/lib/solargraph/complex_type/unique_type.rb +154 -57
  16. data/lib/solargraph/complex_type.rb +91 -17
  17. data/lib/solargraph/convention.rb +0 -3
  18. data/lib/solargraph/converters/dd.rb +5 -0
  19. data/lib/solargraph/converters/dl.rb +3 -0
  20. data/lib/solargraph/converters/dt.rb +3 -0
  21. data/lib/solargraph/diagnostics/rubocop.rb +8 -7
  22. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
  23. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  24. data/lib/solargraph/diagnostics.rb +2 -2
  25. data/lib/solargraph/doc_map.rb +146 -0
  26. data/lib/solargraph/gem_pins.rb +64 -0
  27. data/lib/solargraph/language_server/host/cataloger.rb +1 -0
  28. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  29. data/lib/solargraph/language_server/host/dispatch.rb +10 -4
  30. data/lib/solargraph/language_server/host/message_worker.rb +4 -0
  31. data/lib/solargraph/language_server/host/sources.rb +7 -4
  32. data/lib/solargraph/language_server/host.rb +26 -7
  33. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  34. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  35. data/lib/solargraph/language_server/message/initialize.rb +11 -0
  36. data/lib/solargraph/language_server/message/initialized.rb +1 -0
  37. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +4 -1
  38. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -4
  39. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  40. data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
  41. data/lib/solargraph/language_server/message/text_document.rb +1 -1
  42. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  43. data/lib/solargraph/language_server/message.rb +1 -0
  44. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  45. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  46. data/lib/solargraph/library.rb +86 -16
  47. data/lib/solargraph/location.rb +1 -0
  48. data/lib/solargraph/parser/comment_ripper.rb +4 -0
  49. data/lib/solargraph/parser/node_methods.rb +47 -7
  50. data/lib/solargraph/parser/node_processor/base.rb +9 -0
  51. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -5
  52. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  53. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +57 -41
  54. data/lib/solargraph/parser/parser_gem/node_methods.rb +499 -0
  55. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  56. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +53 -0
  57. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  58. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  59. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
  60. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  61. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +1 -1
  62. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  63. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  64. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  65. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
  66. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  67. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  68. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  69. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
  70. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +2 -2
  71. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
  72. data/lib/solargraph/parser/parser_gem/node_processors.rb +54 -0
  73. data/lib/solargraph/parser/parser_gem.rb +12 -0
  74. data/lib/solargraph/parser/region.rb +1 -1
  75. data/lib/solargraph/parser/snippet.rb +2 -0
  76. data/lib/solargraph/parser.rb +9 -10
  77. data/lib/solargraph/pin/base.rb +64 -9
  78. data/lib/solargraph/pin/base_variable.rb +6 -2
  79. data/lib/solargraph/pin/block.rb +19 -9
  80. data/lib/solargraph/pin/closure.rb +17 -2
  81. data/lib/solargraph/pin/common.rb +7 -3
  82. data/lib/solargraph/pin/conversions.rb +33 -3
  83. data/lib/solargraph/pin/delegated_method.rb +97 -0
  84. data/lib/solargraph/pin/documenting.rb +25 -34
  85. data/lib/solargraph/pin/instance_variable.rb +4 -0
  86. data/lib/solargraph/pin/local_variable.rb +13 -1
  87. data/lib/solargraph/pin/method.rb +182 -18
  88. data/lib/solargraph/pin/namespace.rb +18 -5
  89. data/lib/solargraph/pin/parameter.rb +44 -14
  90. data/lib/solargraph/pin/reference/override.rb +2 -2
  91. data/lib/solargraph/pin/reference.rb +8 -0
  92. data/lib/solargraph/pin/search.rb +4 -4
  93. data/lib/solargraph/pin/signature.rb +123 -3
  94. data/lib/solargraph/pin.rb +1 -1
  95. data/lib/solargraph/range.rb +4 -6
  96. data/lib/solargraph/rbs_map/conversions.rb +294 -50
  97. data/lib/solargraph/rbs_map/core_fills.rb +7 -24
  98. data/lib/solargraph/rbs_map/core_map.rb +3 -2
  99. data/lib/solargraph/rbs_map/core_signs.rb +2 -0
  100. data/lib/solargraph/rbs_map/stdlib_map.rb +2 -5
  101. data/lib/solargraph/rbs_map.rb +20 -11
  102. data/lib/solargraph/shell.rb +62 -59
  103. data/lib/solargraph/source/chain/array.rb +32 -0
  104. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  105. data/lib/solargraph/source/chain/call.rb +99 -46
  106. data/lib/solargraph/source/chain/constant.rb +15 -1
  107. data/lib/solargraph/source/chain/if.rb +23 -0
  108. data/lib/solargraph/source/chain/link.rb +8 -2
  109. data/lib/solargraph/source/chain/or.rb +1 -1
  110. data/lib/solargraph/source/chain/z_super.rb +3 -3
  111. data/lib/solargraph/source/chain.rb +29 -14
  112. data/lib/solargraph/source/change.rb +3 -0
  113. data/lib/solargraph/source/cursor.rb +2 -0
  114. data/lib/solargraph/source/source_chainer.rb +8 -5
  115. data/lib/solargraph/source.rb +18 -19
  116. data/lib/solargraph/source_map/clip.rb +25 -23
  117. data/lib/solargraph/source_map/mapper.rb +12 -1
  118. data/lib/solargraph/source_map.rb +30 -7
  119. data/lib/solargraph/type_checker/checks.rb +10 -2
  120. data/lib/solargraph/type_checker.rb +123 -45
  121. data/lib/solargraph/version.rb +1 -1
  122. data/lib/solargraph/workspace/config.rb +14 -11
  123. data/lib/solargraph/workspace.rb +3 -2
  124. data/lib/solargraph/yard_map/cache.rb +6 -0
  125. data/lib/solargraph/yard_map/helpers.rb +1 -1
  126. data/lib/solargraph/yard_map/mapper/to_method.rb +11 -1
  127. data/lib/solargraph/yard_map/mapper.rb +1 -1
  128. data/lib/solargraph/yard_map/to_method.rb +11 -4
  129. data/lib/solargraph/yard_map.rb +1 -284
  130. data/lib/solargraph/yard_tags.rb +20 -0
  131. data/lib/solargraph/yardoc.rb +52 -0
  132. data/lib/solargraph.rb +6 -4
  133. data/solargraph.gemspec +11 -5
  134. metadata +131 -75
  135. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  136. data/lib/solargraph/convention/rspec.rb +0 -30
  137. data/lib/solargraph/documentor.rb +0 -76
  138. data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
  139. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  140. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
  141. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  142. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +0 -23
  143. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +0 -23
  144. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
  145. data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
  146. data/lib/solargraph/parser/legacy.rb +0 -12
  147. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -149
  148. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  149. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
  150. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  151. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  152. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
  153. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
  154. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
  155. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  156. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  157. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  158. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  159. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  160. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  161. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  162. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
  163. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
  164. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  165. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
  166. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
  167. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
  168. data/lib/solargraph/parser/rubyvm.rb +0 -40
  169. data/lib/yard-solargraph.rb +0 -33
@@ -6,6 +6,8 @@ class Solargraph::LanguageServer::Message::TextDocument::DocumentSymbol < Solarg
6
6
  def process
7
7
  pins = host.document_symbols params['textDocument']['uri']
8
8
  info = pins.map do |pin|
9
+ next nil unless pin.location&.filename
10
+
9
11
  result = {
10
12
  name: pin.name,
11
13
  containerName: pin.namespace,
@@ -17,7 +19,8 @@ class Solargraph::LanguageServer::Message::TextDocument::DocumentSymbol < Solarg
17
19
  deprecated: pin.deprecated?
18
20
  }
19
21
  result
20
- end
22
+ end.compact
23
+
21
24
  set_result info
22
25
  end
23
26
  end
@@ -17,17 +17,17 @@ module Solargraph
17
17
  args = cli_args(file_uri, config)
18
18
 
19
19
  require_rubocop(config['version'])
20
- options, paths = RuboCop::Options.new.parse(args)
20
+ options, paths = ::RuboCop::Options.new.parse(args)
21
21
  options[:stdin] = original
22
22
  corrections = redirect_stdout do
23
- RuboCop::Runner.new(options, RuboCop::ConfigStore.new).run(paths)
23
+ ::RuboCop::Runner.new(options, ::RuboCop::ConfigStore.new).run(paths)
24
24
  end
25
25
  result = options[:stdin]
26
26
 
27
27
  log_corrections(corrections)
28
28
 
29
29
  format original, result
30
- rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
30
+ rescue ::RuboCop::ValidationError, ::RuboCop::ConfigNotFoundError => e
31
31
  set_error(Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}")
32
32
  end
33
33
 
@@ -54,7 +54,7 @@ module Solargraph
54
54
  def cli_args file_uri, config
55
55
  file = UriHelpers.uri_to_file(file_uri)
56
56
  args = [
57
- config['cops'] == 'all' ? '--autocorrect-all' : '--autocorrect',
57
+ config['cops'] == 'all' ? '-A' : '-a',
58
58
  '--cache', 'false',
59
59
  '--format', formatter_class(config).name,
60
60
  ]
@@ -37,6 +37,8 @@ module Solargraph
37
37
 
38
38
  private
39
39
 
40
+ # @param contents [Array<String>]
41
+ # @return [Hash{Symbol => Hash{Symbol => String}}, nil]
40
42
  def contents_or_nil contents
41
43
  stripped = contents
42
44
  .map(&:strip)
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph::LanguageServer::Message::TextDocument
4
+ class TypeDefinition < Base
5
+ def process
6
+ @line = params['position']['line']
7
+ @column = params['position']['character']
8
+ set_result(code_location || [])
9
+ end
10
+
11
+ private
12
+
13
+ def code_location
14
+ suggestions = host.type_definitions_at(params['textDocument']['uri'], @line, @column)
15
+ return nil if suggestions.empty?
16
+ suggestions.reject { |pin| pin.location.nil? || pin.location.filename.nil? }.map do |pin|
17
+ {
18
+ uri: file_to_uri(pin.location.filename),
19
+ range: pin.location.range.to_hash
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -12,9 +12,9 @@ module Solargraph
12
12
  autoload :DidSave, 'solargraph/language_server/message/text_document/did_save'
13
13
  autoload :Hover, 'solargraph/language_server/message/text_document/hover'
14
14
  autoload :SignatureHelp, 'solargraph/language_server/message/text_document/signature_help'
15
- autoload :DiagnosticsQueue, 'solargraph/language_server/message/text_document/diagnostics_queue'
16
15
  autoload :OnTypeFormatting, 'solargraph/language_server/message/text_document/on_type_formatting'
17
16
  autoload :Definition, 'solargraph/language_server/message/text_document/definition'
17
+ autoload :TypeDefinition, 'solargraph/language_server/message/text_document/type_definition'
18
18
  autoload :DocumentSymbol, 'solargraph/language_server/message/text_document/document_symbol'
19
19
  autoload :Formatting, 'solargraph/language_server/message/text_document/formatting'
20
20
  autoload :References, 'solargraph/language_server/message/text_document/references'
@@ -11,8 +11,12 @@ module Solargraph::LanguageServer::Message::Workspace
11
11
 
12
12
  private
13
13
 
14
+ # @return [void]
14
15
  def register_from_options
16
+ Solargraph.logger.debug "Registering capabilities from options: #{host.options.inspect}"
17
+ # @type [Array<String>]
15
18
  y = []
19
+ # @type [Array<String>]
16
20
  n = []
17
21
  (host.options['completion'] ? y : n).push('textDocument/completion')
18
22
  (host.options['hover'] ? y : n).push('textDocument/hover', 'textDocument/signatureHelp')
@@ -20,6 +24,7 @@ module Solargraph::LanguageServer::Message::Workspace
20
24
  (host.options['formatting'] ? y : n).push('textDocument/formatting')
21
25
  (host.options['symbols'] ? y : n).push('textDocument/documentSymbol', 'workspace/symbol')
22
26
  (host.options['definitions'] ? y : n).push('textDocument/definition')
27
+ (host.options['typeDefinitions'] ? y : n).push('textDocument/typeDefinition')
23
28
  (host.options['references'] ? y : n).push('textDocument/references')
24
29
  (host.options['folding'] ? y : n).push('textDocument/folding')
25
30
  (host.options['highlights'] ? y : n).push('textDocument/documentHighlight')
@@ -66,6 +66,7 @@ module Solargraph
66
66
  register 'textDocument/didClose', TextDocument::DidClose
67
67
  register 'textDocument/hover', TextDocument::Hover
68
68
  register 'textDocument/definition', TextDocument::Definition
69
+ register 'textDocument/typeDefinition', TextDocument::TypeDefinition
69
70
  register 'textDocument/formatting', TextDocument::Formatting
70
71
  register 'textDocument/onTypeFormatting', TextDocument::OnTypeFormatting
71
72
  register 'textDocument/documentSymbol', TextDocument::DocumentSymbol
@@ -8,6 +8,17 @@ module Solargraph
8
8
  # A common module for running language servers in Backport.
9
9
  #
10
10
  module Adapter
11
+ # This runs in the context of Backport::Adapter, which
12
+ # provides write() - but if we didn't hide this behind a parse
13
+ # tag, it would override the one in the class.
14
+ #
15
+ # @!method write(text)
16
+ # @abstract
17
+ # Write the change to the specified text.
18
+ # @param text [String] The text to be changed.
19
+ # @return [String] The updated text.
20
+
21
+ # @return [void]
11
22
  def opening
12
23
  @host = Solargraph::LanguageServer::Host.new
13
24
  @host.add_observer self
@@ -18,15 +29,18 @@ module Solargraph
18
29
  end
19
30
  end
20
31
 
32
+ # @return [void]
21
33
  def closing
22
34
  @host.stop
23
35
  end
24
36
 
25
37
  # @param data [String]
38
+ # @return [void]
26
39
  def receiving data
27
40
  @data_reader.receive data
28
41
  end
29
42
 
43
+ # @return [void]
30
44
  def update
31
45
  if @host.stopped?
32
46
  shutdown
@@ -38,12 +52,13 @@ module Solargraph
38
52
 
39
53
  private
40
54
 
41
- # @param request [String]
55
+ # @param request [Hash]
42
56
  # @return [void]
43
57
  def process request
44
58
  @host.process(request)
45
59
  end
46
60
 
61
+ # @return [void]
47
62
  def shutdown
48
63
  Backport.stop unless @host.options['transport'] == 'external'
49
64
  end
@@ -16,6 +16,7 @@ module Solargraph
16
16
  # client.
17
17
  #
18
18
  # @yieldparam [Hash] The message received from the client
19
+ # @return [void]
19
20
  def set_message_handler &block
20
21
  @message_handler = block
21
22
  end
@@ -26,6 +27,7 @@ module Solargraph
26
27
  # will be buffered and subsequent data will be appended to the buffer.
27
28
  #
28
29
  # @param data [String]
30
+ # @return [void]
29
31
  def receive data
30
32
  data.each_char do |char|
31
33
  @buffer.concat char
@@ -97,7 +97,7 @@ module Solargraph
97
97
  def create filename, text
98
98
  result = false
99
99
  mutex.synchronize do
100
- next unless contain?(filename) || open?(filename) || workspace.would_merge?(filename)
100
+ next unless contain?(filename) || open?(filename)
101
101
  @synchronized = false
102
102
  source = Solargraph::Source.load_string(text, filename)
103
103
  workspace.merge(source)
@@ -159,7 +159,7 @@ module Solargraph
159
159
  # @param filename [String] The file to analyze
160
160
  # @param line [Integer] The zero-based line number
161
161
  # @param column [Integer] The zero-based column number
162
- # @return [SourceMap::Completion]
162
+ # @return [SourceMap::Completion, nil]
163
163
  # @todo Take a Location instead of filename/line/column
164
164
  def completions_at filename, line, column
165
165
  position = Position.new(line, column)
@@ -175,7 +175,7 @@ module Solargraph
175
175
  # @param filename [String] The file to analyze
176
176
  # @param line [Integer] The zero-based line number
177
177
  # @param column [Integer] The zero-based column number
178
- # @return [Array<Solargraph::Pin::Base>]
178
+ # @return [Array<Solargraph::Pin::Base>, nil]
179
179
  # @todo Take filename/position instead of filename/line/column
180
180
  def definitions_at filename, line, column
181
181
  position = Position.new(line, column)
@@ -199,6 +199,22 @@ module Solargraph
199
199
  handle_file_not_found(filename, e)
200
200
  end
201
201
 
202
+ # Get type definition suggestions for the expression at the specified file and
203
+ # location.
204
+ #
205
+ # @param filename [String] The file to analyze
206
+ # @param line [Integer] The zero-based line number
207
+ # @param column [Integer] The zero-based column number
208
+ # @return [Array<Solargraph::Pin::Base>, nil]
209
+ # @todo Take filename/position instead of filename/line/column
210
+ def type_definitions_at filename, line, column
211
+ position = Position.new(line, column)
212
+ cursor = Source::Cursor.new(read(filename), position)
213
+ api_map.clip(cursor).types
214
+ rescue FileNotFoundError => e
215
+ handle_file_not_found filename, e
216
+ end
217
+
202
218
  # Get signature suggestions for the method at the specified file and
203
219
  # location.
204
220
  #
@@ -267,10 +283,16 @@ module Solargraph
267
283
  return if map.nil?
268
284
  pin = map.requires.select { |p| p.location.range.contain?(location.range.start) }.first
269
285
  return nil if pin.nil?
286
+ # @param full [String]
287
+ return_if_match = proc do |full|
288
+ if source_map_hash.key?(full)
289
+ return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0))
290
+ end
291
+ end
270
292
  workspace.require_paths.each do |path|
271
- full = Pathname.new(path).join("#{pin.name}.rb").to_s
272
- next unless source_map_hash.key?(full)
273
- return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0))
293
+ full = File.join path, pin.name
294
+ return_if_match.(full)
295
+ return_if_match.(full << ".rb")
274
296
  end
275
297
  nil
276
298
  rescue FileNotFoundError
@@ -280,13 +302,13 @@ module Solargraph
280
302
  # Get an array of pins that match a path.
281
303
  #
282
304
  # @param path [String]
283
- # @return [Array<Solargraph::Pin::Base>]
305
+ # @return [Enumerable<Solargraph::Pin::Base>]
284
306
  def get_path_pins path
285
307
  api_map.get_path_suggestions(path)
286
308
  end
287
309
 
288
310
  # @param query [String]
289
- # @return [Array<YARD::CodeObjects::Base>]
311
+ # @return [Enumerable<YARD::CodeObjects::Base>]
290
312
  def document query
291
313
  api_map.document query
292
314
  end
@@ -318,11 +340,12 @@ module Solargraph
318
340
  end
319
341
 
320
342
  # @param path [String]
321
- # @return [Array<Solargraph::Pin::Base>]
343
+ # @return [Enumerable<Solargraph::Pin::Base>]
322
344
  def path_pins path
323
345
  api_map.get_path_suggestions(path)
324
346
  end
325
347
 
348
+ # @return [Array<SourceMap>]
326
349
  def source_maps
327
350
  source_map_hash.values
328
351
  end
@@ -379,14 +402,19 @@ module Solargraph
379
402
  end
380
403
  end
381
404
 
405
+ # @return [void]
382
406
  private def catalog_inlock
383
- return if synchronized?
384
- logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
385
- api_map.catalog bench
386
- @synchronized = true
387
- logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)" if logger.info?
407
+ return if synchronized?
408
+
409
+ logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
410
+ api_map.catalog bench
411
+ @synchronized = true
412
+ logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
413
+ logger.info "#{api_map.uncached_gemspecs.length} uncached gemspecs"
414
+ cache_next_gemspec
388
415
  end
389
416
 
417
+ # @return [Bench]
390
418
  def bench
391
419
  Bench.new(
392
420
  source_maps: source_map_hash.values,
@@ -431,6 +459,7 @@ module Solargraph
431
459
  result
432
460
  end
433
461
 
462
+ # @return [Hash{String => SourceMap}]
434
463
  def source_map_hash
435
464
  @source_map_hash ||= {}
436
465
  end
@@ -439,6 +468,7 @@ module Solargraph
439
468
  (workspace.filenames - source_map_hash.keys).empty?
440
469
  end
441
470
 
471
+ # @return [SourceMap, Boolean]
442
472
  def next_map
443
473
  return false if mapped?
444
474
  mutex.synchronize do
@@ -455,6 +485,7 @@ module Solargraph
455
485
  end
456
486
  end
457
487
 
488
+ # @return [self]
458
489
  def map!
459
490
  workspace.sources.each do |src|
460
491
  source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
@@ -463,28 +494,34 @@ module Solargraph
463
494
  self
464
495
  end
465
496
 
497
+ # @return [Array<Solargraph::Pin::Base>]
466
498
  def pins
467
499
  @pins ||= []
468
500
  end
469
501
 
502
+ # @return [Set<String>]
470
503
  def external_requires
471
504
  @external_requires ||= source_map_external_require_hash.values.flatten.to_set
472
505
  end
473
506
 
474
507
  private
475
508
 
509
+ # @return [Hash{String => Set<String>}]
476
510
  def source_map_external_require_hash
477
511
  @source_map_external_require_hash ||= {}
478
512
  end
479
513
 
480
514
  # @param source_map [SourceMap]
515
+ # @return [void]
481
516
  def find_external_requires source_map
482
517
  new_set = source_map.requires.map(&:name).to_set
483
518
  # return if new_set == source_map_external_require_hash[source_map.filename]
519
+ _filenames = nil
520
+ filenames = ->{ _filenames ||= workspace.filenames.to_set }
484
521
  source_map_external_require_hash[source_map.filename] = new_set.reject do |path|
485
522
  workspace.require_paths.any? do |base|
486
- full = Pathname.new(base).join("#{path}.rb").to_s
487
- workspace.filenames.include?(full)
523
+ full = File.join(base, path)
524
+ filenames[].include?(full) or filenames[].include?(full << ".rb")
488
525
  end
489
526
  end
490
527
  @external_requires = nil
@@ -514,6 +551,9 @@ module Solargraph
514
551
  workspace.source(filename)
515
552
  end
516
553
 
554
+ # @param filename [String]
555
+ # @param error [FileNotFoundError]
556
+ # @return [nil]
517
557
  def handle_file_not_found filename, error
518
558
  if workspace.source(filename)
519
559
  Solargraph.logger.debug "#{filename} is not cataloged in the ApiMap"
@@ -523,6 +563,8 @@ module Solargraph
523
563
  end
524
564
  end
525
565
 
566
+ # @param source [Source]
567
+ # @return [void]
526
568
  def maybe_map source
527
569
  return unless source
528
570
  return unless @current == source || workspace.has_file?(source.filename)
@@ -547,5 +589,33 @@ module Solargraph
547
589
  @synchronized = false
548
590
  end
549
591
  end
592
+
593
+ # @return [Set<Gem::Specification>]
594
+ def cache_errors
595
+ @cache_errors ||= Set.new
596
+ end
597
+
598
+ # @return [void]
599
+ def cache_next_gemspec
600
+ return if @cache_pid
601
+ spec = api_map.uncached_gemspecs.find { |spec| !cache_errors.include?(spec)}
602
+ return unless spec
603
+
604
+ logger.info "Caching #{spec.name} #{spec.version}"
605
+ Thread.new do
606
+ @cache_pid = Process.spawn('solargraph', 'cache', spec.name, spec.version.to_s)
607
+ Process.wait(@cache_pid)
608
+ logger.info "Cached #{spec.name} #{spec.version}"
609
+ @synchronized = false
610
+ rescue Errno::EINVAL => e
611
+ logger.info "Cached #{spec.name} #{spec.version} with EINVAL"
612
+ @synchronized = false
613
+ rescue StandardError => e
614
+ cache_errors.add spec
615
+ Solargraph.logger.warn "Error caching gemspec #{spec.name} #{spec.version}: [#{e.class}] #{e.message}"
616
+ ensure
617
+ @cache_pid = nil
618
+ end
619
+ end
550
620
  end
551
621
  end
@@ -25,6 +25,7 @@ module Solargraph
25
25
  }
26
26
  end
27
27
 
28
+ # @param other [BasicObject]
28
29
  def == other
29
30
  return false unless other.is_a?(Location)
30
31
  filename == other.filename and range == other.range
@@ -3,6 +3,9 @@ require 'ripper'
3
3
  module Solargraph
4
4
  module Parser
5
5
  class CommentRipper < Ripper::SexpBuilderPP
6
+ # @param src [String]
7
+ # @param filename [String]
8
+ # @param lineno [Integer]
6
9
  def initialize src, filename = '(ripper)', lineno = 0
7
10
  super
8
11
  @buffer = src
@@ -42,6 +45,7 @@ module Solargraph
42
45
  result
43
46
  end
44
47
 
48
+ # @return [Hash{Integer => String}]
45
49
  def parse
46
50
  @comments = {}
47
51
  super
@@ -3,38 +3,78 @@ module Solargraph
3
3
  class NodeMethods
4
4
  module_function
5
5
 
6
+ # @abstract
7
+ # @param node [Parser::AST::Node]
8
+ # @return [String]
6
9
  def unpack_name node
7
10
  raise NotImplementedError
8
11
  end
9
12
 
10
- def infer_literal_type node
13
+ # @abstract
14
+ # @todo Temporarily here for testing. Move to Solargraph::Parser.
15
+ # @param node [Parser::AST::Node]
16
+ # @return [Array<Parser::AST::Node>]
17
+ def call_nodes_from node
11
18
  raise NotImplementedError
12
19
  end
13
20
 
14
- def calls_from node
21
+ # Find all the nodes within the provided node that potentially return a
22
+ # value.
23
+ #
24
+ # The node parameter typically represents a method's logic, e.g., the
25
+ # second child (after the :args node) of a :def node. A simple one-line
26
+ # method would typically return itself, while a node with conditions
27
+ # would return the resulting node from each conditional branch. Nodes
28
+ # that follow a :return node are assumed to be unreachable. Nil values
29
+ # are converted to nil node types.
30
+ #
31
+ # @abstract
32
+ # @param node [Parser::AST::Node]
33
+ # @return [Array<Parser::AST::Node>]
34
+ def returns_from_method_body node
15
35
  raise NotImplementedError
16
36
  end
17
37
 
18
- def returns_from node
38
+ # @abstract
39
+ # @param node [Parser::AST::Node]
40
+ #
41
+ # @return [Array<Parser::AST::Node>]
42
+ def const_nodes_from node
19
43
  raise NotImplementedError
20
44
  end
21
45
 
22
- def process node
46
+ # @abstract
47
+ # @param cursor [Solargraph::Source::Cursor]
48
+ # @return [Parser::AST::Node, nil]
49
+ def find_recipient_node cursor
23
50
  raise NotImplementedError
24
51
  end
25
52
 
26
- def references node
53
+ # @abstract
54
+ # @param node [Parser::AST::Node]
55
+ # @return [Array<AST::Node>] low-level value nodes in
56
+ # value position. Does not include explicit return
57
+ # statements
58
+ def value_position_nodes_only(node)
27
59
  raise NotImplementedError
28
60
  end
29
61
 
30
- def chain node, filename = nil, in_block = false
62
+ # @abstract
63
+ # @param nodes [Enumerable<Parser::AST::Node>]
64
+ def any_splatted_call?(nodes)
31
65
  raise NotImplementedError
32
66
  end
33
67
 
34
- def node? node
68
+ # @abstract
69
+ # @param node [Parser::AST::Node]
70
+ # @return [void]
71
+ def process node
35
72
  raise NotImplementedError
36
73
  end
37
74
 
75
+ # @abstract
76
+ # @param node [Parser::AST::Node]
77
+ # @return [Hash{Parser::AST::Node => Chain}]
38
78
  def convert_hash node
39
79
  raise NotImplementedError
40
80
  end
@@ -19,6 +19,7 @@ module Solargraph
19
19
  # @param node [Parser::AST::Node]
20
20
  # @param region [Region]
21
21
  # @param pins [Array<Pin::Base>]
22
+ # @param locals [Array<Pin::LocalVariable>]
22
23
  def initialize node, region, pins, locals
23
24
  @node = node
24
25
  @region = region
@@ -54,20 +55,28 @@ module Solargraph
54
55
  Location.new(region.filename, range)
55
56
  end
56
57
 
58
+ # @param node [Parser::AST::Node]
59
+ # @return [String, nil]
57
60
  def comments_for(node)
58
61
  region.source.comments_for(node)
59
62
  end
60
63
 
64
+ # @param position [Solargraph::Position]
65
+ # @return [Pin::Base, nil]
61
66
  def named_path_pin position
62
67
  pins.select{|pin| pin.is_a?(Pin::Closure) && pin.path && !pin.path.empty? && pin.location.range.contain?(position)}.last
63
68
  end
64
69
 
65
70
  # @todo Candidate for deprecation
71
+ # @param position [Solargraph::Position]
72
+ # @return [Pin::Closure, nil]
66
73
  def block_pin position
67
74
  pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
68
75
  end
69
76
 
70
77
  # @todo Candidate for deprecation
78
+ # @param position [Solargraph::Position]
79
+ # @return [Pin::Closure, nil]
71
80
  def closure_pin position
72
81
  pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
73
82
  end