solargraph 0.25.1 → 0.26.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solargraph.rb +18 -16
  3. data/lib/solargraph/api_map.rb +100 -161
  4. data/lib/solargraph/api_map/source_to_yard.rb +9 -9
  5. data/lib/solargraph/api_map/store.rb +50 -13
  6. data/lib/solargraph/basic_type.rb +33 -0
  7. data/lib/solargraph/basic_type_methods.rb +111 -0
  8. data/lib/solargraph/complex_type.rb +51 -89
  9. data/lib/solargraph/core_fills.rb +12 -8
  10. data/lib/solargraph/diagnostics/type_not_defined.rb +2 -2
  11. data/lib/solargraph/language_server.rb +3 -0
  12. data/lib/solargraph/language_server/completion_item_kinds.rb +2 -0
  13. data/lib/solargraph/language_server/error_codes.rb +2 -0
  14. data/lib/solargraph/language_server/host.rb +53 -6
  15. data/lib/solargraph/language_server/message.rb +13 -0
  16. data/lib/solargraph/language_server/message/text_document/definition.rb +4 -6
  17. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -1
  18. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -1
  19. data/lib/solargraph/language_server/message_types.rb +2 -0
  20. data/lib/solargraph/language_server/request.rb +4 -0
  21. data/lib/solargraph/language_server/symbol_kinds.rb +28 -26
  22. data/lib/solargraph/language_server/transport.rb +3 -0
  23. data/lib/solargraph/language_server/uri_helpers.rb +2 -0
  24. data/lib/solargraph/library.rb +12 -7
  25. data/lib/solargraph/pin.rb +1 -1
  26. data/lib/solargraph/pin/attribute.rb +5 -5
  27. data/lib/solargraph/pin/base.rb +51 -16
  28. data/lib/solargraph/pin/base_variable.rb +25 -7
  29. data/lib/solargraph/pin/block.rb +18 -1
  30. data/lib/solargraph/pin/block_parameter.rb +42 -5
  31. data/lib/solargraph/pin/conversions.rb +4 -2
  32. data/lib/solargraph/pin/method.rb +6 -6
  33. data/lib/solargraph/pin/method_parameter.rb +6 -6
  34. data/lib/solargraph/pin/namespace.rb +7 -2
  35. data/lib/solargraph/pin/proxy_type.rb +39 -0
  36. data/lib/solargraph/pin/symbol.rb +20 -12
  37. data/lib/solargraph/pin/yard_pin/method.rb +2 -2
  38. data/lib/solargraph/source.rb +89 -38
  39. data/lib/solargraph/source/call_chainer.rb +273 -0
  40. data/lib/solargraph/source/chain.rb +104 -0
  41. data/lib/solargraph/source/chain/call.rb +72 -0
  42. data/lib/solargraph/source/chain/class_variable.rb +11 -0
  43. data/lib/solargraph/source/chain/constant.rb +17 -0
  44. data/lib/solargraph/source/chain/definition.rb +16 -0
  45. data/lib/solargraph/source/chain/global_variable.rb +11 -0
  46. data/lib/solargraph/source/chain/head.rb +20 -0
  47. data/lib/solargraph/source/chain/instance_variable.rb +11 -0
  48. data/lib/solargraph/source/chain/link.rb +33 -0
  49. data/lib/solargraph/source/chain/literal.rb +21 -0
  50. data/lib/solargraph/source/chain/variable.rb +11 -0
  51. data/lib/solargraph/source/change.rb +3 -1
  52. data/lib/solargraph/{api_map → source}/completion.rb +3 -1
  53. data/lib/solargraph/source/encoding_fixes.rb +21 -0
  54. data/lib/solargraph/source/fragment.rb +139 -284
  55. data/lib/solargraph/source/mapper.rb +27 -16
  56. data/lib/solargraph/source/node_chainer.rb +94 -0
  57. data/lib/solargraph/source/node_methods.rb +2 -2
  58. data/lib/solargraph/source/position.rb +4 -0
  59. data/lib/solargraph/source/range.rb +10 -2
  60. data/lib/solargraph/version.rb +1 -1
  61. data/lib/solargraph/yard_map.rb +13 -2
  62. metadata +20 -6
  63. data/lib/solargraph/api_map/probe.rb +0 -251
  64. data/lib/solargraph/api_map/type_methods.rb +0 -40
  65. data/lib/solargraph/pin/proxy_method.rb +0 -30
@@ -20,7 +20,7 @@ module Solargraph
20
20
  autoload :Documenting, 'solargraph/pin/documenting'
21
21
  autoload :Block, 'solargraph/pin/block'
22
22
  autoload :Localized, 'solargraph/pin/localized'
23
- autoload :ProxyMethod, 'solargraph/pin/proxy_method'
23
+ autoload :ProxyType, 'solargraph/pin/proxy_type'
24
24
  autoload :DuckMethod, 'solargraph/pin/duck_method'
25
25
  autoload :YardPin, 'solargraph/pin/yard_pin'
26
26
 
@@ -29,13 +29,13 @@ module Solargraph
29
29
  @path ||= namespace + (scope == :instance ? '#' : '.') + name
30
30
  end
31
31
 
32
- def return_complex_types
33
- if @return_complex_types.nil?
34
- @return_complex_types = []
32
+ def return_complex_type
33
+ if @return_complex_type.nil?
34
+ @return_complex_type = ComplexType.new
35
35
  tag = docstring.tag(:return)
36
- @return_complex_types.concat ComplexType.parse(*tag.types) unless tag.nil?
36
+ @return_complex_type = ComplexType.parse(*tag.types) unless tag.nil?
37
37
  end
38
- @return_complex_types
38
+ @return_complex_type
39
39
  end
40
40
 
41
41
  def visibility
@@ -9,15 +9,15 @@ module Solargraph
9
9
  # @return [Solargraph::Source::Location]
10
10
  attr_reader :location
11
11
 
12
+ # The namespace in which this pin is defined.
13
+ # The root namespace is an empty string.
14
+ #
12
15
  # @return [String]
13
16
  attr_reader :namespace
14
17
 
15
18
  # @return [String]
16
19
  attr_reader :name
17
20
 
18
- # @return [String]
19
- attr_reader :comments
20
-
21
21
  # @return [Integer]
22
22
  attr_reader :kind
23
23
 
@@ -32,7 +32,12 @@ module Solargraph
32
32
  @location = location
33
33
  @namespace = namespace
34
34
  @name = name
35
- @comments = comments || ''
35
+ @comments = comments
36
+ end
37
+
38
+ # @return [String]
39
+ def comments
40
+ @comments ||= ''
36
41
  end
37
42
 
38
43
  # @return [String]
@@ -65,6 +70,7 @@ module Solargraph
65
70
  false
66
71
  end
67
72
 
73
+ # @return [Boolean]
68
74
  def yard_pin?
69
75
  false
70
76
  end
@@ -105,33 +111,38 @@ module Solargraph
105
111
  #
106
112
  # @return [String]
107
113
  def return_type
108
- return nil if return_complex_types.empty?
109
- return_complex_types.first.tag
114
+ return nil if return_complex_type.void?
115
+ return_complex_type.first.tag
110
116
  end
111
117
 
112
118
  # The namespace of the first return type.
113
119
  # Use return_complex_types for an array of all return types.
114
120
  #
121
+ # @deprecated Not in active internal use
122
+ #
115
123
  # @return [String]
116
124
  def return_namespace
117
- return nil if return_complex_types.empty?
118
- @return_namespace ||= return_complex_types.first.namespace
125
+ return_type
126
+ return nil if return_complex_type.void?
127
+ @return_namespace ||= return_complex_type.first.namespace
119
128
  end
120
129
 
121
130
  # The scope of the first return type.
122
131
  # Use return_complex_types for an array of all return types.
123
132
  #
133
+ # @deprecated Not in active internal use
134
+ #
124
135
  # @return [String]
125
136
  def return_scope
126
- return nil if return_complex_types.empty?
127
- @return_scope ||= return_complex_types.first.scope
137
+ return nil if return_complex_type.void?
138
+ @return_scope ||= return_complex_type.first.scope
128
139
  end
129
140
 
130
141
  # All of the pin's return types as an array of ComplexTypes.
131
142
  #
132
- # @return [Array<ComplexType>]
133
- def return_complex_types
134
- @return_complex_types ||= []
143
+ # @return [ComplexType]
144
+ def return_complex_type
145
+ @return_complex_type ||= ComplexType.new
135
146
  end
136
147
 
137
148
  # @return [YARD::Docstring]
@@ -140,7 +151,7 @@ module Solargraph
140
151
  @docstring ||= YARD::Docstring.parser.parse('').to_docstring
141
152
  end
142
153
 
143
- # @param [Array<YARD::Tags::Directive>]
154
+ # @return [Array<YARD::Tags::Directive>]
144
155
  def directives
145
156
  parse_comments unless defined?(@directives)
146
157
  @directives
@@ -159,6 +170,17 @@ module Solargraph
159
170
  @maybe_directives ||= comments.include?('@!')
160
171
  end
161
172
 
173
+ # @return [Boolean]
174
+ def deprecated?
175
+ @deprecated ||= docstring.has_tag?('deprecated')
176
+ end
177
+
178
+ # @param api_map [ApiMap]
179
+ # @return [ComplexType]
180
+ def infer api_map
181
+ return_complex_type.qualify(api_map, namespace)
182
+ end
183
+
162
184
  # Try to merge data from another pin. Merges are only possible if the
163
185
  # pins are near matches (see the #nearly? method). The changes should
164
186
  # not have any side effects on the API surface.
@@ -171,8 +193,9 @@ module Solargraph
171
193
  if comments != pin.comments
172
194
  @comments = pin.comments
173
195
  @docstring = pin.docstring
174
- @return_complex_types = pin.return_complex_types
196
+ @return_complex_type = pin.return_complex_type
175
197
  @documentation = nil
198
+ @deprecated = nil
176
199
  reset_conversions
177
200
  end
178
201
  true
@@ -192,6 +215,12 @@ module Solargraph
192
215
  end
193
216
  end
194
217
 
218
+ # True if two docstrings have the same tags, regardless of any other
219
+ # differences.
220
+ #
221
+ # @param d1 [YARD::Docstring]
222
+ # @param d2 [YARD::Docstring]
223
+ # @return [boolean]
195
224
  def compare_docstring_tags d1, d2
196
225
  return false if d1.tags.length != d2.tags.length
197
226
  d1.tags.each_index do |i|
@@ -200,6 +229,9 @@ module Solargraph
200
229
  true
201
230
  end
202
231
 
232
+ # @param d1 [Array<YARD::Tags::Directive>]
233
+ # @param d2 [Array<YARD::Tags::Directive>]
234
+ # @return [Boolean]
203
235
  def compare_directives d1, d2
204
236
  return false if d1.length != d2.length
205
237
  d1.each_index do |i|
@@ -208,8 +240,11 @@ module Solargraph
208
240
  true
209
241
  end
210
242
 
243
+ # @param t1 [YARD::Tags::Tag]
244
+ # @param t2 [YARD::Tags::Tag]
245
+ # @return [Boolean]
211
246
  def compare_tags t1, t2
212
- return true if t1.class == t2.class and
247
+ t1.class == t2.class and
213
248
  t1.tag_name == t2.tag_name and
214
249
  t1.text == t2.text and
215
250
  t1.name == t2.name and
@@ -1,17 +1,23 @@
1
1
  module Solargraph
2
2
  module Pin
3
3
  class BaseVariable < Base
4
+ include Solargraph::Source::NodeMethods
5
+
4
6
  attr_reader :signature
5
7
 
6
8
  attr_reader :context
7
9
 
8
- def initialize location, namespace, name, comments, signature, literal, context
10
+ def initialize location, namespace, name, comments, assignment, literal, context
9
11
  super(location, namespace, name, comments)
10
- @signature = signature
12
+ @assignment = assignment
11
13
  @literal = literal
12
14
  @context = context
13
15
  end
14
16
 
17
+ def signature
18
+ @signature ||= resolve_node_signature(@assignment)
19
+ end
20
+
15
21
  def scope
16
22
  @scope ||= (context.kind == Pin::METHOD and context.scope == :instance ? :instance : :class)
17
23
  end
@@ -25,8 +31,8 @@ module Solargraph
25
31
  Solargraph::LanguageServer::SymbolKinds::VARIABLE
26
32
  end
27
33
 
28
- def return_complex_types
29
- @return_complex_types ||= generate_complex_types
34
+ def return_complex_type
35
+ @return_complex_type ||= generate_complex_type
30
36
  end
31
37
 
32
38
  def nil_assignment?
@@ -37,6 +43,18 @@ module Solargraph
37
43
  true
38
44
  end
39
45
 
46
+ # @param api_map [ApiMap]
47
+ def infer api_map
48
+ result = super
49
+ return result if result.defined? or @assignment.nil?
50
+ # chain = Source::Chain.new(filename, @assignment)
51
+ # @todo Use NodeChainer
52
+ chain = Source::NodeChainer.chain(location.filename, @assignment)
53
+ fragment = api_map.fragment_at(location)
54
+ locals = fragment.locals - [self]
55
+ chain.infer_type_with(api_map, context, locals)
56
+ end
57
+
40
58
  def == other
41
59
  return false unless super
42
60
  signature == other.signature
@@ -45,17 +63,17 @@ module Solargraph
45
63
  def try_merge! pin
46
64
  return false unless super
47
65
  @signature = pin.signature
48
- @return_complex_types = pin.return_complex_types
66
+ @return_complex_type = pin.return_complex_type
49
67
  true
50
68
  end
51
69
 
52
70
  private
53
71
 
54
- def generate_complex_types
72
+ def generate_complex_type
55
73
  tag = docstring.tag(:type)
56
74
  return ComplexType.parse(*tag.types) unless tag.nil?
57
75
  return ComplexType.parse(@literal) unless @literal.nil?
58
- []
76
+ ComplexType.new
59
77
  end
60
78
  end
61
79
  end
@@ -1,21 +1,38 @@
1
1
  module Solargraph
2
2
  module Pin
3
3
  class Block < Base
4
+ # The signature of the method that receives this block.
5
+ #
6
+ # @return [Parser::AST::Node]
4
7
  attr_reader :receiver
8
+
9
+ # @return [Array<String>]
5
10
  attr_reader :parameters
6
11
 
7
- def initialize location, namespace, name, comments, receiver
12
+ attr_reader :scope
13
+
14
+ def initialize location, namespace, name, comments, receiver, scope
8
15
  super(location, namespace, name, comments)
9
16
  @receiver = receiver
17
+ @scope = scope
10
18
  end
11
19
 
12
20
  def kind
13
21
  Pin::BLOCK
14
22
  end
15
23
 
24
+ def return_complex_type
25
+ @return_complex_type ||= Solargraph::ComplexType.parse(namespace)
26
+ end
27
+
16
28
  def parameters
17
29
  @parameters ||= []
18
30
  end
31
+
32
+ def nearly? other
33
+ return false unless super
34
+ receiver == other.receiver and parameters == other.parameters
35
+ end
19
36
  end
20
37
  end
21
38
  end
@@ -34,19 +34,56 @@ module Solargraph
34
34
  block.parameters.index(self)
35
35
  end
36
36
 
37
+ def nearly? other
38
+ return false unless super
39
+ block.nearly?(other.block)
40
+ end
41
+
42
+ def try_merge! other
43
+ return false unless super
44
+ @block = other.block
45
+ @presence = block.location.range
46
+ @return_complex_type = nil
47
+ end
48
+
37
49
  # @return [Array<Solargraph::ComplexType>]
38
- def return_complex_types
39
- if @return_complex_types.nil?
40
- @return_complex_types = []
50
+ def return_complex_type
51
+ if @return_complex_type.nil?
52
+ @return_complex_type = ComplexType.new
41
53
  found = nil
42
54
  params = block.docstring.tags(:param)
43
55
  params.each do |p|
44
56
  next unless p.name == name
45
57
  found = p
46
58
  end
47
- @return_complex_types.concat ComplexType.parse(*found.types) unless found.nil? or found.types.nil?
59
+ @return_complex_type = ComplexType.parse(*found.types) unless found.nil? or found.types.nil?
60
+ end
61
+ @return_complex_type
62
+ end
63
+
64
+ def context
65
+ block
66
+ end
67
+
68
+ def infer api_map
69
+ return return_complex_type unless return_complex_type.undefined?
70
+ chain = Source::NodeChainer.chain(location.filename, block.receiver)
71
+ fragment = api_map.fragment_at(location)
72
+ locals = fragment.locals - [self]
73
+ meths = chain.define_with(api_map, block, fragment.locals)
74
+ meths.each do |meth|
75
+ if (Solargraph::CoreFills::METHODS_WITH_YIELDPARAM_SUBTYPES.include?(meth.path))
76
+ bmeth = chain.define_base_with(api_map, context, locals).first
77
+ return ComplexType::UNDEFINED if bmeth.nil? or bmeth.return_complex_type.undefined? or bmeth.return_complex_type.subtypes.empty?
78
+ return bmeth.return_complex_type.subtypes.first.qualify(api_map)
79
+ else
80
+ yps = meth.docstring.tags(:yieldparam)
81
+ unless yps[index].nil? or yps[index].types.nil? or yps[index].types.empty?
82
+ return ComplexType.parse(yps[index].types[0]).first
83
+ end
84
+ end
48
85
  end
49
- @return_complex_types
86
+ ComplexType::UNDEFINED
50
87
  end
51
88
  end
52
89
  end
@@ -11,7 +11,8 @@ module Solargraph
11
11
  data: {
12
12
  path: path,
13
13
  return_type: return_type,
14
- location: location
14
+ location: location,
15
+ deprecated: deprecated?
15
16
  }
16
17
  }
17
18
  end
@@ -43,7 +44,7 @@ module Solargraph
43
44
  if @detail.nil?
44
45
  @detail = ''
45
46
  @detail += "(#{parameters.join(', ')}) " unless kind != Pin::METHOD or parameters.empty?
46
- @detail += "=> #{return_type}" unless return_type.nil?
47
+ @detail += "=> #{return_complex_type.tag}" unless return_complex_type.undefined?
47
48
  @detail.strip!
48
49
  end
49
50
  return nil if @detail.empty?
@@ -68,6 +69,7 @@ module Solargraph
68
69
  private
69
70
 
70
71
  def generate_link
72
+ return nil if return_complex_type.undefined?
71
73
  this_path = path || return_type
72
74
  return nil if this_path.nil?
73
75
  "[#{this_path.gsub('_', '\\\\_')}](solargraph:/document?query=#{URI.encode(this_path)})"
@@ -39,8 +39,8 @@ module Solargraph
39
39
  LanguageServer::SymbolKinds::METHOD
40
40
  end
41
41
 
42
- def return_complex_types
43
- @return_complex_types ||= generate_complex_types
42
+ def return_complex_type
43
+ @return_complex_type ||= generate_complex_type
44
44
  end
45
45
 
46
46
  def documentation
@@ -72,19 +72,19 @@ module Solargraph
72
72
 
73
73
  private
74
74
 
75
- # @return [Array<ComplexType>]
76
- def generate_complex_types
75
+ # @return [ComplexType]
76
+ def generate_complex_type
77
77
  tag = docstring.tag(:return)
78
78
  if tag.nil?
79
79
  ol = docstring.tag(:overload)
80
80
  tag = ol.tag(:return) unless ol.nil?
81
81
  end
82
- return [] if tag.nil?
82
+ return ComplexType::UNDEFINED if tag.nil? or tag.types.nil? or tag.types.empty?
83
83
  begin
84
84
  ComplexType.parse *tag.types
85
85
  rescue Solargraph::ComplexTypeError => e
86
86
  STDERR.puts e.message
87
- []
87
+ ComplexType::UNDEFINED
88
88
  end
89
89
  end
90
90
  end
@@ -1,26 +1,26 @@
1
1
  module Solargraph
2
2
  module Pin
3
3
  class MethodParameter < LocalVariable
4
- def return_complex_types
5
- if @return_complex_types.nil?
6
- @return_complex_types = []
4
+ def return_complex_type
5
+ if @return_complex_type.nil?
6
+ @return_complex_type = ComplexType.new
7
7
  found = nil
8
8
  params = block.docstring.tags(:param)
9
9
  params.each do |p|
10
10
  next unless p.name == name
11
11
  found = p
12
12
  end
13
- @return_complex_types.concat ComplexType.parse(*found.types) unless found.nil? or found.types.nil?
13
+ @return_complex_type = ComplexType.parse(*found.types) unless found.nil? or found.types.nil?
14
14
  end
15
15
  super
16
- @return_complex_types
16
+ @return_complex_type
17
17
  end
18
18
 
19
19
  def try_merge! pin
20
20
  return false unless super
21
21
  # @todo This is a little expensive, but it's necessary because
22
22
  # parameter data depends on the method's docstring.
23
- @return_complex_types = pin.return_complex_types
23
+ @return_complex_type = pin.return_complex_type
24
24
  reset_conversions
25
25
  true
26
26
  end