solargraph 0.54.4 → 0.57.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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +125 -0
  3. data/.github/workflows/plugins.yml +149 -5
  4. data/.github/workflows/rspec.yml +39 -4
  5. data/.github/workflows/typecheck.yml +8 -3
  6. data/.gitignore +7 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +2627 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +104 -0
  13. data/README.md +20 -6
  14. data/Rakefile +125 -13
  15. data/lib/solargraph/api_map/cache.rb +3 -2
  16. data/lib/solargraph/api_map/constants.rb +218 -0
  17. data/lib/solargraph/api_map/index.rb +44 -42
  18. data/lib/solargraph/api_map/source_to_yard.rb +10 -4
  19. data/lib/solargraph/api_map/store.rb +165 -32
  20. data/lib/solargraph/api_map.rb +319 -243
  21. data/lib/solargraph/bench.rb +18 -1
  22. data/lib/solargraph/complex_type/type_methods.rb +7 -1
  23. data/lib/solargraph/complex_type/unique_type.rb +105 -16
  24. data/lib/solargraph/complex_type.rb +40 -7
  25. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  26. data/lib/solargraph/convention/base.rb +20 -3
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  29. data/lib/solargraph/convention/data_definition.rb +105 -0
  30. data/lib/solargraph/convention/gemspec.rb +3 -2
  31. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
  32. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
  33. data/lib/solargraph/convention/struct_definition.rb +164 -0
  34. data/lib/solargraph/convention.rb +35 -4
  35. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  36. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
  37. data/lib/solargraph/doc_map.rb +313 -65
  38. data/lib/solargraph/environ.rb +9 -2
  39. data/lib/solargraph/gem_pins.rb +60 -38
  40. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  41. data/lib/solargraph/language_server/host/message_worker.rb +13 -7
  42. data/lib/solargraph/language_server/host.rb +14 -3
  43. data/lib/solargraph/language_server/message/base.rb +2 -1
  44. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
  45. data/lib/solargraph/language_server/message/extended/document.rb +5 -2
  46. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  47. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/text_document/formatting.rb +16 -2
  49. data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
  50. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  51. data/lib/solargraph/language_server/progress.rb +8 -0
  52. data/lib/solargraph/language_server/request.rb +1 -0
  53. data/lib/solargraph/library.rb +53 -32
  54. data/lib/solargraph/location.rb +23 -0
  55. data/lib/solargraph/logging.rb +12 -2
  56. data/lib/solargraph/page.rb +4 -0
  57. data/lib/solargraph/parser/comment_ripper.rb +20 -7
  58. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
  59. data/lib/solargraph/parser/node_methods.rb +16 -2
  60. data/lib/solargraph/parser/node_processor/base.rb +10 -5
  61. data/lib/solargraph/parser/node_processor.rb +26 -9
  62. data/lib/solargraph/parser/parser_gem/class_methods.rb +17 -15
  63. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  64. data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
  65. data/lib/solargraph/parser/parser_gem/node_methods.rb +8 -4
  66. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  67. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
  68. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
  69. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
  70. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
  71. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  72. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
  73. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
  74. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  75. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
  76. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
  77. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
  78. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
  79. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
  80. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +42 -0
  81. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
  82. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
  83. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
  84. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +63 -30
  85. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
  86. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  87. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  88. data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
  89. data/lib/solargraph/parser/region.rb +4 -1
  90. data/lib/solargraph/parser/snippet.rb +2 -0
  91. data/lib/solargraph/parser.rb +1 -0
  92. data/lib/solargraph/pin/base.rb +360 -30
  93. data/lib/solargraph/pin/base_variable.rb +16 -10
  94. data/lib/solargraph/pin/block.rb +2 -0
  95. data/lib/solargraph/pin/breakable.rb +9 -0
  96. data/lib/solargraph/pin/callable.rb +83 -3
  97. data/lib/solargraph/pin/closure.rb +20 -1
  98. data/lib/solargraph/pin/common.rb +10 -1
  99. data/lib/solargraph/pin/constant.rb +2 -0
  100. data/lib/solargraph/pin/delegated_method.rb +21 -1
  101. data/lib/solargraph/pin/documenting.rb +16 -0
  102. data/lib/solargraph/pin/keyword.rb +7 -2
  103. data/lib/solargraph/pin/local_variable.rb +18 -6
  104. data/lib/solargraph/pin/method.rb +175 -46
  105. data/lib/solargraph/pin/method_alias.rb +3 -0
  106. data/lib/solargraph/pin/namespace.rb +17 -9
  107. data/lib/solargraph/pin/parameter.rb +78 -19
  108. data/lib/solargraph/pin/proxy_type.rb +13 -6
  109. data/lib/solargraph/pin/reference/override.rb +24 -6
  110. data/lib/solargraph/pin/reference/require.rb +2 -2
  111. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  112. data/lib/solargraph/pin/reference.rb +26 -0
  113. data/lib/solargraph/pin/search.rb +3 -1
  114. data/lib/solargraph/pin/signature.rb +44 -0
  115. data/lib/solargraph/pin/singleton.rb +1 -1
  116. data/lib/solargraph/pin/symbol.rb +8 -2
  117. data/lib/solargraph/pin/until.rb +18 -0
  118. data/lib/solargraph/pin/while.rb +18 -0
  119. data/lib/solargraph/pin.rb +4 -1
  120. data/lib/solargraph/pin_cache.rb +245 -0
  121. data/lib/solargraph/position.rb +11 -0
  122. data/lib/solargraph/range.rb +10 -0
  123. data/lib/solargraph/rbs_map/conversions.rb +226 -70
  124. data/lib/solargraph/rbs_map/core_fills.rb +32 -16
  125. data/lib/solargraph/rbs_map/core_map.rb +37 -11
  126. data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
  127. data/lib/solargraph/rbs_map.rb +88 -18
  128. data/lib/solargraph/shell.rb +20 -18
  129. data/lib/solargraph/source/chain/array.rb +11 -7
  130. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  131. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  132. data/lib/solargraph/source/chain/call.rb +53 -23
  133. data/lib/solargraph/source/chain/constant.rb +1 -1
  134. data/lib/solargraph/source/chain/hash.rb +4 -3
  135. data/lib/solargraph/source/chain/head.rb +1 -1
  136. data/lib/solargraph/source/chain/if.rb +1 -1
  137. data/lib/solargraph/source/chain/link.rb +12 -1
  138. data/lib/solargraph/source/chain/literal.rb +22 -2
  139. data/lib/solargraph/source/chain/or.rb +1 -1
  140. data/lib/solargraph/source/chain/z_super.rb +1 -1
  141. data/lib/solargraph/source/chain.rb +84 -47
  142. data/lib/solargraph/source/change.rb +2 -2
  143. data/lib/solargraph/source/cursor.rb +2 -3
  144. data/lib/solargraph/source/source_chainer.rb +3 -3
  145. data/lib/solargraph/source.rb +5 -2
  146. data/lib/solargraph/source_map/clip.rb +4 -2
  147. data/lib/solargraph/source_map/data.rb +4 -0
  148. data/lib/solargraph/source_map/mapper.rb +13 -7
  149. data/lib/solargraph/source_map.rb +21 -31
  150. data/lib/solargraph/type_checker/checks.rb +4 -0
  151. data/lib/solargraph/type_checker/param_def.rb +2 -0
  152. data/lib/solargraph/type_checker/rules.rb +8 -0
  153. data/lib/solargraph/type_checker.rb +208 -128
  154. data/lib/solargraph/version.rb +1 -1
  155. data/lib/solargraph/views/_method.erb +10 -10
  156. data/lib/solargraph/views/_namespace.erb +3 -3
  157. data/lib/solargraph/views/document.erb +10 -10
  158. data/lib/solargraph/workspace/config.rb +1 -3
  159. data/lib/solargraph/workspace/require_paths.rb +98 -0
  160. data/lib/solargraph/workspace.rb +38 -52
  161. data/lib/solargraph/yard_map/helpers.rb +29 -1
  162. data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
  163. data/lib/solargraph/yard_map/mapper/to_method.rb +53 -18
  164. data/lib/solargraph/yard_map/mapper/to_namespace.rb +9 -7
  165. data/lib/solargraph/yard_map/mapper.rb +4 -3
  166. data/lib/solargraph/yard_map/to_method.rb +4 -2
  167. data/lib/solargraph/yardoc.rb +22 -10
  168. data/lib/solargraph.rb +34 -1
  169. data/rbs/fills/tuple.rbs +149 -0
  170. data/rbs_collection.yaml +19 -0
  171. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  172. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  173. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  174. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  175. data/solargraph.gemspec +15 -4
  176. metadata +157 -15
  177. data/lib/.rubocop.yml +0 -22
  178. data/lib/solargraph/cache.rb +0 -77
@@ -7,9 +7,16 @@ module Solargraph
7
7
  #
8
8
  class MessageWorker
9
9
  UPDATE_METHODS = [
10
- 'textDocument/didOpen',
11
10
  'textDocument/didChange',
12
- 'workspace/didChangeWatchedFiles'
11
+ 'textDocument/didClose',
12
+ 'textDocument/didOpen',
13
+ 'textDocument/didSave',
14
+ 'workspace/didChangeConfiguration',
15
+ 'workspace/didChangeWatchedFiles',
16
+ 'workspace/didCreateFiles',
17
+ 'workspace/didChangeWorkspaceFolders',
18
+ 'workspace/didDeleteFiles',
19
+ 'workspace/didRenameFiles'
13
20
  ].freeze
14
21
 
15
22
  # @param host [Host]
@@ -65,10 +72,12 @@ module Solargraph
65
72
 
66
73
  private
67
74
 
75
+ # @return [Hash, nil]
68
76
  def next_message
69
77
  cancel_message || next_priority
70
78
  end
71
79
 
80
+ # @return [Hash, nil]
72
81
  def cancel_message
73
82
  # Handle cancellations first
74
83
  idx = messages.find_index { |msg| msg['method'] == '$/cancelRequest' }
@@ -79,16 +88,13 @@ module Solargraph
79
88
  msg
80
89
  end
81
90
 
91
+ # @return [Hash, nil]
82
92
  def next_priority
83
93
  # Prioritize updates and version-dependent messages for performance
84
94
  idx = messages.find_index do |msg|
85
95
  UPDATE_METHODS.include?(msg['method']) || version_dependent?(msg)
86
96
  end
87
- return messages.shift unless idx
88
-
89
- msg = messages[idx]
90
- messages.delete_at idx
91
- msg
97
+ idx ? messages.delete_at(idx) : messages.shift
92
98
  end
93
99
 
94
100
  # True if the message requires a previous update to have executed in
@@ -299,6 +299,11 @@ module Solargraph
299
299
  end
300
300
  end
301
301
 
302
+ # @return [String]
303
+ def command_path
304
+ options['commandPath'] || 'solargraph'
305
+ end
306
+
302
307
  # Prepare multiple folders.
303
308
  #
304
309
  # @param array [Array<Hash{String => String}>]
@@ -501,7 +506,8 @@ module Solargraph
501
506
  parameters: pin.parameters,
502
507
  return_type: ComplexType.try_parse(params['data']['path']),
503
508
  comments: pin.comments,
504
- closure: pin.closure
509
+ closure: pin.closure,
510
+ source: :solargraph
505
511
  )
506
512
  end)
507
513
  end
@@ -597,7 +603,11 @@ module Solargraph
597
603
  # @return [Array]
598
604
  def document query
599
605
  result = []
600
- libraries.each { |lib| result.concat lib.document(query) }
606
+ if libraries.empty?
607
+ result.concat generic_library.document(query)
608
+ else
609
+ libraries.each { |lib| result.concat lib.document(query) }
610
+ end
601
611
  result
602
612
  end
603
613
 
@@ -707,7 +717,7 @@ module Solargraph
707
717
  # A hash of client requests by ID. The host uses this to keep track of
708
718
  # pending responses.
709
719
  #
710
- # @return [Hash{Integer => Solargraph::LanguageServer::Host}]
720
+ # @return [Hash{Integer => Solargraph::LanguageServer::Request}]
711
721
  def requests
712
722
  @requests ||= {}
713
723
  end
@@ -749,6 +759,7 @@ module Solargraph
749
759
  return change if source.code.length + 1 != change['text'].length
750
760
  diffs = Diff::LCS.diff(source.code, change['text'])
751
761
  return change if diffs.length.zero? || diffs.length > 1 || diffs.first.length > 1
762
+ # @sg-ignore push this upstream
752
763
  # @type [Diff::LCS::Change]
753
764
  diff = diffs.first.first
754
765
  return change unless diff.adding? && ['.', ':', '(', ',', ' '].include?(diff.element)
@@ -16,7 +16,7 @@ module Solargraph
16
16
  # @return [String]
17
17
  attr_reader :method
18
18
 
19
- # @return [Hash{String => Array<undefined>, Hash{String => undefined}, String, Integer}]
19
+ # @return [Hash{String => undefined}]
20
20
  attr_reader :params
21
21
 
22
22
  # @return [Hash, Array, nil]
@@ -79,6 +79,7 @@ module Solargraph
79
79
 
80
80
  private
81
81
 
82
+ # @return [void]
82
83
  def accept_or_cancel
83
84
  if host.cancel?(id)
84
85
  # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#cancelRequest
@@ -83,6 +83,8 @@ module Solargraph
83
83
  @fetched = true
84
84
  begin
85
85
  @available ||= begin
86
+ # @sg-ignore Variable type could not be inferred for tuple
87
+ # @type [Gem::Dependency, nil]
86
88
  tuple = CheckGemVersion.fetcher.search_for_dependency(Gem::Dependency.new('solargraph')).flatten.first
87
89
  if tuple.nil?
88
90
  @error = 'An error occurred fetching the gem data'
@@ -6,12 +6,15 @@ module Solargraph
6
6
  module Extended
7
7
  class Document < Base
8
8
  def process
9
- objects = host.document(params['query'])
9
+ api_map, pins = host.document(params['query'])
10
10
  page = Solargraph::Page.new(host.options['viewsPath'])
11
- content = page.render('document', layout: true, locals: {objects: objects})
11
+ content = page.render('document', layout: true, locals: { api_map: api_map, pins: pins })
12
12
  set_result(
13
13
  content: content
14
14
  )
15
+ rescue StandardError => e
16
+ Solargraph.logger.warn "Error processing document: [#{e.class}] #{e.message}"
17
+ Solargraph.logger.debug e.backtrace.join("\n")
15
18
  end
16
19
  end
17
20
  end
@@ -11,9 +11,9 @@ module Solargraph
11
11
  #
12
12
  class DocumentGems < Base
13
13
  def process
14
- cmd = "yard gems"
15
- cmd += " --rebuild" if params['rebuild']
16
- o, s = Open3.capture2(cmd)
14
+ cmd = [host.command_path, 'gems']
15
+ cmd.push '--rebuild' if params['rebuild']
16
+ o, s = Open3.capture2(*cmd)
17
17
  if s != 0
18
18
  host.show_message "An error occurred while building gem documentation.", LanguageServer::MessageTypes::ERROR
19
19
  set_result({
@@ -10,6 +10,7 @@ module Solargraph::LanguageServer::Message::TextDocument
10
10
 
11
11
  private
12
12
 
13
+ # @return [Array<Hash>]
13
14
  def code_location
14
15
  suggestions = host.definitions_at(params['textDocument']['uri'], @line, @column)
15
16
  return nil if suggestions.empty?
@@ -21,6 +22,7 @@ module Solargraph::LanguageServer::Message::TextDocument
21
22
  end
22
23
  end
23
24
 
25
+ # @return [Array<Hash>]
24
26
  def require_location
25
27
  # @todo Terrible hack
26
28
  lib = host.library_for(params['textDocument']['uri'])
@@ -19,8 +19,14 @@ module Solargraph
19
19
  require_rubocop(config['version'])
20
20
  options, paths = ::RuboCop::Options.new.parse(args)
21
21
  options[:stdin] = original
22
- corrections = redirect_stdout do
23
- ::RuboCop::Runner.new(options, ::RuboCop::ConfigStore.new).run(paths)
22
+
23
+ # Ensure only one instance of RuboCop::Runner is running at
24
+ # a time - it uses 'chdir' to read config files with ERB,
25
+ # which can conflict with other chdirs.
26
+ corrections = Solargraph::CHDIR_MUTEX.synchronize do
27
+ redirect_stdout do
28
+ ::RuboCop::Runner.new(options, ::RuboCop::ConfigStore.new).run(paths)
29
+ end
24
30
  end
25
31
  result = options[:stdin]
26
32
 
@@ -34,6 +40,7 @@ module Solargraph
34
40
  private
35
41
 
36
42
  # @param corrections [String]
43
+ # @return [void]
37
44
  def log_corrections(corrections)
38
45
  corrections = corrections&.strip
39
46
  return if corrections&.empty?
@@ -45,6 +52,8 @@ module Solargraph
45
52
  end
46
53
  end
47
54
 
55
+ # @param file_uri [String]
56
+ # @return [Hash{String => undefined}]
48
57
  def config_for(file_uri)
49
58
  conf = host.formatter_config(file_uri)
50
59
  return {} unless conf.is_a?(Hash)
@@ -52,7 +61,9 @@ module Solargraph
52
61
  conf['rubocop'] || {}
53
62
  end
54
63
 
64
+ # @param file_uri [String]
55
65
  # @param config [Hash{String => String}]
66
+ # @return [Array<String>]
56
67
  def cli_args file_uri, config
57
68
  file = UriHelpers.uri_to_file(file_uri)
58
69
  args = [
@@ -71,6 +82,8 @@ module Solargraph
71
82
  end
72
83
 
73
84
  # @param config [Hash{String => String}]
85
+ # @sg-ignore
86
+ # @return [Class<RuboCop::Formatter::BaseFormatter>]
74
87
  def formatter_class(config)
75
88
  if self.class.const_defined?('BlankRubocopFormatter')
76
89
  # @sg-ignore
@@ -83,6 +96,7 @@ module Solargraph
83
96
  end
84
97
 
85
98
  # @param value [Array, String]
99
+ # @return [String]
86
100
  def cop_list(value)
87
101
  value = value.join(',') if value.respond_to?(:join)
88
102
  return nil if value == '' || !value.is_a?(String)
@@ -10,6 +10,7 @@ module Solargraph::LanguageServer::Message::TextDocument
10
10
 
11
11
  private
12
12
 
13
+ # @return [Array<Hash>]
13
14
  def code_location
14
15
  suggestions = host.type_definitions_at(params['textDocument']['uri'], @line, @column)
15
16
  return nil if suggestions.empty?
@@ -9,11 +9,13 @@ module Solargraph::LanguageServer::Message::Workspace
9
9
 
10
10
  private
11
11
 
12
+ # @return [void]
12
13
  def add_folders
13
14
  return unless params['event'] && params['event']['added']
14
15
  host.prepare_folders params['event']['added']
15
16
  end
16
17
 
18
+ # @return [void]
17
19
  def remove_folders
18
20
  return unless params['event'] && params['event']['removed']
19
21
  params['event']['removed'].each do |folder|
@@ -39,6 +39,7 @@ module Solargraph
39
39
 
40
40
  # @param message [String]
41
41
  # @param percentage [Integer]
42
+ # @return [void]
42
43
  def begin message, percentage
43
44
  @kind = 'begin'
44
45
  @message = message
@@ -47,6 +48,7 @@ module Solargraph
47
48
 
48
49
  # @param message [String]
49
50
  # @param percentage [Integer]
51
+ # @return [void]
50
52
  def report message, percentage
51
53
  @kind = 'report'
52
54
  @message = message
@@ -54,6 +56,7 @@ module Solargraph
54
56
  end
55
57
 
56
58
  # @param message [String]
59
+ # @return [void]
57
60
  def finish message
58
61
  @kind = 'end'
59
62
  @message = message
@@ -62,6 +65,7 @@ module Solargraph
62
65
  end
63
66
 
64
67
  # @param host [Solargraph::LanguageServer::Host]
68
+ # @return [void]
65
69
  def send host
66
70
  return unless host.client_supports_progress? && !finished?
67
71
 
@@ -91,6 +95,7 @@ module Solargraph
91
95
  @status = CREATED
92
96
  end
93
97
 
98
+ # @return [Hash]
94
99
  def build
95
100
  {
96
101
  token: uuid,
@@ -101,6 +106,7 @@ module Solargraph
101
106
  }
102
107
  end
103
108
 
109
+ # @return [Hash]
104
110
  def build_value
105
111
  case kind
106
112
  when 'begin'
@@ -115,6 +121,7 @@ module Solargraph
115
121
  end
116
122
 
117
123
  # @param host [Host]
124
+ # @return [void]
118
125
  def keep_alive host
119
126
  mutex.synchronize { @last = Time.now }
120
127
  @keep_alive ||= Thread.new do
@@ -127,6 +134,7 @@ module Solargraph
127
134
  end
128
135
  end
129
136
 
137
+ # @return [Mutex]
130
138
  def mutex
131
139
  @mutex ||= Mutex.new
132
140
  end
@@ -16,6 +16,7 @@ module Solargraph
16
16
  @block.call(result) unless @block.nil?
17
17
  end
18
18
 
19
+ # @return [void]
19
20
  def send_response
20
21
  # noop
21
22
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'pathname'
4
4
  require 'observer'
5
+ require 'open3'
5
6
 
6
7
  module Solargraph
7
8
  # A Library handles coordination between a Workspace and an ApiMap.
@@ -327,9 +328,10 @@ module Solargraph
327
328
 
328
329
  # @param query [String]
329
330
  # @return [Enumerable<YARD::CodeObjects::Base>]
331
+ # @return [Array(ApiMap, Enumerable<Pin::Base>)]
330
332
  def document query
331
333
  sync_catalog
332
- mutex.synchronize { api_map.document query }
334
+ mutex.synchronize { [api_map, api_map.get_path_pins(query)] }
333
335
  end
334
336
 
335
337
  # @param query [String]
@@ -400,8 +402,8 @@ module Solargraph
400
402
  repargs = {}
401
403
  workspace.config.reporters.each do |line|
402
404
  if line == 'all!'
403
- Diagnostics.reporters.each do |reporter|
404
- repargs[reporter] ||= []
405
+ Diagnostics.reporters.each do |reporter_name|
406
+ repargs[Diagnostics.reporter(reporter_name)] ||= []
405
407
  end
406
408
  else
407
409
  args = line.split(':').map(&:strip)
@@ -430,21 +432,11 @@ module Solargraph
430
432
  Bench.new(
431
433
  source_maps: source_map_hash.values,
432
434
  workspace: workspace,
433
- external_requires: external_requires
435
+ external_requires: external_requires,
436
+ live_map: @current ? source_map_hash[@current.filename] : nil
434
437
  )
435
438
  end
436
439
 
437
- # Get an array of foldable ranges for the specified file.
438
- #
439
- # @deprecated The library should not need to handle folding ranges. The
440
- # source itself has all the information it needs.
441
- #
442
- # @param filename [String]
443
- # @return [Array<Range>]
444
- def folding_ranges filename
445
- read(filename).folding_ranges
446
- end
447
-
448
440
  # Create a library from a directory.
449
441
  #
450
442
  # @param directory [String] The path to be used for the workspace
@@ -508,7 +500,7 @@ module Solargraph
508
500
 
509
501
  private
510
502
 
511
- # @return [Hash{String => Set<String>}]
503
+ # @return [Hash{String => Array<String>}]
512
504
  def source_map_external_require_hash
513
505
  @source_map_external_require_hash ||= {}
514
506
  end
@@ -516,6 +508,7 @@ module Solargraph
516
508
  # @param source_map [SourceMap]
517
509
  # @return [void]
518
510
  def find_external_requires source_map
511
+ # @type [Set<String>]
519
512
  new_set = source_map.requires.map(&:name).to_set
520
513
  # return if new_set == source_map_external_require_hash[source_map.filename]
521
514
  _filenames = nil
@@ -586,28 +579,54 @@ module Solargraph
586
579
  # @return [void]
587
580
  def cache_next_gemspec
588
581
  return if @cache_progress
589
- spec = api_map.uncached_gemspecs.find { |spec| !cache_errors.include?(spec) }
582
+
583
+ spec = cacheable_specs.first
590
584
  return end_cache_progress unless spec
591
585
 
592
586
  pending = api_map.uncached_gemspecs.length - cache_errors.length - 1
593
- logger.info "Caching #{spec.name} #{spec.version}"
594
- Thread.new do
595
- cache_pid = Process.spawn(workspace.command_path, 'cache', spec.name, spec.version.to_s)
596
- report_cache_progress spec.name, pending
597
- Process.wait(cache_pid)
598
- logger.info "Cached #{spec.name} #{spec.version}"
599
- rescue Errno::EINVAL => _e
600
- logger.info "Cached #{spec.name} #{spec.version} with EINVAL"
601
- rescue StandardError => e
602
- cache_errors.add spec
603
- Solargraph.logger.warn "Error caching gemspec #{spec.name} #{spec.version}: [#{e.class}] #{e.message}"
604
- ensure
605
- end_cache_progress
587
+
588
+ if Yardoc.processing?(spec)
589
+ logger.info "Enqueuing cache of #{spec.name} #{spec.version} (already being processed)"
590
+ queued_gemspec_cache.push(spec)
591
+ return if pending - queued_gemspec_cache.length < 1
592
+
606
593
  catalog
607
594
  sync_catalog
595
+ else
596
+ logger.info "Caching #{spec.name} #{spec.version}"
597
+ Thread.new do
598
+ report_cache_progress spec.name, pending
599
+ _o, e, s = Open3.capture3(workspace.command_path, 'cache', spec.name, spec.version.to_s)
600
+ if s.success?
601
+ logger.info "Cached #{spec.name} #{spec.version}"
602
+ else
603
+ cache_errors.add spec
604
+ logger.warn "Error caching gemspec #{spec.name} #{spec.version}"
605
+ logger.warn e
606
+ end
607
+ end_cache_progress
608
+ catalog
609
+ sync_catalog
610
+ end
608
611
  end
609
612
  end
610
613
 
614
+ # @return [Array<Gem::Specification>]
615
+ def cacheable_specs
616
+ cacheable = api_map.uncached_yard_gemspecs +
617
+ api_map.uncached_rbs_collection_gemspecs -
618
+ queued_gemspec_cache -
619
+ cache_errors.to_a
620
+ return cacheable unless cacheable.empty?
621
+
622
+ queued_gemspec_cache
623
+ end
624
+
625
+ # @return [Array<Gem::Specification>]
626
+ def queued_gemspec_cache
627
+ @queued_gemspec_cache ||= []
628
+ end
629
+
611
630
  # @param gem_name [String]
612
631
  # @param pending [Integer]
613
632
  # @return [void]
@@ -645,15 +664,17 @@ module Solargraph
645
664
  @total = nil
646
665
  end
647
666
 
667
+ # @return [void]
648
668
  def sync_catalog
649
669
  return if @sync_count == 0
650
670
 
651
671
  mutex.synchronize do
652
672
  logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
653
- api_map.catalog bench
654
673
  source_map_hash.values.each { |map| find_external_requires(map) }
674
+ api_map.catalog bench
655
675
  logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
656
- logger.info "#{api_map.uncached_gemspecs.length} uncached gemspecs"
676
+ logger.info "#{api_map.uncached_yard_gemspecs.length} uncached YARD gemspecs"
677
+ logger.info "#{api_map.uncached_rbs_collection_gemspecs.length} uncached RBS collection gemspecs"
657
678
  cache_next_gemspec
658
679
  @sync_count = 0
659
680
  end
@@ -25,11 +25,33 @@ module Solargraph
25
25
  [filename, range]
26
26
  end
27
27
 
28
+ # @param other [self]
29
+ def <=>(other)
30
+ return nil unless other.is_a?(Location)
31
+ if filename == other.filename
32
+ range <=> other.range
33
+ else
34
+ filename <=> other.filename
35
+ end
36
+ end
37
+
38
+ def rbs?
39
+ filename.end_with?('.rbs')
40
+ end
41
+
28
42
  # @param location [self]
29
43
  def contain? location
30
44
  range.contain?(location.range.start) && range.contain?(location.range.ending) && filename == location.filename
31
45
  end
32
46
 
47
+ def inspect
48
+ "<#{self.class.name}: filename=#{filename}, range=#{range.inspect}>"
49
+ end
50
+
51
+ def to_s
52
+ inspect
53
+ end
54
+
33
55
  # @return [Hash]
34
56
  def to_hash
35
57
  {
@@ -39,6 +61,7 @@ module Solargraph
39
61
  end
40
62
 
41
63
  # @param node [Parser::AST::Node, nil]
64
+ # @return [Location, nil]
42
65
  def self.from_node(node)
43
66
  return nil if node.nil? || node.loc.nil?
44
67
  range = Range.from_node(node)
@@ -11,8 +11,18 @@ module Solargraph
11
11
  'info' => Logger::INFO,
12
12
  'debug' => Logger::DEBUG
13
13
  }
14
-
15
- @@logger = Logger.new(STDERR, level: DEFAULT_LOG_LEVEL)
14
+ configured_level = ENV.fetch('SOLARGRAPH_LOG', nil)
15
+ level = if LOG_LEVELS.keys.include?(configured_level)
16
+ LOG_LEVELS.fetch(configured_level)
17
+ else
18
+ if configured_level
19
+ warn "Invalid value for SOLARGRAPH_LOG: #{configured_level.inspect} - " \
20
+ "valid values are #{LOG_LEVELS.keys}"
21
+ end
22
+ DEFAULT_LOG_LEVEL
23
+ end
24
+ @@logger = Logger.new(STDERR, level: level)
25
+ # @sg-ignore Fix cvar issue
16
26
  @@logger.formatter = proc do |severity, datetime, progname, msg|
17
27
  "[#{severity}] #{msg}\n"
18
28
  end
@@ -27,8 +27,10 @@ module Solargraph
27
27
  end
28
28
 
29
29
  # @param text [String]
30
+ # @sg-ignore https://github.com/lsegal/yard/pull/1615
30
31
  # @return [String]
31
32
  def htmlify text
33
+ # @type [String]
32
34
  YARD::Templates::Helpers::Markup::RDocMarkup.new(text).to_html
33
35
  end
34
36
 
@@ -70,8 +72,10 @@ module Solargraph
70
72
  # @param template [String]
71
73
  # @param layout [Boolean]
72
74
  # @param locals [Hash]
75
+ # @sg-ignore
73
76
  # @return [String]
74
77
  def render template, layout: true, locals: {}
78
+ # @type [String]
75
79
  @render_method.call(template, layout: layout, locals: locals)
76
80
  end
77
81
 
@@ -3,6 +3,13 @@ require 'ripper'
3
3
  module Solargraph
4
4
  module Parser
5
5
  class CommentRipper < Ripper::SexpBuilderPP
6
+ # @!override Ripper::SexpBuilder#on_embdoc_beg
7
+ # @return [Array(Symbol, String, Array)]
8
+ # @!override Ripper::SexpBuilder#on_embdoc
9
+ # @return [Array(Symbol, String, Array)]
10
+ # @!override Ripper::SexpBuilder#on_embdoc_end
11
+ # @return [Array(Symbol, String, Array)]
12
+
6
13
  # @param src [String]
7
14
  # @param filename [String]
8
15
  # @param lineno [Integer]
@@ -13,6 +20,8 @@ module Solargraph
13
20
  end
14
21
 
15
22
  def on_comment *args
23
+ # @sg-ignore
24
+ # @type [Array(Symbol, String, Array([Integer, nil], [Integer, nil]))]
16
25
  result = super
17
26
  if @buffer_lines[result[2][0]][0..result[2][1]].strip =~ /^#/
18
27
  chomped = result[1].chomp
@@ -24,28 +33,32 @@ module Solargraph
24
33
  result
25
34
  end
26
35
 
36
+ # @param result [Array(Symbol, String, Array([Integer, nil], [Integer, nil]))]
37
+ # @return [void]
38
+ def create_snippet(result)
39
+ chomped = result[1].chomp
40
+ @comments[result[2][0]] = Snippet.new(Range.from_to(result[2][0] || 0, result[2][1] || 0, result[2][0] || 0, (result[2][1] || 0) + chomped.length), chomped)
41
+ end
42
+
27
43
  def on_embdoc_beg *args
28
44
  result = super
29
- chomped = result[1].chomp
30
- @comments[result[2][0]] = Snippet.new(Range.from_to(result[2][0], result[2][1], result[2][0], result[2][1] + chomped.length), chomped)
45
+ create_snippet(result)
31
46
  result
32
47
  end
33
48
 
34
49
  def on_embdoc *args
35
50
  result = super
36
- chomped = result[1].chomp
37
- @comments[result[2][0]] = Snippet.new(Range.from_to(result[2][0], result[2][1], result[2][0], result[2][1] + chomped.length), chomped)
51
+ create_snippet(result)
38
52
  result
39
53
  end
40
54
 
41
55
  def on_embdoc_end *args
42
56
  result = super
43
- chomped = result[1].chomp
44
- @comments[result[2][0]] = Snippet.new(Range.from_to(result[2][0], result[2][1], result[2][0], result[2][1] + chomped.length), chomped)
57
+ create_snippet(result)
45
58
  result
46
59
  end
47
60
 
48
- # @return [Hash{Integer => String}]
61
+ # @return [Hash{Integer => Solargraph::Parser::Snippet}]
49
62
  def parse
50
63
  @comments = {}
51
64
  super