solargraph 0.24.1 → 0.25.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 (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)