solargraph 0.28.3 → 0.29.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solargraph/api_map/store.rb +13 -0
  3. data/lib/solargraph/api_map.rb +43 -10
  4. data/lib/solargraph/bundle.rb +3 -0
  5. data/lib/solargraph/complex_type.rb +5 -4
  6. data/lib/solargraph/core_fills.rb +3 -2
  7. data/lib/solargraph/language_server/host.rb +0 -1
  8. data/lib/solargraph/language_server/message/completion_item/resolve.rb +0 -3
  9. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +4 -3
  10. data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -0
  11. data/lib/solargraph/language_server/transport/socket.rb +7 -1
  12. data/lib/solargraph/library.rb +1 -1
  13. data/lib/solargraph/page.rb +3 -6
  14. data/lib/solargraph/pin/base.rb +8 -3
  15. data/lib/solargraph/pin/base_variable.rb +1 -1
  16. data/lib/solargraph/pin/block_parameter.rb +5 -0
  17. data/lib/solargraph/pin/conversions.rb +1 -1
  18. data/lib/solargraph/pin/documenting.rb +30 -7
  19. data/lib/solargraph/pin/method.rb +59 -1
  20. data/lib/solargraph/pin/method_alias.rb +19 -0
  21. data/lib/solargraph/pin/yard_pin/method.rb +2 -2
  22. data/lib/solargraph/pin.rb +1 -1
  23. data/lib/solargraph/source/chain/call.rb +39 -20
  24. data/lib/solargraph/source/node_chainer.rb +1 -1
  25. data/lib/solargraph/source/node_methods.rb +81 -0
  26. data/lib/solargraph/source.rb +63 -1
  27. data/lib/solargraph/source_map/clip.rb +1 -1
  28. data/lib/solargraph/source_map/mapper.rb +9 -421
  29. data/lib/solargraph/source_map/node_processor/alias_node.rb +21 -0
  30. data/lib/solargraph/source_map/node_processor/args_node.rb +28 -0
  31. data/lib/solargraph/source_map/node_processor/base.rb +68 -0
  32. data/lib/solargraph/source_map/node_processor/begin_node.rb +11 -0
  33. data/lib/solargraph/source_map/node_processor/block_node.rb +14 -0
  34. data/lib/solargraph/source_map/node_processor/casgn_node.rb +14 -0
  35. data/lib/solargraph/source_map/node_processor/cvasgn_node.rb +14 -0
  36. data/lib/solargraph/source_map/node_processor/def_node.rb +54 -0
  37. data/lib/solargraph/source_map/node_processor/defs_node.rb +21 -0
  38. data/lib/solargraph/source_map/node_processor/gvasgn_node.rb +12 -0
  39. data/lib/solargraph/source_map/node_processor/ivasgn_node.rb +18 -0
  40. data/lib/solargraph/source_map/node_processor/lvasgn_node.rb +16 -0
  41. data/lib/solargraph/source_map/node_processor/namespace_node.rb +26 -0
  42. data/lib/solargraph/source_map/node_processor/orasgn_node.rb +12 -0
  43. data/lib/solargraph/source_map/node_processor/sclass_node.rb +11 -0
  44. data/lib/solargraph/source_map/node_processor/send_node.rb +150 -0
  45. data/lib/solargraph/source_map/node_processor/sym_node.rb +11 -0
  46. data/lib/solargraph/source_map/node_processor.rb +75 -0
  47. data/lib/solargraph/source_map/region.rb +58 -0
  48. data/lib/solargraph/source_map.rb +15 -0
  49. data/lib/solargraph/version.rb +1 -1
  50. data/lib/solargraph/workspace.rb +19 -4
  51. data/lib/solargraph/yard_map.rb +17 -10
  52. data/lib/yard-solargraph.rb +0 -2
  53. metadata +60 -55
  54. data/lib/solargraph/pin/helper.rb +0 -41
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5263886b3711a2cc3a6ff8b93c6162002feae2162055999a42d0e571473e47c
4
- data.tar.gz: e936cac7abedde1efab2c97618c15a0290937211016cb7ae0a71d607b6483e23
3
+ metadata.gz: c715438f197d1c368427a61e4b745993ce0cca12b3db96d647f922be67c39e90
4
+ data.tar.gz: 1b82249c56fdb3014c69ec43e12cdac30b9f029cffb8d09896c4e19da7e24a81
5
5
  SHA512:
6
- metadata.gz: c8dd13d206f759022ab35d9721672b2a0c1c517a18f9e58cfeec7143eacdd6e8d20ad726cb5539bb2e010b9ec82593a4b164dd5bed4ddcb48e4adde17e226689
7
- data.tar.gz: b4e88b5cd5f6c5d4495d4562edfd2510651410fe17e6e6b4db33dcee85afbe0ba7110fba5dabd143c76fd04a94e359ad07adae0588ca67ca2a1e445dd421ce67
6
+ metadata.gz: d9b8ed3db0337ef27ff07e1bb28c6bdac6e37bee655333b8465366a0ed3bf01c614dca4dcbaed4ddb1f535abd32639bd53553b3ab044fcb0b4311aa73778d732
7
+ data.tar.gz: 83f8266b77ff13d9750a889f04bbda44b15c39d2a2dbe0dca975f5a5af1835d3d78ee06e806906b65d7fb66dba08a7d09756df0ecbc7e69a9bc13fab29340e47
@@ -109,6 +109,19 @@ module Solargraph
109
109
  result
110
110
  end
111
111
 
112
+ def named_macros
113
+ @named_macros ||= begin
114
+ result = {}
115
+ pins.each do |pin|
116
+ pin.macros.select{|m| m.tag.tag_name == 'macro'}.each do |macro|
117
+ next if macro.tag.name.nil? || macro.tag.name.empty?
118
+ result[macro.tag.name] = macro
119
+ end
120
+ end
121
+ result
122
+ end
123
+ end
124
+
112
125
  private
113
126
 
114
127
  # @param fqns [String]
@@ -21,7 +21,6 @@ module Solargraph
21
21
  attr_reader :unresolved_requires
22
22
 
23
23
  # @param pins [Array<Solargraph::Pin::Base>]
24
- # def initialize workspace = Solargraph::Workspace.new(nil)
25
24
  def initialize pins: []
26
25
  # @todo Extensions don't work yet
27
26
  # require_extensions
@@ -40,9 +39,15 @@ module Solargraph
40
39
  @store = Store.new(pins + YardMap.new.pins)
41
40
  @unresolved_requires = []
42
41
  }
42
+ resolved = resolve_method_aliases
43
+ unless resolved.nil?
44
+ @mutex.synchronize { @store = Store.new(resolved) }
45
+ end
43
46
  self
44
47
  end
45
48
 
49
+ # Map a single source.
50
+ #
46
51
  # @param source [Source]
47
52
  # @return [self]
48
53
  def map source
@@ -50,8 +55,11 @@ module Solargraph
50
55
  self
51
56
  end
52
57
 
53
- # Catalog a workspace. Additional sources that need to be mapped can be
54
- # included in an optional array.
58
+ def named_macro name
59
+ store.named_macros[name]
60
+ end
61
+
62
+ # Catalog a bundle.
55
63
  #
56
64
  # @param bundle [Bundle]
57
65
  # @return [self]
@@ -106,6 +114,10 @@ module Solargraph
106
114
  @store = new_store
107
115
  @unresolved_requires = yard_map.unresolved_requires
108
116
  }
117
+ resolved = resolve_method_aliases
118
+ unless resolved.nil?
119
+ @mutex.synchronize { @store = Store.new(resolved) }
120
+ end
109
121
  self
110
122
  end
111
123
 
@@ -143,7 +155,7 @@ module Solargraph
143
155
  store.pins
144
156
  end
145
157
 
146
- # An array of suggestions based on Ruby keywords (`if`, `end`, etc.).
158
+ # An array of pins based on Ruby keywords (`if`, `end`, etc.).
147
159
  #
148
160
  # @return [Array<Solargraph::Pin::Keyword>]
149
161
  def self.keywords
@@ -305,7 +317,13 @@ module Solargraph
305
317
  result.concat get_methods('Object')
306
318
  else
307
319
  unless type.nil? || type.name == 'void'
308
- namespace = qualify(type.namespace, context)
320
+ # @todo This method does not qualify the complex type's namespace
321
+ # because it can cause namespace conflicts, e.g., `Foo` vs.
322
+ # `Other::Foo`. It still takes a context argument because it
323
+ # uses context to determine whether protected and private methods
324
+ # are visible.
325
+ # namespace = qualify(type.namespace, context)
326
+ namespace = type.namespace
309
327
  visibility = [:public]
310
328
  if namespace == context || super_and_sub?(namespace, context)
311
329
  visibility.push :protected
@@ -330,12 +348,13 @@ module Solargraph
330
348
  # @param scope [Symbol] :instance or :class
331
349
  # @return [Array<Solargraph::Pin::Base>]
332
350
  def get_method_stack fqns, name, scope: :instance
333
- # @todo This cache is still causing problems.
334
- cached = cache.get_method_stack(fqns, name, scope)
335
- return cached unless cached.nil?
351
+ # @todo This cache is still causing problems, but only when using
352
+ # Solargraph on Solargraph itself.
353
+ # cached = cache.get_method_stack(fqns, name, scope)
354
+ # return cached unless cached.nil?
336
355
  result = get_methods(fqns, scope: scope, visibility: [:private, :protected, :public]).select{|p| p.name == name}
337
- cache.set_method_stack(fqns, name, scope, result)
338
- result
356
+ # cache.set_method_stack(fqns, name, scope, result)
357
+ # result
339
358
  end
340
359
 
341
360
  # Get an array of all suggestions that match the specified path.
@@ -621,5 +640,19 @@ module Solargraph
621
640
  end
622
641
  false
623
642
  end
643
+
644
+ # @return [Array<Pin::Base>, nil]
645
+ def resolve_method_aliases
646
+ aliased = false
647
+ result = pins.map do |pin|
648
+ next pin unless pin.is_a?(Pin::MethodAlias)
649
+ origin = get_method_stack(pin.namespace, pin.original, scope: pin.scope).select{|pin| pin.class == Pin::Method}.first
650
+ next pin if origin.nil?
651
+ aliased = true
652
+ Pin::Method.new(pin.location, pin.namespace, pin.name, origin.comments, origin.scope, origin.visibility, origin.parameters)
653
+ end
654
+ return nil unless aliased
655
+ result
656
+ end
624
657
  end
625
658
  end
@@ -1,4 +1,7 @@
1
1
  module Solargraph
2
+ # An aggregation of a workspace and additional sources to be cataloged in an
3
+ # ApiMap.
4
+ #
2
5
  class Bundle
3
6
  # @return [Workspace]
4
7
  attr_reader :workspace
@@ -28,6 +28,7 @@ module Solargraph
28
28
  end
29
29
 
30
30
  def method_missing name, *args, &block
31
+ return if first.nil?
31
32
  return first.send(name, *args, &block) if respond_to_missing?(name)
32
33
  super
33
34
  end
@@ -76,7 +77,7 @@ module Solargraph
76
77
  elsif char == '<'
77
78
  point_stack += 1
78
79
  elsif char == '>'
79
- if subtype_string.end_with?('=') and curly_stack > 0
80
+ if subtype_string.end_with?('=') && curly_stack > 0
80
81
  subtype_string += char
81
82
  elsif base.end_with?('=')
82
83
  raise ComplexTypeError, "Invalid hash thing" unless key_types.nil?
@@ -106,13 +107,13 @@ module Solargraph
106
107
  subtype_string += char if paren_stack == 0
107
108
  raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack < 0
108
109
  next
109
- elsif char == ',' and point_stack == 0 and curly_stack == 0 and paren_stack == 0
110
+ elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0
110
111
  types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)])
111
112
  base = ''
112
113
  subtype_string = ''
113
114
  next
114
115
  end
115
- if point_stack == 0 and curly_stack == 0 and paren_stack == 0
116
+ if point_stack == 0 && curly_stack == 0 && paren_stack == 0
116
117
  base += char
117
118
  else
118
119
  subtype_string += char
@@ -120,7 +121,7 @@ module Solargraph
120
121
  end
121
122
  base.strip!
122
123
  subtype_string.strip!
123
- raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 or curly_stack != 0 or paren_stack != 0
124
+ raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 || curly_stack != 0 || paren_stack != 0
124
125
  types.push ComplexType.new([UniqueType.new(base, subtype_string)])
125
126
  end
126
127
  unless key_types.nil?
@@ -20,13 +20,14 @@ module Solargraph
20
20
  ].freeze
21
21
 
22
22
  METHODS_WITH_YIELDPARAM_SUBTYPES = %w[
23
- Array#each Array#map Array#any? Array#all?
23
+ Array#each Array#map Array#any? Array#all? Array#index
24
24
  Enumerable#each_entry Enumerable#map Enumerable#any? Enumerable#all?
25
25
  Set#each
26
26
  ].freeze
27
27
 
28
28
  CUSTOM_RETURN_TYPES = {
29
- 'String#split' => 'Array<String>'
29
+ 'String#split' => 'Array<String>',
30
+ 'String#lines' => 'Array<String>'
30
31
  }.freeze
31
32
  end
32
33
  end
@@ -322,7 +322,6 @@ module Solargraph
322
322
  end
323
323
 
324
324
  def locate_pin params
325
- pin = nil
326
325
  pin = nil
327
326
  unless params['data']['location'].nil?
328
327
  location = Location.new(
@@ -1,6 +1,3 @@
1
- require 'reverse_markdown'
2
- require 'uri'
3
-
4
1
  module Solargraph
5
2
  module LanguageServer
6
3
  module Message
@@ -14,9 +14,9 @@ module Solargraph
14
14
  fetcher = Gem::SpecFetcher.new
15
15
  tuple = fetcher.search_for_dependency(Gem::Dependency.new('solargraph')).flatten.first
16
16
  if tuple.nil?
17
- msg = "An error occurred checking the Solargraph gem version."
17
+ msg = 'An error occurred checking the Solargraph gem version.'
18
18
  STDERR.puts msg
19
- host.show_message(msg, MessageTypes::ERROR) if params['verbose']
19
+ host.show_message(msg, MessageTypes::ERROR)
20
20
  else
21
21
  available = Gem::Version.new(tuple.version)
22
22
  current = Gem::Version.new(Solargraph::VERSION)
@@ -24,10 +24,11 @@ module Solargraph
24
24
  host.show_message_request "Solagraph gem version #{available} is available.",
25
25
  LanguageServer::MessageTypes::INFO,
26
26
  ['Update now'] do |result|
27
- break unless result == 'Update now'
27
+ next unless result == 'Update now'
28
28
  o, s = Open3.capture2("gem update solargraph")
29
29
  if s == 0
30
30
  host.show_message 'Successfully updated the Solargraph gem.', LanguageServer::MessageTypes::INFO
31
+ host.send_notification '$/solargraph/restart'
31
32
  else
32
33
  host.show_message 'An error occurred while updating the gem.', LanguageServer::MessageTypes::ERROR
33
34
  end
@@ -14,6 +14,13 @@ module Solargraph
14
14
  o, s = Open3.capture2(cmd)
15
15
  if s != 0
16
16
  host.show_message "An error occurred while building gem documentation.", LanguageServer::MessageTypes::ERROR
17
+ set_result({
18
+ status: 'err'
19
+ })
20
+ else
21
+ set_result({
22
+ status: 'ok'
23
+ })
17
24
  end
18
25
  end
19
26
  end
@@ -33,7 +33,13 @@ module Solargraph
33
33
  EventMachine.add_periodic_timer 0.1 do
34
34
  tmp = @host.flush
35
35
  send_data tmp unless tmp.empty?
36
- EventMachine.stop if @host.stopped?
36
+ if @host.stopped?
37
+ if @host.options['transport'] == 'external'
38
+ @host = Solargraph::LanguageServer::Host.new
39
+ else
40
+ EventMachine.stop
41
+ end
42
+ end
37
43
  end
38
44
  end
39
45
  end
@@ -174,7 +174,7 @@ module Solargraph
174
174
  referenced.any?{|r| r == pin}
175
175
  end
176
176
  # HACK for language clients that exclude special characters from the start of variable names
177
- if strip && match = cursor.word.match(/^[^a-z0-9_]+/)
177
+ if strip && match = cursor.word.match(/^[^a-z0-9_]+/i)
178
178
  found.map! do |loc|
179
179
  Solargraph::Location.new(loc.filename, Solargraph::Range.from_to(loc.range.start.line, loc.range.start.column + match[0].length, loc.range.ending.line, loc.range.ending.column))
180
180
  end
@@ -2,7 +2,7 @@ require 'ostruct'
2
2
  require 'tilt'
3
3
  require 'kramdown'
4
4
  require 'htmlentities'
5
- require 'coderay'
5
+ require 'reverse_markdown'
6
6
 
7
7
  module Solargraph
8
8
  class Page
@@ -18,16 +18,13 @@ module Solargraph
18
18
  end
19
19
 
20
20
  def htmlify text
21
- helper = Solargraph::Pin::Helper.new
22
- html = helper.html_markup_rdoc(text)
23
- conv = ReverseMarkdown.convert(html, github_flavored: true)
24
21
  Kramdown::Document.new(
25
- conv,
22
+ text.to_s.lines.map{|l| l.gsub(/^ /, "\t")}.join,
26
23
  input: 'GFM',
27
24
  entity_output: :symbolic,
28
25
  syntax_highlighter_opts: {
29
26
  block: {
30
- line_numbers: false,
27
+ line_numbers: false
31
28
  },
32
29
  default_lang: :ruby
33
30
  },
@@ -1,5 +1,3 @@
1
- require 'reverse_markdown'
2
-
3
1
  module Solargraph
4
2
  module Pin
5
3
  # The base class for map pins.
@@ -126,7 +124,7 @@ module Solargraph
126
124
 
127
125
  # @return [Array<YARD::Tags::MacroDirective>]
128
126
  def macros
129
- @macros ||= []
127
+ @macros ||= collect_macros
130
128
  end
131
129
 
132
130
  # Perform a quick check to see if this pin possibly includes YARD
@@ -222,6 +220,13 @@ module Solargraph
222
220
  t1.name == t2.name &&
223
221
  t1.types == t2.types
224
222
  end
223
+
224
+ # @return [Array<YARD::Tags::Handlers::Directive>]
225
+ def collect_macros
226
+ return [] unless maybe_directives?
227
+ parse = YARD::Docstring.parser.parse(comments)
228
+ parse.directives.select{ |d| d.tag.tag_name == 'macro' }
229
+ end
225
230
  end
226
231
  end
227
232
  end
@@ -65,7 +65,7 @@ module Solargraph
65
65
 
66
66
  def generate_complex_type
67
67
  tag = docstring.tag(:type)
68
- return ComplexType.parse(*tag.types) unless tag.nil?
68
+ return ComplexType.parse(*tag.types) unless tag.nil? || tag.types.nil? || tag.types.empty?
69
69
  return ComplexType.parse(@literal) unless @literal.nil?
70
70
  ComplexType.new
71
71
  end
@@ -56,9 +56,14 @@ module Solargraph
56
56
  params.each do |p|
57
57
  next unless p.name == name
58
58
  found = p
59
+ break
60
+ end
61
+ if found.nil? and !index.nil?
62
+ found = params[index] if params[index] && (params[index].name.nil? || params[index].name.empty?)
59
63
  end
60
64
  @return_complex_type = ComplexType.parse(*found.types) unless found.nil? or found.types.nil?
61
65
  end
66
+ super
62
67
  @return_complex_type
63
68
  end
64
69
 
@@ -70,8 +70,8 @@ module Solargraph
70
70
 
71
71
  def generate_link
72
72
  this_path = path || return_type.tag
73
+ return nil if this_path.nil? || this_path == 'undefined'
73
74
  return this_path if comments.empty?
74
- return nil if this_path.nil? or this_path == 'undefined'
75
75
  "[#{this_path.gsub('_', '\\\\_')}](solargraph:/document?query=#{URI.encode(this_path)})"
76
76
  end
77
77
  end
@@ -1,18 +1,41 @@
1
+ require 'rdoc'
2
+ require 'reverse_markdown'
3
+ require 'kramdown'
4
+
1
5
  module Solargraph
2
6
  module Pin
7
+ # A module to add the Pin::Base#documentation method.
8
+ #
3
9
  module Documenting
4
10
  # @return [String]
5
11
  def documentation
6
- if @documentation.nil?
7
- @documentation = ReverseMarkdown.convert(helper.html_markup_rdoc(docstring), github_flavored: true)
8
- @documentation.strip!
12
+ @documentation ||= begin
13
+ html = Kramdown::Document.new(
14
+ normalize_indentation(docstring.to_s),
15
+ input: 'GFM',
16
+ entity_output: :symbolic,
17
+ syntax_highlighter: nil
18
+ ).to_html
19
+ ReverseMarkdown.convert(html, github_flavored: true)
9
20
  end
10
- @documentation
11
21
  end
12
22
 
13
- def helper
14
- @helper ||= Solargraph::Pin::Helper.new
23
+ private
24
+
25
+ # @param text [String]
26
+ # @return [String]
27
+ def normalize_indentation text
28
+ text.lines.map { |l| remove_odd_spaces(l).gsub(/^ /, "\t") }.join
29
+ end
30
+
31
+ # @param line [String]
32
+ # @return [String]
33
+ def remove_odd_spaces line
34
+ return line unless line.start_with?(' ')
35
+ spaces = line.match(/^ +/)[0].length
36
+ return line unless spaces.odd?
37
+ line[1..-1]
15
38
  end
16
39
  end
17
40
  end
18
- end
41
+ end
@@ -1,6 +1,8 @@
1
1
  module Solargraph
2
2
  module Pin
3
3
  class Method < Base
4
+ include Source::NodeMethods
5
+
4
6
  # @return [Symbol] :instance or :class
5
7
  attr_reader :scope
6
8
 
@@ -10,11 +12,15 @@ module Solargraph
10
12
  # @return [Array<String>]
11
13
  attr_reader :parameters
12
14
 
13
- def initialize location, namespace, name, comments, scope, visibility, args
15
+ # @return [Parser::AST::Node]
16
+ attr_reader :node
17
+
18
+ def initialize location, namespace, name, comments, scope, visibility, args, node = nil
14
19
  super(location, namespace, name, comments)
15
20
  @scope = scope
16
21
  @visibility = visibility
17
22
  @parameters = args
23
+ @node = node
18
24
  end
19
25
 
20
26
  # @return [Array<String>]
@@ -81,6 +87,20 @@ module Solargraph
81
87
  visibility == other.visibility
82
88
  end
83
89
 
90
+ def infer api_map
91
+ decl = super
92
+ return decl unless decl.undefined?
93
+ type = see_reference(api_map)
94
+ return type unless type.nil?
95
+ infer_from_return_nodes(api_map)
96
+ end
97
+
98
+ def try_merge! pin
99
+ return false unless super
100
+ @node = pin.node
101
+ true
102
+ end
103
+
84
104
  private
85
105
 
86
106
  # @return [ComplexType]
@@ -98,6 +118,44 @@ module Solargraph
98
118
  ComplexType::UNDEFINED
99
119
  end
100
120
  end
121
+
122
+ # @param api_map [ApiMap]
123
+ def infer_from_return_nodes api_map
124
+ return ComplexType::UNDEFINED if node.nil? ||
125
+ (node.type == :def && node.children[2].nil?) ||
126
+ (node.type == :defs && node.children[3].nil?)
127
+ result = []
128
+ nodes = node.type == :def ? returns_from(node.children[2]) : returns_from(node.children[3])
129
+ nodes.each do |n|
130
+ next if n.loc.nil?
131
+ clip = api_map.clip_at(location.filename, Solargraph::Position.new(n.loc.expression.last_line, n.loc.expression.last_column))
132
+ type = clip.infer
133
+ result.push type unless type.undefined?
134
+ end
135
+ return ComplexType::UNDEFINED if result.empty?
136
+ ComplexType.parse(*result.map(&:tag))
137
+ end
138
+
139
+ # @param [ApiMap]
140
+ def see_reference api_map
141
+ docstring.ref_tags.each do |ref|
142
+ next unless ref.tag_name == 'return' && ref.owner
143
+ parts = ref.owner.to_s.split(/[\.#]/)
144
+ if parts.first.empty?
145
+ path = "#{namespace}#{ref.owner.to_s}"
146
+ else
147
+ fqns = api_map.qualify(parts.first, namespace)
148
+ return ComplexType::UNDEFINED if fqns.nil?
149
+ path = fqns + ref.owner.to_s[parts.first.length] + parts.last
150
+ end
151
+ pins = api_map.get_path_pins(path)
152
+ pins.each do |pin|
153
+ type = pin.infer(api_map)
154
+ return type unless type.undefined?
155
+ end
156
+ end
157
+ nil
158
+ end
101
159
  end
102
160
  end
103
161
  end
@@ -0,0 +1,19 @@
1
+ module Solargraph
2
+ module Pin
3
+ # Use this class to track method aliases for later remapping. Common
4
+ # examples are aliases for superclass methods or methods from included
5
+ # modules.
6
+ #
7
+ class MethodAlias < Method
8
+ attr_reader :original
9
+
10
+ def initialize location, namespace, name, scope, original
11
+ # @todo Determine how to handle these parameters. Among other things,
12
+ # determine if the visibility is defined by the location of the
13
+ # alias call or the original method.
14
+ super(location, namespace, name, '', scope, :public, [])
15
+ @original = original
16
+ end
17
+ end
18
+ end
19
+ end
@@ -6,7 +6,7 @@ module Solargraph
6
6
 
7
7
  def initialize code_object, location, name = nil, scope = nil, visibility = nil
8
8
  comments = (code_object.docstring ? code_object.docstring.all : nil)
9
- super(location, code_object.namespace.to_s, name || code_object.name.to_s, comments, scope || code_object.scope, visibility || code_object.visibility, get_parameters(code_object))
9
+ super(location, code_object.namespace.to_s, name || code_object.name.to_s, comments, scope || code_object.scope, visibility || code_object.visibility, get_parameters(code_object), nil)
10
10
  end
11
11
 
12
12
  def return_complex_type
@@ -28,7 +28,7 @@ module Solargraph
28
28
  args.push p
29
29
  end
30
30
  args
31
- end
31
+ end
32
32
  end
33
33
  end
34
34
  end
@@ -2,10 +2,10 @@ module Solargraph
2
2
  # The namespace for pins used in maps.
3
3
  #
4
4
  module Pin
5
- autoload :Helper, 'solargraph/pin/helper'
6
5
  autoload :Conversions, 'solargraph/pin/conversions'
7
6
  autoload :Base, 'solargraph/pin/base'
8
7
  autoload :Method, 'solargraph/pin/method'
8
+ autoload :MethodAlias, 'solargraph/pin/method_alias'
9
9
  autoload :Attribute, 'solargraph/pin/attribute'
10
10
  autoload :BaseVariable, 'solargraph/pin/base_variable'
11
11
  autoload :InstanceVariable, 'solargraph/pin/instance_variable'
@@ -42,16 +42,18 @@ module Solargraph
42
42
  def inferred_pins pins, api_map, context, locals
43
43
  result = pins.map do |p|
44
44
  if CoreFills::METHODS_RETURNING_SELF.include?(p.path)
45
- next Solargraph::Pin::Method.new(p.location, p.namespace, p.name, "@return [#{context.tag}]", p.scope, p.visibility, p.parameters)
45
+ next Solargraph::Pin::Method.new(p.location, p.namespace, p.name, "@return [#{context.tag}]", p.scope, p.visibility, p.parameters, p.node)
46
46
  end
47
47
  if CoreFills::METHODS_RETURNING_SUBTYPES.include?(p.path) && !context.subtypes.empty?
48
- next Solargraph::Pin::Method.new(p.location, p.namespace, p.name, "@return [#{context.subtypes.first.tag}]", p.scope, p.visibility, p.parameters)
48
+ next Solargraph::Pin::Method.new(p.location, p.namespace, p.name, "@return [#{context.subtypes.first.tag}]", p.scope, p.visibility, p.parameters, p.node)
49
+ end
50
+ if p.kind == Pin::METHOD && !p.macros.empty?
51
+ result = process_macro(p, api_map, context, locals)
52
+ next result unless result.return_type.undefined?
53
+ elsif !p.directives.empty?
54
+ result = process_directive(p, api_map, context, locals)
55
+ next result unless result.return_type.undefined?
49
56
  end
50
- # @todo Temporarily disabled macros
51
- # if p.kind == Pin::METHOD && !p.macros.empty?
52
- # result = process_macro(p, api_map, context, locals)
53
- # next result unless result.return_type.undefined?
54
- # end
55
57
  next p if p.kind == Pin::METHOD || p.kind == Pin::ATTRIBUTE || p.kind == Pin::NAMESPACE
56
58
  type = p.infer(api_map)
57
59
  next p if p.return_complex_type == type
@@ -67,22 +69,39 @@ module Solargraph
67
69
  # @param pin [Pin::Method]
68
70
  # @param api_map [ApiMap]
69
71
  # @param context [ComplexType]
72
+ # @return [Pin::Base]
70
73
  def process_macro pin, api_map, context, locals
71
74
  pin.macros.each do |macro|
72
- vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
73
- txt = macro.tag.text.clone
74
- i = 1
75
- vals.each do |v|
76
- txt.gsub!(/\$#{i}/, v.context.namespace)
77
- i += 1
78
- end
79
- docstring = YARD::Docstring.parser.parse(txt).to_docstring
80
- tag = docstring.tag(:return)
81
- unless tag.nil? || tag.types.nil?
82
- return Pin::ProxyType.anonymous(ComplexType.parse(*tag.types))
83
- end
75
+ result = inner_process_macro(pin, macro, api_map, context, locals)
76
+ return result unless result.return_type.undefined?
77
+ end
78
+ Pin::ProxyType.new(nil, nil, nil, ComplexType::UNDEFINED)
79
+ end
80
+
81
+ def process_directive pin, api_map, context, locals
82
+ pin.directives.each do |dir|
83
+ macro = api_map.named_macro(dir.tag.name)
84
+ next if macro.nil?
85
+ result = inner_process_macro(pin, macro, api_map, context, locals)
86
+ return result unless result.return_type.undefined?
87
+ end
88
+ Pin::ProxyType.new(nil, nil, nil, ComplexType::UNDEFINED)
89
+ end
90
+
91
+ def inner_process_macro pin, macro, api_map, context, locals
92
+ vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
93
+ txt = macro.tag.text.clone
94
+ i = 1
95
+ vals.each do |v|
96
+ txt.gsub!(/\$#{i}/, v.context.namespace)
97
+ i += 1
98
+ end
99
+ docstring = YARD::Docstring.parser.parse(txt).to_docstring
100
+ tag = docstring.tag(:return)
101
+ unless tag.nil? || tag.types.nil?
102
+ return Pin::ProxyType.anonymous(ComplexType.parse(*tag.types))
84
103
  end
85
- return Pin::ProxyType.new(nil, nil, nil, ComplexType::UNDEFINED)
104
+ Pin::ProxyType.new(nil, nil, nil, ComplexType::UNDEFINED)
86
105
  end
87
106
  end
88
107
  end