solargraph 0.52.0 → 0.53.4

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/.github/workflows/plugins.yml +40 -0
  3. data/.github/workflows/rspec.yml +1 -3
  4. data/.github/workflows/typecheck.yml +34 -0
  5. data/CHANGELOG.md +53 -0
  6. data/README.md +13 -16
  7. data/SPONSORS.md +1 -7
  8. data/lib/solargraph/api_map/cache.rb +59 -21
  9. data/lib/solargraph/api_map/source_to_yard.rb +17 -10
  10. data/lib/solargraph/api_map/store.rb +45 -9
  11. data/lib/solargraph/api_map.rb +178 -113
  12. data/lib/solargraph/bench.rb +3 -2
  13. data/lib/solargraph/cache.rb +29 -5
  14. data/lib/solargraph/complex_type/type_methods.rb +53 -8
  15. data/lib/solargraph/complex_type/unique_type.rb +171 -58
  16. data/lib/solargraph/complex_type.rb +62 -9
  17. data/lib/solargraph/convention.rb +0 -1
  18. data/lib/solargraph/converters/dd.rb +5 -0
  19. data/lib/solargraph/converters/dl.rb +3 -0
  20. data/lib/solargraph/converters/dt.rb +3 -0
  21. data/lib/solargraph/diagnostics/rubocop.rb +8 -7
  22. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
  23. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  24. data/lib/solargraph/diagnostics.rb +2 -2
  25. data/lib/solargraph/doc_map.rb +171 -0
  26. data/lib/solargraph/gem_pins.rb +64 -0
  27. data/lib/solargraph/language_server/host/cataloger.rb +1 -0
  28. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  29. data/lib/solargraph/language_server/host/dispatch.rb +15 -5
  30. data/lib/solargraph/language_server/host/message_worker.rb +4 -0
  31. data/lib/solargraph/language_server/host/sources.rb +7 -4
  32. data/lib/solargraph/language_server/host.rb +35 -7
  33. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  34. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  35. data/lib/solargraph/language_server/message/initialize.rb +5 -2
  36. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  37. data/lib/solargraph/language_server/message/text_document.rb +0 -1
  38. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  39. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  40. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  41. data/lib/solargraph/library.rb +71 -12
  42. data/lib/solargraph/location.rb +1 -0
  43. data/lib/solargraph/page.rb +6 -0
  44. data/lib/solargraph/parser/comment_ripper.rb +3 -0
  45. data/lib/solargraph/parser/node_methods.rb +47 -8
  46. data/lib/solargraph/parser/node_processor/base.rb +9 -0
  47. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +29 -3
  48. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  49. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +42 -34
  50. data/lib/solargraph/parser/{legacy → parser_gem}/node_methods.rb +201 -29
  51. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  52. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/args_node.rb +4 -1
  53. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  54. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  55. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
  56. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  57. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +7 -20
  58. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  59. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  60. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  61. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
  62. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  63. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  64. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  65. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
  66. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +2 -2
  67. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
  68. data/lib/solargraph/parser/parser_gem/node_processors.rb +54 -0
  69. data/lib/solargraph/parser/parser_gem.rb +12 -0
  70. data/lib/solargraph/parser/snippet.rb +2 -0
  71. data/lib/solargraph/parser.rb +8 -11
  72. data/lib/solargraph/pin/base.rb +63 -8
  73. data/lib/solargraph/pin/base_variable.rb +7 -3
  74. data/lib/solargraph/pin/block.rb +26 -38
  75. data/lib/solargraph/pin/closure.rb +17 -2
  76. data/lib/solargraph/pin/common.rb +7 -3
  77. data/lib/solargraph/pin/conversions.rb +33 -3
  78. data/lib/solargraph/pin/documenting.rb +25 -34
  79. data/lib/solargraph/pin/instance_variable.rb +4 -0
  80. data/lib/solargraph/pin/local_variable.rb +13 -1
  81. data/lib/solargraph/pin/method.rb +110 -16
  82. data/lib/solargraph/pin/namespace.rb +16 -10
  83. data/lib/solargraph/pin/parameter.rb +41 -10
  84. data/lib/solargraph/pin/reference/override.rb +2 -2
  85. data/lib/solargraph/pin/reference.rb +8 -0
  86. data/lib/solargraph/pin/search.rb +3 -3
  87. data/lib/solargraph/pin/signature.rb +114 -2
  88. data/lib/solargraph/pin.rb +0 -1
  89. data/lib/solargraph/range.rb +2 -2
  90. data/lib/solargraph/rbs_map/conversions.rb +213 -61
  91. data/lib/solargraph/rbs_map/core_fills.rb +12 -28
  92. data/lib/solargraph/rbs_map/core_map.rb +2 -12
  93. data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
  94. data/lib/solargraph/rbs_map.rb +24 -12
  95. data/lib/solargraph/shell.rb +62 -59
  96. data/lib/solargraph/source/chain/array.rb +4 -1
  97. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  98. data/lib/solargraph/source/chain/call.rb +95 -26
  99. data/lib/solargraph/source/chain/constant.rb +15 -1
  100. data/lib/solargraph/source/chain/if.rb +23 -0
  101. data/lib/solargraph/source/chain/link.rb +7 -1
  102. data/lib/solargraph/source/chain/or.rb +1 -1
  103. data/lib/solargraph/source/chain/z_super.rb +2 -2
  104. data/lib/solargraph/source/chain.rb +20 -4
  105. data/lib/solargraph/source/change.rb +3 -0
  106. data/lib/solargraph/source/cursor.rb +2 -0
  107. data/lib/solargraph/source/source_chainer.rb +6 -5
  108. data/lib/solargraph/source.rb +15 -16
  109. data/lib/solargraph/source_map/clip.rb +14 -9
  110. data/lib/solargraph/source_map/mapper.rb +10 -0
  111. data/lib/solargraph/source_map.rb +12 -10
  112. data/lib/solargraph/type_checker/checks.rb +10 -2
  113. data/lib/solargraph/type_checker.rb +96 -21
  114. data/lib/solargraph/version.rb +1 -1
  115. data/lib/solargraph/workspace/config.rb +8 -6
  116. data/lib/solargraph/workspace.rb +15 -2
  117. data/lib/solargraph/yard_map/cache.rb +6 -0
  118. data/lib/solargraph/yard_map/helpers.rb +1 -1
  119. data/lib/solargraph/yard_map/mapper/to_method.rb +16 -3
  120. data/lib/solargraph/yard_map/to_method.rb +11 -4
  121. data/lib/solargraph/yard_map.rb +0 -292
  122. data/lib/solargraph/yardoc.rb +52 -0
  123. data/lib/solargraph.rb +4 -1
  124. data/solargraph.gemspec +2 -2
  125. metadata +35 -58
  126. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  127. data/lib/solargraph/documentor.rb +0 -76
  128. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  129. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  130. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
  131. data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
  132. data/lib/solargraph/parser/legacy.rb +0 -12
  133. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -151
  134. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -163
  135. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
  136. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  137. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  138. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
  139. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
  140. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
  141. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
  142. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  143. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  144. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  145. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  146. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  147. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  148. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  149. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  150. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -51
  151. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
  152. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  153. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
  154. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
  155. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
  156. data/lib/solargraph/parser/rubyvm.rb +0 -40
  157. data/lib/solargraph/rbs_map/core_signs.rb +0 -33
@@ -11,9 +11,10 @@ module Solargraph
11
11
  def initialize api_map, cursor
12
12
  @api_map = api_map
13
13
  @cursor = cursor
14
+ block.rebind(api_map) if block.is_a?(Pin::Block)
14
15
  end
15
16
 
16
- # @return [Array<Pin::Base>]
17
+ # @return [Array<Pin::Base>] Relevant pins for infering the type of the Cursor's position
17
18
  def define
18
19
  return [] if cursor.comment? || cursor.chain.literal?
19
20
  result = cursor.chain.define(api_map, block, locals)
@@ -50,23 +51,24 @@ module Solargraph
50
51
  def infer
51
52
  result = cursor.chain.infer(api_map, block, locals)
52
53
  if result.tag == 'Class'
53
- # HACK: Exception to return Object from Class#new
54
+ # HACK: Exception to return BasicObject from Class#new
54
55
  dfn = cursor.chain.define(api_map, block, locals).first
55
- return ComplexType.try_parse('Object') if dfn && dfn.path == 'Class#new'
56
+ return ComplexType.try_parse('BasicObject') if dfn && dfn.path == 'Class#new'
56
57
  end
57
58
  return result unless result.tag == 'self'
58
- ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).namespace)
59
+ ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).tag)
59
60
  end
60
61
 
61
62
  # Get an array of all the locals that are visible from the cursors's
62
63
  # position. Locals can be local variables, method parameters, or block
63
64
  # parameters. The array starts with the nearest local pin.
64
65
  #
65
- # @return [Array<Solargraph::Pin::Base>]
66
+ # @return [::Array<Solargraph::Pin::Base>]
66
67
  def locals
67
68
  @locals ||= source_map.locals_at(location)
68
69
  end
69
70
 
71
+ # @return [::Array<String>]
70
72
  def gates
71
73
  block.gates
72
74
  end
@@ -99,11 +101,12 @@ module Solargraph
99
101
  @source_map ||= api_map.source_map(cursor.filename)
100
102
  end
101
103
 
104
+ # @return [Location]
102
105
  def location
103
106
  Location.new(source_map.filename, Solargraph::Range.new(cursor.position, cursor.position))
104
107
  end
105
108
 
106
- # @return [Solargraph::Pin::Base]
109
+ # @return [Solargraph::Pin::Closure]
107
110
  def block
108
111
  @block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
109
112
  end
@@ -115,7 +118,7 @@ module Solargraph
115
118
  @context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
116
119
  end
117
120
 
118
- # @return [Array<Pin::KeywordParam]
121
+ # @return [Array<Pin::KeywordParam>]
119
122
  def complete_keyword_parameters
120
123
  return [] unless cursor.argument? && cursor.chain.links.one? && cursor.word =~ /^[a-z0-9_]*:?$/
121
124
  pins = signify
@@ -139,7 +142,7 @@ module Solargraph
139
142
  result
140
143
  end
141
144
 
142
- # @param result [Array<Pin::Base>]
145
+ # @param result [Enumerable<Pin::Base>]
143
146
  # @return [Completion]
144
147
  def package_completions result
145
148
  frag_start = cursor.start_of_word.to_s.downcase
@@ -150,6 +153,7 @@ module Solargraph
150
153
  Completion.new(filtered, cursor.range)
151
154
  end
152
155
 
156
+ # @return [Completion]
153
157
  def tag_complete
154
158
  result = []
155
159
  match = source_map.code[0..cursor.offset-1].match(/[\[<, ]([a-z0-9_:]*)\z/i)
@@ -168,6 +172,7 @@ module Solargraph
168
172
  package_completions(result)
169
173
  end
170
174
 
175
+ # @return [Completion]
171
176
  def code_complete
172
177
  result = []
173
178
  result.concat complete_keyword_parameters
@@ -209,13 +214,13 @@ module Solargraph
209
214
  result.concat api_map.get_constants(context_pin.context.namespace, *gates)
210
215
  result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
211
216
  result.concat api_map.get_methods('Kernel')
212
- # result.concat ApiMap.keywords
213
217
  result.concat api_map.keyword_pins.to_a
214
218
  end
215
219
  end
216
220
  package_completions(result)
217
221
  end
218
222
 
223
+ # @return [Array<Pin::Base>]
219
224
  def file_global_methods
220
225
  return [] if cursor.word.empty?
221
226
  source_map.pins.select do |pin|
@@ -64,6 +64,10 @@ module Solargraph
64
64
  pins.select{|pin| pin.is_a?(Pin::Closure) and pin.location.range.contain?(position)}.last
65
65
  end
66
66
 
67
+ # @param source_position [Position]
68
+ # @param comment_position [Position]
69
+ # @param comment [String]
70
+ # @return [void]
67
71
  def process_comment source_position, comment_position, comment
68
72
  return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
69
73
  cmnt = remove_inline_comment_hashes(comment)
@@ -79,6 +83,8 @@ module Solargraph
79
83
  end
80
84
 
81
85
  # @param comment [String]
86
+ # @param tag [String]
87
+ # @param start [Integer]
82
88
  # @return [Integer]
83
89
  def find_directive_line_number comment, tag, start
84
90
  # Avoid overruning the index
@@ -204,10 +210,14 @@ module Solargraph
204
210
  end
205
211
  end
206
212
 
213
+ # @param line1 [Integer]
214
+ # @param line2 [Integer]
207
215
  def no_empty_lines?(line1, line2)
208
216
  @code.lines[line1..line2].none? { |line| line.strip.empty? }
209
217
  end
210
218
 
219
+ # @param comment [String]
220
+ # @return [String]
211
221
  def remove_inline_comment_hashes comment
212
222
  ctxt = ''
213
223
  num = nil
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'yard'
4
4
  require 'solargraph/yard_tags'
5
- require 'set'
6
5
 
7
6
  module Solargraph
8
7
  # An index of pins and other ApiMap-related data for a Source.
@@ -18,7 +17,7 @@ module Solargraph
18
17
  # @return [Array<Pin::Base>]
19
18
  attr_reader :pins
20
19
 
21
- # @return [Array<Pin::Base>]
20
+ # @return [Array<Pin::LocalVariable>]
22
21
  attr_reader :locals
23
22
 
24
23
  # @param source [Source]
@@ -35,17 +34,12 @@ module Solargraph
35
34
  @pin_select_cache = {}
36
35
  end
37
36
 
37
+ # @param klass [Class]
38
+ # @return [Array<Pin::Base>]
38
39
  def pins_by_class klass
39
40
  @pin_select_cache[klass] ||= @pin_class_hash.select { |key, _| key <= klass }.values.flatten
40
41
  end
41
42
 
42
- def rebindable_method_names
43
- @rebindable_method_names ||= pins_by_class(Pin::Method)
44
- .select { |pin| pin.comments && pin.comments.include?('@yieldreceiver') }
45
- .map(&:name)
46
- .to_set
47
- end
48
-
49
43
  # @return [String]
50
44
  def filename
51
45
  source.filename
@@ -99,10 +93,16 @@ module Solargraph
99
93
  (pins + locals).select { |pin| pin.location == location }
100
94
  end
101
95
 
96
+ # @param line [Integer]
97
+ # @param character [Integer]
98
+ # @return [Pin::Method,Pin::Namespace]
102
99
  def locate_named_path_pin line, character
103
100
  _locate_pin line, character, Pin::Namespace, Pin::Method
104
101
  end
105
102
 
103
+ # @param line [Integer]
104
+ # @param character [Integer]
105
+ # @return [Pin::Namespace,Pin::Method,Pin::Block]
106
106
  def locate_block_pin line, character
107
107
  _locate_pin line, character, Pin::Namespace, Pin::Method, Pin::Block
108
108
  end
@@ -166,6 +166,8 @@ module Solargraph
166
166
  @convention_pins || []
167
167
  end
168
168
 
169
+ # @param pins [Array<Pin::Base>]
170
+ # @return [Array<Pin::Base>]
169
171
  def convention_pins=(pins)
170
172
  # unmemoizing the document_symbols in case it was called from any of convnetions
171
173
  @document_symbols = nil
@@ -175,7 +177,7 @@ module Solargraph
175
177
  # @param line [Integer]
176
178
  # @param character [Integer]
177
179
  # @param klasses [Array<Class>]
178
- # @return [Pin::Base]
180
+ # @return [Pin::Base, nil]
179
181
  def _locate_pin line, character, *klasses
180
182
  position = Position.new(line, character)
181
183
  found = nil
@@ -51,8 +51,13 @@ module Solargraph
51
51
  # @return [Boolean]
52
52
  def any_types_match? api_map, expected, inferred
53
53
  return duck_types_match?(api_map, expected, inferred) if expected.duck_type?
54
+ # walk through the union expected type and see if any members
55
+ # of the union match the inferred type
54
56
  expected.each do |exp|
55
57
  next if exp.duck_type?
58
+ # @todo: there should be a level of typechecking where all
59
+ # unique types in the inferred must match one of the
60
+ # expected unique types
56
61
  inferred.each do |inf|
57
62
  # return true if exp == inf || api_map.super_and_sub?(fuzz(inf), fuzz(exp))
58
63
  return true if exp == inf || either_way?(api_map, inf, exp)
@@ -103,9 +108,12 @@ module Solargraph
103
108
  # @param cls2 [ComplexType::UniqueType]
104
109
  # @return [Boolean]
105
110
  def either_way?(api_map, cls1, cls2)
106
- f1 = fuzz(cls1)
107
- f2 = fuzz(cls2)
111
+ # @todo there should be a level of typechecking which uses the
112
+ # full tag with parameters to determine compatibility
113
+ f1 = cls1.name
114
+ f2 = cls2.name
108
115
  api_map.type_include?(f1, f2) || api_map.super_and_sub?(f1, f2) || api_map.super_and_sub?(f2, f1)
116
+ # api_map.type_include?(f1, f2) || api_map.super_and_sub?(f1, f2) || api_map.super_and_sub?(f2, f1)
109
117
  end
110
118
  end
111
119
  end
@@ -51,6 +51,7 @@ module Solargraph
51
51
 
52
52
  class << self
53
53
  # @param filename [String]
54
+ # @param level [Symbol]
54
55
  # @return [self]
55
56
  def load filename, level = :normal
56
57
  source = Solargraph::Source.load(filename)
@@ -61,6 +62,7 @@ module Solargraph
61
62
 
62
63
  # @param code [String]
63
64
  # @param filename [String, nil]
65
+ # @param level [Symbol]
64
66
  # @return [self]
65
67
  def load_string code, filename = nil, level = :normal
66
68
  source = Solargraph::Source.load_string(code, filename)
@@ -126,11 +128,16 @@ module Solargraph
126
128
  # @return [Boolean]
127
129
  def resolved_constant? pin
128
130
  return true if pin.typify(api_map).defined?
129
- api_map.get_constants('', *pin.closure.gates)
130
- .select { |p| p.name == pin.return_type.namespace }
131
- .any? { |p| p.infer(api_map).defined? }
131
+ constant_pins = api_map.get_constants('', *pin.closure.gates)
132
+ .select { |p| p.name == pin.return_type.namespace }
133
+ return true if constant_pins.find { |p| p.typify(api_map).defined? }
134
+ # will need to probe when a constant name is assigned to a
135
+ # class/module (alias)
136
+ return true if constant_pins.find { |p| p.probe(api_map).defined? }
137
+ false
132
138
  end
133
139
 
140
+ # @param pin [Pin::Base]
134
141
  def virtual_pin? pin
135
142
  pin.location && source_map.source.comment_at?(pin.location.range.ending)
136
143
  end
@@ -158,7 +165,11 @@ module Solargraph
158
165
  end
159
166
  end
160
167
  end
168
+ # @todo Should be able to probe type of name and data here
169
+ # @param name [String]
170
+ # @param data [Hash{Symbol => BasicObject}]
161
171
  params.each_pair do |name, data|
172
+ # @type [ComplexType]
162
173
  type = data[:qualified]
163
174
  if type.undefined?
164
175
  result.push Problem.new(pin.location, "Unresolved type #{data[:tagged]} for #{name} param on #{pin.path}", pin: pin)
@@ -167,6 +178,7 @@ module Solargraph
167
178
  result
168
179
  end
169
180
 
181
+ # @return [Array<Pin::Base>]
170
182
  def ignored_pins
171
183
  @ignored_pins ||= []
172
184
  end
@@ -214,6 +226,7 @@ module Solargraph
214
226
  source_map.pins_by_class(Pin::BaseVariable) + source_map.locals.select { |pin| pin.is_a?(Pin::LocalVariable) }
215
227
  end
216
228
 
229
+ # @return [Array<Problem>]
217
230
  def const_problems
218
231
  return [] unless rules.validate_consts?
219
232
  result = []
@@ -232,6 +245,7 @@ module Solargraph
232
245
  result
233
246
  end
234
247
 
248
+ # @return [Array<Problem>]
235
249
  def call_problems
236
250
  result = []
237
251
  Solargraph::Parser::NodeMethods.call_nodes_from(source_map.source.node).each do |call|
@@ -254,6 +268,7 @@ module Solargraph
254
268
  base = base.base
255
269
  end
256
270
  closest = found.typify(api_map) if found
271
+ # @todo remove the internal_or_core? check at a higher-than-strict level
257
272
  if !found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))
258
273
  unless closest.generic? || ignored_pins.include?(found)
259
274
  result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
@@ -271,6 +286,7 @@ module Solargraph
271
286
  # @param block_pin [Solargraph::Pin::Base]
272
287
  # @param locals [Array<Solargraph::Pin::Base>]
273
288
  # @param location [Solargraph::Location]
289
+ # @return [Array<Problem>]
274
290
  def argument_problems_for chain, api_map, block_pin, locals, location
275
291
  result = []
276
292
  base = chain
@@ -284,6 +300,14 @@ module Solargraph
284
300
  pin = pins.first
285
301
  ap = if base.links.last.is_a?(Solargraph::Source::Chain::ZSuper)
286
302
  arity_problems_for(pin, fake_args_for(block_pin), location)
303
+ elsif pin.path == 'Class#new'
304
+ fqns = if base.links.one?
305
+ block_pin.namespace
306
+ else
307
+ base.base.infer(api_map, block_pin, locals).namespace
308
+ end
309
+ init = api_map.get_method_stack(fqns, 'initialize').first
310
+ init ? arity_problems_for(init, base.links.last.arguments, location) : []
287
311
  else
288
312
  arity_problems_for(pin, base.links.last.arguments, location)
289
313
  end
@@ -298,12 +322,21 @@ module Solargraph
298
322
  all_errors = []
299
323
  pin.signatures.sort { |sig| sig.parameters.length }.each do |sig|
300
324
  errors = []
325
+ # @todo these should be able to be probed
326
+ # @param par [Parameter]
327
+ # @param idx [Integer]
301
328
  sig.parameters.each_with_index do |par, idx|
302
329
  argchain = base.links.last.arguments[idx]
303
330
  if argchain.nil?
304
331
  if par.decl == :arg
305
- errors.push Problem.new(location, "Not enough arguments to #{pin.path}")
306
- next
332
+ last = base.links.last.arguments.last
333
+ if last && last.node.type == :splat
334
+ argchain = last
335
+ next # don't try to apply the type of the splat - unlikely to be specific enough
336
+ else
337
+ errors.push Problem.new(location, "Not enough arguments to #{pin.path}")
338
+ next
339
+ end
307
340
  else
308
341
  last = base.links.last.arguments.last
309
342
  argchain = last if last && [:kwsplat, :hash].include?(last.node.type)
@@ -311,10 +344,15 @@ module Solargraph
311
344
  end
312
345
  if argchain
313
346
  if par.decl != :arg
314
- errors.concat kwarg_problems_for argchain, api_map, block_pin, locals, location, pin, params, idx
347
+ errors.concat kwarg_problems_for sig, argchain, api_map, block_pin, locals, location, pin, params, idx
315
348
  next
316
349
  else
350
+ last = base.links.last.arguments.last
351
+ if last && last.node.type == :splat
352
+ next # don't try to apply the type of the splat - unlikely to be specific enough
353
+ end
317
354
  ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
355
+ ptype = ptype.self_to(par.context.namespace)
318
356
  if ptype.nil?
319
357
  # @todo Some level (strong, I guess) should require the param here
320
358
  else
@@ -343,10 +381,21 @@ module Solargraph
343
381
  result
344
382
  end
345
383
 
346
- def kwarg_problems_for argchain, api_map, block_pin, locals, location, pin, params, idx
384
+ # @param sig [Pin::Signature]
385
+ # @param argchain [Source::Chain]
386
+ # @param api_map [ApiMap]
387
+ # @param block_pin [Pin::Block]
388
+ # @param locals [Array<Pin::LocalVariable>]
389
+ # @param location [Location]
390
+ # @param pin [Pin::Method]
391
+ # @param params [Hash{String => [nil, Hash]}]
392
+ # @param idx [Integer]
393
+ #
394
+ # @return [Array<Problem>]
395
+ def kwarg_problems_for sig, argchain, api_map, block_pin, locals, location, pin, params, idx
347
396
  result = []
348
397
  kwargs = convert_hash(argchain.node)
349
- par = pin.signatures.first.parameters[idx]
398
+ par = sig.parameters[idx]
350
399
  argchain = kwargs[par.name.to_sym]
351
400
  if par.decl == :kwrestarg || (par.decl == :optarg && idx == pin.parameters.length - 1 && par.asgn_code == '{}')
352
401
  result.concat kwrestarg_problems_for(api_map, block_pin, locals, location, pin, params, kwargs)
@@ -371,6 +420,14 @@ module Solargraph
371
420
  result
372
421
  end
373
422
 
423
+ # @param api_map [ApiMap]
424
+ # @param block_pin [Pin::Block]
425
+ # @param locals [Array<Pin::LocalVariable>]
426
+ # @param location [Location]
427
+ # @param pin [Pin::Method]
428
+ # @param params [Hash{String => [nil, Hash]}]
429
+ # @param kwargs [Hash{Symbol => Source::Chain}]
430
+ # @return [Array<Problem>]
374
431
  def kwrestarg_problems_for(api_map, block_pin, locals, location, pin, params, kwargs)
375
432
  result = []
376
433
  kwargs.each_pair do |pname, argchain|
@@ -384,8 +441,8 @@ module Solargraph
384
441
  result
385
442
  end
386
443
 
387
- # @param [Pin::Method]
388
- # @return [Hash]
444
+ # @param pin [Pin::Method]
445
+ # @return [Hash{String => Hash{Symbol => BaseObject}}]
389
446
  def param_hash(pin)
390
447
  tags = pin.docstring.tags(:param)
391
448
  return {} if tags.empty?
@@ -400,10 +457,12 @@ module Solargraph
400
457
  result
401
458
  end
402
459
 
403
- # @param [Array<Pin::Method>]
404
- # @return [Hash]
460
+ # @param pins [Array<Pin::Method>]
461
+ # @return [Hash{String => Hash{Symbol => BasicObject}}]
405
462
  def first_param_hash(pins)
406
463
  pins.each do |pin|
464
+ # @todo this assignment from parametric use of Hash should not lose its generic
465
+ # @type [Hash{String => Hash{Symbol => BasicObject}]
407
466
  result = param_hash(pin)
408
467
  return result unless result.empty?
409
468
  end
@@ -417,6 +476,7 @@ module Solargraph
417
476
  end
418
477
 
419
478
  # True if the pin is either internal (part of the workspace) or from the core/stdlib
479
+ # @param pin [Pin::Base]
420
480
  def internal_or_core? pin
421
481
  # @todo RBS pins are not necessarily core/stdlib pins
422
482
  internal?(pin) || pin.source == :rbs
@@ -427,6 +487,7 @@ module Solargraph
427
487
  !internal? pin
428
488
  end
429
489
 
490
+ # @param pin [Pin::Base]
430
491
  def declared_externally? pin
431
492
  return true if pin.assignment.nil?
432
493
  chain = Solargraph::Parser.chain(pin.assignment, filename)
@@ -454,6 +515,10 @@ module Solargraph
454
515
  true
455
516
  end
456
517
 
518
+ # @param pin [Pin::Method]
519
+ # @param arguments [Array<Source::Chain>]
520
+ # @param location [Location]
521
+ # @return [Array<Problem>]
457
522
  def arity_problems_for pin, arguments, location
458
523
  results = pin.signatures.map do |sig|
459
524
  r = parameterized_arity_problems_for(pin, sig.parameters, arguments, location)
@@ -463,14 +528,15 @@ module Solargraph
463
528
  results.first
464
529
  end
465
530
 
531
+ # @param pin [Pin::Method]
532
+ # @param parameters [Array<Pin::Parameter>]
533
+ # @param arguments [Array<Source::Chain>]
534
+ # @param location [Location]
535
+ # @return [Array<Problem>]
466
536
  def parameterized_arity_problems_for(pin, parameters, arguments, location)
467
537
  return [] unless pin.explicit?
468
538
  return [] if parameters.empty? && arguments.empty?
469
539
  return [] if pin.anon_splat?
470
- if parameters.empty?
471
- return [] if arguments.length == 1 && arguments.last.links.last.is_a?(Source::Chain::BlockVariable)
472
- return [Problem.new(location, "Too many arguments to #{pin.path}")]
473
- end
474
540
  unchecked = arguments.clone
475
541
  add_params = 0
476
542
  if unchecked.empty? && parameters.any? { |param| param.decl == :kwarg }
@@ -510,9 +576,6 @@ module Solargraph
510
576
  return [] if parameters.any?(&:rest?)
511
577
  opt = optional_param_count(parameters)
512
578
  return [] if unchecked.length <= req + opt
513
- if unchecked.length == req + opt + 1 && unchecked.last.links.last.is_a?(Source::Chain::BlockVariable)
514
- return []
515
- end
516
579
  if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) && (parameters.map(&:decl) & [:kwarg, :kwoptarg, :kwrestarg]).any?
517
580
  return []
518
581
  end
@@ -528,20 +591,30 @@ module Solargraph
528
591
  []
529
592
  end
530
593
 
594
+ # @param parameters [Enumerable<Pin::Parameter>]
595
+ # @todo need to use generic types in method to choose correct
596
+ # signature and generate Integer as return type
597
+ # @sg-ignore
598
+ # @return [Integer]
531
599
  def required_param_count(parameters)
532
600
  parameters.sum { |param| %i[arg kwarg].include?(param.decl) ? 1 : 0 }
533
601
  end
534
602
 
603
+ # @param parameters [Enumerable<Pin::Parameter>]
535
604
  # @param pin [Pin::Method]
605
+ # @return [Integer]
536
606
  def optional_param_count(parameters)
537
607
  parameters.select { |p| p.decl == :optarg }.length
538
608
  end
539
609
 
610
+ # @param pin [Pin::Method]
540
611
  def abstract? pin
541
- pin.docstring.has_tag?(:abstract) ||
542
- (pin.closure && pin.closure.docstring.has_tag?(:abstract))
612
+ pin.docstring.has_tag?('abstract') ||
613
+ (pin.closure && pin.closure.docstring.has_tag?('abstract'))
543
614
  end
544
615
 
616
+ # @param pin [Pin::Base]
617
+ # @return [Array<Source::Chain>]
545
618
  def fake_args_for(pin)
546
619
  args = []
547
620
  with_opts = false
@@ -562,6 +635,8 @@ module Solargraph
562
635
  args
563
636
  end
564
637
 
638
+ # @param problems [Array<Problem>]
639
+ # @return [Array<Problem>]
565
640
  def without_ignored problems
566
641
  problems.reject do |problem|
567
642
  node = source_map.source.node_at(problem.location.range.start.line, problem.location.range.start.column)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.52.0'
4
+ VERSION = '0.53.4'
5
5
  end
@@ -14,7 +14,7 @@ module Solargraph
14
14
  # @return [String]
15
15
  attr_reader :directory
16
16
 
17
- # @return [Hash]
17
+ # @return [Hash{String => BasicObject}]
18
18
  attr_reader :raw_data
19
19
 
20
20
  # @param directory [String]
@@ -41,6 +41,7 @@ module Solargraph
41
41
  @excluded ||= process_exclusions(@raw_data['exclude'])
42
42
  end
43
43
 
44
+ # @param filename [String]
44
45
  def allow? filename
45
46
  filename = File.absolute_path(filename, directory)
46
47
  filename.start_with?(directory) &&
@@ -111,7 +112,7 @@ module Solargraph
111
112
 
112
113
  # @return [String]
113
114
  def global_config_path
114
- ENV['SOLARGRAPH_GLOBAL_CONFIG'] ||
115
+ ENV['SOLARGRAPH_GLOBAL_CONFIG'] ||
115
116
  File.join(Dir.home, '.config', 'solargraph', 'config.yml')
116
117
  end
117
118
 
@@ -121,7 +122,7 @@ module Solargraph
121
122
  File.join(@directory, '.solargraph.yml')
122
123
  end
123
124
 
124
- # @return [Hash]
125
+ # @return [Hash{String => Array, Hash, Integer}]
125
126
  def config_data
126
127
  workspace_config = read_config(workspace_config_path)
127
128
  global_config = read_config(global_config_path)
@@ -136,15 +137,15 @@ module Solargraph
136
137
 
137
138
  # Read a .solargraph yaml config
138
139
  #
139
- # @param directory [String]
140
- # @return [Hash, nil]
140
+ # @param config_path [String]
141
+ # @return [Hash{String => Array, Hash, Integer}, nil]
141
142
  def read_config config_path = ''
142
143
  return nil if config_path.empty?
143
144
  return nil unless File.file?(config_path)
144
145
  YAML.safe_load(File.read(config_path))
145
146
  end
146
147
 
147
- # @return [Hash]
148
+ # @return [Hash{String => Array, Hash, Integer}]
148
149
  def default_config
149
150
  {
150
151
  'include' => ['**/*.rb'],
@@ -222,6 +223,7 @@ module Solargraph
222
223
  glob.gsub(/(\/\*|\/\*\*\/\*\*?)$/, '')
223
224
  end
224
225
 
226
+ # @return [Array<String>]
225
227
  def excluded_directories
226
228
  @raw_data['exclude']
227
229
  .select { |g| glob_is_directory?(g) }
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'open3'
4
- require 'rubygems'
5
4
  require 'json'
6
5
 
7
6
  module Solargraph
@@ -26,9 +25,11 @@ module Solargraph
26
25
 
27
26
  # @param directory [String]
28
27
  # @param config [Config, nil]
29
- def initialize directory = '', config = nil
28
+ # @param server [Hash]
29
+ def initialize directory = '', config = nil, server = {}
30
30
  @directory = directory
31
31
  @config = config
32
+ @server = server
32
33
  load_sources
33
34
  @gemnames = []
34
35
  @require_paths = generate_require_paths
@@ -135,8 +136,19 @@ module Solargraph
135
136
  source_hash[updater.filename] = source_hash[updater.filename].synchronize(updater)
136
137
  end
137
138
 
139
+ # @return [String]
140
+ def command_path
141
+ server['commandPath'] || 'solargraph'
142
+ end
143
+
138
144
  private
139
145
 
146
+ # The language server configuration (or an empty hash if the workspace was
147
+ # not initialized from a server).
148
+ #
149
+ # @return [Hash]
150
+ attr_reader :server
151
+
140
152
  # @return [Hash{String => Solargraph::Source}]
141
153
  def source_hash
142
154
  @source_hash ||= {}
@@ -200,6 +212,7 @@ module Solargraph
200
212
  config.require_paths.map{|p| File.join(directory, p)}
201
213
  end
202
214
 
215
+ # @return [void]
203
216
  def require_plugins
204
217
  config.plugins.each do |plugin|
205
218
  begin
@@ -4,13 +4,19 @@ module Solargraph
4
4
  class YardMap
5
5
  class Cache
6
6
  def initialize
7
+ # @type [Hash{String => Array<Solargraph::Pin::Base>}]
7
8
  @path_pins = {}
8
9
  end
9
10
 
11
+ # @param path [String]
12
+ # @param pins [Array<Solargraph::Pin::Base>]
13
+ # @return [Array<Solargraph::Pin::Base>]
10
14
  def set_path_pins path, pins
11
15
  @path_pins[path] = pins
12
16
  end
13
17
 
18
+ # @param path [String]
19
+ # @return [Array<Solargraph::Pin::Base>]
14
20
  def get_path_pins path
15
21
  @path_pins[path]
16
22
  end
@@ -4,7 +4,7 @@ module Solargraph
4
4
  module_function
5
5
 
6
6
  # @param code_object [YARD::CodeObjects::Base]
7
- # @param spec [Gem::Specification]
7
+ # @param spec [Gem::Specification, nil]
8
8
  # @return [Solargraph::Location, nil]
9
9
  def object_location code_object, spec
10
10
  return nil if spec.nil? || code_object.nil? || code_object.file.nil? || code_object.line.nil?