solargraph 0.24.1 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solargraph/api_map.rb +93 -46
  3. data/lib/solargraph/api_map/cache.rb +51 -0
  4. data/lib/solargraph/api_map/probe.rb +23 -12
  5. data/lib/solargraph/api_map/source_to_yard.rb +2 -2
  6. data/lib/solargraph/api_map/store.rb +20 -9
  7. data/lib/solargraph/complex_type.rb +10 -1
  8. data/lib/solargraph/diagnostics/require_not_found.rb +1 -1
  9. data/lib/solargraph/diagnostics/rubocop.rb +35 -27
  10. data/lib/solargraph/diagnostics/type_not_defined.rb +10 -13
  11. data/lib/solargraph/language_server/host.rb +11 -11
  12. data/lib/solargraph/language_server/message.rb +0 -1
  13. data/lib/solargraph/language_server/message/base.rb +24 -4
  14. data/lib/solargraph/language_server/message/text_document/completion.rb +9 -16
  15. data/lib/solargraph/language_server/message/text_document/did_change.rb +0 -2
  16. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -10
  17. data/lib/solargraph/language_server/transport/socket.rb +0 -1
  18. data/lib/solargraph/language_server/transport/stdio.rb +0 -1
  19. data/lib/solargraph/pin.rb +1 -1
  20. data/lib/solargraph/pin/attribute.rb +4 -7
  21. data/lib/solargraph/pin/base.rb +113 -8
  22. data/lib/solargraph/pin/base_variable.rb +17 -25
  23. data/lib/solargraph/pin/block.rb +2 -2
  24. data/lib/solargraph/pin/block_parameter.rb +8 -10
  25. data/lib/solargraph/pin/constant.rb +2 -2
  26. data/lib/solargraph/pin/conversions.rb +8 -0
  27. data/lib/solargraph/pin/documenting.rb +2 -2
  28. data/lib/solargraph/pin/duck_method.rb +0 -1
  29. data/lib/solargraph/pin/local_variable.rb +8 -2
  30. data/lib/solargraph/pin/method.rb +26 -16
  31. data/lib/solargraph/pin/method_parameter.rb +15 -8
  32. data/lib/solargraph/pin/namespace.rb +2 -2
  33. data/lib/solargraph/pin/reference.rb +7 -0
  34. data/lib/solargraph/pin/yard_pin.rb +10 -0
  35. data/lib/solargraph/pin/yard_pin/constant.rb +14 -0
  36. data/lib/solargraph/pin/yard_pin/method.rb +35 -0
  37. data/lib/solargraph/pin/yard_pin/namespace.rb +27 -0
  38. data/lib/solargraph/pin/yard_pin/yard_mixin.rb +18 -0
  39. data/lib/solargraph/source.rb +59 -15
  40. data/lib/solargraph/source/mapper.rb +46 -99
  41. data/lib/solargraph/version.rb +1 -1
  42. data/lib/solargraph/workspace.rb +11 -2
  43. data/lib/solargraph/workspace/config.rb +47 -1
  44. data/lib/solargraph/yard_map.rb +103 -278
  45. data/lib/solargraph/yard_map/cache.rb +13 -38
  46. metadata +7 -3
  47. data/lib/solargraph/pin/yard_object.rb +0 -119
@@ -7,10 +7,9 @@ module Solargraph
7
7
  # @return [Symbol] :class or :instance
8
8
  attr_reader :scope
9
9
 
10
- def initialize location, namespace, name, docstring, access, scope
11
- super(location, namespace, name, docstring)
10
+ def initialize location, namespace, name, comments, access, scope
11
+ super(location, namespace, name, comments)
12
12
  @access = access
13
- @docstring = docstring
14
13
  @scope = scope
15
14
  end
16
15
 
@@ -33,10 +32,8 @@ module Solargraph
33
32
  def return_complex_types
34
33
  if @return_complex_types.nil?
35
34
  @return_complex_types = []
36
- unless docstring.nil?
37
- tag = docstring.tag(:return)
38
- @return_complex_types.concat ComplexType.parse(*tag.types) unless tag.nil?
39
- end
35
+ tag = docstring.tag(:return)
36
+ @return_complex_types.concat ComplexType.parse(*tag.types) unless tag.nil?
40
37
  end
41
38
  @return_complex_types
42
39
  end
@@ -15,8 +15,8 @@ module Solargraph
15
15
  # @return [String]
16
16
  attr_reader :name
17
17
 
18
- # @return [YARD::Docstring]
19
- attr_reader :docstring
18
+ # @return [String]
19
+ attr_reader :comments
20
20
 
21
21
  # @return [Integer]
22
22
  attr_reader :kind
@@ -27,16 +27,17 @@ module Solargraph
27
27
  # @param location [Solargraph::Source::Location]
28
28
  # @param namespace [String]
29
29
  # @param name [String]
30
- # @param docstring [YARD::Docstring]
31
- def initialize location, namespace, name, docstring
30
+ # @param comments [String]
31
+ def initialize location, namespace, name, comments
32
32
  @location = location
33
33
  @namespace = namespace
34
34
  @name = name
35
- @docstring = docstring
35
+ @comments = comments || ''
36
36
  end
37
37
 
38
38
  # @return [String]
39
39
  def filename
40
+ return nil if location.nil?
40
41
  location.filename
41
42
  end
42
43
 
@@ -64,17 +65,39 @@ module Solargraph
64
65
  false
65
66
  end
66
67
 
68
+ def yard_pin?
69
+ false
70
+ end
71
+
67
72
  # @return [String]
68
73
  def named_context
69
74
  namespace
70
75
  end
71
76
 
77
+ # Pin equality is determined using the #nearly? method and also
78
+ # requiring both pins to have the same location.
79
+ #
72
80
  def == other
73
- return false unless self.class == other.class
74
- location == other.location and
81
+ return false unless nearly? other
82
+ location == other.location
83
+ end
84
+
85
+ # True if the specified pin is a near match to this one. A near match
86
+ # indicates that the pins contain mostly the same data. Any differences
87
+ # between them should not have an impact on the API surface.
88
+ #
89
+ # @param other [Solargraph::Pin::Base, Object]
90
+ # @return [Boolean]
91
+ def nearly? other
92
+ # @todo The directives test needs to be a deep check similar to
93
+ # compare_docstring_tags.
94
+ self.class == other.class and
75
95
  namespace == other.namespace and
76
96
  name == other.name and
77
- ( (docstring.nil? and other.docstring.nil?) or (docstring == other.docstring and docstring.all == other.docstring.all) )
97
+ (comments == other.comments or
98
+ ( ((maybe_directives? == false and other.maybe_directives? == false) or compare_directives(directives, other.directives)) and
99
+ compare_docstring_tags(docstring, other.docstring) )
100
+ )
78
101
  end
79
102
 
80
103
  # The first return type associated with the pin.
@@ -110,6 +133,88 @@ module Solargraph
110
133
  def return_complex_types
111
134
  @return_complex_types ||= []
112
135
  end
136
+
137
+ # @return [YARD::Docstring]
138
+ def docstring
139
+ parse_comments unless defined?(@docstring)
140
+ @docstring ||= YARD::Docstring.parser.parse('').to_docstring
141
+ end
142
+
143
+ # @param [Array<YARD::Tags::Directive>]
144
+ def directives
145
+ parse_comments unless defined?(@directives)
146
+ @directives
147
+ end
148
+
149
+ # Perform a quick check to see if this pin possibly includes YARD
150
+ # directives. This method does not require parsing the comments.
151
+ #
152
+ # After the comments have been parsed, this method will return false if
153
+ # no directives were found, regardless of whether it previously appeared
154
+ # possible.
155
+ #
156
+ # @return [Boolean]
157
+ def maybe_directives?
158
+ return !@directives.empty? if defined?(@directives)
159
+ @maybe_directives ||= comments.include?('@!')
160
+ end
161
+
162
+ # Try to merge data from another pin. Merges are only possible if the
163
+ # pins are near matches (see the #nearly? method). The changes should
164
+ # not have any side effects on the API surface.
165
+ #
166
+ # @param pin [Pin::Base] The pin to merge into this one
167
+ # @return [Boolean] True if the pins were merged
168
+ def try_merge! pin
169
+ return false unless nearly?(pin)
170
+ @location = pin.location
171
+ if comments != pin.comments
172
+ @comments = pin.comments
173
+ @docstring = pin.docstring
174
+ @return_complex_types = pin.return_complex_types
175
+ @documentation = nil
176
+ reset_conversions
177
+ end
178
+ true
179
+ end
180
+
181
+ private
182
+
183
+ # @return [void]
184
+ def parse_comments
185
+ if comments.empty?
186
+ @docstring = nil
187
+ @directives = []
188
+ else
189
+ parse = YARD::Docstring.parser.parse(comments)
190
+ @docstring = parse.to_docstring
191
+ @directives = parse.directives
192
+ end
193
+ end
194
+
195
+ def compare_docstring_tags d1, d2
196
+ return false if d1.tags.length != d2.tags.length
197
+ d1.tags.each_index do |i|
198
+ return false unless compare_tags(d1.tags[i], d2.tags[i])
199
+ end
200
+ true
201
+ end
202
+
203
+ def compare_directives d1, d2
204
+ return false if d1.length != d2.length
205
+ d1.each_index do |i|
206
+ return false unless compare_tags(d1[i].tag, d2[i].tag)
207
+ end
208
+ true
209
+ end
210
+
211
+ def compare_tags t1, t2
212
+ return true if t1.class == t2.class and
213
+ t1.tag_name == t2.tag_name and
214
+ t1.text == t2.text and
215
+ t1.name == t2.name and
216
+ t1.types == t2.types
217
+ end
113
218
  end
114
219
  end
115
220
  end
@@ -5,8 +5,8 @@ module Solargraph
5
5
 
6
6
  attr_reader :context
7
7
 
8
- def initialize location, namespace, name, docstring, signature, literal, context
9
- super(location, namespace, name, docstring)
8
+ def initialize location, namespace, name, comments, signature, literal, context
9
+ super(location, namespace, name, comments)
10
10
  @signature = signature
11
11
  @literal = literal
12
12
  @context = context
@@ -25,26 +25,6 @@ module Solargraph
25
25
  Solargraph::LanguageServer::SymbolKinds::VARIABLE
26
26
  end
27
27
 
28
- def return_type
29
- # if @return_type.nil?
30
- # if !docstring.nil?
31
- # tag = docstring.tag(:type)
32
- # @return_type = tag.types[0] unless tag.nil?
33
- # else
34
- # @return_type = @literal
35
- # end
36
- # end
37
- # @return_type
38
- if @return_type.nil?
39
- if return_complex_types.empty?
40
- @return_type = @literal
41
- else
42
- @return_type = return_complex_types.first.tag
43
- end
44
- end
45
- @return_type
46
- end
47
-
48
28
  def return_complex_types
49
29
  @return_complex_types ||= generate_complex_types
50
30
  end
@@ -57,13 +37,25 @@ module Solargraph
57
37
  true
58
38
  end
59
39
 
40
+ def == other
41
+ return false unless super
42
+ signature == other.signature
43
+ end
44
+
45
+ def try_merge! pin
46
+ return false unless super
47
+ @signature = pin.signature
48
+ @return_complex_types = pin.return_complex_types
49
+ true
50
+ end
51
+
60
52
  private
61
53
 
62
54
  def generate_complex_types
63
- return [] if docstring.nil?
64
55
  tag = docstring.tag(:type)
65
- return [] if tag.nil?
66
- ComplexType.parse *tag.types
56
+ return ComplexType.parse(*tag.types) unless tag.nil?
57
+ return ComplexType.parse(@literal) unless @literal.nil?
58
+ []
67
59
  end
68
60
  end
69
61
  end
@@ -4,8 +4,8 @@ module Solargraph
4
4
  attr_reader :receiver
5
5
  attr_reader :parameters
6
6
 
7
- def initialize location, namespace, name, docstring, receiver
8
- super(location, namespace, name, docstring)
7
+ def initialize location, namespace, name, comments, receiver
8
+ super(location, namespace, name, comments)
9
9
  @receiver = receiver
10
10
  end
11
11
 
@@ -6,8 +6,8 @@ module Solargraph
6
6
  # @return [Pin::Block]
7
7
  attr_reader :block
8
8
 
9
- def initialize location, namespace, name, docstring, block
10
- super(location, namespace, name, docstring)
9
+ def initialize location, namespace, name, comments, block
10
+ super(location, namespace, name, comments)
11
11
  @block = block
12
12
  @presence = block.location.range
13
13
  end
@@ -38,15 +38,13 @@ module Solargraph
38
38
  def return_complex_types
39
39
  if @return_complex_types.nil?
40
40
  @return_complex_types = []
41
- unless block.docstring.nil?
42
- found = nil
43
- params = block.docstring.tags(:param)
44
- params.each do |p|
45
- next unless p.name == name
46
- found = p
47
- end
48
- @return_complex_types.concat ComplexType.parse(*found.types) unless found.nil? or found.types.nil?
41
+ found = nil
42
+ params = block.docstring.tags(:param)
43
+ params.each do |p|
44
+ next unless p.name == name
45
+ found = p
49
46
  end
47
+ @return_complex_types.concat ComplexType.parse(*found.types) unless found.nil? or found.types.nil?
50
48
  end
51
49
  @return_complex_types
52
50
  end
@@ -3,8 +3,8 @@ module Solargraph
3
3
  class Constant < BaseVariable
4
4
  attr_reader :visibility
5
5
 
6
- def initialize location, namespace, name, docstring, signature, literal, context, visibility
7
- super(location, namespace, name, docstring, signature, literal, context)
6
+ def initialize location, namespace, name, comments, signature, literal, context, visibility
7
+ super(location, namespace, name, comments, signature, literal, context)
8
8
  @visibility = visibility
9
9
  end
10
10
 
@@ -57,6 +57,14 @@ module Solargraph
57
57
  @link_documentation ||= generate_link
58
58
  end
59
59
 
60
+ def reset_conversions
61
+ @completion_item = nil
62
+ @resolve_completion_item = nil
63
+ @signature_help = nil
64
+ @detail = nil
65
+ @link_documentation = nil
66
+ end
67
+
60
68
  private
61
69
 
62
70
  def generate_link
@@ -3,7 +3,7 @@ module Solargraph
3
3
  module Documenting
4
4
  # @return [String]
5
5
  def documentation
6
- if @documentation.nil? and !docstring.nil?
6
+ if @documentation.nil?
7
7
  @documentation = ReverseMarkdown.convert(helper.html_markup_rdoc(docstring), github_flavored: true)
8
8
  @documentation.strip!
9
9
  end
@@ -16,7 +16,7 @@ module Solargraph
16
16
  #
17
17
  # @return [Boolean]
18
18
  def has_doc?
19
- !docstring.nil? and !docstring.all.empty?
19
+ !docstring.all.empty?
20
20
  end
21
21
 
22
22
  def helper
@@ -6,7 +6,6 @@ module Solargraph
6
6
  class DuckMethod < Pin::Method
7
7
  # @param location [Solargraph::Source::Location]
8
8
  # @param name [String]
9
- #
10
9
  def initialize location, name
11
10
  super(location, 'Object', name, nil, :instance, :public, [])
12
11
  end
@@ -3,8 +3,8 @@ module Solargraph
3
3
  class LocalVariable < BaseVariable
4
4
  include Localized
5
5
 
6
- def initialize location, namespace, name, docstring, assignment, literal, context, block, presence
7
- super(location, namespace, name, docstring, assignment, literal, context)
6
+ def initialize location, namespace, name, comments, assignment, literal, context, block, presence
7
+ super(location, namespace, name, comments, assignment, literal, context)
8
8
  @block = block
9
9
  @presence = presence
10
10
  end
@@ -12,6 +12,12 @@ module Solargraph
12
12
  def kind
13
13
  Pin::LOCAL_VARIABLE
14
14
  end
15
+
16
+ def try_merge! pin
17
+ return false unless super
18
+ @presence = pin.presence
19
+ true
20
+ end
15
21
  end
16
22
  end
17
23
  end
@@ -1,17 +1,23 @@
1
1
  module Solargraph
2
2
  module Pin
3
3
  class Method < Base
4
+ # @return [Symbol] :instance or :class
4
5
  attr_reader :scope
6
+
7
+ # @return [Symbol] :public, :private, or :protected
5
8
  attr_reader :visibility
9
+
10
+ # @return [Array<String>]
6
11
  attr_reader :parameters
7
12
 
8
- def initialize location, namespace, name, docstring, scope, visibility, args
9
- super(location, namespace, name, docstring)
13
+ def initialize location, namespace, name, comments, scope, visibility, args
14
+ super(location, namespace, name, comments)
10
15
  @scope = scope
11
16
  @visibility = visibility
12
17
  @parameters = args
13
18
  end
14
19
 
20
+ # @return [Array<String>]
15
21
  def parameter_names
16
22
  @parameter_names ||= parameters.map{|p| p.split(/[ =:]/).first}
17
23
  end
@@ -40,29 +46,33 @@ module Solargraph
40
46
  def documentation
41
47
  if @documentation.nil?
42
48
  @documentation ||= super || ''
43
- unless docstring.nil?
44
- param_tags = docstring.tags(:param)
45
- unless param_tags.nil? or param_tags.empty?
46
- @documentation += "\n\n"
47
- @documentation += "Params:\n"
48
- lines = []
49
- param_tags.each do |p|
50
- l = "* #{p.name}"
51
- l += " [#{p.types.join(', ')}]" unless p.types.empty?
52
- l += " #{p.text}"
53
- lines.push l
54
- end
55
- @documentation += lines.join("\n")
49
+ param_tags = docstring.tags(:param)
50
+ unless param_tags.nil? or param_tags.empty?
51
+ @documentation += "\n\n" unless @documentation.empty?
52
+ @documentation += "Params:\n"
53
+ lines = []
54
+ param_tags.each do |p|
55
+ l = "* #{p.name}"
56
+ l += " [#{p.types.join(', ')}]" unless p.types.nil? or p.types.empty?
57
+ l += " #{p.text}"
58
+ lines.push l
56
59
  end
60
+ @documentation += lines.join("\n")
57
61
  end
58
62
  end
59
63
  @documentation
60
64
  end
61
65
 
66
+ def nearly? other
67
+ return false unless super
68
+ parameters == other.parameters and
69
+ scope == other.scope and
70
+ visibility == other.visibility
71
+ end
72
+
62
73
  private
63
74
 
64
75
  def generate_complex_types
65
- return [] if docstring.nil?
66
76
  tag = docstring.tag(:return)
67
77
  if tag.nil?
68
78
  ol = docstring.tag(:overload)