solargraph 0.58.2 → 0.59.0.dev.1

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 (154) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +40 -36
  5. data/.github/workflows/rspec.yml +45 -13
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.gitignore +0 -1
  8. data/.rubocop_todo.yml +27 -49
  9. data/CHANGELOG.md +1 -7
  10. data/README.md +3 -3
  11. data/Rakefile +1 -0
  12. data/lib/solargraph/api_map/cache.rb +3 -3
  13. data/lib/solargraph/api_map/constants.rb +13 -3
  14. data/lib/solargraph/api_map/index.rb +22 -11
  15. data/lib/solargraph/api_map/source_to_yard.rb +13 -1
  16. data/lib/solargraph/api_map/store.rb +11 -8
  17. data/lib/solargraph/api_map.rb +105 -50
  18. data/lib/solargraph/complex_type/conformance.rb +176 -0
  19. data/lib/solargraph/complex_type/type_methods.rb +16 -2
  20. data/lib/solargraph/complex_type/unique_type.rb +170 -20
  21. data/lib/solargraph/complex_type.rb +119 -14
  22. data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
  23. data/lib/solargraph/convention/data_definition.rb +4 -1
  24. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  25. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +1 -0
  26. data/lib/solargraph/convention/struct_definition.rb +5 -1
  27. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  28. data/lib/solargraph/diagnostics/rubocop.rb +1 -0
  29. data/lib/solargraph/diagnostics/rubocop_helpers.rb +2 -0
  30. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  31. data/lib/solargraph/doc_map.rb +134 -373
  32. data/lib/solargraph/equality.rb +1 -1
  33. data/lib/solargraph/gem_pins.rb +14 -15
  34. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  35. data/lib/solargraph/language_server/host/dispatch.rb +1 -0
  36. data/lib/solargraph/language_server/host/message_worker.rb +2 -1
  37. data/lib/solargraph/language_server/host/sources.rb +1 -0
  38. data/lib/solargraph/language_server/host.rb +6 -1
  39. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -7
  40. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  41. data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
  42. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  43. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -0
  44. data/lib/solargraph/language_server/message/text_document/formatting.rb +2 -0
  45. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  46. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -0
  47. data/lib/solargraph/language_server/message/text_document/type_definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -0
  49. data/lib/solargraph/library.rb +59 -13
  50. data/lib/solargraph/location.rb +9 -4
  51. data/lib/solargraph/logging.rb +21 -1
  52. data/lib/solargraph/parser/comment_ripper.rb +7 -0
  53. data/lib/solargraph/parser/flow_sensitive_typing.rb +330 -102
  54. data/lib/solargraph/parser/node_processor/base.rb +32 -2
  55. data/lib/solargraph/parser/node_processor.rb +7 -6
  56. data/lib/solargraph/parser/parser_gem/class_methods.rb +28 -10
  57. data/lib/solargraph/parser/parser_gem/node_chainer.rb +31 -6
  58. data/lib/solargraph/parser/parser_gem/node_methods.rb +27 -7
  59. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  60. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +2 -0
  61. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  62. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -11
  63. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +7 -0
  64. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  65. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +3 -2
  66. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  68. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +2 -2
  69. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  71. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  72. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +1 -0
  73. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +12 -7
  74. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  75. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +5 -1
  76. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  77. data/lib/solargraph/parser/region.rb +9 -3
  78. data/lib/solargraph/parser/snippet.rb +1 -1
  79. data/lib/solargraph/pin/base.rb +53 -21
  80. data/lib/solargraph/pin/base_variable.rb +312 -20
  81. data/lib/solargraph/pin/block.rb +26 -4
  82. data/lib/solargraph/pin/breakable.rb +5 -1
  83. data/lib/solargraph/pin/callable.rb +50 -3
  84. data/lib/solargraph/pin/closure.rb +2 -6
  85. data/lib/solargraph/pin/common.rb +20 -5
  86. data/lib/solargraph/pin/compound_statement.rb +55 -0
  87. data/lib/solargraph/pin/conversions.rb +2 -1
  88. data/lib/solargraph/pin/delegated_method.rb +15 -4
  89. data/lib/solargraph/pin/documenting.rb +1 -0
  90. data/lib/solargraph/pin/instance_variable.rb +5 -1
  91. data/lib/solargraph/pin/keyword.rb +0 -4
  92. data/lib/solargraph/pin/local_variable.rb +13 -57
  93. data/lib/solargraph/pin/method.rb +90 -42
  94. data/lib/solargraph/pin/method_alias.rb +8 -0
  95. data/lib/solargraph/pin/namespace.rb +7 -1
  96. data/lib/solargraph/pin/parameter.rb +76 -13
  97. data/lib/solargraph/pin/proxy_type.rb +2 -1
  98. data/lib/solargraph/pin/reference/override.rb +1 -1
  99. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  100. data/lib/solargraph/pin/reference.rb +2 -0
  101. data/lib/solargraph/pin/search.rb +1 -0
  102. data/lib/solargraph/pin/signature.rb +8 -0
  103. data/lib/solargraph/pin/symbol.rb +1 -1
  104. data/lib/solargraph/pin/until.rb +1 -1
  105. data/lib/solargraph/pin/while.rb +1 -1
  106. data/lib/solargraph/pin.rb +2 -0
  107. data/lib/solargraph/pin_cache.rb +477 -57
  108. data/lib/solargraph/position.rb +12 -26
  109. data/lib/solargraph/range.rb +6 -6
  110. data/lib/solargraph/rbs_map/conversions.rb +33 -10
  111. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  112. data/lib/solargraph/rbs_map/stdlib_map.rb +34 -5
  113. data/lib/solargraph/rbs_map.rb +74 -20
  114. data/lib/solargraph/shell.rb +73 -28
  115. data/lib/solargraph/source/chain/call.rb +52 -17
  116. data/lib/solargraph/source/chain/constant.rb +2 -0
  117. data/lib/solargraph/source/chain/hash.rb +1 -0
  118. data/lib/solargraph/source/chain/if.rb +1 -0
  119. data/lib/solargraph/source/chain/instance_variable.rb +22 -1
  120. data/lib/solargraph/source/chain/literal.rb +5 -0
  121. data/lib/solargraph/source/chain/or.rb +9 -1
  122. data/lib/solargraph/source/chain.rb +25 -22
  123. data/lib/solargraph/source/change.rb +9 -2
  124. data/lib/solargraph/source/cursor.rb +7 -1
  125. data/lib/solargraph/source/source_chainer.rb +13 -3
  126. data/lib/solargraph/source/updater.rb +4 -0
  127. data/lib/solargraph/source.rb +33 -7
  128. data/lib/solargraph/source_map/clip.rb +13 -2
  129. data/lib/solargraph/source_map/data.rb +4 -1
  130. data/lib/solargraph/source_map/mapper.rb +24 -1
  131. data/lib/solargraph/source_map.rb +14 -6
  132. data/lib/solargraph/type_checker/problem.rb +3 -1
  133. data/lib/solargraph/type_checker/rules.rb +75 -2
  134. data/lib/solargraph/type_checker.rb +111 -30
  135. data/lib/solargraph/version.rb +1 -1
  136. data/lib/solargraph/workspace/config.rb +3 -1
  137. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  138. data/lib/solargraph/workspace/require_paths.rb +1 -0
  139. data/lib/solargraph/workspace.rb +158 -16
  140. data/lib/solargraph/yard_map/helpers.rb +2 -1
  141. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -1
  142. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  143. data/lib/solargraph/yard_map/mapper.rb +5 -0
  144. data/lib/solargraph/yardoc.rb +33 -23
  145. data/lib/solargraph.rb +24 -3
  146. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  147. data/rbs/fills/tuple/tuple.rbs +28 -0
  148. data/rbs/shims/ast/0/node.rbs +1 -1
  149. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  150. data/solargraph.gemspec +2 -1
  151. metadata +12 -7
  152. data/lib/solargraph/type_checker/checks.rb +0 -124
  153. data/lib/solargraph/type_checker/param_def.rb +0 -37
  154. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -1,89 +1,89 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module LanguageServer
5
- class Host
6
- # An asynchronous diagnosis reporter.
7
- #
8
- class Diagnoser
9
- # @param host [Host]
10
- def initialize host
11
- @host = host
12
- @mutex = Mutex.new
13
- @queue = []
14
- @stopped = true
15
- end
16
-
17
- # Schedule a file to be diagnosed.
18
- #
19
- # @param uri [String]
20
- # @return [void]
21
- def schedule uri
22
- mutex.synchronize { queue.push uri }
23
- end
24
-
25
- # Stop the diagnosis thread.
26
- #
27
- # @return [void]
28
- def stop
29
- @stopped = true
30
- end
31
-
32
- # True is the diagnoser is stopped.
33
- #
34
- # @return [Boolean]
35
- def stopped?
36
- @stopped
37
- end
38
-
39
- # Start the diagnosis thread.
40
- #
41
- # @return [self, nil]
42
- def start
43
- return unless @stopped
44
- @stopped = false
45
- Thread.new do
46
- until stopped?
47
- tick
48
- sleep 0.1
49
- end
50
- end
51
- self
52
- end
53
-
54
- # Perform diagnoses.
55
- #
56
- # @return [void]
57
- def tick
58
- return if queue.empty? || host.synchronizing?
59
- if !host.options['diagnostics']
60
- mutex.synchronize { queue.clear }
61
- return
62
- end
63
- current = mutex.synchronize { queue.shift }
64
- return if queue.include?(current)
65
- begin
66
- host.diagnose current
67
- rescue InvalidOffsetError
68
- # @todo This error can occur when the Source is out of sync with
69
- # with the ApiMap. It's probably not the best way to handle it,
70
- # but it's quick and easy.
71
- Logging.logger.warn "Deferring diagnosis due to invalid offset: #{current}"
72
- mutex.synchronize { queue.push current }
73
- end
74
- end
75
-
76
- private
77
-
78
- # @return [Host]
79
- attr_reader :host
80
-
81
- # @return [Mutex]
82
- attr_reader :mutex
83
-
84
- # @return [::Array]
85
- attr_reader :queue
86
- end
87
- end
88
- end
89
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module LanguageServer
5
+ class Host
6
+ # An asynchronous diagnosis reporter.
7
+ #
8
+ class Diagnoser
9
+ # @param host [Host]
10
+ def initialize host
11
+ @host = host
12
+ @mutex = Mutex.new
13
+ @queue = []
14
+ @stopped = true
15
+ end
16
+
17
+ # Schedule a file to be diagnosed.
18
+ #
19
+ # @param uri [String]
20
+ # @return [void]
21
+ def schedule uri
22
+ mutex.synchronize { queue.push uri }
23
+ end
24
+
25
+ # Stop the diagnosis thread.
26
+ #
27
+ # @return [void]
28
+ def stop
29
+ @stopped = true
30
+ end
31
+
32
+ # True is the diagnoser is stopped.
33
+ #
34
+ # @return [Boolean]
35
+ def stopped?
36
+ @stopped
37
+ end
38
+
39
+ # Start the diagnosis thread.
40
+ #
41
+ # @return [self, nil]
42
+ def start
43
+ return unless @stopped
44
+ @stopped = false
45
+ Thread.new do
46
+ until stopped?
47
+ tick
48
+ sleep 0.1
49
+ end
50
+ end
51
+ self
52
+ end
53
+
54
+ # Perform diagnoses.
55
+ #
56
+ # @return [void]
57
+ def tick
58
+ return if queue.empty? || host.synchronizing?
59
+ if !host.options['diagnostics']
60
+ mutex.synchronize { queue.clear }
61
+ return
62
+ end
63
+ current = mutex.synchronize { queue.shift }
64
+ return if queue.include?(current)
65
+ begin
66
+ host.diagnose current
67
+ rescue InvalidOffsetError
68
+ # @todo This error can occur when the Source is out of sync with
69
+ # with the ApiMap. It's probably not the best way to handle it,
70
+ # but it's quick and easy.
71
+ Logging.logger.warn "Deferring diagnosis due to invalid offset: #{current}"
72
+ mutex.synchronize { queue.push current }
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ # @return [Host]
79
+ attr_reader :host
80
+
81
+ # @return [Mutex]
82
+ attr_reader :mutex
83
+
84
+ # @return [::Array]
85
+ attr_reader :queue
86
+ end
87
+ end
88
+ end
89
+ end
@@ -33,6 +33,7 @@ module Solargraph
33
33
  # @return [void]
34
34
  def update_libraries uri
35
35
  src = sources.find(uri)
36
+ # @sg-ignore Need to add nil check here
36
37
  using = libraries.select { |lib| lib.contain?(src.filename) }
37
38
  using.push library_for(uri) if using.empty?
38
39
  using.each { |lib| lib.merge src }
@@ -28,7 +28,7 @@ module Solargraph
28
28
  end
29
29
 
30
30
  # pending handle messages
31
- # @return [Array<Hash>]
31
+ # @return [Array<Hash{String => undefined}>]
32
32
  def messages
33
33
  @messages ||= []
34
34
  end
@@ -66,6 +66,7 @@ module Solargraph
66
66
  @resource.wait(@mutex) if messages.empty?
67
67
  next_message
68
68
  end
69
+ # @sg-ignore Need to add nil check here
69
70
  handler = @host.receive(message)
70
71
  handler&.send_response
71
72
  end
@@ -55,6 +55,7 @@ module Solargraph
55
55
  # @raise [FileNotFoundError] if the URI does not match an open source.
56
56
  #
57
57
  # @param uri [String]
58
+ # @sg-ignore flow ensitive typing should understand raise
58
59
  # @return [Solargraph::Source]
59
60
  def find uri
60
61
  open_source_hash[uri] || raise(Solargraph::FileNotFoundError, "Host could not find #{uri}")
@@ -105,6 +105,7 @@ module Solargraph
105
105
  message.process unless cancel?(request['id'])
106
106
  rescue StandardError => e
107
107
  logger.warn "Error processing request: [#{e.class}] #{e.message}"
108
+ # @sg-ignore Need to add nil check here
108
109
  logger.warn e.backtrace.join("\n")
109
110
  message.set_error Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}"
110
111
  end
@@ -300,8 +301,11 @@ module Solargraph
300
301
  end
301
302
  end
302
303
 
304
+ # @sg-ignore Need to validate config
303
305
  # @return [String]
306
+ # @sg-ignore Need to validate config
304
307
  def command_path
308
+ # @type [String]
305
309
  options['commandPath'] || 'solargraph'
306
310
  end
307
311
 
@@ -729,9 +733,11 @@ module Solargraph
729
733
  end
730
734
 
731
735
  # @param path [String]
736
+ # @sg-ignore Need to be able to choose signature on String#gsub
732
737
  # @return [String]
733
738
  def normalize_separators path
734
739
  return path if File::ALT_SEPARATOR.nil?
740
+ # @sg-ignore flow sensitive typing needs to handle constants
735
741
  path.gsub(File::ALT_SEPARATOR, File::SEPARATOR)
736
742
  end
737
743
 
@@ -765,7 +771,6 @@ module Solargraph
765
771
  return change if source.code.length + 1 != change['text'].length
766
772
  diffs = Diff::LCS.diff(source.code, change['text'])
767
773
  return change if diffs.length.zero? || diffs.length > 1 || diffs.first.length > 1
768
- # @sg-ignore push this upstream
769
774
  # @type [Diff::LCS::Change]
770
775
  diff = diffs.first.first
771
776
  return change unless diff.adding? && ['.', ':', '(', ',', ' '].include?(diff.element)
@@ -1,12 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
 
4
- # @todo PR the RBS gem to add this
5
- # @!parse
6
- # module ::Gem
7
- # class SpecFetcher; end
8
- # end
9
-
10
4
  module Solargraph
11
5
  module LanguageServer
12
6
  module Message
@@ -64,6 +58,7 @@ module Solargraph
64
58
  end
65
59
  elsif fetched?
66
60
  Solargraph::Logging.logger.warn error
61
+ # @sg-ignore Need to add nil check here
67
62
  host.show_message(error, MessageTypes::ERROR) if params['verbose']
68
63
  end
69
64
  set_result({
@@ -78,12 +73,12 @@ module Solargraph
78
73
  attr_reader :current
79
74
 
80
75
  # @return [Gem::Version]
76
+ # @sg-ignore Need to add nil check here
81
77
  def available
82
78
  if !@available && !@fetched
83
79
  @fetched = true
84
80
  begin
85
81
  @available ||= begin
86
- # @sg-ignore Variable type could not be inferred for tuple
87
82
  # @type [Gem::Dependency, nil]
88
83
  tuple = CheckGemVersion.fetcher.search_for_dependency(Gem::Dependency.new('solargraph')).flatten.first
89
84
  if tuple.nil?
@@ -14,6 +14,7 @@ module Solargraph
14
14
  )
15
15
  rescue StandardError => e
16
16
  Solargraph.logger.warn "Error processing document: [#{e.class}] #{e.message}"
17
+ # @sg-ignore Need to add nil check here
17
18
  Solargraph.logger.debug e.backtrace.join("\n")
18
19
  end
19
20
  end
@@ -15,6 +15,7 @@ module Solargraph
15
15
  items = []
16
16
  last_context = nil
17
17
  idx = -1
18
+ # @sg-ignore Need to add nil check here
18
19
  completion.pins.each do |pin|
19
20
  idx += 1 if last_context != pin.context
20
21
  items.push pin.completion_item.merge({
@@ -37,6 +38,7 @@ module Solargraph
37
38
  end
38
39
  rescue FileNotFoundError => e
39
40
  Logging.logger.warn "[#{e.class}] #{e.message}"
41
+ # @sg-ignore Need to add nil check here
40
42
  Logging.logger.warn e.backtrace.join("\n")
41
43
  set_result empty_result
42
44
  end
@@ -13,7 +13,9 @@ module Solargraph::LanguageServer::Message::TextDocument
13
13
  # @return [Array<Hash>, nil]
14
14
  def code_location
15
15
  suggestions = host.definitions_at(params['textDocument']['uri'], @line, @column)
16
+ # @sg-ignore Need to add nil check here
16
17
  return nil if suggestions.empty?
18
+ # @sg-ignore Need to add nil check here
17
19
  suggestions.reject { |pin| pin.best_location.nil? || pin.best_location.filename.nil? }.map do |pin|
18
20
  {
19
21
  uri: file_to_uri(pin.best_location.filename),
@@ -13,7 +13,9 @@ class Solargraph::LanguageServer::Message::TextDocument::DocumentSymbol < Solarg
13
13
  containerName: pin.namespace,
14
14
  kind: pin.symbol_kind,
15
15
  location: {
16
+ # @sg-ignore Need to add nil check here
16
17
  uri: file_to_uri(pin.best_location.filename),
18
+ # @sg-ignore Need to add nil check here
17
19
  range: pin.best_location.range.to_hash
18
20
  },
19
21
  deprecated: pin.deprecated?
@@ -98,9 +98,11 @@ module Solargraph
98
98
  end
99
99
 
100
100
  # @param value [Array, String]
101
+ #
101
102
  # @return [String, nil]
102
103
  def cop_list(value)
103
104
  # @type [String]
105
+ # @sg-ignore Translate to something flow sensitive typing understands
104
106
  value = value.join(',') if value.respond_to?(:join)
105
107
  return nil if value == '' || !value.is_a?(String)
106
108
  value
@@ -11,6 +11,7 @@ module Solargraph
11
11
  contents = []
12
12
  suggestions = host.definitions_at(params['textDocument']['uri'], line, col)
13
13
  last_link = nil
14
+ # @sg-ignore Need to add nil check here
14
15
  suggestions.each do |pin|
15
16
  parts = []
16
17
  this_link = host.options['enablePages'] ? pin.link_documentation : pin.text_documentation
@@ -31,6 +32,7 @@ module Solargraph
31
32
  )
32
33
  rescue FileNotFoundError => e
33
34
  Logging.logger.warn "[#{e.class}] #{e.message}"
35
+ # @sg-ignore Need to add nil check here
34
36
  Logging.logger.warn e.backtrace.join("\n")
35
37
  set_result nil
36
38
  end
@@ -14,6 +14,7 @@ module Solargraph
14
14
  })
15
15
  rescue FileNotFoundError => e
16
16
  Logging.logger.warn "[#{e.class}] #{e.message}"
17
+ # @sg-ignore Need to add nil check here
17
18
  Logging.logger.warn e.backtrace.join("\n")
18
19
  set_result nil
19
20
  end
@@ -13,7 +13,9 @@ module Solargraph::LanguageServer::Message::TextDocument
13
13
  # @return [Array<Hash>, nil]
14
14
  def code_location
15
15
  suggestions = host.type_definitions_at(params['textDocument']['uri'], @line, @column)
16
+ # @sg-ignore Need to add nil check here
16
17
  return nil if suggestions.empty?
18
+ # @sg-ignore Need to add nil check here
17
19
  suggestions.reject { |pin| pin.best_location.nil? || pin.best_location.filename.nil? }.map do |pin|
18
20
  {
19
21
  uri: file_to_uri(pin.best_location.filename),
@@ -6,6 +6,7 @@ class Solargraph::LanguageServer::Message::Workspace::WorkspaceSymbol < Solargra
6
6
  def process
7
7
  pins = host.query_symbols(params['query'])
8
8
  info = pins.map do |pin|
9
+ # @sg-ignore Need to add nil check here
9
10
  uri = file_to_uri(pin.best_location.filename)
10
11
  {
11
12
  name: pin.path,
@@ -13,6 +14,7 @@ class Solargraph::LanguageServer::Message::Workspace::WorkspaceSymbol < Solargra
13
14
  kind: pin.symbol_kind,
14
15
  location: {
15
16
  uri: uri,
17
+ # @sg-ignore Need to add nil check here
16
18
  range: pin.best_location.range.to_hash
17
19
  },
18
20
  deprecated: pin.deprecated?
@@ -1,9 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rubygems'
3
4
  require 'pathname'
4
5
  require 'observer'
5
6
  require 'open3'
6
7
 
8
+ # @!parse
9
+ # class ::Gem::Specification
10
+ # # @return [String]
11
+ # def name; end
12
+ # end
13
+
7
14
  module Solargraph
8
15
  # A Library handles coordination between a Workspace and an ApiMap.
9
16
  #
@@ -33,6 +40,7 @@ module Solargraph
33
40
  # @type [Source, nil]
34
41
  @current = nil
35
42
  @sync_count = 0
43
+ @cache_progress = nil
36
44
  end
37
45
 
38
46
  def inspect
@@ -57,8 +65,11 @@ module Solargraph
57
65
  # @param source [Source, nil]
58
66
  # @return [void]
59
67
  def attach source
68
+ # @sg-ignore Need to add nil check here
60
69
  if @current && (!source || @current.filename != source.filename) && source_map_hash.key?(@current.filename) && !workspace.has_file?(@current.filename)
70
+ # @sg-ignore Need to add nil check here
61
71
  source_map_hash.delete @current.filename
72
+ # @sg-ignore Need to add nil check here
62
73
  source_map_external_require_hash.delete @current.filename
63
74
  @external_requires = nil
64
75
  end
@@ -182,9 +193,14 @@ module Solargraph
182
193
  if cursor.comment?
183
194
  source = read(filename)
184
195
  offset = Solargraph::Position.to_offset(source.code, Solargraph::Position.new(line, column))
196
+ # @sg-ignore Need to add nil check here
197
+ # @type [MatchData, nil]
185
198
  lft = source.code[0..offset-1].match(/\[[a-z0-9_:<, ]*?([a-z0-9_:]*)\z/i)
199
+ # @sg-ignore Need to add nil check here
200
+ # @type [MatchData, nil]
186
201
  rgt = source.code[offset..-1].match(/^([a-z0-9_]*)(:[a-z0-9_:]*)?[\]>, ]/i)
187
202
  if lft && rgt
203
+ # @sg-ignore Need to add nil check here
188
204
  tag = (lft[1] + rgt[1]).sub(/:+$/, '')
189
205
  clip = mutex.synchronize { api_map.clip(cursor) }
190
206
  clip.translate tag
@@ -255,15 +271,19 @@ module Solargraph
255
271
  files.uniq(&:filename).each do |source|
256
272
  found = source.references(pin.name)
257
273
  found.select! do |loc|
274
+ # @sg-ignore Need to add nil check here
275
+ # @type [Solargraph::Pin::Base, nil]
258
276
  referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character).first
259
277
  referenced&.path == pin.path
260
278
  end
261
279
  if pin.path == 'Class#new'
280
+ # @todo flow sensitive typing should allow shadowing of Kernel#caller
262
281
  caller = cursor.chain.base.infer(api_map, clip.send(:closure), clip.locals).first
263
282
  if caller.defined?
264
283
  found.select! do |loc|
265
284
  clip = api_map.clip_at(loc.filename, loc.range.start)
266
285
  other = clip.send(:cursor).chain.base.infer(api_map, clip.send(:closure), clip.locals).first
286
+ # @todo flow sensitive typing should allow shadowing of Kernel#caller
267
287
  caller == other
268
288
  end
269
289
  else
@@ -273,12 +293,13 @@ module Solargraph
273
293
  # HACK: for language clients that exclude special characters from the start of variable names
274
294
  if strip && match = cursor.word.match(/^[^a-z0-9_]+/i)
275
295
  found.map! do |loc|
276
- Solargraph::Location.new(loc.filename, Solargraph::Range.from_to(loc.range.start.line, loc.range.start.column + match[0].length, loc.range.ending.line, loc.range.ending.column))
296
+ Solargraph::Location.new(loc.filename,
297
+ # @sg-ignore flow sensitive typing needs to handle if foo = bar
298
+ Solargraph::Range.from_to(loc.range.start.line, loc.range.start.column + match[0].length, loc.range.ending.line,
299
+ loc.range.ending.column))
277
300
  end
278
301
  end
279
- result.concat(found.sort do |a, b|
280
- a.range.start.line <=> b.range.start.line
281
- end)
302
+ result.concat(found.sort { |a, b| a.range.start.line <=> b.range.start.line })
282
303
  end
283
304
  result.uniq
284
305
  end
@@ -299,13 +320,12 @@ module Solargraph
299
320
  def locate_ref location
300
321
  map = source_map_hash[location.filename]
301
322
  return if map.nil?
323
+ # @sg-ignore Need to add nil check here
302
324
  pin = map.requires.select { |p| p.location.range.contain?(location.range.start) }.first
303
325
  return nil if pin.nil?
304
326
  # @param full [String]
305
327
  return_if_match = proc do |full|
306
- if source_map_hash.key?(full)
307
- return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0))
308
- end
328
+ return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0)) if source_map_hash.key?(full)
309
329
  end
310
330
  workspace.require_paths.each do |path|
311
331
  full = File.join path, pin.name
@@ -403,6 +423,7 @@ module Solargraph
403
423
  workspace.config.reporters.each do |line|
404
424
  if line == 'all!'
405
425
  Diagnostics.reporters.each do |reporter_name|
426
+ # @sg-ignore Need to add nil check here
406
427
  repargs[Diagnostics.reporter(reporter_name)] ||= []
407
428
  end
408
429
  else
@@ -410,7 +431,9 @@ module Solargraph
410
431
  name = args.shift
411
432
  reporter = Diagnostics.reporter(name)
412
433
  raise DiagnosticsError, "Diagnostics reporter #{name} does not exist" if reporter.nil?
434
+ # @sg-ignore flow sensitive typing needs to handle 'raise if'
413
435
  repargs[reporter] ||= []
436
+ # @sg-ignore flow sensitive typing needs to handle 'raise if'
414
437
  repargs[reporter].concat args
415
438
  end
416
439
  end
@@ -433,6 +456,7 @@ module Solargraph
433
456
  source_maps: source_map_hash.values,
434
457
  workspace: workspace,
435
458
  external_requires: external_requires,
459
+ # @sg-ignore Need to add nil check here
436
460
  live_map: @current ? source_map_hash[@current.filename] : nil
437
461
  )
438
462
  end
@@ -469,10 +493,13 @@ module Solargraph
469
493
  # @return [SourceMap, Boolean]
470
494
  def next_map
471
495
  return false if mapped?
496
+ # @sg-ignore Need to add nil check here
472
497
  src = workspace.sources.find { |s| !source_map_hash.key?(s.filename) }
473
498
  if src
474
499
  Logging.logger.debug "Mapping #{src.filename}"
500
+ # @sg-ignore Need to add nil check here
475
501
  source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
502
+ # @sg-ignore Need to add nil check here
476
503
  source_map_hash[src.filename]
477
504
  else
478
505
  false
@@ -482,7 +509,9 @@ module Solargraph
482
509
  # @return [self]
483
510
  def map!
484
511
  workspace.sources.each do |src|
512
+ # @sg-ignore Need to add nil check here
485
513
  source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
514
+ # @sg-ignore Need to add nil check here
486
515
  find_external_requires source_map_hash[src.filename]
487
516
  end
488
517
  self
@@ -500,6 +529,11 @@ module Solargraph
500
529
 
501
530
  private
502
531
 
532
+ # @return [PinCache]
533
+ def pin_cache
534
+ workspace.pin_cache
535
+ end
536
+
503
537
  # @return [Hash{String => Array<String>}]
504
538
  def source_map_external_require_hash
505
539
  @source_map_external_require_hash ||= {}
@@ -513,6 +547,7 @@ module Solargraph
513
547
  # return if new_set == source_map_external_require_hash[source_map.filename]
514
548
  _filenames = nil
515
549
  filenames = ->{ _filenames ||= workspace.filenames.to_set }
550
+ # @sg-ignore Need to add nil check here
516
551
  source_map_external_require_hash[source_map.filename] = new_set.reject do |path|
517
552
  workspace.require_paths.any? do |base|
518
553
  full = File.join(base, path)
@@ -562,11 +597,15 @@ module Solargraph
562
597
  # @return [void]
563
598
  def maybe_map source
564
599
  return unless source
600
+ # @sg-ignore Need to add nil check here
565
601
  return unless @current == source || workspace.has_file?(source.filename)
602
+ # @sg-ignore Need to add nil check here
566
603
  if source_map_hash.key?(source.filename)
567
604
  new_map = Solargraph::SourceMap.map(source)
605
+ # @sg-ignore Need to add nil check here
568
606
  source_map_hash[source.filename] = new_map
569
607
  else
608
+ # @sg-ignore Need to add nil check here
570
609
  source_map_hash[source.filename] = Solargraph::SourceMap.map(source)
571
610
  end
572
611
  end
@@ -585,7 +624,7 @@ module Solargraph
585
624
 
586
625
  pending = api_map.uncached_gemspecs.length - cache_errors.length - 1
587
626
 
588
- if Yardoc.processing?(spec)
627
+ if pin_cache.yardoc_processing?(spec)
589
628
  logger.info "Enqueuing cache of #{spec.name} #{spec.version} (already being processed)"
590
629
  queued_gemspec_cache.push(spec)
591
630
  return if pending - queued_gemspec_cache.length < 1
@@ -596,7 +635,10 @@ module Solargraph
596
635
  logger.info "Caching #{spec.name} #{spec.version}"
597
636
  Thread.new do
598
637
  report_cache_progress spec.name, pending
599
- _o, e, s = Open3.capture3(workspace.command_path, 'cache', spec.name, spec.version.to_s)
638
+ kwargs = {}
639
+ kwargs[:chdir] = workspace.directory.to_s if workspace.directory && !workspace.directory.empty?
640
+ _o, e, s = Open3.capture3(workspace.command_path, 'cache', spec.name, spec.version.to_s,
641
+ **kwargs)
600
642
  if s.success?
601
643
  logger.info "Cached #{spec.name} #{spec.version}"
602
644
  else
@@ -613,8 +655,7 @@ module Solargraph
613
655
 
614
656
  # @return [Array<Gem::Specification>]
615
657
  def cacheable_specs
616
- cacheable = api_map.uncached_yard_gemspecs +
617
- api_map.uncached_rbs_collection_gemspecs -
658
+ cacheable = api_map.uncached_gemspecs +
618
659
  queued_gemspec_cache -
619
660
  cache_errors.to_a
620
661
  return cacheable unless cacheable.empty?
@@ -632,11 +673,15 @@ module Solargraph
632
673
  # @return [void]
633
674
  def report_cache_progress gem_name, pending
634
675
  @total ||= pending
676
+ # @sg-ignore flow sensitive typing needs better handling of ||= on lvars
635
677
  @total = pending if pending > @total
678
+ # @sg-ignore flow sensitive typing needs better handling of ||= on lvars
636
679
  finished = @total - pending
680
+ # @sg-ignore flow sensitive typing needs better handling of ||= on lvars
637
681
  pct = if @total.zero?
638
682
  0
639
683
  else
684
+ # @sg-ignore flow sensitive typing needs better handling of ||= on lvars
640
685
  ((finished.to_f / @total.to_f) * 100).to_i
641
686
  end
642
687
  message = "#{gem_name}#{pending > 0 ? " (+#{pending})" : ''}"
@@ -647,9 +692,11 @@ module Solargraph
647
692
  @cache_progress = LanguageServer::Progress.new('Caching gem')
648
693
  # If we don't send both a begin and a report, the progress notification
649
694
  # might get stuck in the status bar forever
695
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
650
696
  @cache_progress.begin(message, pct)
651
697
  changed
652
698
  notify_observers @cache_progress
699
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
653
700
  @cache_progress.report(message, pct)
654
701
  end
655
702
  changed
@@ -673,8 +720,7 @@ module Solargraph
673
720
  source_map_hash.values.each { |map| find_external_requires(map) }
674
721
  api_map.catalog bench
675
722
  logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
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"
723
+ logger.info "#{api_map.uncached_gemspecs.length} uncached gemspecs"
678
724
  cache_next_gemspec
679
725
  @sync_count = 0
680
726
  end