ruby-lsp 0.17.7 → 0.17.9

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.
@@ -7,12 +7,16 @@ module RubyLsp
7
7
  class TypeInferrer
8
8
  extend T::Sig
9
9
 
10
- sig { params(index: RubyIndexer::Index).void }
11
- def initialize(index)
10
+ sig { params(experimental_features: T::Boolean).returns(T::Boolean) }
11
+ attr_writer :experimental_features
12
+
13
+ sig { params(index: RubyIndexer::Index, experimental_features: T::Boolean).void }
14
+ def initialize(index, experimental_features = true)
12
15
  @index = index
16
+ @experimental_features = experimental_features
13
17
  end
14
18
 
15
- sig { params(node_context: NodeContext).returns(T.nilable(String)) }
19
+ sig { params(node_context: NodeContext).returns(T.nilable(Type)) }
16
20
  def infer_receiver_type(node_context)
17
21
  node = node_context.node
18
22
 
@@ -28,7 +32,7 @@ module RubyLsp
28
32
 
29
33
  private
30
34
 
31
- sig { params(node: Prism::CallNode, node_context: NodeContext).returns(T.nilable(String)) }
35
+ sig { params(node: Prism::CallNode, node_context: NodeContext).returns(T.nilable(Type)) }
32
36
  def infer_receiver_for_call_node(node, node_context)
33
37
  receiver = node.receiver
34
38
 
@@ -47,23 +51,40 @@ module RubyLsp
47
51
  return unless name
48
52
 
49
53
  *parts, last = name.split("::")
50
- return "#{last}::<Class:#{last}>" if parts.empty?
54
+ return Type.new("#{last}::<Class:#{last}>") if parts.empty?
55
+
56
+ Type.new("#{parts.join("::")}::#{last}::<Class:#{last}>")
57
+ else
58
+ return unless @experimental_features
59
+
60
+ raw_receiver = node.receiver&.slice
51
61
 
52
- "#{parts.join("::")}::#{last}::<Class:#{last}>"
62
+ if raw_receiver
63
+ guessed_name = raw_receiver
64
+ .delete_prefix("@")
65
+ .delete_prefix("@@")
66
+ .split("_")
67
+ .map(&:capitalize)
68
+ .join
69
+
70
+ entries = @index.resolve(guessed_name, node_context.nesting) || @index.first_unqualified_const(guessed_name)
71
+ name = entries&.first&.name
72
+ GuessedType.new(name) if name
73
+ end
53
74
  end
54
75
  end
55
76
 
56
- sig { params(node_context: NodeContext).returns(String) }
77
+ sig { params(node_context: NodeContext).returns(Type) }
57
78
  def self_receiver_handling(node_context)
58
79
  nesting = node_context.nesting
59
80
  # If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
60
81
  # inherits from Object
61
- return "Object" if nesting.empty?
62
- return node_context.fully_qualified_name if node_context.surrounding_method
82
+ return Type.new("Object") if nesting.empty?
83
+ return Type.new(node_context.fully_qualified_name) if node_context.surrounding_method
63
84
 
64
85
  # If we're not inside a method, then we're inside the body of a class or module, which is a singleton
65
86
  # context
66
- "#{nesting.join("::")}::<Class:#{nesting.last}>"
87
+ Type.new("#{nesting.join("::")}::<Class:#{nesting.last}>")
67
88
  end
68
89
 
69
90
  sig do
@@ -80,5 +101,22 @@ module RubyLsp
80
101
  Prism::ConstantPathNode::MissingNodesInConstantPathError
81
102
  nil
82
103
  end
104
+
105
+ # A known type
106
+ class Type
107
+ extend T::Sig
108
+
109
+ sig { returns(String) }
110
+ attr_reader :name
111
+
112
+ sig { params(name: String).void }
113
+ def initialize(name)
114
+ @name = name
115
+ end
116
+ end
117
+
118
+ # A type that was guessed based on the receiver raw name
119
+ class GuessedType < Type
120
+ end
83
121
  end
84
122
  end
@@ -25,6 +25,7 @@ module RubyLsp
25
25
  end,
26
26
  String,
27
27
  )
28
+ GUESSED_TYPES_URL = "https://github.com/Shopify/ruby-lsp/blob/main/DESIGN_AND_ROADMAP.md#guessed-types"
28
29
 
29
30
  # A notification to be sent to the client
30
31
  class Message
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.7
4
+ version: 0.17.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-11 00:00:00.000000000 Z
11
+ date: 2024-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: language_server-protocol
@@ -84,7 +84,6 @@ email:
84
84
  executables:
85
85
  - ruby-lsp
86
86
  - ruby-lsp-check
87
- - ruby-lsp-doctor
88
87
  extensions: []
89
88
  extra_rdoc_files: []
90
89
  files:
@@ -93,7 +92,6 @@ files:
93
92
  - VERSION
94
93
  - exe/ruby-lsp
95
94
  - exe/ruby-lsp-check
96
- - exe/ruby-lsp-doctor
97
95
  - lib/core_ext/uri.rb
98
96
  - lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb
99
97
  - lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb
@@ -206,7 +204,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
206
204
  - !ruby/object:Gem::Version
207
205
  version: '0'
208
206
  requirements: []
209
- rubygems_version: 3.5.14
207
+ rubygems_version: 3.5.16
210
208
  signing_key:
211
209
  specification_version: 4
212
210
  summary: An opinionated language server for Ruby
data/exe/ruby-lsp-doctor DELETED
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- $LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
5
- require "ruby_lsp/internal"
6
-
7
- if File.exist?(".index.yml")
8
- begin
9
- config = YAML.parse_file(".index.yml").to_ruby
10
- rescue => e
11
- abort("Error parsing config: #{e.message}")
12
- end
13
- RubyIndexer.configuration.apply_config(config)
14
- end
15
-
16
- index = RubyIndexer::Index.new
17
-
18
- puts "Globbing for indexable files"
19
-
20
- RubyIndexer.configuration.indexables.each do |indexable|
21
- puts "indexing: #{indexable.full_path}"
22
- index.index_single(indexable)
23
- end