solargraph 0.45.0 → 0.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/rspec.yml +1 -1
  4. data/CHANGELOG.md +41 -0
  5. data/LICENSE +1 -1
  6. data/README.md +8 -0
  7. data/SPONSORS.md +2 -4
  8. data/lib/solargraph/api_map/store.rb +13 -1
  9. data/lib/solargraph/api_map.rb +55 -32
  10. data/lib/solargraph/cache.rb +51 -0
  11. data/lib/solargraph/complex_type/type_methods.rb +10 -6
  12. data/lib/solargraph/complex_type/unique_type.rb +57 -0
  13. data/lib/solargraph/complex_type.rb +35 -2
  14. data/lib/solargraph/convention/rakefile.rb +17 -0
  15. data/lib/solargraph/convention.rb +2 -0
  16. data/lib/solargraph/diagnostics/require_not_found.rb +16 -0
  17. data/lib/solargraph/diagnostics/rubocop.rb +17 -3
  18. data/lib/solargraph/diagnostics/rubocop_helpers.rb +3 -1
  19. data/lib/solargraph/language_server/host.rb +22 -18
  20. data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
  21. data/lib/solargraph/language_server/message/initialize.rb +2 -0
  22. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -1
  23. data/lib/solargraph/language_server/message/text_document/hover.rb +16 -4
  24. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
  25. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
  26. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +1 -1
  27. data/lib/solargraph/library.rb +21 -20
  28. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +12 -2
  29. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +24 -3
  30. data/lib/solargraph/parser/rubyvm/class_methods.rb +7 -2
  31. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +13 -2
  32. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +20 -9
  33. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +14 -3
  34. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +2 -2
  35. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +14 -3
  36. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +4 -2
  37. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
  38. data/lib/solargraph/pin/base.rb +5 -2
  39. data/lib/solargraph/pin/block.rb +2 -1
  40. data/lib/solargraph/pin/conversions.rb +2 -6
  41. data/lib/solargraph/pin/method.rb +100 -10
  42. data/lib/solargraph/pin/namespace.rb +4 -1
  43. data/lib/solargraph/pin/parameter.rb +10 -7
  44. data/lib/solargraph/pin/search.rb +56 -0
  45. data/lib/solargraph/pin/signature.rb +23 -0
  46. data/lib/solargraph/pin.rb +2 -0
  47. data/lib/solargraph/rbs_map/conversions.rb +394 -0
  48. data/lib/solargraph/rbs_map/core_fills.rb +61 -0
  49. data/lib/solargraph/rbs_map/core_map.rb +38 -0
  50. data/lib/solargraph/rbs_map/core_signs.rb +33 -0
  51. data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
  52. data/lib/solargraph/rbs_map.rb +73 -0
  53. data/lib/solargraph/shell.rb +38 -30
  54. data/lib/solargraph/source/chain/call.rb +34 -23
  55. data/lib/solargraph/source/chain.rb +21 -6
  56. data/lib/solargraph/source.rb +1 -1
  57. data/lib/solargraph/source_map/clip.rb +5 -0
  58. data/lib/solargraph/source_map/mapper.rb +31 -2
  59. data/lib/solargraph/source_map.rb +1 -10
  60. data/lib/solargraph/type_checker/checks.rb +13 -0
  61. data/lib/solargraph/type_checker.rb +88 -68
  62. data/lib/solargraph/version.rb +1 -1
  63. data/lib/solargraph/views/environment.erb +2 -2
  64. data/lib/solargraph/workspace.rb +12 -14
  65. data/lib/solargraph/yard_map/mapper/to_method.rb +7 -4
  66. data/lib/solargraph/yard_map.rb +51 -195
  67. data/lib/solargraph.rb +2 -2
  68. data/solargraph.gemspec +8 -6
  69. metadata +44 -36
  70. data/lib/solargraph/compat.rb +0 -37
  71. data/lib/solargraph/yard_map/core_docs.rb +0 -170
  72. data/lib/solargraph/yard_map/core_fills.rb +0 -208
  73. data/lib/solargraph/yard_map/core_gen.rb +0 -76
  74. data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
  75. data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
  76. data/yardoc/2.2.2.tar.gz +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99cf1c663bb1a93324ff9c860b82e60d47988a4c48e9c0e977176cb94852f29c
4
- data.tar.gz: 9b10324bcf7493f9ed5f8a67a8d47e4f0a379b76ed2aeb31514d1fa06b88dbf6
3
+ metadata.gz: b0b66abd5cf5a0376d5521532dda16db328592eb38bac6acd84f997b19cb328c
4
+ data.tar.gz: 51e038df27bae1457393c7ff023c9951b0f8919267678e29aab2e21efeb2b1a8
5
5
  SHA512:
6
- metadata.gz: a981e45a500d2469972d0fab1e4bcfdbde99dc46de7ef7b377d486a9a027ce617b8806790ed3565a673fbf3d3fd206d246408b5ce744a0b575e02ee3a3a9b699
7
- data.tar.gz: 0bcb7a9957581cac9c066076938dbbdcbcc596bf7ddc8f4cd4539d71dadabab68cfdbc18f59df8daedd02dcff8f45b671a0a742c6ec1afbd39ede15fb3db381b
6
+ metadata.gz: 9b8310748d4754c27fd62763ce1bd8759fc43fc825b1b40353d4537130f2b6143cdb59101da679a8b4a7fb0778430eeac2eccbb845f7a9a5ac11f402b3a71461
7
+ data.tar.gz: 1b2f79f5396a3c056d0b2acbcb49d6c1385b02a49b33edbe1a3e452a7b451b9b87547b8b8d5974a17e25ea2f5c21db8dd315d2b3d856fb3c7ce2d300a4595c70
@@ -0,0 +1 @@
1
+ patreon: castwide
@@ -22,7 +22,7 @@ jobs:
22
22
  runs-on: ubuntu-latest
23
23
  strategy:
24
24
  matrix:
25
- ruby-version: ['2.4', '2.5', '2.6', '2.7', '3.0']
25
+ ruby-version: ['2.6', '2.7', '3.0', '3.1']
26
26
 
27
27
  steps:
28
28
  - uses: actions/checkout@v3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,44 @@
1
+ ## 0.49.0 - April 9, 2023
2
+ - Better union type handling
3
+ - First version of RBS support
4
+ - Dependency updates
5
+ - Update RuboCop config options
6
+ - RBS core and stdlib mapping
7
+ - Anonymous splats and multisig arity
8
+ - Infinite loop when checking if a class is a superclass (#641)
9
+
10
+ ## 0.48.0 - December 19, 2022
11
+ - Add Sublime Text to README (#604)
12
+ - Map nested constant assignments
13
+ - Handle rest/kwrest modifiers on overload arguments (#601)
14
+ - Make rubocop info severity Severity::HINT (#576)
15
+ - Process non-self singleton classes (#581)
16
+ - Fix nest gemspec dependency (#599)
17
+ - Strip 'file ' prefix from all filenames in RdocToYard (#585)
18
+ - Show why rubocop fails (#605)
19
+ - Link solargraph-rails (#611)
20
+
21
+ ## 0.47.2 - September 30, 2022
22
+ - Fix complex type inference (#578)
23
+ - Off-by-one diagnostic (#595)
24
+
25
+ ## 0.47.1 - September 27, 2022
26
+ - Remove debug code from release (#600)
27
+
28
+ ## 0.47.0 - September 25, 2022
29
+ - Completion candidates for union types (#507)
30
+ - Nullify Hover object instead of contents value (#583)
31
+ - Mapping workspace stuck in 0 (#587)
32
+ - Fix parsing of nested subtypes (#589)
33
+ - Update YARD tags on Pin::Block methods (#588)
34
+ - @!visibility directive support (#566)
35
+
36
+ ## 0.46.0 - August 22, 2022
37
+ - Ignore typecheck errors with @sg-ignore tag (#419)
38
+ - Strict checks report undefined method calls on variables (#553)
39
+ - Infer type from method arguments (#554)
40
+ - Return nil value for empty hover contents (#543)
41
+
1
42
  ## 0.45.0 - May 23, 2022
2
43
  - Basic support for RSpec #describe and #it
3
44
  - fix: domain can complete private method (#490)
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017-2019 by Fred Snyder for Castwide Technologies
3
+ Copyright (c) 2017-2023 by Fred Snyder for Castwide Technologies
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -32,6 +32,11 @@ Plug-ins and extensions are available for the following editors:
32
32
  * Package: https://atom.io/packages/ruby-solargraph
33
33
  * GitHub: https://github.com/castwide/atom-solargraph
34
34
 
35
+ * **Sublime Text**
36
+ * Extension: https://packagecontrol.io/packages/LSP
37
+ * GitHub: https://github.com/sublimelsp/LSP
38
+ * Instructions: https://lsp.sublimetext.io/language_servers/#solargraph
39
+
35
40
  * **Vim**
36
41
  * GitHub: `LanguageClient-neovim`, https://github.com/autozimu/LanguageClient-neovim
37
42
  * GitHub: `coc`, https://github.com/neoclide/coc-solargraph
@@ -49,6 +54,9 @@ Plug-ins and extensions are available for the following editors:
49
54
 
50
55
  Solargraph's behavior can be controlled via optional [configuration](https://solargraph.org/guides/configuration) files. The highest priority file is a `.solargraph.yml` file at the root of the project. If not present, any global configuration at `~/.config/solargraph/config.yml` will apply. The path to the global configuration can be overridden with the `SOLARGRAPH_GLOBAL_CONFIG` environment variable.
51
56
 
57
+ ### Rails Support
58
+ For better Rails support, please consider using [solargraph-rails](https://github.com/iftheshoefritz/solargraph-rails/)
59
+
52
60
  ### Gem Support
53
61
 
54
62
  Solargraph is capable of providing code completion and documentation for gems that have YARD documentation. You can make sure your gems are documented by running `yard gems` from the command line. (YARD is included as one of Solargraph's gem dependencies. The first time you run it might take a while if you have a lot of gems installed).
data/SPONSORS.md CHANGED
@@ -10,8 +10,6 @@ The following people and organizations provide funding or other resources. [Beco
10
10
 
11
11
  ## Named Sponsors
12
12
 
13
- - Emily Strickland
14
- - Tom de Grunt
15
13
  - Akira Yamada
16
- - Erlend Finvåg
17
- - Matt Massicotte
14
+ - Joel Drapper
15
+ - Yutaka Tachibana
@@ -247,10 +247,22 @@ module Solargraph
247
247
  end
248
248
  ovr.tags.each do |tag|
249
249
  pin.docstring.add_tag(tag)
250
- new_pin.docstring.add_tag(tag) if new_pin
250
+ redefine_return_type pin, tag
251
+ if new_pin
252
+ new_pin.docstring.add_tag(tag)
253
+ redefine_return_type new_pin, tag
254
+ end
251
255
  end
252
256
  end
253
257
  end
258
+
259
+ def redefine_return_type pin, tag
260
+ return unless pin && tag.tag_name == 'return'
261
+ pin.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
262
+ pin.signatures.each do |sig|
263
+ sig.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
264
+ end
265
+ end
254
266
  end
255
267
  end
256
268
  end
@@ -21,6 +21,11 @@ module Solargraph
21
21
  # @return [Array<String>]
22
22
  attr_reader :unresolved_requires
23
23
 
24
+ @@core_map = RbsMap::CoreMap.new
25
+
26
+ # @return [Array<String>]
27
+ attr_reader :missing_docs
28
+
24
29
  # @param pins [Array<Solargraph::Pin::Base>]
25
30
  def initialize pins: []
26
31
  @source_map_hash = {}
@@ -37,7 +42,7 @@ module Solargraph
37
42
  @source_map_hash = {}
38
43
  implicit.clear
39
44
  cache.clear
40
- @store = Store.new(yard_map.pins + pins)
45
+ @store = Store.new(@@core_map.pins + pins)
41
46
  self
42
47
  end
43
48
 
@@ -65,14 +70,25 @@ module Solargraph
65
70
  end
66
71
  external_requires.merge implicit.requires
67
72
  external_requires.merge bench.workspace.config.required
68
- yard_map.change(external_requires, bench.workspace.directory, bench.workspace.source_gems)
69
- @store = Store.new(yard_map.pins + implicit.pins + pins)
73
+ @rbs_maps = external_requires.map { |r| load_rbs_map(r) }
74
+ unresolved_requires = @rbs_maps.reject(&:resolved?).map(&:library)
75
+ yard_map.change(unresolved_requires, bench.workspace.directory, bench.workspace.source_gems)
76
+ @store = Store.new(@@core_map.pins + @rbs_maps.flat_map(&:pins) + yard_map.pins + implicit.pins + pins)
70
77
  @unresolved_requires = yard_map.unresolved_requires
78
+ @missing_docs = yard_map.missing_docs
71
79
  @rebindable_method_names = nil
72
80
  store.block_pins.each { |blk| blk.rebind(self) }
73
81
  self
74
82
  end
75
83
 
84
+ def core_pins
85
+ @@core_map.pins
86
+ end
87
+
88
+ def yard_map
89
+ @yard_map ||= YardMap.new
90
+ end
91
+
76
92
  # @param name [String]
77
93
  # @return [YARD::Tags::MacroDirective, nil]
78
94
  def named_macro name
@@ -128,7 +144,8 @@ module Solargraph
128
144
 
129
145
  def rebindable_method_names
130
146
  @rebindable_method_names ||= begin
131
- result = yard_map.rebindable_method_names
147
+ # result = yard_map.rebindable_method_names
148
+ result = ['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec', 'define_method'].to_set
132
149
  source_maps.each do |map|
133
150
  result.merge map.rebindable_method_names
134
151
  end
@@ -187,7 +204,7 @@ module Solargraph
187
204
  #
188
205
  # @param namespace [String, nil] The namespace to match
189
206
  # @param context [String] The context to search
190
- # @return [String]
207
+ # @return [String, nil]
191
208
  def qualify namespace, context = ''
192
209
  return namespace if ['self', nil].include?(namespace)
193
210
  cached = cache.get_qualified_namespace(namespace, context)
@@ -281,33 +298,33 @@ module Solargraph
281
298
  # type = Solargraph::ComplexType.parse('String')
282
299
  # api_map.get_complex_type_methods(type)
283
300
  #
284
- # @param type [Solargraph::ComplexType] The complex type of the namespace
301
+ # @param complex_type [Solargraph::ComplexType] The complex type of the namespace
285
302
  # @param context [String] The context from which the type is referenced
286
303
  # @param internal [Boolean] True to include private methods
287
304
  # @return [Array<Solargraph::Pin::Base>]
288
- def get_complex_type_methods type, context = '', internal = false
305
+ def get_complex_type_methods complex_type, context = '', internal = false
289
306
  # This method does not qualify the complex type's namespace because
290
307
  # it can cause conflicts between similar names, e.g., `Foo` vs.
291
308
  # `Other::Foo`. It still takes a context argument to determine whether
292
309
  # protected and private methods are visible.
293
- return [] if type.undefined? || type.void?
294
- result = []
295
- if type.duck_type?
296
- type.select(&:duck_type?).each do |t|
297
- result.push Pin::DuckMethod.new(name: t.tag[1..-1])
298
- end
299
- result.concat get_methods('Object')
300
- else
301
- unless type.nil? || type.name == 'void'
302
- visibility = [:public]
303
- if type.namespace == context || super_and_sub?(type.namespace, context)
304
- visibility.push :protected
305
- visibility.push :private if internal
310
+ return [] if complex_type.undefined? || complex_type.void?
311
+ result = Set.new
312
+ complex_type.each do |type|
313
+ if type.duck_type?
314
+ result.add Pin::DuckMethod.new(name: type.to_s[1..-1])
315
+ result.merge get_methods('Object')
316
+ else
317
+ unless type.nil? || type.name == 'void'
318
+ visibility = [:public]
319
+ if type.namespace == context || super_and_sub?(type.namespace, context)
320
+ visibility.push :protected
321
+ visibility.push :private if internal
322
+ end
323
+ result.merge get_methods(type.namespace, scope: type.scope, visibility: visibility)
306
324
  end
307
- result.concat get_methods(type.namespace, scope: type.scope, visibility: visibility)
308
325
  end
309
326
  end
310
- result
327
+ result.to_a
311
328
  end
312
329
 
313
330
  # Get a stack of method pins for a method name in a namespace. The order
@@ -383,9 +400,10 @@ module Solargraph
383
400
  # @param query [String]
384
401
  # @return [Array<Pin::Base>]
385
402
  def query_symbols query
386
- result = []
387
- source_map_hash.each_value { |s| result.concat s.query_symbols(query) }
388
- result
403
+ Pin::Search.new(
404
+ source_map_hash.values.flat_map(&:document_symbols),
405
+ query
406
+ ).results
389
407
  end
390
408
 
391
409
  # @param location [Solargraph::Location]
@@ -442,18 +460,15 @@ module Solargraph
442
460
  def super_and_sub?(sup, sub)
443
461
  fqsup = qualify(sup)
444
462
  cls = qualify(sub)
445
- until fqsup.nil? || cls.nil?
463
+ tested = []
464
+ until fqsup.nil? || cls.nil? || tested.include?(cls)
446
465
  return true if cls == fqsup
466
+ tested.push cls
447
467
  cls = qualify_superclass(cls)
448
468
  end
449
469
  false
450
470
  end
451
471
 
452
- # @return [YardMap]
453
- def yard_map
454
- @yard_map ||= YardMap.new
455
- end
456
-
457
472
  # Check if the host class includes the specified module.
458
473
  #
459
474
  # @param host [String] The class
@@ -470,6 +485,14 @@ module Solargraph
470
485
  # @return [Hash{String => SourceMap}]
471
486
  attr_reader :source_map_hash
472
487
 
488
+ # @param library [String]
489
+ # @return [RbsMap]
490
+ def load_rbs_map library
491
+ # map = RbsMap.load(library)
492
+ # return map if map.resolved?
493
+ RbsMap::StdlibMap.load(library)
494
+ end
495
+
473
496
  # @return [ApiMap::Store]
474
497
  def store
475
498
  @store ||= Store.new
@@ -672,7 +695,7 @@ module Solargraph
672
695
  comments: origin.comments,
673
696
  scope: origin.scope,
674
697
  visibility: origin.visibility,
675
- parameters: origin.parameters,
698
+ signatures: origin.signatures,
676
699
  attribute: origin.attribute?
677
700
  }
678
701
  Pin::Method.new **args
@@ -0,0 +1,51 @@
1
+ require 'fileutils'
2
+
3
+ module Solargraph
4
+ module Cache
5
+ class << self
6
+ # The base directory where cached documentation is installed.
7
+ #
8
+ # @return [String]
9
+ def base_dir
10
+ # The directory is not stored in a variable so it can be overridden
11
+ # in specs.
12
+ ENV['SOLARGRAPH_CACHE'] || File.join(Dir.home, '.solargraph', 'cache')
13
+ end
14
+
15
+ # The working directory for the current Ruby and Solargraph versions.
16
+ #
17
+ # @return [String]
18
+ def work_dir
19
+ # The directory is not stored in a variable so it can be overridden
20
+ # in specs.
21
+ File.join(base_dir, "ruby-#{RUBY_VERSION}", "rbs-#{RBS::VERSION}", "solargraph-#{Solargraph::VERSION}")
22
+ end
23
+
24
+ # @return [Array<Solargraph::Pin::Base>, nil]
25
+ def load *path
26
+ file = File.join(work_dir, *path)
27
+ return nil unless File.file?(file)
28
+ Marshal.load(File.read(file, mode: 'rb'))
29
+ rescue StandardError => e
30
+ Solargraph.logger.warn "Failed to load cached file #{file}: [#{e.class}] #{e.message}"
31
+ FileUtils.rm_f file
32
+ nil
33
+ end
34
+
35
+ # @return [Boolean]
36
+ def save *path, pins
37
+ return false if pins.empty?
38
+ file = File.join(work_dir, *path)
39
+ base = File.dirname(file)
40
+ FileUtils.mkdir_p base unless File.directory?(base)
41
+ ser = Marshal.dump(pins)
42
+ File.write file, ser, mode: 'wb'
43
+ true
44
+ end
45
+
46
+ def clear
47
+ FileUtils.rm_rf base_dir, secure: true
48
+ end
49
+ end
50
+ end
51
+ end
@@ -101,6 +101,7 @@ module Solargraph
101
101
  # @param context [String] The namespace from which to resolve names
102
102
  # @return [ComplexType] The generated ComplexType
103
103
  def qualify api_map, context = ''
104
+ return self if name == 'param'
104
105
  return ComplexType.new([self]) if duck_type? || void? || undefined?
105
106
  recon = (rooted? ? '' : context)
106
107
  fqns = api_map.qualify(name, recon)
@@ -109,12 +110,8 @@ module Solargraph
109
110
  return UniqueType::UNDEFINED
110
111
  end
111
112
  fqns = "::#{fqns}" # Ensure the resulting complex type is rooted
112
- ltypes = key_types.map do |t|
113
- t.qualify api_map, context
114
- end
115
- rtypes = value_types.map do |t|
116
- t.qualify api_map, context
117
- end
113
+ ltypes = key_types.map { |t| t.qualify api_map, context }.uniq
114
+ rtypes = value_types.map { |t| t.qualify api_map, context }.uniq
118
115
  if list_parameters?
119
116
  Solargraph::ComplexType.parse("#{fqns}<#{rtypes.map(&:tag).join(', ')}>")
120
117
  elsif fixed_parameters?
@@ -125,6 +122,13 @@ module Solargraph
125
122
  Solargraph::ComplexType.parse(fqns)
126
123
  end
127
124
  end
125
+
126
+ # @yieldparam [UniqueType]
127
+ # @return [Enumerator<UniqueType>]
128
+ def each_unique_type &block
129
+ return enum_for(__method__) unless block_given?
130
+ yield self
131
+ end
128
132
  end
129
133
  end
130
134
  end
@@ -8,6 +8,8 @@ module Solargraph
8
8
  class UniqueType
9
9
  include TypeMethods
10
10
 
11
+ attr_reader :all_params
12
+
11
13
  # Create a UniqueType with the specified name and an optional substring.
12
14
  # The substring is the parameter section of a parametrized type, e.g.,
13
15
  # for the type `Array<String>`, the name is `Array` and the substring is
@@ -27,6 +29,7 @@ module Solargraph
27
29
  @tag = @name + substring
28
30
  @key_types = []
29
31
  @subtypes = []
32
+ @all_params = []
30
33
  return unless parameters?
31
34
  if @substring.start_with?('<(') && @substring.end_with?(')>')
32
35
  subs = ComplexType.parse(substring[2..-3], partial: true)
@@ -40,12 +43,66 @@ module Solargraph
40
43
  else
41
44
  @subtypes.concat subs
42
45
  end
46
+ @all_params.concat @key_types
47
+ @all_params.concat @subtypes
43
48
  end
44
49
 
45
50
  def to_s
46
51
  tag
47
52
  end
48
53
 
54
+ def to_rbs
55
+ "#{namespace}#{parameters? ? "[#{subtypes.map { |s| s.to_rbs }.join(', ')}]" : ''}"
56
+ end
57
+
58
+ def parameterized?
59
+ name == 'param' || all_params.any?(&:parameterized?)
60
+ end
61
+
62
+ def resolve_parameters definitions, context
63
+ new_name = if name == 'param'
64
+ idx = definitions.parameters.index(subtypes.first.name)
65
+ return ComplexType::UNDEFINED if idx.nil?
66
+ param_type = context.return_type.all_params[idx]
67
+ return ComplexType::UNDEFINED unless param_type
68
+ param_type.to_s
69
+ else
70
+ name
71
+ end
72
+ new_key_types = if name != 'param'
73
+ @key_types.map { |t| t.resolve_parameters(definitions, context) }.select(&:defined?)
74
+ else
75
+ []
76
+ end
77
+ new_subtypes = if name != 'param'
78
+ @subtypes.map { |t| t.resolve_parameters(definitions, context) }.select(&:defined?)
79
+ else
80
+ []
81
+ end
82
+ if name != 'param' && !(new_key_types.empty? && new_subtypes.empty?)
83
+ if hash_parameters?
84
+ UniqueType.new(new_name, "{#{new_key_types.join(', ')} => #{new_subtypes.join(', ')}}")
85
+ elsif parameters?
86
+ if @substring.start_with?'<('
87
+ UniqueType.new(new_name, "<(#{new_subtypes.join(', ')})>")
88
+ else
89
+ UniqueType.new(new_name, "<#{new_subtypes.join(', ')}>")
90
+ end
91
+ else
92
+ UniqueType.new(new_name)
93
+ end
94
+ else
95
+ UniqueType.new(new_name)
96
+ end
97
+
98
+ # idx = definitions.parameters.index(subtypes.first.name)
99
+ # STDERR.puts "Index: #{idx}"
100
+ # return ComplexType::UNDEFINED if idx.nil?
101
+ # param_type = context.return_type.all_params[idx]
102
+ # return ComplexType::UNDEFINED unless param_type
103
+ # ComplexType.try_parse(param_type.to_s)
104
+ end
105
+
49
106
  def self_to dst
50
107
  return self unless selfy?
51
108
  new_name = (@name == 'self' ? dst : @name)
@@ -30,6 +30,12 @@ module Solargraph
30
30
  @items.first
31
31
  end
32
32
 
33
+ def to_rbs
34
+ ((@items.length > 1 ? '(' : '') + @items.map do |item|
35
+ "#{item.namespace}#{item.parameters? ? "[#{item.subtypes.map { |s| s.to_rbs }.join(', ')}]" : ''}"
36
+ end.join(' | ') + (@items.length > 1 ? ')' : '')).gsub(/undefined/, 'untyped')
37
+ end
38
+
33
39
  def map &block
34
40
  @items.map &block
35
41
  end
@@ -40,6 +46,16 @@ module Solargraph
40
46
  @items.each &block
41
47
  end
42
48
 
49
+ # @yieldparam [UniqueType]
50
+ # @return [Enumerator<UniqueType>]
51
+ def each_unique_type &block
52
+ return enum_for(__method__) unless block_given?
53
+
54
+ @items.each do |item|
55
+ item.each_unique_type &block
56
+ end
57
+ end
58
+
43
59
  def length
44
60
  @items.length
45
61
  end
@@ -74,10 +90,23 @@ module Solargraph
74
90
  @items.all? &block
75
91
  end
76
92
 
93
+ def any? &block
94
+ @items.compact.any? &block
95
+ end
96
+
77
97
  def selfy?
78
98
  @items.any?(&:selfy?)
79
99
  end
80
100
 
101
+ def parameterized?
102
+ any?(&:parameterized?)
103
+ end
104
+
105
+ def resolve_parameters definitions, context
106
+ result = @items.map { |i| i.resolve_parameters(definitions, context) }
107
+ ComplexType.parse(*result.map(&:tag))
108
+ end
109
+
81
110
  # @param dst [String]
82
111
  # @return [ComplexType]
83
112
  def self_to dst
@@ -91,6 +120,10 @@ module Solargraph
91
120
  @items.any?(&:nil_type?)
92
121
  end
93
122
 
123
+ def all_params
124
+ @items.first.all_params || []
125
+ end
126
+
94
127
  private
95
128
 
96
129
  # @todo This is a quick and dirty hack that forces `self` keywords
@@ -154,9 +187,9 @@ module Solargraph
154
187
  subtype_string.clear
155
188
  next
156
189
  else
190
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack == 0
157
191
  point_stack -= 1
158
- subtype_string += char if point_stack == 0
159
- raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack < 0
192
+ subtype_string += char
160
193
  end
161
194
  next
162
195
  elsif char == '{'
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Convention
5
+ class Rakefile < Base
6
+ def local source_map
7
+ basename = File.basename(source_map.filename)
8
+ return EMPTY_ENVIRON unless basename.end_with?('.rake') || basename == 'Rakefile'
9
+
10
+ @environ ||= Environ.new(
11
+ requires: ['rake'],
12
+ domains: ['Rake::DSL']
13
+ )
14
+ end
15
+ end
16
+ end
17
+ end
@@ -11,6 +11,7 @@ module Solargraph
11
11
  autoload :Gemfile, 'solargraph/convention/gemfile'
12
12
  autoload :Rspec, 'solargraph/convention/rspec'
13
13
  autoload :Gemspec, 'solargraph/convention/gemspec'
14
+ autoload :Rakefile, 'solargraph/convention/rakefile'
14
15
 
15
16
  @@conventions = Set.new
16
17
 
@@ -43,5 +44,6 @@ module Solargraph
43
44
  register Gemfile
44
45
  register Gemspec
45
46
  register Rspec
47
+ register Rakefile
46
48
  end
47
49
  end
@@ -12,6 +12,10 @@ module Solargraph
12
12
  refs = {}
13
13
  map = api_map.source_map(source.filename)
14
14
  map.requires.each { |ref| refs[ref.name] = ref }
15
+ api_map.missing_docs.each do |r|
16
+ next unless refs.key?(r)
17
+ result.push docs_error(r, refs[r].location)
18
+ end
15
19
  api_map.unresolved_requires.each do |r|
16
20
  next unless refs.key?(r)
17
21
  result.push require_error(r, refs[r].location)
@@ -21,6 +25,18 @@ module Solargraph
21
25
 
22
26
  private
23
27
 
28
+ # @param path [String]
29
+ # @param location [Location]
30
+ # @return [Hash]
31
+ def docs_error path, location
32
+ {
33
+ range: location.range.to_hash,
34
+ severity: Diagnostics::Severities::WARNING,
35
+ source: 'RequireNotFound',
36
+ message: "YARD docs not found for #{path}"
37
+ }
38
+ end
39
+
24
40
  # @param path [String]
25
41
  # @param location [Location]
26
42
  # @return [Hash]
@@ -11,6 +11,7 @@ module Solargraph
11
11
 
12
12
  # Conversion of RuboCop severity names to LSP constants
13
13
  SEVERITIES = {
14
+ 'info' => Severities::HINT,
14
15
  'refactor' => Severities::HINT,
15
16
  'convention' => Severities::INFORMATION,
16
17
  'warning' => Severities::WARNING,
@@ -22,16 +23,20 @@ module Solargraph
22
23
  # @param _api_map [Solargraph::ApiMap]
23
24
  # @return [Array<Hash>]
24
25
  def diagnose source, _api_map
26
+ @source = source
25
27
  require_rubocop(rubocop_version)
26
28
  options, paths = generate_options(source.filename, source.code)
27
29
  store = RuboCop::ConfigStore.new
28
30
  runner = RuboCop::Runner.new(options, store)
29
31
  result = redirect_stdout{ runner.run(paths) }
32
+
33
+ return [] if result.empty?
34
+
30
35
  make_array JSON.parse(result)
31
36
  rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
32
37
  raise DiagnosticsError, "Error in RuboCop configuration: #{e.message}"
33
- rescue JSON::ParserError
34
- raise DiagnosticsError, 'RuboCop returned invalid data'
38
+ rescue JSON::ParserError => e
39
+ raise DiagnosticsError, "RuboCop returned invalid data: #{e.message}"
35
40
  end
36
41
 
37
42
  private
@@ -88,8 +93,17 @@ module Solargraph
88
93
  if off['location']['start_line'] != off['location']['last_line']
89
94
  Position.new(off['location']['start_line'], 0)
90
95
  else
96
+ start_line = off['location']['start_line'] - 1
97
+ last_column = off['location']['last_column']
98
+ line = @source.code.lines[start_line]
99
+ col_off = if line.nil? || line.empty?
100
+ 1
101
+ else
102
+ 0
103
+ end
104
+
91
105
  Position.new(
92
- off['location']['start_line'] - 1, off['location']['last_column']
106
+ start_line, last_column - col_off
93
107
  )
94
108
  end
95
109
  end