solargraph 0.49.0 → 0.51.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +4 -6
  3. data/CHANGELOG.md +38 -0
  4. data/README.md +2 -4
  5. data/SPONSORS.md +2 -1
  6. data/lib/solargraph/cache.rb +3 -1
  7. data/lib/solargraph/complex_type.rb +9 -2
  8. data/lib/solargraph/convention.rb +0 -2
  9. data/lib/solargraph/language_server/host/cataloger.rb +1 -1
  10. data/lib/solargraph/language_server/host.rb +11 -1
  11. data/lib/solargraph/language_server/message/initialize.rb +8 -0
  12. data/lib/solargraph/language_server/message/initialized.rb +1 -0
  13. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +4 -1
  14. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -4
  15. data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
  16. data/lib/solargraph/language_server/message/text_document.rb +1 -0
  17. data/lib/solargraph/language_server/message.rb +1 -0
  18. data/lib/solargraph/library.rb +22 -2
  19. data/lib/solargraph/parser/rubyvm/class_methods.rb +4 -0
  20. data/lib/solargraph/parser/rubyvm/node_chainer.rb +1 -1
  21. data/lib/solargraph/parser/rubyvm/node_methods.rb +3 -1
  22. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +10 -4
  23. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +2 -2
  24. data/lib/solargraph/parser/rubyvm/node_processors.rb +1 -0
  25. data/lib/solargraph/parser.rb +2 -2
  26. data/lib/solargraph/pin/base_variable.rb +1 -1
  27. data/lib/solargraph/pin/block.rb +1 -1
  28. data/lib/solargraph/pin/delegated_method.rb +97 -0
  29. data/lib/solargraph/pin/method.rb +5 -0
  30. data/lib/solargraph/pin/search.rb +1 -1
  31. data/lib/solargraph/pin.rb +1 -0
  32. data/lib/solargraph/range.rb +2 -4
  33. data/lib/solargraph/rbs_map/conversions.rb +8 -6
  34. data/lib/solargraph/rbs_map/core_fills.rb +7 -1
  35. data/lib/solargraph/rbs_map/core_map.rb +1 -1
  36. data/lib/solargraph/rbs_map/stdlib_map.rb +3 -0
  37. data/lib/solargraph/shell.rb +16 -6
  38. data/lib/solargraph/source/chain/call.rb +1 -1
  39. data/lib/solargraph/source/chain.rb +1 -1
  40. data/lib/solargraph/source_map/clip.rb +14 -0
  41. data/lib/solargraph/source_map/mapper.rb +6 -4
  42. data/lib/solargraph/source_map.rb +15 -2
  43. data/lib/solargraph/type_checker.rb +33 -21
  44. data/lib/solargraph/version.rb +1 -1
  45. data/lib/solargraph/workspace/config.rb +6 -5
  46. data/lib/solargraph/yard_map.rb +15 -7
  47. data/solargraph.gemspec +11 -5
  48. metadata +73 -22
  49. data/.travis.yml +0 -19
  50. data/lib/solargraph/convention/rspec.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0b66abd5cf5a0376d5521532dda16db328592eb38bac6acd84f997b19cb328c
4
- data.tar.gz: 51e038df27bae1457393c7ff023c9951b0f8919267678e29aab2e21efeb2b1a8
3
+ metadata.gz: 925e6692e134d83820ade3224a10e1e25ba8b7f65c5a8399b185574f225ad8e7
4
+ data.tar.gz: 319f943451956ac714e110f48db851391cfb5c4b2ceb1e3e8d2eb2d22dc56c05
5
5
  SHA512:
6
- metadata.gz: 9b8310748d4754c27fd62763ce1bd8759fc43fc825b1b40353d4537130f2b6143cdb59101da679a8b4a7fb0778430eeac2eccbb845f7a9a5ac11f402b3a71461
7
- data.tar.gz: 1b2f79f5396a3c056d0b2acbcb49d6c1385b02a49b33edbe1a3e452a7b451b9b87547b8b8d5974a17e25ea2f5c21db8dd315d2b3d856fb3c7ce2d300a4595c70
6
+ metadata.gz: df03f1f0ed8e51f8c286395c4b87b1c254c78a897761ec71a9af896ef86c01e6d4285530ddf2e40c72f17afb6b5d87be11e219cc46859d7d7b7c2e05e24687bf
7
+ data.tar.gz: dd6b4f96bc8e6361bcfd313129a4ba9d680c8db45484deea040ec5fa6ba5a8873dcefa2980af4824d26f2ecc16d68bd5b5554e4978ae71853e22df49ed427894
@@ -22,19 +22,17 @@ jobs:
22
22
  runs-on: ubuntu-latest
23
23
  strategy:
24
24
  matrix:
25
- ruby-version: ['2.6', '2.7', '3.0', '3.1']
25
+ ruby-version: ['2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4', 'head']
26
26
 
27
27
  steps:
28
28
  - uses: actions/checkout@v3
29
29
  - name: Set up Ruby
30
- # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
31
- # change this to (see https://github.com/ruby/setup-ruby#versioning):
32
- # uses: ruby/setup-ruby@v1
33
- uses: ruby/setup-ruby@2b019609e2b0f1ea1a2bc8ca11cb82ab46ada124
30
+ uses: ruby/setup-ruby@v1
34
31
  with:
35
32
  ruby-version: ${{ matrix.ruby-version }}
36
33
  bundler-cache: false
37
- - run: bundle install
34
+ - name: Install gems
35
+ run: bundle install
38
36
  - name: Set up yardocs
39
37
  run: bundle exec yard gems
40
38
  - name: Run tests
data/CHANGELOG.md CHANGED
@@ -1,3 +1,41 @@
1
+ ## 0.51.0 - January 19, 2025
2
+ - Resolve self in yieldself tags
3
+ - Include absolute paths in config (#674)
4
+ - Enable diagnostics by default
5
+ - Fix cache resolution (#704)
6
+ - Modify rubocop option for rubocop < 1.30 (#665)
7
+ - Include absolute paths in config (#674)
8
+ - Enable diagnostics by default
9
+ - Remove RSpec convention (#716)
10
+ - Include convention pins in document_symbols (#724)
11
+ - Remove e2mmap dependency (#699)
12
+ - Update rbs to 3.0
13
+ - Relax reverse_markdown dependency (#729)
14
+ - Fix Ruby 3.4 and move all parsing to whitequark (#739)
15
+ - Add Pin::DelegatedMethod (#602)
16
+ - Complete global methods from a file inside namespaces (#714)
17
+ - gemspec dashes and required path slashes (#697)
18
+
19
+ ## 0.50.0 - December 5, 2023
20
+ - Remove .travis.yml as its not longer used (#627)
21
+ - Fix empty string case when processing requires (#644)
22
+ - Fix scope() method call on wrong object (#670)
23
+ - Parse comments that start with multiple hashes (#667)
24
+ - Use XDG_CACHE_HOME if it exists (#664)
25
+ - Add rbs mention to readme (#693)
26
+ - Remove Atom from the readme (#692)
27
+ - Add more metadata to the gemspec (#691)
28
+ - Do not deprecate clear command
29
+ - Library#locate_ref returns nil for unresolved requires (#675)
30
+ - Hide deprecated commands
31
+ - List command
32
+ - Fixes (or ignores) ffi crash (#676)
33
+ - increase sleep time on cataloger (#677)
34
+ - YardMap ignores absolute paths (#678)
35
+ - Clarify macros vs. directives
36
+ - Infer complex types from method calls
37
+ - Default cache uses XDG_CACHE_HOME default (#664)
38
+
1
39
  ## 0.49.0 - April 9, 2023
2
40
  - Better union type handling
3
41
  - First version of RBS support
data/README.md CHANGED
@@ -28,10 +28,6 @@ Plug-ins and extensions are available for the following editors:
28
28
  * Extension: https://marketplace.visualstudio.com/items?itemName=castwide.solargraph
29
29
  * GitHub: https://github.com/castwide/vscode-solargraph
30
30
 
31
- * **Atom**
32
- * Package: https://atom.io/packages/ruby-solargraph
33
- * GitHub: https://github.com/castwide/atom-solargraph
34
-
35
31
  * **Sublime Text**
36
32
  * Extension: https://packagecontrol.io/packages/LSP
37
33
  * GitHub: https://github.com/sublimelsp/LSP
@@ -71,6 +67,8 @@ As of version 0.33.0, Solargraph includes a [type checker](https://github.com/ca
71
67
 
72
68
  ### Updating Core Documentation
73
69
 
70
+ As of version 0.49.0, Solargraph uses [rbs](https://github.com/ruby/rbs) for core and stdlib documentation. The following only applies to prior versions.
71
+
74
72
  The Solargraph gem ships with documentation for Ruby 2.2.2. You can download documentation for other Ruby versions from the command line.
75
73
 
76
74
  $ solargraph list-cores # List the installed documentation versions
data/SPONSORS.md CHANGED
@@ -12,4 +12,5 @@ The following people and organizations provide funding or other resources. [Beco
12
12
 
13
13
  - Akira Yamada
14
14
  - Joel Drapper
15
- - Yutaka Tachibana
15
+ - Spencer
16
+ - Vince Broz
@@ -9,7 +9,9 @@ module Solargraph
9
9
  def base_dir
10
10
  # The directory is not stored in a variable so it can be overridden
11
11
  # in specs.
12
- ENV['SOLARGRAPH_CACHE'] || File.join(Dir.home, '.solargraph', 'cache')
12
+ ENV['SOLARGRAPH_CACHE'] ||
13
+ (ENV['XDG_CACHE_HOME'] ? File.join(ENV['XDG_CACHE_HOME'], 'solargraph') : nil) ||
14
+ File.join(Dir.home, '.cache', 'solargraph')
13
15
  end
14
16
 
15
17
  # The working directory for the current Ruby and Solargraph versions.
@@ -67,11 +67,18 @@ module Solargraph
67
67
  def select &block
68
68
  @items.select &block
69
69
  end
70
+
71
+ # @return [String]
70
72
  def namespace
71
73
  # cache this attr for high frequency call
72
74
  @namespace ||= method_missing(:namespace).to_s
73
75
  end
74
76
 
77
+ # @return [Array<String>]
78
+ def namespaces
79
+ @items.map(&:namespace)
80
+ end
81
+
75
82
  def method_missing name, *args, &block
76
83
  return if @items.first.nil?
77
84
  return @items.first.send(name, *args, &block) if respond_to_missing?(name)
@@ -113,7 +120,7 @@ module Solargraph
113
120
  return self unless selfy?
114
121
  red = reduce_class(dst)
115
122
  result = @items.map { |i| i.self_to red }
116
- ComplexType.parse(*result.map(&:tag))
123
+ ComplexType.parse(*result.map(&:to_s))
117
124
  end
118
125
 
119
126
  def nullable?
@@ -169,7 +176,7 @@ module Solargraph
169
176
  paren_stack = 0
170
177
  base = String.new
171
178
  subtype_string = String.new
172
- type_string.each_char do |char|
179
+ type_string&.each_char do |char|
173
180
  if char == '='
174
181
  #raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
175
182
  elsif char == '<'
@@ -9,7 +9,6 @@ module Solargraph
9
9
  module Convention
10
10
  autoload :Base, 'solargraph/convention/base'
11
11
  autoload :Gemfile, 'solargraph/convention/gemfile'
12
- autoload :Rspec, 'solargraph/convention/rspec'
13
12
  autoload :Gemspec, 'solargraph/convention/gemspec'
14
13
  autoload :Rakefile, 'solargraph/convention/rakefile'
15
14
 
@@ -43,7 +42,6 @@ module Solargraph
43
42
 
44
43
  register Gemfile
45
44
  register Gemspec
46
- register Rspec
47
45
  register Rakefile
48
46
  end
49
47
  end
@@ -34,7 +34,7 @@ module Solargraph
34
34
  Thread.new do
35
35
  until stopped?
36
36
  tick
37
- sleep 0.01
37
+ sleep 0.1
38
38
  end
39
39
  end
40
40
  end
@@ -533,6 +533,15 @@ module Solargraph
533
533
  library.definitions_at(uri_to_file(uri), line, column)
534
534
  end
535
535
 
536
+ # @param uri [String]
537
+ # @param line [Integer]
538
+ # @param column [Integer]
539
+ # @return [Array<Solargraph::Pin::Base>]
540
+ def type_definitions_at uri, line, column
541
+ library = library_for(uri)
542
+ library.type_definitions_at(uri_to_file(uri), line, column)
543
+ end
544
+
536
545
  # @param uri [String]
537
546
  # @param line [Integer]
538
547
  # @param column [Integer]
@@ -630,10 +639,11 @@ module Solargraph
630
639
  'hover' => true,
631
640
  'symbols' => true,
632
641
  'definitions' => true,
642
+ 'typeDefinitions' => true,
633
643
  'rename' => true,
634
644
  'references' => true,
635
645
  'autoformat' => false,
636
- 'diagnostics' => false,
646
+ 'diagnostics' => true,
637
647
  'formatting' => false,
638
648
  'folding' => true,
639
649
  'highlights' => true,
@@ -34,6 +34,7 @@ module Solargraph
34
34
  result[:capabilities].merge! static_document_formatting unless dynamic_registration_for?('textDocument', 'formatting')
35
35
  result[:capabilities].merge! static_document_symbols unless dynamic_registration_for?('textDocument', 'documentSymbol')
36
36
  result[:capabilities].merge! static_definitions unless dynamic_registration_for?('textDocument', 'definition')
37
+ result[:capabilities].merge! static_type_definitions unless dynamic_registration_for?('textDocument', 'typeDefinition')
37
38
  result[:capabilities].merge! static_rename unless dynamic_registration_for?('textDocument', 'rename')
38
39
  result[:capabilities].merge! static_references unless dynamic_registration_for?('textDocument', 'references')
39
40
  result[:capabilities].merge! static_workspace_symbols unless dynamic_registration_for?('workspace', 'symbol')
@@ -121,6 +122,13 @@ module Solargraph
121
122
  }
122
123
  end
123
124
 
125
+ def static_type_definitions
126
+ return {} unless host.options['type_definitions']
127
+ {
128
+ definitionProvider: true
129
+ }
130
+ end
131
+
124
132
  def static_rename
125
133
  {
126
134
  renameProvider: {prepareProvider: true}
@@ -13,6 +13,7 @@ module Solargraph
13
13
  textDocument/formatting
14
14
  textDocument/documentSymbol
15
15
  textDocument/definition
16
+ textDocument/typeDefinition
16
17
  textDocument/references
17
18
  textDocument/rename
18
19
  textDocument/prepareRename
@@ -6,6 +6,8 @@ class Solargraph::LanguageServer::Message::TextDocument::DocumentSymbol < Solarg
6
6
  def process
7
7
  pins = host.document_symbols params['textDocument']['uri']
8
8
  info = pins.map do |pin|
9
+ next nil unless pin.location&.filename
10
+
9
11
  result = {
10
12
  name: pin.name,
11
13
  containerName: pin.namespace,
@@ -17,7 +19,8 @@ class Solargraph::LanguageServer::Message::TextDocument::DocumentSymbol < Solarg
17
19
  deprecated: pin.deprecated?
18
20
  }
19
21
  result
20
- end
22
+ end.compact
23
+
21
24
  set_result info
22
25
  end
23
26
  end
@@ -17,17 +17,17 @@ module Solargraph
17
17
  args = cli_args(file_uri, config)
18
18
 
19
19
  require_rubocop(config['version'])
20
- options, paths = RuboCop::Options.new.parse(args)
20
+ options, paths = ::RuboCop::Options.new.parse(args)
21
21
  options[:stdin] = original
22
22
  corrections = redirect_stdout do
23
- RuboCop::Runner.new(options, RuboCop::ConfigStore.new).run(paths)
23
+ ::RuboCop::Runner.new(options, ::RuboCop::ConfigStore.new).run(paths)
24
24
  end
25
25
  result = options[:stdin]
26
26
 
27
27
  log_corrections(corrections)
28
28
 
29
29
  format original, result
30
- rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
30
+ rescue ::RuboCop::ValidationError, ::RuboCop::ConfigNotFoundError => e
31
31
  set_error(Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}")
32
32
  end
33
33
 
@@ -54,7 +54,7 @@ module Solargraph
54
54
  def cli_args file_uri, config
55
55
  file = UriHelpers.uri_to_file(file_uri)
56
56
  args = [
57
- config['cops'] == 'all' ? '--autocorrect-all' : '--autocorrect',
57
+ config['cops'] == 'all' ? '-A' : '-a',
58
58
  '--cache', 'false',
59
59
  '--format', formatter_class(config).name,
60
60
  ]
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph::LanguageServer::Message::TextDocument
4
+ class TypeDefinition < Base
5
+ def process
6
+ @line = params['position']['line']
7
+ @column = params['position']['character']
8
+ set_result(code_location || [])
9
+ end
10
+
11
+ private
12
+
13
+ def code_location
14
+ suggestions = host.type_definitions_at(params['textDocument']['uri'], @line, @column)
15
+ return nil if suggestions.empty?
16
+ suggestions.reject { |pin| pin.location.nil? || pin.location.filename.nil? }.map do |pin|
17
+ {
18
+ uri: file_to_uri(pin.location.filename),
19
+ range: pin.location.range.to_hash
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -15,6 +15,7 @@ module Solargraph
15
15
  autoload :DiagnosticsQueue, 'solargraph/language_server/message/text_document/diagnostics_queue'
16
16
  autoload :OnTypeFormatting, 'solargraph/language_server/message/text_document/on_type_formatting'
17
17
  autoload :Definition, 'solargraph/language_server/message/text_document/definition'
18
+ autoload :TypeDefinition, 'solargraph/language_server/message/text_document/type_definition'
18
19
  autoload :DocumentSymbol, 'solargraph/language_server/message/text_document/document_symbol'
19
20
  autoload :Formatting, 'solargraph/language_server/message/text_document/formatting'
20
21
  autoload :References, 'solargraph/language_server/message/text_document/references'
@@ -66,6 +66,7 @@ module Solargraph
66
66
  register 'textDocument/didClose', TextDocument::DidClose
67
67
  register 'textDocument/hover', TextDocument::Hover
68
68
  register 'textDocument/definition', TextDocument::Definition
69
+ register 'textDocument/typeDefinition', TextDocument::TypeDefinition
69
70
  register 'textDocument/formatting', TextDocument::Formatting
70
71
  register 'textDocument/onTypeFormatting', TextDocument::OnTypeFormatting
71
72
  register 'textDocument/documentSymbol', TextDocument::DocumentSymbol
@@ -97,7 +97,7 @@ module Solargraph
97
97
  def create filename, text
98
98
  result = false
99
99
  mutex.synchronize do
100
- next unless contain?(filename) || open?(filename) || workspace.would_merge?(filename)
100
+ next unless contain?(filename) || open?(filename)
101
101
  @synchronized = false
102
102
  source = Solargraph::Source.load_string(text, filename)
103
103
  workspace.merge(source)
@@ -199,6 +199,22 @@ module Solargraph
199
199
  handle_file_not_found(filename, e)
200
200
  end
201
201
 
202
+ # Get type definition suggestions for the expression at the specified file and
203
+ # location.
204
+ #
205
+ # @param filename [String] The file to analyze
206
+ # @param line [Integer] The zero-based line number
207
+ # @param column [Integer] The zero-based column number
208
+ # @return [Array<Solargraph::Pin::Base>]
209
+ # @todo Take filename/position instead of filename/line/column
210
+ def type_definitions_at filename, line, column
211
+ position = Position.new(line, column)
212
+ cursor = Source::Cursor.new(read(filename), position)
213
+ api_map.clip(cursor).types
214
+ rescue FileNotFoundError => e
215
+ handle_file_not_found filename, e
216
+ end
217
+
202
218
  # Get signature suggestions for the method at the specified file and
203
219
  # location.
204
220
  #
@@ -258,6 +274,10 @@ module Solargraph
258
274
  api_map.locate_pins(location).map { |pin| pin.realize(api_map) }
259
275
  end
260
276
 
277
+ # Match a require reference to a file.
278
+ #
279
+ # @param location [Location]
280
+ # @return [Location, nil]
261
281
  def locate_ref location
262
282
  map = source_map_hash[location.filename]
263
283
  return if map.nil?
@@ -268,7 +288,7 @@ module Solargraph
268
288
  next unless source_map_hash.key?(full)
269
289
  return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0))
270
290
  end
271
- # api_map.yard_map.require_reference(pin.name)
291
+ nil
272
292
  rescue FileNotFoundError
273
293
  nil
274
294
  end
@@ -108,9 +108,13 @@ module Solargraph
108
108
  end
109
109
 
110
110
  def node_range node
111
+ if node.nil?
112
+ nil
113
+ else
111
114
  st = Position.new(node.first_lineno - 1, node.first_column)
112
115
  en = Position.new(node.last_lineno - 1, node.last_column)
113
116
  Range.new(st, en)
117
+ end
114
118
  end
115
119
 
116
120
  def recipient_node tree
@@ -98,7 +98,7 @@ module Solargraph
98
98
  result.concat generate_links(n.children.last)
99
99
  elsif n.type == :OR
100
100
  result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename), NodeChainer.chain(n.children[1], @filename)])
101
- elsif n.type == :begin
101
+ elsif n.type == :BEGIN
102
102
  result.concat generate_links(n.children[0])
103
103
  elsif n.type == :BLOCK_PASS
104
104
  result.push Chain::BlockVariable.new("&#{n.children[1].children[0].to_s}")
@@ -32,10 +32,12 @@ module Solargraph
32
32
  def infer_literal_node_type node
33
33
  return nil unless Parser.is_ast_node?(node)
34
34
  case node.type
35
- when :LIT, :STR
35
+ when :LIT, :STR, :SYM
36
36
  "::#{node.children.first.class.to_s}"
37
37
  when :DSTR
38
38
  "::String"
39
+ when :INTEGER
40
+ '::Integer'
39
41
  when :ARRAY, :ZARRAY, :LIST, :ZLIST
40
42
  '::Array'
41
43
  when :HASH
@@ -22,7 +22,7 @@ module Solargraph
22
22
  locals.push Solargraph::Pin::LocalVariable.new(
23
23
  location: loc,
24
24
  closure: region.closure,
25
- name: node.children[1].children.first.children.first.to_s,
25
+ name: node.children[1].children.first.to_s,
26
26
  comments: "@type [#{types.join(',')}]",
27
27
  presence: presence
28
28
  )
@@ -34,9 +34,15 @@ module Solargraph
34
34
  private
35
35
 
36
36
  def exception_variable?
37
- Parser.is_ast_node?(node.children[1]) &&
38
- Parser.is_ast_node?(node.children[1].children.first) &&
39
- node.children[1].children.first.type == :LASGN
37
+ if RUBY_VERSION =~ /^3\.4\./
38
+ Parser.is_ast_node?(node.children[1]) &&
39
+ # Parser.is_ast_node?(node.children[1].children.first) &&
40
+ node.children[1].type == :LASGN
41
+ else
42
+ Parser.is_ast_node?(node.children[1]) &&
43
+ Parser.is_ast_node?(node.children[1].children.first) &&
44
+ node.children[1].children.first.type == :LASGN
45
+ end
40
46
  end
41
47
  end
42
48
  end
@@ -43,7 +43,7 @@ module Solargraph
43
43
  if node.type == :FCALL && Parser.is_ast_node?(node.children.last)
44
44
  node.children.last.children[0..-2].each do |child|
45
45
  # next unless child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
46
- if child.type == :LIT || child.type == :STR
46
+ if child.type == :LIT || child.type == :STR || child.type == :SYM
47
47
  name = child.children[0].to_s
48
48
  matches = pins.select{ |pin| pin.is_a?(Pin::Method) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
49
49
  matches.each do |pin|
@@ -175,7 +175,7 @@ module Solargraph
175
175
  NodeProcessor.process node.children.last.children[0], region.update(visibility: :module_function), pins, locals
176
176
  else
177
177
  node.children.last.children[0..-2].each do |x|
178
- next unless [:LIT, :STR].include?(x.type)
178
+ next unless [:LIT, :STR, :SYM].include?(x.type)
179
179
  cn = x.children[0].to_s
180
180
  ref = pins.select { |p| p.is_a?(Pin::Method) && p.namespace == region.closure.full_context.namespace && p.name == cn }.first
181
181
  unless ref.nil?
@@ -58,6 +58,7 @@ module Solargraph
58
58
  register :FOR, Rubyvm::NodeProcessors::BlockNode
59
59
  register :OP_ASGN_OR, Rubyvm::NodeProcessors::OrasgnNode
60
60
  register :LIT, Rubyvm::NodeProcessors::LitNode
61
+ register :SYM, Rubyvm::NodeProcessors::LitNode
61
62
  end
62
63
  end
63
64
  end
@@ -13,8 +13,8 @@ module Solargraph
13
13
  # True if the parser can use RubyVM.
14
14
  #
15
15
  def self.rubyvm?
16
- !!defined?(RubyVM::AbstractSyntaxTree)
17
- # false
16
+ # !!defined?(RubyVM::AbstractSyntaxTree)
17
+ false
18
18
  end
19
19
 
20
20
  selected = rubyvm? ? Rubyvm : Legacy
@@ -56,7 +56,7 @@ module Solargraph
56
56
  end
57
57
  end
58
58
  return ComplexType::UNDEFINED if types.empty?
59
- ComplexType.try_parse(*types.map(&:tag))
59
+ ComplexType.try_parse(*types.map(&:to_s))
60
60
  end
61
61
 
62
62
  def == other
@@ -63,7 +63,7 @@ module Solargraph
63
63
  if receiver_pin && receiver_pin.docstring
64
64
  ys = receiver_pin.docstring.tag(:yieldself)
65
65
  if ys && ys.types && !ys.types.empty?
66
- return ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
66
+ return ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace).self_to(receiver_pin.full_context.namespace)
67
67
  end
68
68
  end
69
69
  nil
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ # A DelegatedMethod is a more complicated version of a MethodAlias that
6
+ # allows aliasing a method from a different closure (class/module etc).
7
+ class DelegatedMethod < Pin::Method
8
+ # A DelegatedMethod can be constructed with either a :resolved_method
9
+ # pin, or a :receiver_chain. When a :receiver_chain is supplied, it
10
+ # will be used to *dynamically* resolve a receiver type within the
11
+ # given closure/scope, and the delegated method will then be resolved
12
+ # to a method pin on that type.
13
+ #
14
+ # @param resolved_method [Method] an already resolved method pin.
15
+ # @param receiver [Source::Chain] the source code used to resolve the receiver for this delegated method.
16
+ # @param receiver_method_name [String] the method name that will be called on the receiver (defaults to :name).
17
+ def initialize(method: nil, receiver: nil, name: method&.name, receiver_method_name: name, **splat)
18
+ raise ArgumentError, 'either :method or :receiver is required' if (method && receiver) || (!method && !receiver)
19
+ super(name: name, **splat)
20
+
21
+ @receiver_chain = receiver
22
+ @resolved_method = method
23
+ @receiver_method_name = receiver_method_name
24
+ end
25
+
26
+ %i[comments parameters return_type location].each do |method|
27
+ define_method(method) do
28
+ @resolved_method ? @resolved_method.send(method) : super()
29
+ end
30
+ end
31
+
32
+ %i[typify realize infer probe].each do |method|
33
+ # @param api_map [ApiMap]
34
+ define_method(method) do |api_map|
35
+ resolve_method(api_map)
36
+ @resolved_method ? @resolved_method.send(method, api_map) : super(api_map)
37
+ end
38
+ end
39
+
40
+ def resolvable?(api_map)
41
+ resolve_method(api_map)
42
+ !!@resolved_method
43
+ end
44
+
45
+ private
46
+
47
+ # Resolves the receiver chain and method name to a method pin, resetting any previously resolution.
48
+ #
49
+ # @param api_map [ApiMap]
50
+ # @return [Pin::Method, nil]
51
+ def resolve_method api_map
52
+ return if @resolved_method
53
+
54
+ resolver = @receiver_chain.define(api_map, self, []).first
55
+
56
+ unless resolver
57
+ Solargraph.logger.warn \
58
+ "Delegated receiver for #{path} was resolved to nil from `#{print_chain(@receiver_chain)}'"
59
+ return
60
+ end
61
+
62
+ receiver_type = resolver.return_type
63
+
64
+ return if receiver_type.undefined?
65
+
66
+ receiver_path, method_scope =
67
+ if @receiver_chain.constant?
68
+ # HACK: the `return_type` of a constant is Class<Whatever>, but looking up a method expects
69
+ # the arguments `"Whatever"` and `scope: :class`.
70
+ [receiver_type.to_s.sub(/^Class<(.+)>$/, '\1'), :class]
71
+ else
72
+ [receiver_type.to_s, :instance]
73
+ end
74
+
75
+ method_stack = api_map.get_method_stack(receiver_path, @receiver_method_name, scope: method_scope)
76
+ @resolved_method = method_stack.first
77
+ end
78
+
79
+ # helper to print a source chain as code, probably not 100% correct.
80
+ #
81
+ # @param chain [Source::Chain]
82
+ def print_chain(chain)
83
+ out = +''
84
+ chain.links.each_with_index do |link, index|
85
+ if index > 0
86
+ if Source::Chain::Constant
87
+ out << '::' unless link.word.start_with?('::')
88
+ else
89
+ out << '.'
90
+ end
91
+ end
92
+ out << link.word
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -130,6 +130,11 @@ module Solargraph
130
130
  end
131
131
  @documentation += "\n\n" unless @documentation.empty?
132
132
  @documentation += "Visibility: #{visibility}"
133
+ example_tags = docstring.tags(:example)
134
+ unless example_tags.empty?
135
+ @documentation += "\n\nExamples:\n\n"
136
+ @documentation += example_tags.map(&:text).join("\n")
137
+ end
133
138
  end
134
139
  @documentation.to_s
135
140
  end
@@ -49,7 +49,7 @@ module Solargraph
49
49
  # @return [Float]
50
50
  def fuzzy_string_match str1, str2
51
51
  return (1.0 + (str2.length.to_f / str1.length.to_f)) if str1.downcase.include?(str2.downcase)
52
- JaroWinkler.distance(str1, str2, ignore_case: true)
52
+ JaroWinkler.similarity(str1, str2, ignore_case: true)
53
53
  end
54
54
  end
55
55
  end
@@ -12,6 +12,7 @@ module Solargraph
12
12
  autoload :Method, 'solargraph/pin/method'
13
13
  autoload :Signature, 'solargraph/pin/signature'
14
14
  autoload :MethodAlias, 'solargraph/pin/method_alias'
15
+ autoload :DelegatedMethod, 'solargraph/pin/delegated_method'
15
16
  autoload :BaseVariable, 'solargraph/pin/base_variable'
16
17
  autoload :InstanceVariable, 'solargraph/pin/instance_variable'
17
18
  autoload :ClassVariable, 'solargraph/pin/class_variable'