solargraph 0.47.2 → 0.54.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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/plugins.yml +40 -0
  4. data/.github/workflows/rspec.yml +4 -8
  5. data/.github/workflows/typecheck.yml +34 -0
  6. data/.yardopts +2 -2
  7. data/CHANGELOG.md +166 -3
  8. data/LICENSE +1 -1
  9. data/README.md +19 -16
  10. data/SPONSORS.md +2 -9
  11. data/lib/solargraph/api_map/cache.rb +50 -20
  12. data/lib/solargraph/api_map/source_to_yard.rb +17 -10
  13. data/lib/solargraph/api_map/store.rb +68 -15
  14. data/lib/solargraph/api_map.rb +238 -112
  15. data/lib/solargraph/bench.rb +3 -2
  16. data/lib/solargraph/cache.rb +77 -0
  17. data/lib/solargraph/complex_type/type_methods.rb +116 -35
  18. data/lib/solargraph/complex_type/unique_type.rb +261 -33
  19. data/lib/solargraph/complex_type.rb +149 -30
  20. data/lib/solargraph/convention/rakefile.rb +17 -0
  21. data/lib/solargraph/convention.rb +2 -3
  22. data/lib/solargraph/converters/dd.rb +5 -0
  23. data/lib/solargraph/converters/dl.rb +3 -0
  24. data/lib/solargraph/converters/dt.rb +3 -0
  25. data/lib/solargraph/diagnostics/rubocop.rb +23 -8
  26. data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
  27. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  28. data/lib/solargraph/diagnostics.rb +2 -2
  29. data/lib/solargraph/doc_map.rb +187 -0
  30. data/lib/solargraph/gem_pins.rb +72 -0
  31. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  32. data/lib/solargraph/language_server/host/dispatch.rb +22 -5
  33. data/lib/solargraph/language_server/host/message_worker.rb +4 -0
  34. data/lib/solargraph/language_server/host/sources.rb +8 -65
  35. data/lib/solargraph/language_server/host.rb +88 -93
  36. data/lib/solargraph/language_server/message/base.rb +1 -1
  37. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  38. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  39. data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
  40. data/lib/solargraph/language_server/message/initialize.rb +27 -0
  41. data/lib/solargraph/language_server/message/initialized.rb +1 -0
  42. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +4 -1
  43. data/lib/solargraph/language_server/message/text_document/formatting.rb +5 -4
  44. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  45. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
  46. data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
  47. data/lib/solargraph/language_server/message/text_document.rb +1 -1
  48. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  49. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
  50. data/lib/solargraph/language_server/message.rb +1 -0
  51. data/lib/solargraph/language_server/progress.rb +118 -0
  52. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  53. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  54. data/lib/solargraph/language_server.rb +1 -0
  55. data/lib/solargraph/library.rb +231 -104
  56. data/lib/solargraph/location.rb +1 -0
  57. data/lib/solargraph/page.rb +6 -0
  58. data/lib/solargraph/parser/comment_ripper.rb +4 -0
  59. data/lib/solargraph/parser/node_methods.rb +47 -7
  60. data/lib/solargraph/parser/node_processor/base.rb +11 -1
  61. data/lib/solargraph/parser/node_processor.rb +1 -0
  62. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
  63. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  64. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +57 -41
  65. data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
  66. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  67. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +53 -0
  68. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  69. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  70. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +14 -4
  71. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  72. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/def_node.rb +7 -20
  73. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  74. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  75. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  76. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
  77. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +47 -0
  78. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  79. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  80. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  81. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +42 -0
  82. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +7 -5
  83. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +1 -1
  84. data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
  85. data/lib/solargraph/parser/parser_gem.rb +12 -0
  86. data/lib/solargraph/parser/region.rb +1 -1
  87. data/lib/solargraph/parser/snippet.rb +2 -0
  88. data/lib/solargraph/parser.rb +9 -10
  89. data/lib/solargraph/pin/base.rb +69 -11
  90. data/lib/solargraph/pin/base_variable.rb +40 -7
  91. data/lib/solargraph/pin/block.rb +81 -33
  92. data/lib/solargraph/pin/closure.rb +17 -2
  93. data/lib/solargraph/pin/common.rb +7 -3
  94. data/lib/solargraph/pin/conversions.rb +34 -8
  95. data/lib/solargraph/pin/delegated_method.rb +101 -0
  96. data/lib/solargraph/pin/documenting.rb +25 -32
  97. data/lib/solargraph/pin/instance_variable.rb +4 -0
  98. data/lib/solargraph/pin/local_variable.rb +13 -1
  99. data/lib/solargraph/pin/method.rb +273 -17
  100. data/lib/solargraph/pin/namespace.rb +17 -1
  101. data/lib/solargraph/pin/parameter.rb +40 -28
  102. data/lib/solargraph/pin/reference/override.rb +2 -2
  103. data/lib/solargraph/pin/reference.rb +8 -0
  104. data/lib/solargraph/pin/search.rb +4 -4
  105. data/lib/solargraph/pin/signature.rb +143 -0
  106. data/lib/solargraph/pin.rb +2 -1
  107. data/lib/solargraph/range.rb +4 -6
  108. data/lib/solargraph/rbs_map/conversions.rb +607 -0
  109. data/lib/solargraph/rbs_map/core_fills.rb +50 -0
  110. data/lib/solargraph/rbs_map/core_map.rb +28 -0
  111. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -0
  112. data/lib/solargraph/rbs_map.rb +92 -0
  113. data/lib/solargraph/shell.rb +85 -59
  114. data/lib/solargraph/source/chain/array.rb +32 -0
  115. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  116. data/lib/solargraph/source/chain/call.rb +125 -61
  117. data/lib/solargraph/source/chain/constant.rb +15 -1
  118. data/lib/solargraph/source/chain/if.rb +23 -0
  119. data/lib/solargraph/source/chain/link.rb +8 -2
  120. data/lib/solargraph/source/chain/or.rb +1 -1
  121. data/lib/solargraph/source/chain/z_super.rb +3 -3
  122. data/lib/solargraph/source/chain.rb +64 -14
  123. data/lib/solargraph/source/change.rb +3 -0
  124. data/lib/solargraph/source/cursor.rb +2 -0
  125. data/lib/solargraph/source/source_chainer.rb +8 -5
  126. data/lib/solargraph/source/updater.rb +1 -0
  127. data/lib/solargraph/source.rb +18 -63
  128. data/lib/solargraph/source_map/clip.rb +31 -23
  129. data/lib/solargraph/source_map/mapper.rb +23 -7
  130. data/lib/solargraph/source_map.rb +36 -11
  131. data/lib/solargraph/type_checker/checks.rb +10 -2
  132. data/lib/solargraph/type_checker.rb +229 -100
  133. data/lib/solargraph/version.rb +1 -1
  134. data/lib/solargraph/views/environment.erb +2 -2
  135. data/lib/solargraph/workspace/config.rb +15 -11
  136. data/lib/solargraph/workspace.rb +41 -17
  137. data/lib/solargraph/yard_map/cache.rb +6 -0
  138. data/lib/solargraph/yard_map/helpers.rb +1 -1
  139. data/lib/solargraph/yard_map/mapper/to_method.rb +23 -7
  140. data/lib/solargraph/yard_map/mapper.rb +1 -1
  141. data/lib/solargraph/yard_map/to_method.rb +11 -4
  142. data/lib/solargraph/yard_map.rb +1 -443
  143. data/lib/solargraph/yard_tags.rb +20 -0
  144. data/lib/solargraph/yardoc.rb +52 -0
  145. data/lib/solargraph.rb +8 -6
  146. data/solargraph.gemspec +19 -8
  147. metadata +164 -99
  148. data/.travis.yml +0 -19
  149. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  150. data/lib/solargraph/compat.rb +0 -37
  151. data/lib/solargraph/convention/rspec.rb +0 -30
  152. data/lib/solargraph/documentor.rb +0 -76
  153. data/lib/solargraph/language_server/host/cataloger.rb +0 -56
  154. data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
  155. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  156. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
  157. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  158. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +0 -23
  159. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +0 -63
  160. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +0 -21
  161. data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
  162. data/lib/solargraph/parser/legacy.rb +0 -12
  163. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -144
  164. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  165. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
  166. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  167. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  168. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -22
  169. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -57
  170. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  171. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  172. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  173. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  174. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  175. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  176. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  177. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  178. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
  179. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -21
  180. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  181. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -277
  182. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +0 -18
  183. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
  184. data/lib/solargraph/parser/rubyvm.rb +0 -40
  185. data/lib/solargraph/yard_map/core_docs.rb +0 -170
  186. data/lib/solargraph/yard_map/core_fills.rb +0 -208
  187. data/lib/solargraph/yard_map/core_gen.rb +0 -76
  188. data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
  189. data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
  190. data/lib/yard-solargraph.rb +0 -33
  191. data/yardoc/2.2.2.tar.gz +0 -0
@@ -42,6 +42,7 @@ module Solargraph
42
42
  @output
43
43
  end
44
44
 
45
+ # @param text [String]
45
46
  # @return [String]
46
47
  def repair text
47
48
  changes.each do |ch|
@@ -8,7 +8,6 @@ module Solargraph
8
8
  class Source
9
9
  autoload :Updater, 'solargraph/source/updater'
10
10
  autoload :Change, 'solargraph/source/change'
11
- autoload :Mapper, 'solargraph/source/mapper'
12
11
  autoload :EncodingFixes, 'solargraph/source/encoding_fixes'
13
12
  autoload :Cursor, 'solargraph/source/cursor'
14
13
  autoload :Chain, 'solargraph/source/chain'
@@ -33,7 +32,7 @@ module Solargraph
33
32
  attr_reader :version
34
33
 
35
34
  # @param code [String]
36
- # @param filename [String]
35
+ # @param filename [String, nil]
37
36
  # @param version [Integer]
38
37
  def initialize code, filename = nil, version = 0
39
38
  @code = normalize(code)
@@ -93,50 +92,6 @@ module Solargraph
93
92
  stack
94
93
  end
95
94
 
96
- # Start synchronizing the source. This method updates the code without
97
- # parsing a new AST. The resulting Source object will be marked not
98
- # synchronized (#synchronized? == false).
99
- #
100
- # @param updater [Source::Updater]
101
- # @return [Source]
102
- def start_synchronize updater
103
- raise 'Invalid synchronization' unless updater.filename == filename
104
- real_code = updater.write(@code)
105
- src = Source.allocate
106
- src.filename = filename
107
- src.code = real_code
108
- src.version = updater.version
109
- src.parsed = parsed?
110
- src.repaired = updater.repair(@repaired)
111
- src.synchronized = false
112
- src.node = @node
113
- src.comments = @comments
114
- src.error_ranges = error_ranges
115
- src.last_updater = updater
116
- return src.finish_synchronize unless real_code.lines.length == @code.lines.length
117
- src
118
- end
119
-
120
- # Finish synchronizing a source that was updated via #start_synchronize.
121
- # This method returns self if the source is already synchronized. Otherwise
122
- # it parses the AST and returns a new synchronized Source.
123
- #
124
- # @return [Source]
125
- def finish_synchronize
126
- return self if synchronized?
127
- synced = Source.new(@code, filename)
128
- if synced.parsed?
129
- synced.version = version
130
- return synced
131
- end
132
- synced = Source.new(@repaired, filename)
133
- synced.error_ranges.concat (error_ranges + last_updater.changes.map(&:range))
134
- synced.code = @code
135
- synced.synchronized = true
136
- synced.version = version
137
- synced
138
- end
139
-
140
95
  # Synchronize the Source with an update. This method applies changes to the
141
96
  # code, parses the new code's AST, and returns the resulting Source object.
142
97
  #
@@ -213,6 +168,7 @@ module Solargraph
213
168
  end
214
169
  end
215
170
 
171
+ # @return [::Array<Range>]
216
172
  def string_ranges
217
173
  @string_ranges ||= Parser.string_ranges(node)
218
174
  end
@@ -250,7 +206,7 @@ module Solargraph
250
206
  end
251
207
 
252
208
  # @param node [Parser::AST::Node]
253
- # @return [String]
209
+ # @return [String, nil]
254
210
  def comments_for node
255
211
  rng = Range.from_node(node)
256
212
  stringified_comments[rng.start.line] ||= begin
@@ -301,7 +257,7 @@ module Solargraph
301
257
 
302
258
  # Get a hash of comments grouped by the line numbers of the associated code.
303
259
  #
304
- # @return [Hash{Integer => Array<Parser::Source::Comment>}]
260
+ # @return [Hash{Integer => String}]
305
261
  def associated_comments
306
262
  @associated_comments ||= begin
307
263
  result = {}
@@ -323,6 +279,8 @@ module Solargraph
323
279
 
324
280
  private
325
281
 
282
+ # @param line [Integer]
283
+ # @return [Integer]
326
284
  def first_not_empty_from line
327
285
  cursor = line
328
286
  cursor += 1 while cursor < code_lines.length && code_lines[cursor].strip.empty?
@@ -332,7 +290,7 @@ module Solargraph
332
290
 
333
291
  # @param top [Parser::AST::Node]
334
292
  # @param result [Array<Range>]
335
- # @param parent [Symbol]
293
+ # @param parent [Symbol, nil]
336
294
  # @return [void]
337
295
  def inner_folding_ranges top, result = [], parent = nil
338
296
  return unless Parser.is_ast_node?(top)
@@ -411,7 +369,7 @@ module Solargraph
411
369
  result
412
370
  end
413
371
 
414
- # @param n [Parser::AST::Node]
372
+ # @param n [Parser::AST::Node, nil]
415
373
  # @return [Array<Parser::AST::Node>]
416
374
  def string_nodes_in n
417
375
  result = []
@@ -425,30 +383,23 @@ module Solargraph
425
383
  result
426
384
  end
427
385
 
428
- # @param node [Parser::AST::Node]
386
+ # @param node [Parser::AST::Node, nil]
429
387
  # @param position [Position]
430
388
  # @param stack [Array<Parser::AST::Node>]
431
389
  # @return [void]
432
390
  def inner_tree_at node, position, stack
433
391
  return if node.nil?
434
392
  here = Range.from_node(node)
435
- if here.contain?(position) || colonized(here, position, node)
393
+ if here.contain?(position)
436
394
  stack.unshift node
437
395
  node.children.each do |c|
438
396
  next unless Parser.is_ast_node?(c)
439
- next if !Parser.rubyvm? && c.loc.expression.nil?
397
+ next if c.loc.expression.nil?
440
398
  inner_tree_at(c, position, stack)
441
399
  end
442
400
  end
443
401
  end
444
402
 
445
- def colonized range, position, node
446
- node.type == :COLON2 &&
447
- range.ending.line == position.line &&
448
- range.ending.character == position.character - 2 &&
449
- code[Position.to_offset(code, Position.new(position.line, position.character - 2)), 2] == '::'
450
- end
451
-
452
403
  protected
453
404
 
454
405
  # @return [String]
@@ -464,7 +415,7 @@ module Solargraph
464
415
  @code = val
465
416
  end
466
417
 
467
- # @return [Parser::AST::Node]
418
+ # @return [Parser::AST::Node, nil]
468
419
  attr_writer :node
469
420
 
470
421
  # @return [Array<Range>]
@@ -476,7 +427,7 @@ module Solargraph
476
427
  # @return [Boolean]
477
428
  attr_writer :parsed
478
429
 
479
- # @return [Array<Parser::Source::Comment>]
430
+ # @return [Hash{Integer => String}
480
431
  attr_writer :comments
481
432
 
482
433
  # @return [Boolean]
@@ -503,7 +454,7 @@ module Solargraph
503
454
  end
504
455
 
505
456
  # @param code [String]
506
- # @param filename [String]
457
+ # @param filename [String, nil]
507
458
  # @param version [Integer]
508
459
  # @return [Solargraph::Source]
509
460
  def load_string code, filename = nil, version = 0
@@ -516,6 +467,10 @@ module Solargraph
516
467
  # HACK: Pass a dummy code object to the parser for plugins that
517
468
  # expect it not to be nil
518
469
  YARD::Docstring.parser.parse(comments, YARD::CodeObjects::Base.new(:root, 'stub'))
470
+ rescue StandardError => e
471
+ Solargraph.logger.info "YARD failed to parse docstring: [#{e.class}] #{e.message}"
472
+ Solargraph.logger.debug "Unparsed comment: #{comments}"
473
+ YARD::Docstring.parser
519
474
  end
520
475
  end
521
476
  end
@@ -11,16 +11,23 @@ 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)
21
+ result.concat file_global_methods
20
22
  result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
21
23
  result
22
24
  end
23
25
 
26
+ # @return [Array<Pin::Base>]
27
+ def types
28
+ infer.namespaces.map { |namespace| api_map.get_path_pins(namespace) }.flatten
29
+ end
30
+
24
31
  # @return [Completion]
25
32
  def complete
26
33
  return package_completions([]) if !source_map.source.parsed? || cursor.string?
@@ -43,19 +50,25 @@ module Solargraph
43
50
  # @return [ComplexType]
44
51
  def infer
45
52
  result = cursor.chain.infer(api_map, block, locals)
53
+ if result.tag == 'Class'
54
+ # HACK: Exception to return BasicObject from Class#new
55
+ dfn = cursor.chain.define(api_map, block, locals).first
56
+ return ComplexType.try_parse('BasicObject') if dfn && dfn.path == 'Class#new'
57
+ end
46
58
  return result unless result.tag == 'self'
47
- 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)
48
60
  end
49
61
 
50
62
  # Get an array of all the locals that are visible from the cursors's
51
63
  # position. Locals can be local variables, method parameters, or block
52
64
  # parameters. The array starts with the nearest local pin.
53
65
  #
54
- # @return [Array<Solargraph::Pin::Base>]
66
+ # @return [::Array<Solargraph::Pin::Base>]
55
67
  def locals
56
68
  @locals ||= source_map.locals_at(location)
57
69
  end
58
70
 
71
+ # @return [::Array<String>]
59
72
  def gates
60
73
  block.gates
61
74
  end
@@ -88,11 +101,12 @@ module Solargraph
88
101
  @source_map ||= api_map.source_map(cursor.filename)
89
102
  end
90
103
 
104
+ # @return [Location]
91
105
  def location
92
106
  Location.new(source_map.filename, Solargraph::Range.new(cursor.position, cursor.position))
93
107
  end
94
108
 
95
- # @return [Solargraph::Pin::Base]
109
+ # @return [Solargraph::Pin::Closure]
96
110
  def block
97
111
  @block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
98
112
  end
@@ -104,22 +118,7 @@ module Solargraph
104
118
  @context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
105
119
  end
106
120
 
107
- # @return [Array<Pin::Base>]
108
- def yielded_self_pins
109
- return [] unless block.is_a?(Pin::Block) && block.receiver
110
- chain = Parser.chain(block.receiver, source_map.source.filename)
111
- receiver_pin = chain.define(api_map, context_pin, locals).first
112
- return [] if receiver_pin.nil?
113
- result = []
114
- ys = receiver_pin.docstring.tag(:yieldpublic)
115
- unless ys.nil? || ys.types.empty?
116
- ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
117
- result.concat api_map.get_complex_type_methods(ysct, '', false)
118
- end
119
- result
120
- end
121
-
122
- # @return [Array<Pin::KeywordParam]
121
+ # @return [Array<Pin::KeywordParam>]
123
122
  def complete_keyword_parameters
124
123
  return [] unless cursor.argument? && cursor.chain.links.one? && cursor.word =~ /^[a-z0-9_]*:?$/
125
124
  pins = signify
@@ -143,7 +142,7 @@ module Solargraph
143
142
  result
144
143
  end
145
144
 
146
- # @param result [Array<Pin::Base>]
145
+ # @param result [Enumerable<Pin::Base>]
147
146
  # @return [Completion]
148
147
  def package_completions result
149
148
  frag_start = cursor.start_of_word.to_s.downcase
@@ -154,6 +153,7 @@ module Solargraph
154
153
  Completion.new(filtered, cursor.range)
155
154
  end
156
155
 
156
+ # @return [Completion]
157
157
  def tag_complete
158
158
  result = []
159
159
  match = source_map.code[0..cursor.offset-1].match(/[\[<, ]([a-z0-9_:]*)\z/i)
@@ -172,6 +172,7 @@ module Solargraph
172
172
  package_completions(result)
173
173
  end
174
174
 
175
+ # @return [Completion]
175
176
  def code_complete
176
177
  result = []
177
178
  result.concat complete_keyword_parameters
@@ -209,16 +210,23 @@ module Solargraph
209
210
  return package_completions(api_map.get_global_variable_pins)
210
211
  end
211
212
  result.concat locals
213
+ result.concat file_global_methods unless block.binder.namespace.empty?
212
214
  result.concat api_map.get_constants(context_pin.context.namespace, *gates)
213
215
  result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
214
216
  result.concat api_map.get_methods('Kernel')
215
- # result.concat ApiMap.keywords
216
217
  result.concat api_map.keyword_pins.to_a
217
- result.concat yielded_self_pins
218
218
  end
219
219
  end
220
220
  package_completions(result)
221
221
  end
222
+
223
+ # @return [Array<Pin::Base>]
224
+ def file_global_methods
225
+ return [] if cursor.word.empty?
226
+ source_map.pins.select do |pin|
227
+ pin.is_a?(Pin::Method) && pin.namespace == '' && pin.name.start_with?(cursor.word)
228
+ end
229
+ end
222
230
  end
223
231
  end
224
232
  end
@@ -12,7 +12,7 @@ module Solargraph
12
12
 
13
13
  private_class_method :new
14
14
 
15
- MACRO_REGEXP = /(@\!method|@\!attribute|@\!visibility|@\!domain|@\!macro|@\!parse|@\!override)/.freeze
15
+ DIRECTIVE_REGEXP = /(@\!method|@\!attribute|@\!visibility|@\!domain|@\!macro|@\!parse|@\!override)/.freeze
16
16
 
17
17
  # Generate the data.
18
18
  #
@@ -24,6 +24,8 @@ module Solargraph
24
24
  @code = source.code
25
25
  @comments = source.comments
26
26
  @pins, @locals = Parser.map(source)
27
+ @pins.each { |p| p.source = :code }
28
+ @locals.each { |l| l.source = :code }
27
29
  process_comment_directives
28
30
  [@pins, @locals]
29
31
  # rescue Exception => e
@@ -62,8 +64,12 @@ module Solargraph
62
64
  pins.select{|pin| pin.is_a?(Pin::Closure) and pin.location.range.contain?(position)}.last
63
65
  end
64
66
 
67
+ # @param source_position [Position]
68
+ # @param comment_position [Position]
69
+ # @param comment [String]
70
+ # @return [void]
65
71
  def process_comment source_position, comment_position, comment
66
- return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~ MACRO_REGEXP
72
+ return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
67
73
  cmnt = remove_inline_comment_hashes(comment)
68
74
  parse = Solargraph::Source.parse_docstring(cmnt)
69
75
  last_line = 0
@@ -77,6 +83,8 @@ module Solargraph
77
83
  end
78
84
 
79
85
  # @param comment [String]
86
+ # @param tag [String]
87
+ # @param start [Integer]
80
88
  # @return [Integer]
81
89
  def find_directive_line_number comment, tag, start
82
90
  # Avoid overruning the index
@@ -105,7 +113,8 @@ module Solargraph
105
113
  begin
106
114
  src = Solargraph::Source.load_string("def #{directive.tag.name};end", @source.filename)
107
115
  region = Parser::Region.new(source: src, closure: namespace)
108
- gen_pin = Parser.process_node(src.node, region).first.last
116
+ method_gen_pins = Parser.process_node(src.node, region).first.select { |pin| pin.is_a?(Pin::Method) }
117
+ gen_pin = method_gen_pins.last
109
118
  return if gen_pin.nil?
110
119
  # Move the location to the end of the line so it gets recognized
111
120
  # as originating from a comment
@@ -135,7 +144,7 @@ module Solargraph
135
144
  )
136
145
  end
137
146
  if t.nil? || t.include?('w')
138
- pins.push Solargraph::Pin::Method.new(
147
+ method_pin = Solargraph::Pin::Method.new(
139
148
  location: location,
140
149
  closure: namespace,
141
150
  name: "#{directive.tag.name}=",
@@ -144,7 +153,8 @@ module Solargraph
144
153
  visibility: :public,
145
154
  attribute: true
146
155
  )
147
- pins.last.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
156
+ pins.push method_pin
157
+ method_pin.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
148
158
  if pins.last.return_type.defined?
149
159
  pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
150
160
  end
@@ -196,20 +206,26 @@ module Solargraph
196
206
  namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
197
207
  when 'override'
198
208
  pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags)
209
+ when 'macro'
210
+ # @todo Handle macros
199
211
  end
200
212
  end
201
213
 
214
+ # @param line1 [Integer]
215
+ # @param line2 [Integer]
202
216
  def no_empty_lines?(line1, line2)
203
217
  @code.lines[line1..line2].none? { |line| line.strip.empty? }
204
218
  end
205
219
 
220
+ # @param comment [String]
221
+ # @return [String]
206
222
  def remove_inline_comment_hashes comment
207
223
  ctxt = ''
208
224
  num = nil
209
225
  started = false
210
226
  comment.lines.each { |l|
211
227
  # Trim the comment and minimum leading whitespace
212
- p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#/, '')
228
+ p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#+/, '')
213
229
  if num.nil? && !p.strip.empty?
214
230
  num = p.index(/[^ ]/)
215
231
  started = true
@@ -224,7 +240,7 @@ module Solargraph
224
240
 
225
241
  # @return [void]
226
242
  def process_comment_directives
227
- return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~ MACRO_REGEXP
243
+ return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
228
244
  code_lines = @code.lines
229
245
  @source.associated_comments.each do |line, comments|
230
246
  src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'yard'
4
- require 'yard-solargraph'
5
- require 'set'
4
+ require 'solargraph/yard_tags'
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]
@@ -30,19 +29,25 @@ module Solargraph
30
29
  @pins = pins
31
30
  @locals = locals
32
31
  environ.merge Convention.for_local(self) unless filename.nil?
32
+ self.convention_pins = environ.pins
33
33
  @pin_class_hash = pins.to_set.classify(&:class).transform_values(&:to_a)
34
34
  @pin_select_cache = {}
35
35
  end
36
36
 
37
+ # @param klass [Class]
38
+ # @return [Array<Pin::Base>]
37
39
  def pins_by_class klass
38
40
  @pin_select_cache[klass] ||= @pin_class_hash.select { |key, _| key <= klass }.values.flatten
39
41
  end
40
42
 
41
- def rebindable_method_names
42
- @rebindable_method_names ||= pins_by_class(Pin::Method)
43
- .select { |pin| pin.comments && pin.comments.include?('@yieldself') }
44
- .map(&:name)
45
- .to_set
43
+ # A hash representing the state of the source map's API.
44
+ #
45
+ # ApiMap#catalog uses this value to determine whether it needs to clear its
46
+ # cache.
47
+ #
48
+ # @return [Integer]
49
+ def api_hash
50
+ @api_hash ||= (pins_by_class(Pin::Constant) + pins_by_class(Pin::Namespace).select { |pin| pin.namespace.to_s > '' } + pins_by_class(Pin::Reference) + pins_by_class(Pin::Method).map(&:node)).hash
46
51
  end
47
52
 
48
53
  # @return [String]
@@ -65,11 +70,12 @@ module Solargraph
65
70
  @environ ||= Environ.new
66
71
  end
67
72
 
73
+ # all pins except Solargraph::Pin::Reference::Reference
68
74
  # @return [Array<Pin::Base>]
69
75
  def document_symbols
70
- @document_symbols ||= pins.select { |pin|
76
+ @document_symbols ||= (pins + convention_pins).select do |pin|
71
77
  pin.path && !pin.path.empty?
72
- }
78
+ end
73
79
  end
74
80
 
75
81
  # @param query [String]
@@ -97,10 +103,16 @@ module Solargraph
97
103
  (pins + locals).select { |pin| pin.location == location }
98
104
  end
99
105
 
106
+ # @param line [Integer]
107
+ # @param character [Integer]
108
+ # @return [Pin::Method,Pin::Namespace]
100
109
  def locate_named_path_pin line, character
101
110
  _locate_pin line, character, Pin::Namespace, Pin::Method
102
111
  end
103
112
 
113
+ # @param line [Integer]
114
+ # @param character [Integer]
115
+ # @return [Pin::Namespace,Pin::Method,Pin::Block]
104
116
  def locate_block_pin line, character
105
117
  _locate_pin line, character, Pin::Namespace, Pin::Method, Pin::Block
106
118
  end
@@ -159,10 +171,23 @@ module Solargraph
159
171
 
160
172
  private
161
173
 
174
+ # @return [Array<Pin::Base>]
175
+ def convention_pins
176
+ @convention_pins || []
177
+ end
178
+
179
+ # @param pins [Array<Pin::Base>]
180
+ # @return [Array<Pin::Base>]
181
+ def convention_pins=(pins)
182
+ # unmemoizing the document_symbols in case it was called from any of convnetions
183
+ @document_symbols = nil
184
+ @convention_pins = pins
185
+ end
186
+
162
187
  # @param line [Integer]
163
188
  # @param character [Integer]
164
189
  # @param klasses [Array<Class>]
165
- # @return [Pin::Base]
190
+ # @return [Pin::Base, nil]
166
191
  def _locate_pin line, character, *klasses
167
192
  position = Position.new(line, character)
168
193
  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