solargraph 0.25.1 → 0.26.0

Sign up to get free protection for your applications and to get access to all the features.
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