solargraph 0.56.0 → 0.58.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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/linting.yml +127 -0
  4. data/.github/workflows/plugins.yml +183 -7
  5. data/.github/workflows/rspec.yml +55 -5
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.gitignore +5 -0
  8. data/.overcommit.yml +72 -0
  9. data/.rspec +1 -0
  10. data/.rubocop.yml +66 -0
  11. data/.rubocop_todo.yml +1279 -0
  12. data/.yardopts +1 -0
  13. data/CHANGELOG.md +86 -1
  14. data/README.md +8 -4
  15. data/Rakefile +125 -13
  16. data/bin/solargraph +3 -0
  17. data/lib/solargraph/api_map/cache.rb +3 -2
  18. data/lib/solargraph/api_map/constants.rb +279 -0
  19. data/lib/solargraph/api_map/index.rb +49 -31
  20. data/lib/solargraph/api_map/source_to_yard.rb +13 -4
  21. data/lib/solargraph/api_map/store.rb +144 -26
  22. data/lib/solargraph/api_map.rb +217 -245
  23. data/lib/solargraph/bench.rb +1 -0
  24. data/lib/solargraph/complex_type/type_methods.rb +6 -0
  25. data/lib/solargraph/complex_type/unique_type.rb +19 -12
  26. data/lib/solargraph/complex_type.rb +24 -3
  27. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  28. data/lib/solargraph/convention/base.rb +17 -0
  29. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  30. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  31. data/lib/solargraph/convention/data_definition.rb +105 -0
  32. data/lib/solargraph/convention/gemspec.rb +3 -2
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -2
  35. data/lib/solargraph/convention/struct_definition.rb +87 -24
  36. data/lib/solargraph/convention.rb +32 -2
  37. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  38. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  39. data/lib/solargraph/doc_map.rb +52 -18
  40. data/lib/solargraph/environ.rb +9 -2
  41. data/lib/solargraph/equality.rb +1 -0
  42. data/lib/solargraph/gem_pins.rb +21 -11
  43. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  44. data/lib/solargraph/language_server/host/message_worker.rb +3 -0
  45. data/lib/solargraph/language_server/host.rb +12 -5
  46. data/lib/solargraph/language_server/message/base.rb +2 -1
  47. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
  48. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  49. data/lib/solargraph/language_server/message/text_document/formatting.rb +19 -2
  50. data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
  51. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  52. data/lib/solargraph/language_server/progress.rb +8 -0
  53. data/lib/solargraph/language_server/request.rb +4 -1
  54. data/lib/solargraph/library.rb +50 -33
  55. data/lib/solargraph/location.rb +3 -0
  56. data/lib/solargraph/logging.rb +11 -2
  57. data/lib/solargraph/page.rb +3 -0
  58. data/lib/solargraph/parser/comment_ripper.rb +8 -1
  59. data/lib/solargraph/parser/flow_sensitive_typing.rb +33 -5
  60. data/lib/solargraph/parser/node_processor/base.rb +10 -5
  61. data/lib/solargraph/parser/node_processor.rb +24 -8
  62. data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -13
  63. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  64. data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
  65. data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -16
  66. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
  68. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +1 -21
  69. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
  71. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +0 -22
  72. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +65 -8
  73. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
  74. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +1 -0
  75. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
  76. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +36 -16
  77. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +1 -0
  78. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  79. data/lib/solargraph/parser/region.rb +3 -0
  80. data/lib/solargraph/parser/snippet.rb +2 -0
  81. data/lib/solargraph/pin/base.rb +92 -14
  82. data/lib/solargraph/pin/base_variable.rb +6 -5
  83. data/lib/solargraph/pin/block.rb +3 -2
  84. data/lib/solargraph/pin/callable.rb +14 -1
  85. data/lib/solargraph/pin/closure.rb +5 -7
  86. data/lib/solargraph/pin/common.rb +6 -2
  87. data/lib/solargraph/pin/constant.rb +2 -0
  88. data/lib/solargraph/pin/local_variable.rb +1 -2
  89. data/lib/solargraph/pin/method.rb +32 -11
  90. data/lib/solargraph/pin/method_alias.rb +3 -0
  91. data/lib/solargraph/pin/parameter.rb +24 -10
  92. data/lib/solargraph/pin/proxy_type.rb +5 -1
  93. data/lib/solargraph/pin/reference/override.rb +15 -1
  94. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  95. data/lib/solargraph/pin/reference.rb +17 -0
  96. data/lib/solargraph/pin/search.rb +6 -1
  97. data/lib/solargraph/pin/signature.rb +2 -0
  98. data/lib/solargraph/pin/symbol.rb +5 -0
  99. data/lib/solargraph/pin_cache.rb +64 -4
  100. data/lib/solargraph/position.rb +3 -0
  101. data/lib/solargraph/range.rb +5 -0
  102. data/lib/solargraph/rbs_map/conversions.rb +68 -18
  103. data/lib/solargraph/rbs_map/core_fills.rb +18 -0
  104. data/lib/solargraph/rbs_map/core_map.rb +14 -7
  105. data/lib/solargraph/rbs_map.rb +14 -1
  106. data/lib/solargraph/shell.rb +85 -1
  107. data/lib/solargraph/source/chain/call.rb +7 -3
  108. data/lib/solargraph/source/chain/constant.rb +3 -66
  109. data/lib/solargraph/source/chain/if.rb +1 -1
  110. data/lib/solargraph/source/chain/link.rb +11 -2
  111. data/lib/solargraph/source/chain/or.rb +1 -1
  112. data/lib/solargraph/source/chain.rb +11 -2
  113. data/lib/solargraph/source/change.rb +2 -2
  114. data/lib/solargraph/source/cursor.rb +2 -3
  115. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  116. data/lib/solargraph/source/source_chainer.rb +1 -1
  117. data/lib/solargraph/source.rb +6 -3
  118. data/lib/solargraph/source_map/clip.rb +18 -26
  119. data/lib/solargraph/source_map/data.rb +4 -0
  120. data/lib/solargraph/source_map/mapper.rb +2 -2
  121. data/lib/solargraph/source_map.rb +28 -16
  122. data/lib/solargraph/type_checker/param_def.rb +2 -0
  123. data/lib/solargraph/type_checker/rules.rb +30 -8
  124. data/lib/solargraph/type_checker.rb +301 -186
  125. data/lib/solargraph/version.rb +5 -5
  126. data/lib/solargraph/workspace/config.rb +22 -6
  127. data/lib/solargraph/workspace/require_paths.rb +97 -0
  128. data/lib/solargraph/workspace.rb +38 -67
  129. data/lib/solargraph/yard_map/helpers.rb +29 -1
  130. data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -5
  131. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -9
  132. data/lib/solargraph/yard_map/mapper/to_namespace.rb +8 -7
  133. data/lib/solargraph/yard_map/to_method.rb +2 -1
  134. data/lib/solargraph/yardoc.rb +41 -3
  135. data/lib/solargraph.rb +15 -0
  136. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  137. data/rbs/fills/open3/0/open3.rbs +172 -0
  138. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  139. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  140. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  141. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  142. data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
  143. data/rbs_collection.yaml +4 -4
  144. data/sig/shims/ast/0/node.rbs +5 -0
  145. data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
  146. data/sig/shims/ast/2.4/ast.rbs +73 -0
  147. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  148. data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
  149. data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
  150. data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  151. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  152. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  153. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  154. data/solargraph.gemspec +26 -5
  155. metadata +187 -15
  156. data/lib/.rubocop.yml +0 -22
  157. data/lib/solargraph/parser/node_methods.rb +0 -97
@@ -94,7 +94,8 @@ module Solargraph
94
94
  # processed, caller is responsible for sending the response.
95
95
  #
96
96
  # @param request [Hash{String => unspecified}] The contents of the message.
97
- # @return [Solargraph::LanguageServer::Message::Base, nil] The message handler.
97
+ #
98
+ # @return [Solargraph::LanguageServer::Message::Base, Solargraph::LanguageServer::Request, nil] The message handler.
98
99
  def receive request
99
100
  if request['method']
100
101
  logger.info "Host received ##{request['id']} #{request['method']}"
@@ -299,6 +300,7 @@ module Solargraph
299
300
  end
300
301
  end
301
302
 
303
+ # @return [String]
302
304
  def command_path
303
305
  options['commandPath'] || 'solargraph'
304
306
  end
@@ -502,6 +504,7 @@ module Solargraph
502
504
  name: 'new',
503
505
  scope: :class,
504
506
  location: pin.location,
507
+ # @sg-ignore Unresolved call to parameters on Solargraph::Pin::Base
505
508
  parameters: pin.parameters,
506
509
  return_type: ComplexType.try_parse(params['data']['path']),
507
510
  comments: pin.comments,
@@ -533,7 +536,7 @@ module Solargraph
533
536
  # @param uri [String]
534
537
  # @param line [Integer]
535
538
  # @param column [Integer]
536
- # @return [Solargraph::SourceMap::Completion]
539
+ # @return [Solargraph::SourceMap::Completion, nil]
537
540
  def completions_at uri, line, column
538
541
  library = library_for(uri)
539
542
  library.completions_at uri_to_file(uri), line, column
@@ -547,7 +550,7 @@ module Solargraph
547
550
  # @param uri [String]
548
551
  # @param line [Integer]
549
552
  # @param column [Integer]
550
- # @return [Array<Solargraph::Pin::Base>]
553
+ # @return [Array<Solargraph::Pin::Base>, nil]
551
554
  def definitions_at uri, line, column
552
555
  library = library_for(uri)
553
556
  library.definitions_at(uri_to_file(uri), line, column)
@@ -556,7 +559,7 @@ module Solargraph
556
559
  # @param uri [String]
557
560
  # @param line [Integer]
558
561
  # @param column [Integer]
559
- # @return [Array<Solargraph::Pin::Base>]
562
+ # @return [Array<Solargraph::Pin::Base>, nil]
560
563
  def type_definitions_at uri, line, column
561
564
  library = library_for(uri)
562
565
  library.type_definitions_at(uri_to_file(uri), line, column)
@@ -580,6 +583,10 @@ module Solargraph
580
583
  def references_from uri, line, column, strip: true, only: false
581
584
  library = library_for(uri)
582
585
  library.references_from(uri_to_file(uri), line, column, strip: strip, only: only)
586
+ rescue FileNotFoundError, InvalidOffsetError => e
587
+ Solargraph.logger.warn "[#{e.class}] #{e.message}"
588
+ Solargraph.logger.debug e.backtrace
589
+ []
583
590
  end
584
591
 
585
592
  # @param query [String]
@@ -716,7 +723,7 @@ module Solargraph
716
723
  # A hash of client requests by ID. The host uses this to keep track of
717
724
  # pending responses.
718
725
  #
719
- # @return [Hash{Integer => Solargraph::LanguageServer::Host}]
726
+ # @return [Hash{Integer => Solargraph::LanguageServer::Request}]
720
727
  def requests
721
728
  @requests ||= {}
722
729
  end
@@ -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,7 +83,7 @@ module Solargraph
83
83
  @fetched = true
84
84
  begin
85
85
  @available ||= begin
86
- # @sg-ignore
86
+ # @sg-ignore Variable type could not be inferred for tuple
87
87
  # @type [Gem::Dependency, nil]
88
88
  tuple = CheckGemVersion.fetcher.search_for_dependency(Gem::Dependency.new('solargraph')).flatten.first
89
89
  if tuple.nil?
@@ -10,6 +10,7 @@ module Solargraph::LanguageServer::Message::TextDocument
10
10
 
11
11
  private
12
12
 
13
+ # @return [Array<Hash>, nil]
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>, nil]
24
26
  def require_location
25
27
  # @todo Terrible hack
26
28
  lib = host.library_for(params['textDocument']['uri'])
@@ -18,10 +18,18 @@ module Solargraph
18
18
 
19
19
  require_rubocop(config['version'])
20
20
  options, paths = ::RuboCop::Options.new.parse(args)
21
+ # @sg-ignore Unresolved call to []=
21
22
  options[:stdin] = original
22
- corrections = redirect_stdout do
23
- ::RuboCop::Runner.new(options, ::RuboCop::ConfigStore.new).run(paths)
23
+
24
+ # Ensure only one instance of RuboCop::Runner is running at
25
+ # a time - it uses 'chdir' to read config files with ERB,
26
+ # which can conflict with other chdirs.
27
+ corrections = Solargraph::CHDIR_MUTEX.synchronize do
28
+ redirect_stdout do
29
+ ::RuboCop::Runner.new(options, ::RuboCop::ConfigStore.new).run(paths)
30
+ end
24
31
  end
32
+ # @sg-ignore Unresolved call to []=
25
33
  result = options[:stdin]
26
34
 
27
35
  log_corrections(corrections)
@@ -34,6 +42,7 @@ module Solargraph
34
42
  private
35
43
 
36
44
  # @param corrections [String]
45
+ # @return [void]
37
46
  def log_corrections(corrections)
38
47
  corrections = corrections&.strip
39
48
  return if corrections&.empty?
@@ -45,6 +54,8 @@ module Solargraph
45
54
  end
46
55
  end
47
56
 
57
+ # @param file_uri [String]
58
+ # @return [Hash{String => undefined}]
48
59
  def config_for(file_uri)
49
60
  conf = host.formatter_config(file_uri)
50
61
  return {} unless conf.is_a?(Hash)
@@ -52,7 +63,9 @@ module Solargraph
52
63
  conf['rubocop'] || {}
53
64
  end
54
65
 
66
+ # @param file_uri [String]
55
67
  # @param config [Hash{String => String}]
68
+ # @return [Array<String>]
56
69
  def cli_args file_uri, config
57
70
  file = UriHelpers.uri_to_file(file_uri)
58
71
  args = [
@@ -71,6 +84,8 @@ module Solargraph
71
84
  end
72
85
 
73
86
  # @param config [Hash{String => String}]
87
+ # @sg-ignore
88
+ # @return [Class<RuboCop::Formatter::BaseFormatter>]
74
89
  def formatter_class(config)
75
90
  if self.class.const_defined?('BlankRubocopFormatter')
76
91
  # @sg-ignore
@@ -83,7 +98,9 @@ module Solargraph
83
98
  end
84
99
 
85
100
  # @param value [Array, String]
101
+ # @return [String, nil]
86
102
  def cop_list(value)
103
+ # @type [String]
87
104
  value = value.join(',') if value.respond_to?(:join)
88
105
  return nil if value == '' || !value.is_a?(String)
89
106
  value
@@ -10,6 +10,7 @@ module Solargraph::LanguageServer::Message::TextDocument
10
10
 
11
11
  private
12
12
 
13
+ # @return [Array<Hash>, nil]
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 [Thread::Mutex]
130
138
  def mutex
131
139
  @mutex ||= Mutex.new
132
140
  end
@@ -11,11 +11,14 @@ module Solargraph
11
11
  end
12
12
 
13
13
  # @param result [Object]
14
- # @return [void]
14
+ # @generic T
15
+ # @yieldreturn [generic<T>]
16
+ # @return [generic<T>, nil]
15
17
  def process result
16
18
  @block.call(result) unless @block.nil?
17
19
  end
18
20
 
21
+ # @return [void]
19
22
  def send_response
20
23
  # noop
21
24
  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.
@@ -258,11 +259,11 @@ module Solargraph
258
259
  referenced&.path == pin.path
259
260
  end
260
261
  if pin.path == 'Class#new'
261
- caller = cursor.chain.base.infer(api_map, clip.send(:block), clip.locals).first
262
+ caller = cursor.chain.base.infer(api_map, clip.send(:closure), clip.locals).first
262
263
  if caller.defined?
263
264
  found.select! do |loc|
264
265
  clip = api_map.clip_at(loc.filename, loc.range.start)
265
- other = clip.send(:cursor).chain.base.infer(api_map, clip.send(:block), clip.locals).first
266
+ other = clip.send(:cursor).chain.base.infer(api_map, clip.send(:closure), clip.locals).first
266
267
  caller == other
267
268
  end
268
269
  else
@@ -401,8 +402,8 @@ module Solargraph
401
402
  repargs = {}
402
403
  workspace.config.reporters.each do |line|
403
404
  if line == 'all!'
404
- Diagnostics.reporters.each do |reporter|
405
- repargs[reporter] ||= []
405
+ Diagnostics.reporters.each do |reporter_name|
406
+ repargs[Diagnostics.reporter(reporter_name)] ||= []
406
407
  end
407
408
  else
408
409
  args = line.split(':').map(&:strip)
@@ -436,17 +437,6 @@ module Solargraph
436
437
  )
437
438
  end
438
439
 
439
- # Get an array of foldable ranges for the specified file.
440
- #
441
- # @deprecated The library should not need to handle folding ranges. The
442
- # source itself has all the information it needs.
443
- #
444
- # @param filename [String]
445
- # @return [Array<Range>]
446
- def folding_ranges filename
447
- read(filename).folding_ranges
448
- end
449
-
450
440
  # Create a library from a directory.
451
441
  #
452
442
  # @param directory [String] The path to be used for the workspace
@@ -510,7 +500,7 @@ module Solargraph
510
500
 
511
501
  private
512
502
 
513
- # @return [Hash{String => Set<String>}]
503
+ # @return [Hash{String => Array<String>}]
514
504
  def source_map_external_require_hash
515
505
  @source_map_external_require_hash ||= {}
516
506
  end
@@ -518,6 +508,7 @@ module Solargraph
518
508
  # @param source_map [SourceMap]
519
509
  # @return [void]
520
510
  def find_external_requires source_map
511
+ # @type [Set<String>]
521
512
  new_set = source_map.requires.map(&:name).to_set
522
513
  # return if new_set == source_map_external_require_hash[source_map.filename]
523
514
  _filenames = nil
@@ -531,7 +522,7 @@ module Solargraph
531
522
  @external_requires = nil
532
523
  end
533
524
 
534
- # @return [Mutex]
525
+ # @return [Thread::Mutex]
535
526
  def mutex
536
527
  @mutex ||= Mutex.new
537
528
  end
@@ -588,29 +579,54 @@ module Solargraph
588
579
  # @return [void]
589
580
  def cache_next_gemspec
590
581
  return if @cache_progress
591
- spec = (api_map.uncached_yard_gemspecs + api_map.uncached_rbs_collection_gemspecs).
592
- find { |spec| !cache_errors.include?(spec) }
582
+
583
+ spec = cacheable_specs.first
593
584
  return end_cache_progress unless spec
594
585
 
595
586
  pending = api_map.uncached_gemspecs.length - cache_errors.length - 1
596
- logger.info "Caching #{spec.name} #{spec.version}"
597
- Thread.new do
598
- cache_pid = Process.spawn(workspace.command_path, 'cache', spec.name, spec.version.to_s)
599
- report_cache_progress spec.name, pending
600
- Process.wait(cache_pid)
601
- logger.info "Cached #{spec.name} #{spec.version}"
602
- rescue Errno::EINVAL => _e
603
- logger.info "Cached #{spec.name} #{spec.version} with EINVAL"
604
- rescue StandardError => e
605
- cache_errors.add spec
606
- Solargraph.logger.warn "Error caching gemspec #{spec.name} #{spec.version}: [#{e.class}] #{e.message}"
607
- ensure
608
- 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
+
609
593
  catalog
610
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
611
611
  end
612
612
  end
613
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
+
614
630
  # @param gem_name [String]
615
631
  # @param pending [Integer]
616
632
  # @return [void]
@@ -648,13 +664,14 @@ module Solargraph
648
664
  @total = nil
649
665
  end
650
666
 
667
+ # @return [void]
651
668
  def sync_catalog
652
669
  return if @sync_count == 0
653
670
 
654
671
  mutex.synchronize do
655
672
  logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
656
- api_map.catalog bench
657
673
  source_map_hash.values.each { |map| find_external_requires(map) }
674
+ api_map.catalog bench
658
675
  logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
659
676
  logger.info "#{api_map.uncached_yard_gemspecs.length} uncached YARD gemspecs"
660
677
  logger.info "#{api_map.uncached_rbs_collection_gemspecs.length} uncached RBS collection gemspecs"
@@ -25,6 +25,7 @@ module Solargraph
25
25
  [filename, range]
26
26
  end
27
27
 
28
+ # @param other [self]
28
29
  def <=>(other)
29
30
  return nil unless other.is_a?(Location)
30
31
  if filename == other.filename
@@ -60,6 +61,7 @@ module Solargraph
60
61
  end
61
62
 
62
63
  # @param node [Parser::AST::Node, nil]
64
+ # @return [Location, nil]
63
65
  def self.from_node(node)
64
66
  return nil if node.nil? || node.loc.nil?
65
67
  range = Range.from_node(node)
@@ -69,6 +71,7 @@ module Solargraph
69
71
  # @param other [BasicObject]
70
72
  def == other
71
73
  return false unless other.is_a?(Location)
74
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
72
75
  filename == other.filename and range == other.range
73
76
  end
74
77
 
@@ -11,8 +11,17 @@ 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)
16
25
  # @sg-ignore Fix cvar issue
17
26
  @@logger.formatter = proc do |severity, datetime, progname, msg|
18
27
  "[#{severity}] #{msg}\n"
@@ -29,6 +29,7 @@ module Solargraph
29
29
  # @param text [String]
30
30
  # @return [String]
31
31
  def htmlify text
32
+ # @type [String]
32
33
  YARD::Templates::Helpers::Markup::RDocMarkup.new(text).to_html
33
34
  end
34
35
 
@@ -70,8 +71,10 @@ module Solargraph
70
71
  # @param template [String]
71
72
  # @param layout [Boolean]
72
73
  # @param locals [Hash]
74
+ # @sg-ignore
73
75
  # @return [String]
74
76
  def render template, layout: true, locals: {}
77
+ # @type [String]
75
78
  @render_method.call(template, layout: layout, locals: locals)
76
79
  end
77
80
 
@@ -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]
@@ -51,7 +58,7 @@ module Solargraph
51
58
  result
52
59
  end
53
60
 
54
- # @return [Hash{Integer => String}]
61
+ # @return [Hash{Integer => Solargraph::Parser::Snippet}]
55
62
  def parse
56
63
  @comments = {}
57
64
  super
@@ -4,14 +4,20 @@ module Solargraph
4
4
  include Solargraph::Parser::NodeMethods
5
5
 
6
6
  # @param locals [Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
7
+ # @param enclosing_breakable_pin [Solargraph::Pin::Breakable, nil]
7
8
  def initialize(locals, enclosing_breakable_pin = nil)
8
9
  @locals = locals
9
10
  @enclosing_breakable_pin = enclosing_breakable_pin
10
11
  end
11
12
 
12
13
  # @param and_node [Parser::AST::Node]
14
+ # @param true_ranges [Array<Range>]
15
+ #
16
+ # @return [void]
13
17
  def process_and(and_node, true_ranges = [])
18
+ # @type [Parser::AST::Node]
14
19
  lhs = and_node.children[0]
20
+ # @type [Parser::AST::Node]
15
21
  rhs = and_node.children[1]
16
22
 
17
23
  before_rhs_loc = rhs.location.expression.adjust(begin_pos: -1)
@@ -23,6 +29,8 @@ module Solargraph
23
29
  end
24
30
 
25
31
  # @param if_node [Parser::AST::Node]
32
+ #
33
+ # @return [void]
26
34
  def process_if(if_node)
27
35
  #
28
36
  # See if we can refine a type based on the result of 'if foo.nil?'
@@ -36,7 +44,9 @@ module Solargraph
36
44
  # s(:send, nil, :bar))
37
45
  # [4] pry(main)>
38
46
  conditional_node = if_node.children[0]
47
+ # @type [Parser::AST::Node]
39
48
  then_clause = if_node.children[1]
49
+ # @type [Parser::AST::Node]
40
50
  else_clause = if_node.children[2]
41
51
 
42
52
  true_ranges = []
@@ -72,8 +82,11 @@ module Solargraph
72
82
  # them based on the Closure and Location.
73
83
  #
74
84
  # @param pins [Array<Pin::LocalVariable>]
85
+ # @param name [String]
75
86
  # @param closure [Pin::Closure]
76
87
  # @param location [Location]
88
+ #
89
+ # @return [Array<Pin::LocalVariable>]
77
90
  def self.visible_pins(pins, name, closure, location)
78
91
  logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location})" }
79
92
  pins_with_name = pins.select { |p| p.name == name }
@@ -107,7 +120,10 @@ module Solargraph
107
120
  private
108
121
 
109
122
  # @param pin [Pin::LocalVariable]
110
- # @param if_node [Parser::AST::Node]
123
+ # @param downcast_type_name [String]
124
+ # @param presence [Range]
125
+ #
126
+ # @return [void]
111
127
  def add_downcast_local(pin, downcast_type_name, presence)
112
128
  # @todo Create pin#update method
113
129
  new_pin = Solargraph::Pin::LocalVariable.new(
@@ -126,6 +142,7 @@ module Solargraph
126
142
 
127
143
  # @param facts_by_pin [Hash{Pin::LocalVariable => Array<Hash{Symbol => String}>}]
128
144
  # @param presences [Array<Range>]
145
+ #
129
146
  # @return [void]
130
147
  def process_facts(facts_by_pin, presences)
131
148
  #
@@ -142,6 +159,9 @@ module Solargraph
142
159
  end
143
160
 
144
161
  # @param conditional_node [Parser::AST::Node]
162
+ # @param true_ranges [Array<Range>]
163
+ #
164
+ # @return [void]
145
165
  def process_conditional(conditional_node, true_ranges)
146
166
  if conditional_node.type == :send
147
167
  process_isa(conditional_node, true_ranges)
@@ -151,7 +171,7 @@ module Solargraph
151
171
  end
152
172
 
153
173
  # @param isa_node [Parser::AST::Node]
154
- # @return [Array(String, String)]
174
+ # @return [Array(String, String), nil]
155
175
  def parse_isa(isa_node)
156
176
  return unless isa_node&.type == :send && isa_node.children[1] == :is_a?
157
177
  # Check if conditional node follows this pattern:
@@ -176,12 +196,20 @@ module Solargraph
176
196
  [isa_type_name, variable_name]
177
197
  end
178
198
 
199
+ # @param variable_name [String]
200
+ # @param position [Position]
201
+ #
202
+ # @return [Solargraph::Pin::LocalVariable, nil]
179
203
  def find_local(variable_name, position)
180
204
  pins = locals.select { |pin| pin.name == variable_name && pin.presence.include?(position) }
181
205
  return unless pins.length == 1
182
206
  pins.first
183
207
  end
184
208
 
209
+ # @param isa_node [Parser::AST::Node]
210
+ # @param true_presences [Array<Range>]
211
+ #
212
+ # @return [void]
185
213
  def process_isa(isa_node, true_presences)
186
214
  isa_type_name, variable_name = parse_isa(isa_node)
187
215
  return if variable_name.nil? || variable_name.empty?
@@ -197,10 +225,12 @@ module Solargraph
197
225
  end
198
226
 
199
227
  # @param node [Parser::AST::Node]
228
+ #
229
+ # @return [String, nil]
200
230
  def type_name(node)
201
231
  # e.g.,
202
232
  # s(:const, nil, :Baz)
203
- return unless node.type == :const
233
+ return unless node&.type == :const
204
234
  module_node = node.children[0]
205
235
  class_node = node.children[1]
206
236
 
@@ -212,8 +242,6 @@ module Solargraph
212
242
  "#{module_type_name}::#{class_node}"
213
243
  end
214
244
 
215
- # @todo "return type could not be inferred" should not trigger here
216
- # @sg-ignore
217
245
  # @param clause_node [Parser::AST::Node]
218
246
  def always_breaks?(clause_node)
219
247
  clause_node&.type == :break