solargraph 0.56.2 → 0.58.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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +127 -0
  3. data/.github/workflows/plugins.yml +183 -7
  4. data/.github/workflows/rspec.yml +55 -5
  5. data/.github/workflows/typecheck.yml +6 -3
  6. data/.gitignore +5 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +1279 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +69 -0
  13. data/README.md +8 -4
  14. data/Rakefile +125 -13
  15. data/bin/solargraph +8 -5
  16. data/lib/solargraph/api_map/cache.rb +3 -2
  17. data/lib/solargraph/api_map/constants.rb +279 -0
  18. data/lib/solargraph/api_map/index.rb +49 -31
  19. data/lib/solargraph/api_map/source_to_yard.rb +13 -4
  20. data/lib/solargraph/api_map/store.rb +144 -26
  21. data/lib/solargraph/api_map.rb +217 -245
  22. data/lib/solargraph/bench.rb +1 -0
  23. data/lib/solargraph/complex_type/type_methods.rb +6 -0
  24. data/lib/solargraph/complex_type/unique_type.rb +19 -12
  25. data/lib/solargraph/complex_type.rb +24 -3
  26. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  27. data/lib/solargraph/convention/base.rb +17 -0
  28. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -0
  29. data/lib/solargraph/convention/data_definition/data_definition_node.rb +4 -2
  30. data/lib/solargraph/convention/data_definition.rb +2 -1
  31. data/lib/solargraph/convention/gemspec.rb +1 -1
  32. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  33. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +3 -1
  34. data/lib/solargraph/convention/struct_definition.rb +36 -13
  35. data/lib/solargraph/convention.rb +31 -2
  36. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  37. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  38. data/lib/solargraph/doc_map.rb +44 -13
  39. data/lib/solargraph/environ.rb +9 -2
  40. data/lib/solargraph/equality.rb +1 -0
  41. data/lib/solargraph/gem_pins.rb +21 -11
  42. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  43. data/lib/solargraph/language_server/host/message_worker.rb +3 -0
  44. data/lib/solargraph/language_server/host.rb +12 -5
  45. data/lib/solargraph/language_server/message/base.rb +2 -1
  46. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
  47. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/text_document/formatting.rb +19 -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 +4 -1
  53. data/lib/solargraph/library.rb +11 -18
  54. data/lib/solargraph/location.rb +3 -0
  55. data/lib/solargraph/logging.rb +11 -2
  56. data/lib/solargraph/page.rb +3 -0
  57. data/lib/solargraph/parser/comment_ripper.rb +8 -1
  58. data/lib/solargraph/parser/flow_sensitive_typing.rb +33 -5
  59. data/lib/solargraph/parser/node_processor/base.rb +1 -1
  60. data/lib/solargraph/parser/node_processor.rb +6 -2
  61. data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -13
  62. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  63. data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
  64. data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -16
  65. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
  66. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
  67. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
  68. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -0
  69. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +64 -8
  70. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
  71. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +36 -16
  72. data/lib/solargraph/parser/region.rb +3 -0
  73. data/lib/solargraph/parser/snippet.rb +2 -0
  74. data/lib/solargraph/pin/base.rb +77 -14
  75. data/lib/solargraph/pin/base_variable.rb +6 -5
  76. data/lib/solargraph/pin/block.rb +3 -2
  77. data/lib/solargraph/pin/callable.rb +14 -1
  78. data/lib/solargraph/pin/closure.rb +5 -7
  79. data/lib/solargraph/pin/common.rb +6 -2
  80. data/lib/solargraph/pin/constant.rb +2 -0
  81. data/lib/solargraph/pin/local_variable.rb +1 -2
  82. data/lib/solargraph/pin/method.rb +28 -9
  83. data/lib/solargraph/pin/method_alias.rb +3 -0
  84. data/lib/solargraph/pin/parameter.rb +24 -10
  85. data/lib/solargraph/pin/proxy_type.rb +5 -1
  86. data/lib/solargraph/pin/reference/override.rb +15 -1
  87. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  88. data/lib/solargraph/pin/reference.rb +17 -0
  89. data/lib/solargraph/pin/search.rb +6 -1
  90. data/lib/solargraph/pin/signature.rb +2 -0
  91. data/lib/solargraph/pin/symbol.rb +5 -0
  92. data/lib/solargraph/pin_cache.rb +64 -4
  93. data/lib/solargraph/position.rb +3 -0
  94. data/lib/solargraph/range.rb +5 -0
  95. data/lib/solargraph/rbs_map/conversions.rb +29 -6
  96. data/lib/solargraph/rbs_map/core_fills.rb +18 -0
  97. data/lib/solargraph/rbs_map/core_map.rb +14 -7
  98. data/lib/solargraph/rbs_map.rb +14 -1
  99. data/lib/solargraph/shell.rb +85 -1
  100. data/lib/solargraph/source/chain/call.rb +7 -3
  101. data/lib/solargraph/source/chain/constant.rb +3 -66
  102. data/lib/solargraph/source/chain/if.rb +1 -1
  103. data/lib/solargraph/source/chain/link.rb +11 -2
  104. data/lib/solargraph/source/chain/or.rb +1 -1
  105. data/lib/solargraph/source/chain.rb +11 -2
  106. data/lib/solargraph/source/change.rb +2 -2
  107. data/lib/solargraph/source/cursor.rb +2 -3
  108. data/lib/solargraph/source/source_chainer.rb +1 -1
  109. data/lib/solargraph/source.rb +6 -3
  110. data/lib/solargraph/source_map/clip.rb +18 -26
  111. data/lib/solargraph/source_map/data.rb +4 -0
  112. data/lib/solargraph/source_map/mapper.rb +2 -2
  113. data/lib/solargraph/source_map.rb +28 -16
  114. data/lib/solargraph/type_checker/param_def.rb +2 -0
  115. data/lib/solargraph/type_checker/rules.rb +30 -8
  116. data/lib/solargraph/type_checker.rb +301 -186
  117. data/lib/solargraph/version.rb +1 -1
  118. data/lib/solargraph/workspace/config.rb +21 -5
  119. data/lib/solargraph/workspace/require_paths.rb +97 -0
  120. data/lib/solargraph/workspace.rb +30 -67
  121. data/lib/solargraph/yard_map/mapper/to_method.rb +4 -3
  122. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  123. data/lib/solargraph/yard_map/to_method.rb +2 -1
  124. data/lib/solargraph/yardoc.rb +39 -3
  125. data/lib/solargraph.rb +2 -0
  126. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  127. data/rbs/fills/open3/0/open3.rbs +172 -0
  128. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  129. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  130. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  131. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  132. data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
  133. data/rbs_collection.yaml +4 -4
  134. data/sig/shims/ast/0/node.rbs +5 -0
  135. data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
  136. data/sig/shims/ast/2.4/ast.rbs +73 -0
  137. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  138. data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
  139. data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
  140. data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  141. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  142. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  143. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  144. data/solargraph.gemspec +26 -5
  145. metadata +181 -13
  146. data/lib/.rubocop.yml +0 -22
  147. data/lib/solargraph/parser/node_methods.rb +0 -97
@@ -259,11 +259,11 @@ module Solargraph
259
259
  referenced&.path == pin.path
260
260
  end
261
261
  if pin.path == 'Class#new'
262
- 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
263
263
  if caller.defined?
264
264
  found.select! do |loc|
265
265
  clip = api_map.clip_at(loc.filename, loc.range.start)
266
- 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
267
267
  caller == other
268
268
  end
269
269
  else
@@ -402,8 +402,8 @@ module Solargraph
402
402
  repargs = {}
403
403
  workspace.config.reporters.each do |line|
404
404
  if line == 'all!'
405
- Diagnostics.reporters.each do |reporter|
406
- repargs[reporter] ||= []
405
+ Diagnostics.reporters.each do |reporter_name|
406
+ repargs[Diagnostics.reporter(reporter_name)] ||= []
407
407
  end
408
408
  else
409
409
  args = line.split(':').map(&:strip)
@@ -437,17 +437,6 @@ module Solargraph
437
437
  )
438
438
  end
439
439
 
440
- # Get an array of foldable ranges for the specified file.
441
- #
442
- # @deprecated The library should not need to handle folding ranges. The
443
- # source itself has all the information it needs.
444
- #
445
- # @param filename [String]
446
- # @return [Array<Range>]
447
- def folding_ranges filename
448
- read(filename).folding_ranges
449
- end
450
-
451
440
  # Create a library from a directory.
452
441
  #
453
442
  # @param directory [String] The path to be used for the workspace
@@ -511,7 +500,7 @@ module Solargraph
511
500
 
512
501
  private
513
502
 
514
- # @return [Hash{String => Set<String>}]
503
+ # @return [Hash{String => Array<String>}]
515
504
  def source_map_external_require_hash
516
505
  @source_map_external_require_hash ||= {}
517
506
  end
@@ -519,6 +508,7 @@ module Solargraph
519
508
  # @param source_map [SourceMap]
520
509
  # @return [void]
521
510
  def find_external_requires source_map
511
+ # @type [Set<String>]
522
512
  new_set = source_map.requires.map(&:name).to_set
523
513
  # return if new_set == source_map_external_require_hash[source_map.filename]
524
514
  _filenames = nil
@@ -532,7 +522,7 @@ module Solargraph
532
522
  @external_requires = nil
533
523
  end
534
524
 
535
- # @return [Mutex]
525
+ # @return [Thread::Mutex]
536
526
  def mutex
537
527
  @mutex ||= Mutex.new
538
528
  end
@@ -621,6 +611,7 @@ module Solargraph
621
611
  end
622
612
  end
623
613
 
614
+ # @return [Array<Gem::Specification>]
624
615
  def cacheable_specs
625
616
  cacheable = api_map.uncached_yard_gemspecs +
626
617
  api_map.uncached_rbs_collection_gemspecs -
@@ -631,6 +622,7 @@ module Solargraph
631
622
  queued_gemspec_cache
632
623
  end
633
624
 
625
+ # @return [Array<Gem::Specification>]
634
626
  def queued_gemspec_cache
635
627
  @queued_gemspec_cache ||= []
636
628
  end
@@ -672,13 +664,14 @@ module Solargraph
672
664
  @total = nil
673
665
  end
674
666
 
667
+ # @return [void]
675
668
  def sync_catalog
676
669
  return if @sync_count == 0
677
670
 
678
671
  mutex.synchronize do
679
672
  logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
680
- api_map.catalog bench
681
673
  source_map_hash.values.each { |map| find_external_requires(map) }
674
+ api_map.catalog bench
682
675
  logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
683
676
  logger.info "#{api_map.uncached_yard_gemspecs.length} uncached YARD gemspecs"
684
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
@@ -13,7 +13,7 @@ module Solargraph
13
13
  # @return [Array<Pin::Base>]
14
14
  attr_reader :pins
15
15
 
16
- # @return [Array<Pin::BaseVariable>]
16
+ # @return [Array<Pin::LocalVariable>]
17
17
  attr_reader :locals
18
18
 
19
19
  # @param node [Parser::AST::Node]
@@ -9,7 +9,7 @@ module Solargraph
9
9
  autoload :Base, 'solargraph/parser/node_processor/base'
10
10
 
11
11
  class << self
12
- # @type [Hash<Symbol, Array<Class<NodeProcessor::Base>>>]
12
+ # @type [Hash{Symbol => Array<Class<NodeProcessor::Base>>}]
13
13
  @@processors ||= {}
14
14
 
15
15
  # Register a processor for a node type. You can register multiple processors for the same type.
@@ -17,12 +17,16 @@ module Solargraph
17
17
  #
18
18
  # @param type [Symbol]
19
19
  # @param cls [Class<NodeProcessor::Base>]
20
- # @return [Class<NodeProcessor::Base>]
20
+ # @return [Array<Class<NodeProcessor::Base>>]
21
21
  def register type, cls
22
22
  @@processors[type] ||= []
23
23
  @@processors[type] << cls
24
24
  end
25
25
 
26
+ # @param type [Symbol]
27
+ # @param cls [Class<NodeProcessor::Base>]
28
+ #
29
+ # @return [void]
26
30
  def deregister type, cls
27
31
  @@processors[type].delete(cls)
28
32
  end
@@ -2,22 +2,13 @@
2
2
 
3
3
  require 'prism'
4
4
 
5
- # Awaiting ability to use a version containing https://github.com/whitequark/parser/pull/1076
6
- #
7
- # @!parse
8
- # class ::Parser::Base < ::Parser::Builder
9
- # # @return [Integer]
10
- # def version; end
11
- # end
12
- # class ::Parser::CurrentRuby < ::Parser::Base; end
13
-
14
5
  module Solargraph
15
6
  module Parser
16
7
  module ParserGem
17
8
  module ClassMethods
18
9
  # @param code [String]
19
10
  # @param filename [String, nil]
20
- # @return [Array(Parser::AST::Node, Hash{Integer => String})]
11
+ # @return [Array(Parser::AST::Node, Hash{Integer => Solargraph::Parser::Snippet})]
21
12
  def parse_with_comments code, filename = nil
22
13
  node = parse(code, filename)
23
14
  comments = CommentRipper.new(code, filename, 0).parse
@@ -84,6 +75,7 @@ module Solargraph
84
75
  # @param top [AST::Node]
85
76
  # @return [Array<AST::Node>]
86
77
  def inner_node_references name, top
78
+ # @type [Array<AST::Node>]
87
79
  result = []
88
80
  if top.is_a?(AST::Node) && top.to_s.include?(":#{name}")
89
81
  result.push top if top.children.any? { |c| c.to_s == name }
@@ -137,9 +129,7 @@ module Solargraph
137
129
  def string_ranges node
138
130
  return [] unless is_ast_node?(node)
139
131
  result = []
140
- if node.type == :str
141
- result.push Range.from_node(node)
142
- end
132
+ result.push Range.from_node(node) if node.type == :str
143
133
  node.children.each do |child|
144
134
  result.concat string_ranges(child)
145
135
  end
@@ -9,6 +9,7 @@ module Solargraph
9
9
  class FlawedBuilder < ::Parser::Builders::Default
10
10
  # @param token [::Parser::AST::Node]
11
11
  # @return [String]
12
+ # @sg-ignore
12
13
  def string_value(token)
13
14
  value(token)
14
15
  end
@@ -7,6 +7,7 @@ module Solargraph
7
7
  #
8
8
  class NodeChainer
9
9
  include NodeMethods
10
+
10
11
  Chain = Source::Chain
11
12
 
12
13
  # @param node [Parser::AST::Node]
@@ -98,7 +99,8 @@ module Solargraph
98
99
  elsif [:gvar, :gvasgn].include?(n.type)
99
100
  result.push Chain::GlobalVariable.new(n.children[0].to_s)
100
101
  elsif n.type == :or_asgn
101
- result.concat generate_links n.children[1]
102
+ new_node = n.updated(n.children[0].type, n.children[0].children + [n.children[1]])
103
+ result.concat generate_links new_node
102
104
  elsif [:class, :module, :def, :defs].include?(n.type)
103
105
  # @todo Undefined or what?
104
106
  result.push Chain::UNDEFINED_CALL
@@ -3,20 +3,6 @@
3
3
  require 'parser'
4
4
  require 'ast'
5
5
 
6
- # Teach AST::Node#children about its generic type
7
- #
8
- # @todo contribute back to https://github.com/ruby/gem_rbs_collection/blob/main/gems/ast/2.4/ast.rbs
9
- #
10
- # @!parse
11
- # module ::AST
12
- # class Node
13
- # # New children
14
- #
15
- # # @return [Array<self, Integer, String, Symbol, nil>]
16
- # attr_reader :children
17
- # end
18
- # end
19
-
20
6
  # https://github.com/whitequark/parser
21
7
  module Solargraph
22
8
  module Parser
@@ -120,7 +106,7 @@ module Solargraph
120
106
  end
121
107
 
122
108
  # @param node [Parser::AST::Node]
123
- # @return [Hash{Parser::AST::Node => Chain}]
109
+ # @return [Hash{Symbol => Chain}]
124
110
  def convert_hash node
125
111
  return {} unless Parser.is_ast_node?(node)
126
112
  return convert_hash(node.children[0]) if node.type == :kwsplat
@@ -133,6 +119,7 @@ module Solargraph
133
119
  result
134
120
  end
135
121
 
122
+ # @sg-ignore Wrong argument type for AST::Node.new: type expected AST::_ToSym, received :nil
136
123
  NIL_NODE = ::Parser::AST::Node.new(:nil)
137
124
 
138
125
  # @param node [Parser::AST::Node]
@@ -179,6 +166,7 @@ module Solargraph
179
166
  node.children[1..-1].each { |child| result.concat call_nodes_from(child) }
180
167
  elsif node.type == :send
181
168
  result.push node
169
+ result.concat call_nodes_from(node.children.first)
182
170
  node.children[2..-1].each { |child| result.concat call_nodes_from(child) }
183
171
  elsif [:super, :zsuper].include?(node.type)
184
172
  result.push node
@@ -232,6 +220,7 @@ module Solargraph
232
220
  else
233
221
  source.tree_at(position.line, position.column - 1)
234
222
  end
223
+ # @type [AST::Node, nil]
235
224
  prev = nil
236
225
  tree.each do |node|
237
226
  if node.type == :send
@@ -242,7 +231,7 @@ module Solargraph
242
231
  if source.synchronized?
243
232
  return node if source.code[0..offset-1] =~ /\(\s*\z/ && source.code[offset..-1] =~ /^\s*\)/
244
233
  else
245
- return node if source.code[0..offset-1] =~ /\([^\(]*\z/
234
+ return node if source.code[0..offset-1] =~ /\([^(]*\z/
246
235
  end
247
236
  end
248
237
  end
@@ -11,6 +11,7 @@ module Solargraph
11
11
  process_children
12
12
 
13
13
  position = get_node_start_position(node)
14
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
14
15
  enclosing_breakable_pin = pins.select{|pin| pin.is_a?(Pin::Breakable) && pin.location.range.contain?(position)}.last
15
16
  FlowSensitiveTyping.new(locals, enclosing_breakable_pin).process_and(node)
16
17
  end
@@ -19,7 +19,7 @@ module Solargraph
19
19
  else
20
20
  region.closure
21
21
  end
22
- pins.push Solargraph::Pin::Block.new(
22
+ block_pin = Solargraph::Pin::Block.new(
23
23
  location: location,
24
24
  closure: parent,
25
25
  node: node,
@@ -28,7 +28,8 @@ module Solargraph
28
28
  scope: region.scope || region.closure.context.scope,
29
29
  source: :parser
30
30
  )
31
- process_children region.update(closure: pins.last)
31
+ pins.push block_pin
32
+ process_children region.update(closure: block_pin)
32
33
  end
33
34
 
34
35
  private
@@ -11,6 +11,8 @@ module Solargraph
11
11
  process_children
12
12
 
13
13
  position = get_node_start_position(node)
14
+ # @sg-ignore
15
+ # @type [Solargraph::Pin::Breakable, nil]
14
16
  enclosing_breakable_pin = pins.select{|pin| pin.is_a?(Pin::Breakable) && pin.location.range.contain?(position)}.last
15
17
  FlowSensitiveTyping.new(locals, enclosing_breakable_pin).process_if(node)
16
18
  end
@@ -22,8 +22,11 @@ module Solargraph
22
22
  # s(:int, 2),
23
23
  # s(:int, 3)))
24
24
  masgn = node
25
+ # @type [Parser::AST::Node]
25
26
  mlhs = masgn.children.fetch(0)
27
+ # @type [Array<Parser::AST::Node>]
26
28
  lhs_arr = mlhs.children
29
+ # @type [Parser::AST::Node]
27
30
  mass_rhs = node.children.fetch(1)
28
31
 
29
32
  # Get pins created for the mlhs node
@@ -9,14 +9,70 @@ module Solargraph
9
9
  class OpasgnNode < Parser::NodeProcessor::Base
10
10
  # @return [void]
11
11
  def process
12
- # Parser::CurrentRuby.parse("a += 2")
13
- # => s(:op_asgn,
14
- # s(:lvasgn, :a), :+,
15
- # s(:int, 2))
16
- asgn = node.children[0]
17
- variable_name = asgn.children[0]
12
+ target = node.children[0]
18
13
  operator = node.children[1]
19
14
  argument = node.children[2]
15
+ if target.type == :send
16
+ # @sg-ignore Need a downcast here
17
+ process_send_target(target, operator, argument)
18
+ elsif target.type.to_s.end_with?('vasgn')
19
+ # @sg-ignore Need a downcast here
20
+ process_vasgn_target(target, operator, argument)
21
+ else
22
+ Solargraph.assert_or_log(:opasgn_unknown_target,
23
+ "Unexpected op_asgn target type: #{target.type}")
24
+ end
25
+ end
26
+
27
+ # @param call [Parser::AST::Node] the target of the assignment
28
+ # @param operator [Symbol] the operator, e.g. :+
29
+ # @param argument [Parser::AST::Node] the argument of the operation
30
+ #
31
+ # @return [void]
32
+ def process_send_target call, operator, argument
33
+ # if target is a call:
34
+ # [10] pry(main)> Parser::CurrentRuby.parse("Foo.bar += baz")
35
+ # => s(:op_asgn,
36
+ # s(:send, # call
37
+ # s(:const, nil, :Foo), # calee
38
+ # :bar), # call_method
39
+ # :+, # operator
40
+ # s(:send, nil, :baz)) # argument
41
+ # [11] pry(main)>
42
+ callee = call.children[0]
43
+ call_method = call.children[1]
44
+ asgn_method = :"#{call_method}="
45
+
46
+ # [8] pry(main)> Parser::CurrentRuby.parse("Foo.bar = Foo.bar + baz")
47
+ # => s(:send,
48
+ # s(:const, nil, :Foo), # callee
49
+ # :bar=, # asgn_method
50
+ # s(:send,
51
+ # s(:send,
52
+ # s(:const, nil, :Foo), # callee
53
+ # :bar), # call_method
54
+ # :+, # operator
55
+ # s(:send, nil, :baz))) # argument
56
+ new_send = node.updated(:send,
57
+ [callee,
58
+ asgn_method,
59
+ node.updated(:send, [call, operator, argument])])
60
+ NodeProcessor.process(new_send, region, pins, locals)
61
+ end
62
+
63
+ # @param asgn [Parser::AST::Node] the target of the assignment
64
+ # @param operator [Symbol] the operator, e.g. :+
65
+ # @param argument [Parser::AST::Node] the argument of the operation
66
+ #
67
+ # @return [void]
68
+ def process_vasgn_target asgn, operator, argument
69
+ # => s(:op_asgn,
70
+ # s(:lvasgn, :a), # asgn
71
+ # :+, # operator
72
+ # s(:int, 2)) # argument
73
+
74
+ # @type [Parser::AST::Node]
75
+ variable_name = asgn.children[0]
20
76
  # for lvasgn, gvasgn, cvasgn, convert to lvar, gvar, cvar
21
77
  # [6] pry(main)> Parser::CurrentRuby.parse("a = a + 1")
22
78
  # => s(:lvasgn, :a,
@@ -25,9 +81,9 @@ module Solargraph
25
81
  # s(:int, 1)))
26
82
  # [7] pry(main)>
27
83
  variable_reference_type = asgn.type.to_s.sub(/vasgn$/, 'var').to_sym
28
- variable_reference = node.updated(variable_reference_type, asgn.children)
84
+ target_reference = node.updated(variable_reference_type, asgn.children)
29
85
  send_children = [
30
- variable_reference,
86
+ target_reference,
31
87
  operator,
32
88
  argument
33
89
  ]
@@ -7,9 +7,18 @@ module Solargraph
7
7
  class SclassNode < Parser::NodeProcessor::Base
8
8
  def process
9
9
  sclass = node.children[0]
10
- if sclass.is_a?(AST::Node) && sclass.type == :self
10
+ # @todo Changing Parser::AST::Node to AST::Node below will
11
+ # cause type errors at strong level because the combined
12
+ # pin for AST::Node#children has return type
13
+ # "Array<AST::Node>, Array". YARD annotations in AST
14
+ # provided the Array, RBS for Array<AST::Node>. We
15
+ # should probably have a rule to combine "A, A<T>""
16
+ # types to "A<T>" if the "A" comes from YARD, with the
17
+ # rationale that folks tend to be less formal with types in
18
+ # YARD.
19
+ if sclass.is_a?(::Parser::AST::Node) && sclass.type == :self
11
20
  closure = region.closure
12
- elsif sclass.is_a?(AST::Node) && sclass.type == :casgn
21
+ elsif sclass.is_a?(::Parser::AST::Node) && sclass.type == :casgn
13
22
  names = [region.closure.namespace, region.closure.name]
14
23
  if sclass.children[0].nil? && names.last != sclass.children[1].to_s
15
24
  names << sclass.children[1].to_s
@@ -18,7 +27,7 @@ module Solargraph
18
27
  end
19
28
  name = names.reject(&:empty?).join('::')
20
29
  closure = Solargraph::Pin::Namespace.new(name: name, location: region.closure.location, source: :parser)
21
- elsif sclass.is_a?(AST::Node) && sclass.type == :const
30
+ elsif sclass.is_a?(::Parser::AST::Node) && sclass.type == :const
22
31
  names = [region.closure.namespace, region.closure.name]
23
32
  also = NodeMethods.unpack_name(sclass)
24
33
  if also != region.closure.name