solargraph 0.23.6 → 0.24.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,6 +22,7 @@ module Solargraph
22
22
  autoload :Block, 'solargraph/pin/block'
23
23
  autoload :Localized, 'solargraph/pin/localized'
24
24
  autoload :ProxyMethod, 'solargraph/pin/proxy_method'
25
+ autoload :DuckMethod, 'solargraph/pin/duck_method'
25
26
 
26
27
  ATTRIBUTE = 1
27
28
  CLASS_VARIABLE = 2
@@ -30,12 +30,15 @@ module Solargraph
30
30
  @path ||= namespace + (scope == :instance ? '#' : '.') + name
31
31
  end
32
32
 
33
- def return_type
34
- if @return_type.nil? and !docstring.nil?
35
- tag = docstring.tag(:return)
36
- @return_type = tag.types[0] unless tag.nil?
33
+ def return_complex_types
34
+ if @return_complex_types.nil?
35
+ @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
37
40
  end
38
- @return_type
41
+ @return_complex_types
39
42
  end
40
43
 
41
44
  def visibility
@@ -48,6 +51,10 @@ module Solargraph
48
51
  # them as methods without parameters
49
52
  []
50
53
  end
54
+
55
+ def parameter_names
56
+ []
57
+ end
51
58
  end
52
59
  end
53
60
  end
@@ -18,15 +18,16 @@ module Solargraph
18
18
  # @return [YARD::Docstring]
19
19
  attr_reader :docstring
20
20
 
21
- # @return [String]
22
- attr_reader :return_type
23
-
24
21
  # @return [Integer]
25
22
  attr_reader :kind
26
23
 
27
24
  # @return [String]
28
25
  attr_reader :path
29
26
 
27
+ # @param location [Solargraph::Source::Location]
28
+ # @param namespace [String]
29
+ # @param name [String]
30
+ # @param docstring [YARD::Docstring]
30
31
  def initialize location, namespace, name, docstring
31
32
  @location = location
32
33
  @namespace = namespace
@@ -58,6 +59,7 @@ module Solargraph
58
59
  @identifier ||= "#{path}|#{name}"
59
60
  end
60
61
 
62
+ # @return [Boolean]
61
63
  def variable?
62
64
  false
63
65
  end
@@ -66,6 +68,48 @@ module Solargraph
66
68
  def named_context
67
69
  namespace
68
70
  end
71
+
72
+ def == other
73
+ return false unless self.class == other.class
74
+ location == other.location and
75
+ namespace == other.namespace and
76
+ name == other.name and
77
+ ( (docstring.nil? and other.docstring.nil?) or (docstring == other.docstring and docstring.all == other.docstring.all) )
78
+ end
79
+
80
+ # The first return type associated with the pin.
81
+ # Use return_complex_types for an array of all return types.
82
+ #
83
+ # @return [String]
84
+ def return_type
85
+ return nil if return_complex_types.empty?
86
+ return_complex_types.first.tag
87
+ end
88
+
89
+ # The namespace of the first return type.
90
+ # Use return_complex_types for an array of all return types.
91
+ #
92
+ # @return [String]
93
+ def return_namespace
94
+ return nil if return_complex_types.empty?
95
+ @return_namespace ||= return_complex_types.first.namespace
96
+ end
97
+
98
+ # The scope of the first return type.
99
+ # Use return_complex_types for an array of all return types.
100
+ #
101
+ # @return [String]
102
+ def return_scope
103
+ return nil if complex_types.empty?
104
+ @return_scope ||= return_complex_types.first.scope
105
+ end
106
+
107
+ # All of the pin's return types as an array of ComplexTypes.
108
+ #
109
+ # @return [Array<ComplexType>]
110
+ def return_complex_types
111
+ @return_complex_types ||= []
112
+ end
69
113
  end
70
114
  end
71
115
  end
@@ -26,17 +26,29 @@ module Solargraph
26
26
  end
27
27
 
28
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
29
38
  if @return_type.nil?
30
- if !docstring.nil?
31
- tag = docstring.tag(:type)
32
- @return_type = tag.types[0] unless tag.nil?
33
- else
39
+ if return_complex_types.empty?
34
40
  @return_type = @literal
41
+ else
42
+ @return_type = return_complex_types.first.tag
35
43
  end
36
44
  end
37
45
  @return_type
38
46
  end
39
47
 
48
+ def return_complex_types
49
+ @return_complex_types ||= generate_complex_types
50
+ end
51
+
40
52
  def nil_assignment?
41
53
  return_type == 'NilClass'
42
54
  end
@@ -44,6 +56,15 @@ module Solargraph
44
56
  def variable?
45
57
  true
46
58
  end
59
+
60
+ private
61
+
62
+ def generate_complex_types
63
+ return [] if docstring.nil?
64
+ tag = docstring.tag(:type)
65
+ return [] if tag.nil?
66
+ ComplexType.parse *tag.types
67
+ end
47
68
  end
48
69
  end
49
70
  end
@@ -3,8 +3,7 @@ module Solargraph
3
3
  class BlockParameter < Base
4
4
  include Localized
5
5
 
6
- attr_reader :index
7
-
6
+ # @return [Pin::Block]
8
7
  attr_reader :block
9
8
 
10
9
  def initialize location, namespace, name, docstring, block
@@ -13,33 +12,43 @@ module Solargraph
13
12
  @presence = block.location.range
14
13
  end
15
14
 
15
+ # @return [Integer]
16
16
  def kind
17
17
  Pin::BLOCK_PARAMETER
18
18
  end
19
19
 
20
+ # @return [Integer]
20
21
  def completion_item_kind
21
22
  Solargraph::LanguageServer::CompletionItemKinds::VARIABLE
22
23
  end
23
24
 
25
+ # @return [Integer]
24
26
  def symbol_kind
25
27
  Solargraph::LanguageServer::SymbolKinds::VARIABLE
26
28
  end
27
29
 
30
+ # The parameter's zero-based location in the block's signature.
31
+ #
32
+ # @return [Integer]
28
33
  def index
29
34
  block.parameters.index(self)
30
35
  end
31
36
 
32
- def return_type
33
- if @return_type.nil? and !block.docstring.nil?
34
- found = nil
35
- params = block.docstring.tags(:param)
36
- params.each do |p|
37
- next unless p.name == name
38
- found = p
37
+ # @return [Array<Solargraph::ComplexType>]
38
+ def return_complex_types
39
+ if @return_complex_types.nil?
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?
39
49
  end
40
- @return_type = found.types[0] unless found.nil? or found.types.nil?
41
50
  end
42
- @return_type
51
+ @return_complex_types
43
52
  end
44
53
  end
45
54
  end
@@ -0,0 +1,15 @@
1
+ module Solargraph
2
+ module Pin
3
+ # DuckMethod pins are used to add completion items for type tags that
4
+ # use duck typing, e.g., `@param file [#read]`.
5
+ #
6
+ class DuckMethod < Pin::Method
7
+ # @param location [Solargraph::Source::Location]
8
+ # @param name [String]
9
+ #
10
+ def initialize location, name
11
+ super(location, 'Object', name, nil, :instance, :public, [])
12
+ end
13
+ end
14
+ end
15
+ end
@@ -12,6 +12,10 @@ module Solargraph
12
12
  @parameters = args
13
13
  end
14
14
 
15
+ def parameter_names
16
+ @parameter_names ||= parameters.map{|p| p.split(/[ =:]/).first}
17
+ end
18
+
15
19
  def kind
16
20
  Solargraph::Pin::METHOD
17
21
  end
@@ -29,16 +33,8 @@ module Solargraph
29
33
  LanguageServer::SymbolKinds::METHOD
30
34
  end
31
35
 
32
- def return_type
33
- if @return_type.nil? and !docstring.nil?
34
- tag = docstring.tag(:return)
35
- if tag.nil?
36
- ol = docstring.tag(:overload)
37
- tag = ol.tag(:return) unless ol.nil?
38
- end
39
- @return_type = tag.types[0] unless tag.nil? or tag.types.nil?
40
- end
41
- @return_type
36
+ def return_complex_types
37
+ @return_complex_types ||= generate_complex_types
42
38
  end
43
39
 
44
40
  def documentation
@@ -63,23 +59,17 @@ module Solargraph
63
59
  @documentation
64
60
  end
65
61
 
66
- # @todo This method was temporarily migrated directly from Suggestion
67
- # @return [Array<String>]
68
- def params
69
- if @params.nil?
70
- @params = []
71
- return @params if docstring.nil?
72
- param_tags = docstring.tags(:param)
73
- unless param_tags.empty?
74
- param_tags.each do |t|
75
- txt = t.name.to_s
76
- txt += " [#{t.types.join(',')}]" unless t.types.nil? or t.types.empty?
77
- txt += " #{t.text}" unless t.text.nil? or t.text.empty?
78
- @params.push txt
79
- end
80
- end
62
+ private
63
+
64
+ def generate_complex_types
65
+ return [] if docstring.nil?
66
+ tag = docstring.tag(:return)
67
+ if tag.nil?
68
+ ol = docstring.tag(:overload)
69
+ tag = ol.tag(:return) unless ol.nil?
81
70
  end
82
- @params
71
+ return [] if tag.nil?
72
+ ComplexType.parse *tag.types
83
73
  end
84
74
  end
85
75
  end
@@ -1,18 +1,21 @@
1
1
  module Solargraph
2
2
  module Pin
3
3
  class MethodParameter < LocalVariable
4
- def return_type
5
- if @return_type.nil? and !block.docstring.nil?
6
- found = nil
7
- params = block.docstring.tags(:param)
8
- params.each do |p|
9
- next unless p.name == name
10
- found = p
4
+ def return_complex_types
5
+ if @return_complex_types.nil?
6
+ @return_complex_types = []
7
+ unless block.docstring.nil?
8
+ found = nil
9
+ params = block.docstring.tags(:param)
10
+ params.each do |p|
11
+ next unless p.name == name
12
+ found = p
13
+ end
14
+ @return_complex_types.concat ComplexType.parse(*found.types) unless found.nil? or found.types.nil?
11
15
  end
12
- @return_type = found.types[0] unless found.nil? or found.types.nil?
13
16
  end
14
17
  super
15
- @return_type
18
+ @return_complex_types
16
19
  end
17
20
  end
18
21
  end
@@ -51,8 +51,8 @@ module Solargraph
51
51
  @path ||= (namespace.empty? ? '' : "#{namespace}::") + name
52
52
  end
53
53
 
54
- def return_type
55
- @return_type ||= (type == :class ? 'Class' : 'Module') + "<#{path}>"
54
+ def return_complex_types
55
+ @return_complex_types ||= ComplexType.parse( (type == :class ? 'Class' : 'Module') + "<#{path}>" )
56
56
  end
57
57
  end
58
58
  end
@@ -5,16 +5,15 @@ module Solargraph
5
5
  # method while analyzing signatures.
6
6
  #
7
7
  class ProxyMethod < Base
8
- # @return [String]
9
- attr_reader :return_type
10
-
11
- def initialize return_type
12
- @return_type = return_type
8
+ def initialize *return_types
9
+ @return_complex_types = ComplexType.parse(*return_types.reject(&:nil?))
13
10
  end
14
11
 
15
12
  # @return [String]
16
13
  def namespace
17
- @namespace ||= ApiMap::TypeMethods.extract_namespace(@return_type)
14
+ # @namespace ||= ApiMap::TypeMethods.extract_namespace(return_type)
15
+ return nil if @return_complex_types.empty?
16
+ @namespace ||= @return_complex_types.first.namespace
18
17
  end
19
18
 
20
19
  # @return [Integer]
@@ -86,6 +86,10 @@ module Solargraph
86
86
  @parameters ||= get_method_args
87
87
  end
88
88
 
89
+ def parameter_names
90
+ @parameter_names ||= parameters.map{|p| p.split(/[ =:]/).first}
91
+ end
92
+
89
93
  def visibility
90
94
  @visibility ||= (code_object.respond_to?(:visibility) ? code_object.visibility : :public)
91
95
  end
@@ -100,14 +104,14 @@ module Solargraph
100
104
  def get_method_args
101
105
  return [] unless code_object.kind_of?(YARD::CodeObjects::MethodObject)
102
106
  args = []
103
- code_object.parameters.each { |a|
107
+ code_object.parameters.each do |a|
104
108
  p = a[0]
105
109
  unless a[1].nil?
106
110
  p += ' =' unless p.end_with?(':')
107
111
  p += " #{a[1]}"
108
112
  end
109
113
  args.push p
110
- }
114
+ end
111
115
  args
112
116
  end
113
117
  end
@@ -207,7 +207,7 @@ module Solargraph
207
207
  end
208
208
 
209
209
  # @param updater [Source::Updater]
210
- def synchronize updater
210
+ def synchronize updater, reparse = true
211
211
  raise 'Invalid synchronization' unless updater.filename == filename
212
212
  original_code = @code
213
213
  original_fixed = @fixed
@@ -215,6 +215,7 @@ module Solargraph
215
215
  @fixed = updater.write(original_code, true)
216
216
  @version = updater.version
217
217
  return if @code == original_code
218
+ return unless reparse
218
219
  begin
219
220
  parse
220
221
  @fixed = @code
@@ -248,6 +249,8 @@ module Solargraph
248
249
  @all_pins.select{|pin| pin.location == location}.first
249
250
  end
250
251
 
252
+ # @param line [Integer] A zero-based line number
253
+ # @param column [Integer] A zero-based column number
251
254
  # @return [Solargraph::Source::Fragment]
252
255
  def fragment_at line, column
253
256
  Fragment.new(self, line, column)
@@ -321,8 +324,28 @@ module Solargraph
321
324
  end
322
325
 
323
326
  def process_parsed node, comments
324
- @pins, @locals, @requires, @symbols, @path_macros, @domains = Mapper.map filename, code, node, comments
325
- @stime = Time.now
327
+ new_map_data = Mapper.map(filename, code, node, comments)
328
+ synchronize_mapped *new_map_data
329
+ end
330
+
331
+ def synchronize_mapped new_pins, new_locals, new_requires, new_symbols, new_path_macros, new_domains
332
+ resync = (
333
+ @pins.nil? or
334
+ @locals.nil? or
335
+ @pins[1..-1] != new_pins[1..-1] or
336
+ @locals != new_locals
337
+ # @requires != new_requires or
338
+ # @path_macros != new_path_macros or
339
+ # @new_domains != new_domains
340
+ )
341
+ @pins = new_pins
342
+ @locals = new_locals
343
+ @requires = new_requires
344
+ @symbols = new_symbols
345
+ @path_macros = new_path_macros
346
+ @domains = new_domains
347
+ # Check for bare minimum change required to synchronize workspaces, etc.
348
+ @stime = Time.now if resync
326
349
  end
327
350
 
328
351
  class << self