solargraph 0.47.2 → 0.53.3

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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/plugins.yml +40 -0
  4. data/.github/workflows/rspec.yml +4 -8
  5. data/.github/workflows/typecheck.yml +34 -0
  6. data/.yardopts +2 -2
  7. data/CHANGELOG.md +137 -3
  8. data/LICENSE +1 -1
  9. data/README.md +19 -16
  10. data/SPONSORS.md +2 -9
  11. data/lib/solargraph/api_map/cache.rb +60 -20
  12. data/lib/solargraph/api_map/source_to_yard.rb +17 -10
  13. data/lib/solargraph/api_map/store.rb +60 -12
  14. data/lib/solargraph/api_map.rb +171 -99
  15. data/lib/solargraph/bench.rb +3 -2
  16. data/lib/solargraph/cache.rb +77 -0
  17. data/lib/solargraph/complex_type/type_methods.rb +61 -12
  18. data/lib/solargraph/complex_type/unique_type.rb +193 -16
  19. data/lib/solargraph/complex_type.rb +113 -10
  20. data/lib/solargraph/convention/rakefile.rb +17 -0
  21. data/lib/solargraph/convention.rb +2 -3
  22. data/lib/solargraph/converters/dd.rb +5 -0
  23. data/lib/solargraph/converters/dl.rb +3 -0
  24. data/lib/solargraph/converters/dt.rb +3 -0
  25. data/lib/solargraph/diagnostics/rubocop.rb +23 -8
  26. data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
  27. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  28. data/lib/solargraph/diagnostics.rb +2 -2
  29. data/lib/solargraph/doc_map.rb +171 -0
  30. data/lib/solargraph/gem_pins.rb +64 -0
  31. data/lib/solargraph/language_server/host/cataloger.rb +2 -1
  32. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  33. data/lib/solargraph/language_server/host/dispatch.rb +15 -5
  34. data/lib/solargraph/language_server/host/message_worker.rb +4 -0
  35. data/lib/solargraph/language_server/host/sources.rb +7 -4
  36. data/lib/solargraph/language_server/host.rb +50 -26
  37. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  38. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  39. data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
  40. data/lib/solargraph/language_server/message/initialize.rb +13 -0
  41. data/lib/solargraph/language_server/message/initialized.rb +1 -0
  42. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +4 -1
  43. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -4
  44. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  45. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
  46. data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
  47. data/lib/solargraph/language_server/message/text_document.rb +1 -1
  48. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  49. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
  50. data/lib/solargraph/language_server/message.rb +1 -0
  51. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  52. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  53. data/lib/solargraph/library.rb +124 -37
  54. data/lib/solargraph/location.rb +1 -0
  55. data/lib/solargraph/page.rb +6 -0
  56. data/lib/solargraph/parser/comment_ripper.rb +4 -0
  57. data/lib/solargraph/parser/node_methods.rb +47 -7
  58. data/lib/solargraph/parser/node_processor/base.rb +9 -0
  59. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -5
  60. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  61. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +57 -41
  62. data/lib/solargraph/parser/parser_gem/node_methods.rb +499 -0
  63. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  64. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +53 -0
  65. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  66. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  67. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +14 -4
  68. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  69. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/def_node.rb +7 -20
  70. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  71. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  72. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  73. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
  74. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  75. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  76. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  77. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +42 -0
  78. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +2 -2
  79. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +1 -1
  80. data/lib/solargraph/parser/parser_gem/node_processors.rb +54 -0
  81. data/lib/solargraph/parser/parser_gem.rb +12 -0
  82. data/lib/solargraph/parser/region.rb +1 -1
  83. data/lib/solargraph/parser/snippet.rb +2 -0
  84. data/lib/solargraph/parser.rb +9 -10
  85. data/lib/solargraph/pin/base.rb +69 -11
  86. data/lib/solargraph/pin/base_variable.rb +8 -4
  87. data/lib/solargraph/pin/block.rb +21 -28
  88. data/lib/solargraph/pin/closure.rb +17 -2
  89. data/lib/solargraph/pin/common.rb +7 -3
  90. data/lib/solargraph/pin/conversions.rb +34 -8
  91. data/lib/solargraph/pin/delegated_method.rb +97 -0
  92. data/lib/solargraph/pin/documenting.rb +25 -34
  93. data/lib/solargraph/pin/instance_variable.rb +4 -0
  94. data/lib/solargraph/pin/local_variable.rb +13 -1
  95. data/lib/solargraph/pin/method.rb +270 -16
  96. data/lib/solargraph/pin/namespace.rb +17 -1
  97. data/lib/solargraph/pin/parameter.rb +52 -17
  98. data/lib/solargraph/pin/reference/override.rb +2 -2
  99. data/lib/solargraph/pin/reference.rb +8 -0
  100. data/lib/solargraph/pin/search.rb +4 -4
  101. data/lib/solargraph/pin/signature.rb +143 -0
  102. data/lib/solargraph/pin.rb +2 -1
  103. data/lib/solargraph/range.rb +4 -6
  104. data/lib/solargraph/rbs_map/conversions.rb +601 -0
  105. data/lib/solargraph/rbs_map/core_fills.rb +47 -0
  106. data/lib/solargraph/rbs_map/core_map.rb +28 -0
  107. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -0
  108. data/lib/solargraph/rbs_map.rb +84 -0
  109. data/lib/solargraph/shell.rb +69 -48
  110. data/lib/solargraph/source/chain/array.rb +32 -0
  111. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  112. data/lib/solargraph/source/chain/call.rb +125 -61
  113. data/lib/solargraph/source/chain/constant.rb +15 -1
  114. data/lib/solargraph/source/chain/if.rb +23 -0
  115. data/lib/solargraph/source/chain/link.rb +8 -2
  116. data/lib/solargraph/source/chain/or.rb +1 -1
  117. data/lib/solargraph/source/chain/z_super.rb +3 -3
  118. data/lib/solargraph/source/chain.rb +44 -14
  119. data/lib/solargraph/source/change.rb +3 -0
  120. data/lib/solargraph/source/cursor.rb +2 -0
  121. data/lib/solargraph/source/source_chainer.rb +8 -5
  122. data/lib/solargraph/source.rb +18 -19
  123. data/lib/solargraph/source_map/clip.rb +30 -23
  124. data/lib/solargraph/source_map/mapper.rb +20 -5
  125. data/lib/solargraph/source_map.rb +28 -13
  126. data/lib/solargraph/type_checker/checks.rb +10 -2
  127. data/lib/solargraph/type_checker.rb +201 -98
  128. data/lib/solargraph/version.rb +1 -1
  129. data/lib/solargraph/views/environment.erb +2 -2
  130. data/lib/solargraph/workspace/config.rb +14 -11
  131. data/lib/solargraph/workspace.rb +28 -17
  132. data/lib/solargraph/yard_map/cache.rb +6 -0
  133. data/lib/solargraph/yard_map/helpers.rb +1 -1
  134. data/lib/solargraph/yard_map/mapper/to_method.rb +18 -5
  135. data/lib/solargraph/yard_map/mapper.rb +1 -1
  136. data/lib/solargraph/yard_map/to_method.rb +11 -4
  137. data/lib/solargraph/yard_map.rb +1 -443
  138. data/lib/solargraph/yard_tags.rb +20 -0
  139. data/lib/solargraph/yardoc.rb +52 -0
  140. data/lib/solargraph.rb +8 -6
  141. data/solargraph.gemspec +19 -8
  142. metadata +162 -98
  143. data/.travis.yml +0 -19
  144. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  145. data/lib/solargraph/compat.rb +0 -37
  146. data/lib/solargraph/convention/rspec.rb +0 -30
  147. data/lib/solargraph/documentor.rb +0 -76
  148. data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
  149. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  150. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
  151. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  152. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +0 -63
  153. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +0 -21
  154. data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
  155. data/lib/solargraph/parser/legacy.rb +0 -12
  156. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -144
  157. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  158. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
  159. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  160. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  161. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -22
  162. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
  163. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -57
  164. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  165. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  166. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  167. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  168. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  169. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  170. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  171. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  172. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
  173. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -21
  174. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  175. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -277
  176. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +0 -18
  177. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
  178. data/lib/solargraph/parser/rubyvm.rb +0 -40
  179. data/lib/solargraph/yard_map/core_docs.rb +0 -170
  180. data/lib/solargraph/yard_map/core_fills.rb +0 -208
  181. data/lib/solargraph/yard_map/core_gen.rb +0 -76
  182. data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
  183. data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
  184. data/lib/yard-solargraph.rb +0 -33
  185. data/yardoc/2.2.2.tar.gz +0 -0
@@ -19,8 +19,14 @@ module Solargraph
19
19
  end
20
20
  parts = base.split('::')
21
21
  gates.each do |gate|
22
+ # @todo 'Wrong argument type for
23
+ # Solargraph::Source::Chain::Constant#deep_constant_type:
24
+ # gate expected String, received generic<Elem>' is because
25
+ # we lose 'rooted' information in the 'Chain::Array' class
26
+ # internally, leaving ::Array#each shadowed when it
27
+ # shouldn't be.
22
28
  type = deep_constant_type(gate, api_map)
23
- # Use deep inference to resolve root
29
+ # Use deep inference to resolve root
24
30
  parts[0..-2].each do |sym|
25
31
  pins = api_map.get_constants('', type.namespace).select{ |pin| pin.name == sym }
26
32
  type = first_pin_type(pins, api_map)
@@ -35,6 +41,8 @@ module Solargraph
35
41
 
36
42
  private
37
43
 
44
+ # @param pin [Pin::Base]
45
+ # @return [::Array<String>]
38
46
  def crawl_gates pin
39
47
  clos = pin
40
48
  until clos.nil?
@@ -48,6 +56,9 @@ module Solargraph
48
56
  ['']
49
57
  end
50
58
 
59
+ # @param pins [::Array<Pin::Base>]
60
+ # @param api_map [ApiMap]
61
+ # @return [ComplexType]
51
62
  def first_pin_type(pins, api_map)
52
63
  type = ComplexType::UNDEFINED
53
64
  pins.each do |pin|
@@ -59,6 +70,9 @@ module Solargraph
59
70
  type
60
71
  end
61
72
 
73
+ # @param gate [String]
74
+ # @param api_map [ApiMap]
75
+ # @return [ComplexType]
62
76
  def deep_constant_type(gate, api_map)
63
77
  type = ComplexType::ROOT
64
78
  return type if gate == ''
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class Source
5
+ class Chain
6
+ class If < Link
7
+ def word
8
+ '<if>'
9
+ end
10
+
11
+ # @param links [::Array<Link>]
12
+ def initialize links
13
+ @links = links
14
+ end
15
+
16
+ def resolve api_map, name_pin, locals
17
+ types = @links.map { |link| link.infer(api_map, name_pin, locals) }
18
+ [Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.try_parse(types.map(&:tag).uniq.join(', ')))]
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -7,8 +7,10 @@ module Solargraph
7
7
  # @return [String]
8
8
  attr_reader :word
9
9
 
10
+ # @return [Pin::Base]
10
11
  attr_accessor :last_context
11
12
 
13
+ # @param word [String]
12
14
  def initialize word = '<undefined>'
13
15
  @word = word
14
16
  end
@@ -23,12 +25,16 @@ module Solargraph
23
25
 
24
26
  # @param api_map [ApiMap]
25
27
  # @param name_pin [Pin::Base]
26
- # @param locals [Array<Pin::Base>]
27
- # @return [Array<Pin::Base>]
28
+ # @param locals [::Enumerable<Pin::Base>]
29
+ # @return [::Array<Pin::Base>]
28
30
  def resolve api_map, name_pin, locals
29
31
  []
30
32
  end
31
33
 
34
+ def inspect
35
+ "#{self.class} #{word}"
36
+ end
37
+
32
38
  def head?
33
39
  @head ||= false
34
40
  end
@@ -8,7 +8,7 @@ module Solargraph
8
8
  '<or>'
9
9
  end
10
10
 
11
- # @param type [String]
11
+ # @param links [::Array<Link>]
12
12
  def initialize links
13
13
  @links = links
14
14
  end
@@ -7,11 +7,11 @@ module Solargraph
7
7
  # @return [String]
8
8
  attr_reader :word
9
9
 
10
- # @return [Array<Chain>]
10
+ # @return [::Array<Chain>]
11
11
  attr_reader :arguments
12
12
 
13
13
  # @param word [String]
14
- # @param arguments [Array<Chain>]
14
+ # @param arguments [::Array<Chain>]
15
15
  # @param with_block [Boolean] True if the chain is inside a block
16
16
  # @param head [Boolean] True if the call is the start of its chain
17
17
  def initialize word, with_block = false
@@ -20,7 +20,7 @@ module Solargraph
20
20
 
21
21
  # @param api_map [ApiMap]
22
22
  # @param name_pin [Pin::Base]
23
- # @param locals [Array<Pin::Base>]
23
+ # @param locals [::Array<Pin::Base>]
24
24
  def resolve api_map, name_pin, locals
25
25
  return super_pins(api_map, name_pin)
26
26
  end
@@ -19,10 +19,13 @@ module Solargraph
19
19
  autoload :GlobalVariable, 'solargraph/source/chain/global_variable'
20
20
  autoload :Literal, 'solargraph/source/chain/literal'
21
21
  autoload :Head, 'solargraph/source/chain/head'
22
+ autoload :If, 'solargraph/source/chain/if'
22
23
  autoload :Or, 'solargraph/source/chain/or'
23
24
  autoload :BlockVariable, 'solargraph/source/chain/block_variable'
25
+ autoload :BlockSymbol, 'solargraph/source/chain/block_symbol'
24
26
  autoload :ZSuper, 'solargraph/source/chain/z_super'
25
27
  autoload :Hash, 'solargraph/source/chain/hash'
28
+ autoload :Array, 'solargraph/source/chain/array'
26
29
 
27
30
  @@inference_stack = []
28
31
  @@inference_depth = 0
@@ -30,12 +33,14 @@ module Solargraph
30
33
  UNDEFINED_CALL = Chain::Call.new('<undefined>')
31
34
  UNDEFINED_CONSTANT = Chain::Constant.new('<undefined>')
32
35
 
33
- # @return [Array<Source::Chain::Link>]
36
+ # @return [::Array<Source::Chain::Link>]
34
37
  attr_reader :links
35
38
 
36
39
  attr_reader :node
37
40
 
38
- # @param links [Array<Chain::Link>]
41
+ # @param node [Parser::AST::Node, nil]
42
+ # @param links [::Array<Chain::Link>]
43
+ # @param splat [Boolean]
39
44
  def initialize links, node = nil, splat = false
40
45
  @links = links.clone
41
46
  @links.push UNDEFINED_CALL if @links.empty?
@@ -56,28 +61,33 @@ module Solargraph
56
61
 
57
62
  # @param api_map [ApiMap]
58
63
  # @param name_pin [Pin::Base]
59
- # @param locals [Array<Pin::Base>]
60
- # @return [Array<Pin::Base>]
64
+ # @param locals [::Enumerable<Pin::LocalVariable>]
65
+ #
66
+ # @return [::Array<Pin::Base>]
61
67
  def define api_map, name_pin, locals
62
68
  return [] if undefined?
63
69
  working_pin = name_pin
64
70
  links[0..-2].each do |link|
65
71
  pins = link.resolve(api_map, working_pin, locals)
66
- type = infer_first_defined(pins, working_pin, api_map)
72
+ type = infer_first_defined(pins, working_pin, api_map, locals)
67
73
  return [] if type.undefined?
68
74
  working_pin = Pin::ProxyType.anonymous(type)
69
75
  end
70
- links.last.last_context = working_pin
76
+ links.last.last_context = name_pin
71
77
  links.last.resolve(api_map, working_pin, locals)
72
78
  end
73
79
 
74
80
  # @param api_map [ApiMap]
75
81
  # @param name_pin [Pin::Base]
76
- # @param locals [Array<Pin::Base>]
82
+ # @param locals [::Enumerable<Pin::LocalVariable>]
77
83
  # @return [ComplexType]
78
84
  def infer api_map, name_pin, locals
85
+ from_here = base.infer(api_map, name_pin, locals) unless links.length == 1
86
+ if from_here
87
+ name_pin = name_pin.proxy(from_here)
88
+ end
79
89
  pins = define(api_map, name_pin, locals)
80
- type = infer_first_defined(pins, links.last.last_context, api_map)
90
+ type = infer_first_defined(pins, links.last.last_context, api_map, locals)
81
91
  maybe_nil(type)
82
92
  end
83
93
 
@@ -109,29 +119,46 @@ module Solargraph
109
119
 
110
120
  private
111
121
 
112
- # @param pins [Array<Pin::Base>]
122
+ # @param pins [::Array<Pin::Base>]
123
+ # @param context [Pin::Base]
113
124
  # @param api_map [ApiMap]
125
+ # @param locals [::Enumerable<Pin::LocalVariable>]
114
126
  # @return [ComplexType]
115
- def infer_first_defined pins, context, api_map
127
+ def infer_first_defined pins, context, api_map, locals
116
128
  possibles = []
129
+ # @todo this param tag shouldn't be needed to probe the type
130
+ # @todo ...but given it is needed, typecheck should complain that it is needed
131
+ # @param pin [Pin::Base]
117
132
  pins.each do |pin|
118
133
  # Avoid infinite recursion
119
134
  next if @@inference_stack.include?(pin.identity)
135
+
120
136
  @@inference_stack.push pin.identity
121
137
  type = pin.typify(api_map)
122
138
  @@inference_stack.pop
123
139
  if type.defined?
124
- possibles.push type
125
- break if pin.is_a?(Pin::Method)
140
+ if type.generic?
141
+ # @todo even at strong, no typechecking complaint
142
+ # happens when a [Pin::Base,nil] is passed into a method
143
+ # that accepts only [Pin::Namespace] as an argument
144
+ type = type.resolve_generics(pin.closure, context.return_type)
145
+ end
146
+ if type.defined?
147
+ possibles.push type
148
+ break if pin.is_a?(Pin::Method)
149
+ end
126
150
  end
127
151
  end
128
152
  if possibles.empty?
129
153
  # Limit method inference recursion
130
154
  return ComplexType::UNDEFINED if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
155
+
131
156
  @@inference_depth += 1
157
+ # @param pin [Pin::Base]
132
158
  pins.each do |pin|
133
159
  # Avoid infinite recursion
134
160
  next if @@inference_stack.include?(pin.identity)
161
+
135
162
  @@inference_stack.push pin.identity
136
163
  type = pin.probe(api_map)
137
164
  @@inference_stack.pop
@@ -143,17 +170,20 @@ module Solargraph
143
170
  @@inference_depth -= 1
144
171
  end
145
172
  return ComplexType::UNDEFINED if possibles.empty?
173
+
146
174
  type = if possibles.length > 1
147
175
  sorted = possibles.map { |t| t.rooted? ? "::#{t}" : t.to_s }.sort { |a, _| a == 'nil' ? 1 : 0 }
148
176
  ComplexType.parse(*sorted)
149
177
  else
150
- possibles.first
178
+ ComplexType.parse(possibles.map(&:to_s).join(', '))
151
179
  end
152
180
  return type if context.nil? || context.return_type.undefined?
153
- type.self_to(context.return_type.namespace)
181
+
182
+ type.self_to(context.return_type.tag)
154
183
  end
155
184
 
156
185
  # @param type [ComplexType]
186
+ # @return [ComplexType]
157
187
  def maybe_nil type
158
188
  return type if type.undefined? || type.void? || type.nullable?
159
189
  return type unless nullable?
@@ -69,6 +69,9 @@ module Solargraph
69
69
 
70
70
  private
71
71
 
72
+ # @param text [String]
73
+ # @param insert [String]
74
+ # @return [String]
72
75
  def commit text, insert
73
76
  start_offset = Position.to_offset(text, range.start)
74
77
  end_offset = Position.to_offset(text, range.ending)
@@ -115,6 +115,7 @@ module Solargraph
115
115
  end
116
116
  alias receiver recipient
117
117
 
118
+ # @return [AST::Node]
118
119
  def node
119
120
  @node ||= source.node_at(position.line, position.column)
120
121
  end
@@ -135,6 +136,7 @@ module Solargraph
135
136
  end
136
137
  end
137
138
 
139
+ # @return [Parser::AST::Node, nil]
138
140
  def recipient_node
139
141
  @recipient_node ||= Solargraph::Parser::NodeMethods.find_recipient_node(self)
140
142
  end
@@ -14,10 +14,10 @@ module Solargraph
14
14
 
15
15
  class << self
16
16
  # @param source [Source]
17
- # @param position [Position]
17
+ # @param position [Position, Array(Integer, Integer)]
18
18
  # @return [Source::Chain]
19
19
  def chain source, position
20
- new(source, position).chain
20
+ new(source, Solargraph::Position.normalize(position)).chain
21
21
  end
22
22
  end
23
23
 
@@ -41,12 +41,12 @@ module Solargraph
41
41
  parent = nil
42
42
  if !source.repaired? && source.parsed? && source.synchronized?
43
43
  tree = source.tree_at(position.line, position.column)
44
- # node, parent = source.tree_at(position.line, position.column)[0..2]
45
- tree.shift while tree.length > 1 && tree.first.type == :SCOPE
46
44
  node, parent = tree[0..2]
47
45
  elsif source.parsed? && source.repaired? && end_of_phrase == '.'
48
46
  node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
49
47
  node = Parser.parse(fixed_phrase) if node.nil?
48
+ elsif source.repaired?
49
+ node = Parser.parse(fixed_phrase)
50
50
  else
51
51
  node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2] unless source.error_ranges.any?{|r| r.nil? || r.include?(fixed_position)}
52
52
  # Exception for positions that chain literal nodes in unsynchronized sources
@@ -58,7 +58,7 @@ module Solargraph
58
58
  end
59
59
  return Chain.new([Chain::UNDEFINED_CALL]) if node.nil? || (node.type == :sym && !phrase.start_with?(':'))
60
60
  # chain = NodeChainer.chain(node, source.filename, parent && parent.type == :block)
61
- chain = Parser.chain(node, source.filename, parent && [:ITER, :block].include?(parent.type))
61
+ chain = Parser.chain(node, source.filename, parent)
62
62
  if source.repaired? || !source.parsed? || !source.synchronized?
63
63
  if end_of_phrase.strip == '.'
64
64
  chain.links.push Chain::UNDEFINED_CALL
@@ -126,10 +126,13 @@ module Solargraph
126
126
  Position.line_char_to_offset(@source.code, line, column)
127
127
  end
128
128
 
129
+ # @return [Integer]
129
130
  def signature_data
130
131
  @signature_data ||= get_signature_data_at(offset)
131
132
  end
132
133
 
134
+ # @param index [Integer]
135
+ # @return [Integer]
133
136
  def get_signature_data_at index
134
137
  brackets = 0
135
138
  squares = 0
@@ -8,7 +8,6 @@ module Solargraph
8
8
  class Source
9
9
  autoload :Updater, 'solargraph/source/updater'
10
10
  autoload :Change, 'solargraph/source/change'
11
- autoload :Mapper, 'solargraph/source/mapper'
12
11
  autoload :EncodingFixes, 'solargraph/source/encoding_fixes'
13
12
  autoload :Cursor, 'solargraph/source/cursor'
14
13
  autoload :Chain, 'solargraph/source/chain'
@@ -33,7 +32,7 @@ module Solargraph
33
32
  attr_reader :version
34
33
 
35
34
  # @param code [String]
36
- # @param filename [String]
35
+ # @param filename [String, nil]
37
36
  # @param version [Integer]
38
37
  def initialize code, filename = nil, version = 0
39
38
  @code = normalize(code)
@@ -213,6 +212,7 @@ module Solargraph
213
212
  end
214
213
  end
215
214
 
215
+ # @return [::Array<Range>]
216
216
  def string_ranges
217
217
  @string_ranges ||= Parser.string_ranges(node)
218
218
  end
@@ -250,7 +250,7 @@ module Solargraph
250
250
  end
251
251
 
252
252
  # @param node [Parser::AST::Node]
253
- # @return [String]
253
+ # @return [String, nil]
254
254
  def comments_for node
255
255
  rng = Range.from_node(node)
256
256
  stringified_comments[rng.start.line] ||= begin
@@ -301,7 +301,7 @@ module Solargraph
301
301
 
302
302
  # Get a hash of comments grouped by the line numbers of the associated code.
303
303
  #
304
- # @return [Hash{Integer => Array<Parser::Source::Comment>}]
304
+ # @return [Hash{Integer => String}]
305
305
  def associated_comments
306
306
  @associated_comments ||= begin
307
307
  result = {}
@@ -323,6 +323,8 @@ module Solargraph
323
323
 
324
324
  private
325
325
 
326
+ # @param line [Integer]
327
+ # @return [Integer]
326
328
  def first_not_empty_from line
327
329
  cursor = line
328
330
  cursor += 1 while cursor < code_lines.length && code_lines[cursor].strip.empty?
@@ -332,7 +334,7 @@ module Solargraph
332
334
 
333
335
  # @param top [Parser::AST::Node]
334
336
  # @param result [Array<Range>]
335
- # @param parent [Symbol]
337
+ # @param parent [Symbol, nil]
336
338
  # @return [void]
337
339
  def inner_folding_ranges top, result = [], parent = nil
338
340
  return unless Parser.is_ast_node?(top)
@@ -411,7 +413,7 @@ module Solargraph
411
413
  result
412
414
  end
413
415
 
414
- # @param n [Parser::AST::Node]
416
+ # @param n [Parser::AST::Node, nil]
415
417
  # @return [Array<Parser::AST::Node>]
416
418
  def string_nodes_in n
417
419
  result = []
@@ -425,30 +427,23 @@ module Solargraph
425
427
  result
426
428
  end
427
429
 
428
- # @param node [Parser::AST::Node]
430
+ # @param node [Parser::AST::Node, nil]
429
431
  # @param position [Position]
430
432
  # @param stack [Array<Parser::AST::Node>]
431
433
  # @return [void]
432
434
  def inner_tree_at node, position, stack
433
435
  return if node.nil?
434
436
  here = Range.from_node(node)
435
- if here.contain?(position) || colonized(here, position, node)
437
+ if here.contain?(position)
436
438
  stack.unshift node
437
439
  node.children.each do |c|
438
440
  next unless Parser.is_ast_node?(c)
439
- next if !Parser.rubyvm? && c.loc.expression.nil?
441
+ next if c.loc.expression.nil?
440
442
  inner_tree_at(c, position, stack)
441
443
  end
442
444
  end
443
445
  end
444
446
 
445
- def colonized range, position, node
446
- node.type == :COLON2 &&
447
- range.ending.line == position.line &&
448
- range.ending.character == position.character - 2 &&
449
- code[Position.to_offset(code, Position.new(position.line, position.character - 2)), 2] == '::'
450
- end
451
-
452
447
  protected
453
448
 
454
449
  # @return [String]
@@ -464,7 +459,7 @@ module Solargraph
464
459
  @code = val
465
460
  end
466
461
 
467
- # @return [Parser::AST::Node]
462
+ # @return [Parser::AST::Node, nil]
468
463
  attr_writer :node
469
464
 
470
465
  # @return [Array<Range>]
@@ -476,7 +471,7 @@ module Solargraph
476
471
  # @return [Boolean]
477
472
  attr_writer :parsed
478
473
 
479
- # @return [Array<Parser::Source::Comment>]
474
+ # @return [Hash{Integer => String}
480
475
  attr_writer :comments
481
476
 
482
477
  # @return [Boolean]
@@ -503,7 +498,7 @@ module Solargraph
503
498
  end
504
499
 
505
500
  # @param code [String]
506
- # @param filename [String]
501
+ # @param filename [String, nil]
507
502
  # @param version [Integer]
508
503
  # @return [Solargraph::Source]
509
504
  def load_string code, filename = nil, version = 0
@@ -516,6 +511,10 @@ module Solargraph
516
511
  # HACK: Pass a dummy code object to the parser for plugins that
517
512
  # expect it not to be nil
518
513
  YARD::Docstring.parser.parse(comments, YARD::CodeObjects::Base.new(:root, 'stub'))
514
+ rescue StandardError => e
515
+ Solargraph.logger.info "YARD failed to parse docstring: [#{e.class}] #{e.message}"
516
+ Solargraph.logger.debug "Unparsed comment: #{comments}"
517
+ YARD::Docstring.parser
519
518
  end
520
519
  end
521
520
  end
@@ -13,14 +13,20 @@ module Solargraph
13
13
  @cursor = cursor
14
14
  end
15
15
 
16
- # @return [Array<Pin::Base>]
16
+ # @return [Array<Pin::Base>] Relevant pins for infering the type of the Cursor's position
17
17
  def define
18
18
  return [] if cursor.comment? || cursor.chain.literal?
19
19
  result = cursor.chain.define(api_map, block, locals)
20
+ result.concat file_global_methods
20
21
  result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
21
22
  result
22
23
  end
23
24
 
25
+ # @return [Array<Pin::Base>]
26
+ def types
27
+ infer.namespaces.map { |namespace| api_map.get_path_pins(namespace) }.flatten
28
+ end
29
+
24
30
  # @return [Completion]
25
31
  def complete
26
32
  return package_completions([]) if !source_map.source.parsed? || cursor.string?
@@ -43,19 +49,25 @@ module Solargraph
43
49
  # @return [ComplexType]
44
50
  def infer
45
51
  result = cursor.chain.infer(api_map, block, locals)
52
+ if result.tag == 'Class'
53
+ # HACK: Exception to return BasicObject from Class#new
54
+ dfn = cursor.chain.define(api_map, block, locals).first
55
+ return ComplexType.try_parse('BasicObject') if dfn && dfn.path == 'Class#new'
56
+ end
46
57
  return result unless result.tag == 'self'
47
- ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).namespace)
58
+ ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).tag)
48
59
  end
49
60
 
50
61
  # Get an array of all the locals that are visible from the cursors's
51
62
  # position. Locals can be local variables, method parameters, or block
52
63
  # parameters. The array starts with the nearest local pin.
53
64
  #
54
- # @return [Array<Solargraph::Pin::Base>]
65
+ # @return [::Array<Solargraph::Pin::Base>]
55
66
  def locals
56
67
  @locals ||= source_map.locals_at(location)
57
68
  end
58
69
 
70
+ # @return [::Array<String>]
59
71
  def gates
60
72
  block.gates
61
73
  end
@@ -88,11 +100,12 @@ module Solargraph
88
100
  @source_map ||= api_map.source_map(cursor.filename)
89
101
  end
90
102
 
103
+ # @return [Location]
91
104
  def location
92
105
  Location.new(source_map.filename, Solargraph::Range.new(cursor.position, cursor.position))
93
106
  end
94
107
 
95
- # @return [Solargraph::Pin::Base]
108
+ # @return [Solargraph::Pin::Closure]
96
109
  def block
97
110
  @block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
98
111
  end
@@ -104,22 +117,7 @@ module Solargraph
104
117
  @context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
105
118
  end
106
119
 
107
- # @return [Array<Pin::Base>]
108
- def yielded_self_pins
109
- return [] unless block.is_a?(Pin::Block) && block.receiver
110
- chain = Parser.chain(block.receiver, source_map.source.filename)
111
- receiver_pin = chain.define(api_map, context_pin, locals).first
112
- return [] if receiver_pin.nil?
113
- result = []
114
- ys = receiver_pin.docstring.tag(:yieldpublic)
115
- unless ys.nil? || ys.types.empty?
116
- ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
117
- result.concat api_map.get_complex_type_methods(ysct, '', false)
118
- end
119
- result
120
- end
121
-
122
- # @return [Array<Pin::KeywordParam]
120
+ # @return [Array<Pin::KeywordParam>]
123
121
  def complete_keyword_parameters
124
122
  return [] unless cursor.argument? && cursor.chain.links.one? && cursor.word =~ /^[a-z0-9_]*:?$/
125
123
  pins = signify
@@ -143,7 +141,7 @@ module Solargraph
143
141
  result
144
142
  end
145
143
 
146
- # @param result [Array<Pin::Base>]
144
+ # @param result [Enumerable<Pin::Base>]
147
145
  # @return [Completion]
148
146
  def package_completions result
149
147
  frag_start = cursor.start_of_word.to_s.downcase
@@ -154,6 +152,7 @@ module Solargraph
154
152
  Completion.new(filtered, cursor.range)
155
153
  end
156
154
 
155
+ # @return [Completion]
157
156
  def tag_complete
158
157
  result = []
159
158
  match = source_map.code[0..cursor.offset-1].match(/[\[<, ]([a-z0-9_:]*)\z/i)
@@ -172,6 +171,7 @@ module Solargraph
172
171
  package_completions(result)
173
172
  end
174
173
 
174
+ # @return [Completion]
175
175
  def code_complete
176
176
  result = []
177
177
  result.concat complete_keyword_parameters
@@ -209,16 +209,23 @@ module Solargraph
209
209
  return package_completions(api_map.get_global_variable_pins)
210
210
  end
211
211
  result.concat locals
212
+ result.concat file_global_methods unless block.binder.namespace.empty?
212
213
  result.concat api_map.get_constants(context_pin.context.namespace, *gates)
213
214
  result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
214
215
  result.concat api_map.get_methods('Kernel')
215
- # result.concat ApiMap.keywords
216
216
  result.concat api_map.keyword_pins.to_a
217
- result.concat yielded_self_pins
218
217
  end
219
218
  end
220
219
  package_completions(result)
221
220
  end
221
+
222
+ # @return [Array<Pin::Base>]
223
+ def file_global_methods
224
+ return [] if cursor.word.empty?
225
+ source_map.pins.select do |pin|
226
+ pin.is_a?(Pin::Method) && pin.namespace == '' && pin.name.start_with?(cursor.word)
227
+ end
228
+ end
222
229
  end
223
230
  end
224
231
  end