solargraph 0.51.2 → 0.54.2

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/plugins.yml +40 -0
  3. data/.github/workflows/rspec.yml +1 -3
  4. data/.github/workflows/typecheck.yml +34 -0
  5. data/.yardopts +2 -2
  6. data/CHANGELOG.md +127 -5
  7. data/README.md +13 -16
  8. data/SPONSORS.md +1 -7
  9. data/lib/solargraph/api_map/cache.rb +50 -20
  10. data/lib/solargraph/api_map/source_to_yard.rb +17 -10
  11. data/lib/solargraph/api_map/store.rb +60 -15
  12. data/lib/solargraph/api_map.rb +282 -123
  13. data/lib/solargraph/bench.rb +3 -2
  14. data/lib/solargraph/cache.rb +29 -5
  15. data/lib/solargraph/complex_type/type_methods.rb +122 -39
  16. data/lib/solargraph/complex_type/unique_type.rb +310 -76
  17. data/lib/solargraph/complex_type.rb +166 -44
  18. data/lib/solargraph/convention.rb +0 -1
  19. data/lib/solargraph/converters/dd.rb +5 -0
  20. data/lib/solargraph/converters/dl.rb +3 -0
  21. data/lib/solargraph/converters/dt.rb +3 -0
  22. data/lib/solargraph/diagnostics/rubocop.rb +8 -7
  23. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
  24. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  25. data/lib/solargraph/diagnostics.rb +2 -2
  26. data/lib/solargraph/doc_map.rb +187 -0
  27. data/lib/solargraph/gem_pins.rb +72 -0
  28. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  29. data/lib/solargraph/language_server/host/dispatch.rb +22 -5
  30. data/lib/solargraph/language_server/host/message_worker.rb +49 -5
  31. data/lib/solargraph/language_server/host/sources.rb +8 -65
  32. data/lib/solargraph/language_server/host.rb +65 -84
  33. data/lib/solargraph/language_server/message/base.rb +19 -12
  34. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  35. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  36. data/lib/solargraph/language_server/message/initialize.rb +19 -2
  37. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  38. data/lib/solargraph/language_server/message/text_document/definition.rb +3 -3
  39. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
  40. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
  41. data/lib/solargraph/language_server/message/text_document/hover.rb +3 -1
  42. data/lib/solargraph/language_server/message/text_document/type_definition.rb +3 -3
  43. data/lib/solargraph/language_server/message/text_document.rb +0 -1
  44. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  45. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
  46. data/lib/solargraph/language_server/progress.rb +135 -0
  47. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  48. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  49. data/lib/solargraph/language_server.rb +1 -0
  50. data/lib/solargraph/library.rb +207 -111
  51. data/lib/solargraph/location.rb +15 -1
  52. data/lib/solargraph/page.rb +6 -0
  53. data/lib/solargraph/parser/comment_ripper.rb +4 -0
  54. data/lib/solargraph/parser/node_methods.rb +47 -7
  55. data/lib/solargraph/parser/node_processor/base.rb +11 -1
  56. data/lib/solargraph/parser/node_processor.rb +1 -0
  57. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
  58. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  59. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +62 -43
  60. data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
  61. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  62. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +57 -0
  63. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  64. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  65. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
  66. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  67. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +7 -20
  68. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  69. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  70. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  71. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +4 -4
  72. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
  73. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  74. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  75. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  76. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
  77. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +8 -6
  78. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
  79. data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
  80. data/lib/solargraph/parser/parser_gem.rb +12 -0
  81. data/lib/solargraph/parser/region.rb +1 -1
  82. data/lib/solargraph/parser/snippet.rb +2 -0
  83. data/lib/solargraph/parser.rb +8 -12
  84. data/lib/solargraph/pin/base.rb +78 -10
  85. data/lib/solargraph/pin/base_variable.rb +40 -7
  86. data/lib/solargraph/pin/block.rb +69 -46
  87. data/lib/solargraph/pin/callable.rb +147 -0
  88. data/lib/solargraph/pin/closure.rb +23 -3
  89. data/lib/solargraph/pin/common.rb +6 -6
  90. data/lib/solargraph/pin/conversions.rb +36 -5
  91. data/lib/solargraph/pin/delegated_method.rb +6 -2
  92. data/lib/solargraph/pin/documenting.rb +25 -32
  93. data/lib/solargraph/pin/instance_variable.rb +6 -2
  94. data/lib/solargraph/pin/local_variable.rb +13 -1
  95. data/lib/solargraph/pin/method.rb +205 -32
  96. data/lib/solargraph/pin/namespace.rb +20 -7
  97. data/lib/solargraph/pin/parameter.rb +41 -36
  98. data/lib/solargraph/pin/proxy_type.rb +1 -1
  99. data/lib/solargraph/pin/reference/override.rb +2 -2
  100. data/lib/solargraph/pin/reference.rb +8 -0
  101. data/lib/solargraph/pin/search.rb +3 -3
  102. data/lib/solargraph/pin/signature.rb +8 -14
  103. data/lib/solargraph/pin.rb +4 -2
  104. data/lib/solargraph/range.rb +4 -6
  105. data/lib/solargraph/rbs_map/conversions.rb +326 -76
  106. data/lib/solargraph/rbs_map/core_fills.rb +16 -33
  107. data/lib/solargraph/rbs_map/core_map.rb +3 -13
  108. data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
  109. data/lib/solargraph/rbs_map.rb +32 -13
  110. data/lib/solargraph/shell.rb +95 -72
  111. data/lib/solargraph/source/chain/array.rb +33 -0
  112. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  113. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  114. data/lib/solargraph/source/chain/call.rb +152 -69
  115. data/lib/solargraph/source/chain/constant.rb +15 -1
  116. data/lib/solargraph/source/chain/if.rb +23 -0
  117. data/lib/solargraph/source/chain/link.rb +17 -2
  118. data/lib/solargraph/source/chain/or.rb +2 -2
  119. data/lib/solargraph/source/chain/z_super.rb +3 -3
  120. data/lib/solargraph/source/chain.rb +85 -26
  121. data/lib/solargraph/source/change.rb +3 -0
  122. data/lib/solargraph/source/cursor.rb +16 -2
  123. data/lib/solargraph/source/source_chainer.rb +8 -5
  124. data/lib/solargraph/source/updater.rb +1 -0
  125. data/lib/solargraph/source.rb +120 -148
  126. data/lib/solargraph/source_map/clip.rb +16 -27
  127. data/lib/solargraph/source_map/data.rb +30 -0
  128. data/lib/solargraph/source_map/mapper.rb +15 -3
  129. data/lib/solargraph/source_map.rb +48 -24
  130. data/lib/solargraph/type_checker/checks.rb +10 -2
  131. data/lib/solargraph/type_checker/rules.rb +6 -1
  132. data/lib/solargraph/type_checker.rb +150 -39
  133. data/lib/solargraph/version.rb +1 -1
  134. data/lib/solargraph/views/environment.erb +3 -5
  135. data/lib/solargraph/workspace/config.rb +9 -6
  136. data/lib/solargraph/workspace.rb +30 -3
  137. data/lib/solargraph/yard_map/cache.rb +6 -0
  138. data/lib/solargraph/yard_map/helpers.rb +1 -1
  139. data/lib/solargraph/yard_map/mapper/to_method.rb +16 -3
  140. data/lib/solargraph/yard_map/mapper.rb +1 -1
  141. data/lib/solargraph/yard_map/to_method.rb +11 -4
  142. data/lib/solargraph/yard_map.rb +1 -292
  143. data/lib/solargraph/yard_tags.rb +20 -0
  144. data/lib/solargraph/yardoc.rb +52 -0
  145. data/lib/solargraph.rb +6 -4
  146. data/solargraph.gemspec +7 -6
  147. metadata +71 -82
  148. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  149. data/lib/solargraph/documentor.rb +0 -76
  150. data/lib/solargraph/language_server/host/cataloger.rb +0 -56
  151. data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
  152. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  153. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -50
  154. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  155. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
  156. data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
  157. data/lib/solargraph/parser/legacy.rb +0 -12
  158. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -153
  159. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  160. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
  161. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  162. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  163. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
  164. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
  165. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
  166. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
  167. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  168. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  169. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  170. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  171. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  172. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  173. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  174. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  175. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -51
  176. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
  177. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  178. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
  179. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
  180. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
  181. data/lib/solargraph/parser/rubyvm.rb +0 -40
  182. data/lib/solargraph/rbs_map/core_signs.rb +0 -33
  183. data/lib/yard-solargraph.rb +0 -33
@@ -2,76 +2,99 @@
2
2
 
3
3
  module Solargraph
4
4
  module Pin
5
- class Block < Closure
6
- # The signature of the method that receives this block.
7
- #
5
+ class Block < Callable
8
6
  # @return [Parser::AST::Node]
9
7
  attr_reader :receiver
10
8
 
11
- # @param args [Array<Parameter>]
12
- def initialize receiver: nil, args: [], context: nil, **splat
13
- super(**splat)
9
+ # @return [Parser::AST::Node]
10
+ attr_reader :node
11
+
12
+ # @param receiver [Parser::AST::Node, nil]
13
+ # @param node [Parser::AST::Node, nil]
14
+ # @param context [ComplexType, nil]
15
+ # @param args [::Array<Parameter>]
16
+ def initialize receiver: nil, args: [], context: nil, node: nil, **splat
17
+ super(**splat, parameters: args)
14
18
  @receiver = receiver
15
19
  @context = context
16
- @parameters = args
20
+ @return_type = ComplexType.parse('::Proc')
21
+ @node = node
17
22
  end
18
23
 
19
24
  # @param api_map [ApiMap]
20
25
  # @return [void]
21
26
  def rebind api_map
22
- @binder ||= binder_or_nil(api_map)
27
+ @rebind ||= maybe_rebind(api_map)
23
28
  end
24
29
 
25
30
  def binder
26
- @binder || closure.binder
31
+ @rebind&.defined? ? @rebind : closure.binder
27
32
  end
28
33
 
29
- # @return [Array<Parameter>]
30
- def parameters
31
- @parameters ||= []
34
+ # @param yield_types [::Array<ComplexType>]
35
+ # @param parameters [::Array<Parameter>]
36
+ #
37
+ # @return [::Array<ComplexType>]
38
+ def destructure_yield_types(yield_types, parameters)
39
+ # yielding a tuple into a block will destructure the tuple
40
+ if yield_types.length == 1
41
+ yield_type = yield_types.first
42
+ return yield_type.all_params if yield_type.tuple? && yield_type.all_params.length == parameters.length
43
+ end
44
+ parameters.map.with_index { |_, idx| yield_types[idx] || ComplexType::UNDEFINED }
32
45
  end
33
46
 
34
- # @return [Array<String>]
35
- def parameter_names
36
- @parameter_names ||= parameters.map(&:name)
47
+ # @param api_map [ApiMap]
48
+ # @return [::Array<ComplexType>]
49
+ def typify_parameters(api_map)
50
+ chain = Parser.chain(receiver, filename, node)
51
+ clip = api_map.clip_at(location.filename, location.range.start)
52
+ locals = clip.locals - [self]
53
+ meths = chain.define(api_map, closure, locals)
54
+ # @todo Convert logic to use signatures
55
+ meths.each do |meth|
56
+ next if meth.block.nil?
57
+
58
+ yield_types = meth.block.parameters.map(&:return_type)
59
+ # 'arguments' is what the method says it will yield to the
60
+ # block; 'parameters' is what the block accepts
61
+ argument_types = destructure_yield_types(yield_types, parameters)
62
+ param_types = argument_types.each_with_index.map do |arg_type, idx|
63
+ param = parameters[idx]
64
+ param_type = chain.base.infer(api_map, param, locals)
65
+ unless arg_type.nil?
66
+ if arg_type.generic? && param_type.defined?
67
+ namespace_pin = api_map.get_namespace_pins(meth.namespace, closure.namespace).first
68
+ arg_type.resolve_generics(namespace_pin, param_type)
69
+ else
70
+ arg_type.self_to_type(chain.base.infer(api_map, self, locals)).qualify(api_map, meth.context.namespace)
71
+ end
72
+ end
73
+ end
74
+ return param_types if param_types.all?(&:defined?)
75
+ end
76
+ parameters.map { ComplexType::UNDEFINED }
37
77
  end
38
78
 
39
79
  private
40
80
 
41
81
  # @param api_map [ApiMap]
42
- # @return [ComplexType, nil]
43
- def binder_or_nil api_map
44
- return nil unless receiver
45
- word = receiver.children.find { |c| c.is_a?(::Symbol) }.to_s
46
- return nil unless api_map.rebindable_method_names.include?(word)
82
+ # @return [ComplexType]
83
+ def maybe_rebind api_map
84
+ return ComplexType::UNDEFINED unless receiver
85
+
47
86
  chain = Parser.chain(receiver, location.filename)
48
87
  locals = api_map.source_map(location.filename).locals_at(location)
49
- links_last_word = chain.links.last.word
50
- if %w[instance_eval instance_exec class_eval class_exec module_eval module_exec].include?(links_last_word)
51
- return chain.base.infer(api_map, self, locals)
52
- end
53
- if 'define_method' == links_last_word and chain.define(api_map, self, locals).first&.path == 'Module#define_method' # change class type to instance type
54
- if chain.links.size > 1 # Class.define_method
55
- ty = chain.base.infer(api_map, self, locals)
56
- return Solargraph::ComplexType.parse(ty.namespace)
57
- else # define_method without self
58
- return Solargraph::ComplexType.parse(closure.binder.namespace)
59
- end
60
- end
61
- # other case without early return, read block yieldself tags
62
- receiver_pin = chain.define(api_map, self, locals).first
63
- if receiver_pin && receiver_pin.docstring
64
- ys = receiver_pin.docstring.tag(:yieldself)
65
- if ys && ys.types && !ys.types.empty?
66
- target = if chain.links.first.is_a?(Source::Chain::Constant)
67
- receiver_pin.full_context.namespace
68
- else
69
- full_context.namespace
70
- end
71
- return ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace).self_to(target)
72
- end
73
- end
74
- nil
88
+ receiver_pin = chain.define(api_map, closure, locals).first
89
+ return ComplexType::UNDEFINED unless receiver_pin
90
+
91
+ types = receiver_pin.docstring.tag(:yieldreceiver)&.types
92
+ return ComplexType::UNDEFINED unless types&.any?
93
+
94
+ target = chain.base.infer(api_map, receiver_pin, locals)
95
+ target = full_context unless target.defined?
96
+
97
+ ComplexType.try_parse(*types).qualify(api_map, receiver_pin.context.namespace).self_to_type(target)
75
98
  end
76
99
  end
77
100
  end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class Callable < Closure
6
+ # @return [self]
7
+ attr_reader :block
8
+
9
+ attr_reader :parameters
10
+
11
+ # @return [ComplexType, nil]
12
+ attr_reader :return_type
13
+
14
+ # @param block [Signature, nil]
15
+ # @param return_type [ComplexType, nil]
16
+ # @param parameters [::Array<Pin::Parameter>]
17
+ def initialize block: nil, return_type: nil, parameters: [], **splat
18
+ super(**splat)
19
+ @block = block
20
+ @return_type = return_type
21
+ @parameters = parameters
22
+ end
23
+
24
+ # @return [::Array<String>]
25
+ def parameter_names
26
+ @parameter_names ||= parameters.map(&:name)
27
+ end
28
+
29
+ # @param generics_to_resolve [Enumerable<String>]
30
+ # @param arg_types [Array<ComplexType>, nil]
31
+ # @param return_type_context [ComplexType, nil]
32
+ # @param yield_arg_types [Array<ComplexType>, nil]
33
+ # @param yield_return_type_context [ComplexType, nil]
34
+ # @param context [ComplexType, nil]
35
+ # @param resolved_generic_values [Hash{String => ComplexType}]
36
+ # @return [self]
37
+ def resolve_generics_from_context(generics_to_resolve,
38
+ arg_types = nil,
39
+ return_type_context = nil,
40
+ yield_arg_types = nil,
41
+ yield_return_type_context = nil,
42
+ resolved_generic_values: {})
43
+ callable = super(generics_to_resolve, return_type_context, resolved_generic_values: resolved_generic_values)
44
+ callable.parameters = callable.parameters.each_with_index.map do |param, i|
45
+ if arg_types.nil?
46
+ param.dup
47
+ else
48
+ param.resolve_generics_from_context(generics_to_resolve,
49
+ arg_types[i],
50
+ resolved_generic_values: resolved_generic_values)
51
+ end
52
+ end
53
+ callable.block = block.resolve_generics_from_context(generics_to_resolve,
54
+ yield_arg_types,
55
+ yield_return_type_context,
56
+ resolved_generic_values: resolved_generic_values) if callable.block?
57
+ callable
58
+ end
59
+
60
+ # @param generics_to_resolve [Enumerable<String>]
61
+ # @param arg_types [Array<ComplexType>, nil]
62
+ # @param return_type_context [ComplexType, nil]
63
+ # @param yield_arg_types [Array<ComplexType>, nil]
64
+ # @param yield_return_type_context [ComplexType, nil]
65
+ # @param context [ComplexType, nil]
66
+ # @param resolved_generic_values [Hash{String => ComplexType}]
67
+ # @return [self]
68
+ def resolve_generics_from_context_until_complete(generics_to_resolve,
69
+ arg_types = nil,
70
+ return_type_context = nil,
71
+ yield_arg_types = nil,
72
+ yield_return_type_context = nil,
73
+ resolved_generic_values: {})
74
+ # See
75
+ # https://github.com/soutaro/steep/tree/master/lib/steep/type_inference
76
+ # and
77
+ # https://github.com/sorbet/sorbet/blob/master/infer/inference.cc
78
+ # for other implementations
79
+
80
+ return self if generics_to_resolve.empty?
81
+
82
+ last_resolved_generic_values = resolved_generic_values.dup
83
+ new_pin = resolve_generics_from_context(generics_to_resolve,
84
+ arg_types,
85
+ return_type_context,
86
+ yield_arg_types,
87
+ yield_return_type_context,
88
+ resolved_generic_values: resolved_generic_values)
89
+ if last_resolved_generic_values == resolved_generic_values
90
+ # erase anything unresolved
91
+ return new_pin.erase_generics(self.generics)
92
+ end
93
+ new_pin.resolve_generics_from_context_until_complete(generics_to_resolve,
94
+ arg_types,
95
+ return_type_context,
96
+ yield_arg_types,
97
+ yield_return_type_context,
98
+ resolved_generic_values: resolved_generic_values)
99
+ end
100
+
101
+ # @return [Array<String>]
102
+ # @yieldparam [ComplexType]
103
+ # @yieldreturn [ComplexType]
104
+ # @return [self]
105
+ def transform_types(&transform)
106
+ # @todo 'super' alone should work here I think, but doesn't typecheck at level typed
107
+ callable = super(&transform)
108
+ callable.block = block.transform_types(&transform) if block?
109
+ callable.parameters = parameters.map do |param|
110
+ param.transform_types(&transform)
111
+ end
112
+ callable
113
+ end
114
+
115
+ # @param arguments [::Array<Chain>]
116
+ # @param signature [Pin::Signature]
117
+ # @return [Boolean]
118
+ def arity_matches? arguments, with_block
119
+ argcount = arguments.length
120
+ parcount = mandatory_positional_param_count
121
+ parcount -= 1 if !parameters.empty? && parameters.last.block?
122
+ return false if block? && !with_block
123
+ return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.restarg?)
124
+ true
125
+ end
126
+
127
+ def mandatory_positional_param_count
128
+ parameters.count(&:arg?)
129
+ end
130
+
131
+ # @return [String]
132
+ def to_rbs
133
+ rbs_generics + '(' + parameters.map { |param| param.to_rbs }.join(', ') + ') ' + (block.nil? ? '' : '{ ' + block.to_rbs + ' } ') + '-> ' + return_type.to_rbs
134
+ end
135
+
136
+ def block?
137
+ !!@block
138
+ end
139
+
140
+ protected
141
+
142
+ attr_writer :block
143
+
144
+ attr_writer :parameters
145
+ end
146
+ end
147
+ end
@@ -6,16 +6,19 @@ module Solargraph
6
6
  # @return [::Symbol] :class or :instance
7
7
  attr_reader :scope
8
8
 
9
- def initialize scope: :class, **splat
9
+ # @param scope [::Symbol] :class or :instance
10
+ # @param generics [::Array<Pin::Parameter>, nil]
11
+ def initialize scope: :class, generics: nil, **splat
10
12
  super(**splat)
11
13
  @scope = scope
14
+ @generics = generics
12
15
  end
13
16
 
14
17
  def context
15
18
  @context ||= begin
16
19
  result = super
17
20
  if scope == :instance
18
- Solargraph::ComplexType.parse(result.namespace)
21
+ result.reduce_class_type
19
22
  else
20
23
  result
21
24
  end
@@ -26,12 +29,29 @@ module Solargraph
26
29
  @binder || context
27
30
  end
28
31
 
29
- # @return [Array<String>]
32
+ # @return [::Array<String>]
30
33
  def gates
31
34
  # @todo This check might not be necessary. There should always be a
32
35
  # root pin
33
36
  closure ? closure.gates : ['']
34
37
  end
38
+
39
+ # @return [::Array<String>]
40
+ def generics
41
+ @generics ||= docstring.tags(:generic).map(&:name)
42
+ end
43
+
44
+ # @return [String]
45
+ def to_rbs
46
+ rbs_generics + return_type.to_rbs
47
+ end
48
+
49
+ # @return [String]
50
+ def rbs_generics
51
+ return '' if generics.empty?
52
+
53
+ '[' + generics.map { |gen| gen.to_s }.join(', ') + '] '
54
+ end
35
55
  end
36
56
  end
37
57
  end
@@ -6,7 +6,7 @@ module Solargraph
6
6
  # @return [Location]
7
7
  attr_reader :location
8
8
 
9
- # @return [Pin::Base, nil]
9
+ # @return [Pin::Closure, nil]
10
10
  attr_reader :closure
11
11
 
12
12
  # @return [String]
@@ -46,6 +46,10 @@ module Solargraph
46
46
  @path ||= name.empty? ? context.namespace : "#{context.namespace}::#{name}"
47
47
  end
48
48
 
49
+ protected
50
+
51
+ attr_writer :context
52
+
49
53
  private
50
54
 
51
55
  # @return [ComplexType]
@@ -55,11 +59,7 @@ module Solargraph
55
59
  if here.is_a?(Pin::Namespace)
56
60
  return here.return_type
57
61
  elsif here.is_a?(Pin::Method)
58
- if here.scope == :instance
59
- return ComplexType.try_parse(here.context.namespace)
60
- else
61
- return here.context
62
- end
62
+ return here.context
63
63
  end
64
64
  here = here.closure
65
65
  end
@@ -5,7 +5,35 @@ require 'cgi'
5
5
  module Solargraph
6
6
  module Pin
7
7
  # @todo Move this stuff. It should be the responsibility of the language server.
8
+ # @todo abstract methods below should be verified to be overridden
9
+ # by type checker when mixin included by non-abstract class
8
10
  module Conversions
11
+ # @!parse
12
+ # include Documenting
13
+ # include Common
14
+
15
+ # @return [Integer]
16
+ # @abstract
17
+ def completion_item_kind
18
+ raise NotImplementedError
19
+ end
20
+
21
+ # @abstract
22
+ # @return [Boolean]
23
+ def deprecated?
24
+ raise NotImplementedError
25
+ end
26
+
27
+ # @abstract
28
+ def probed?
29
+ raise NotImplementedError
30
+ end
31
+
32
+ # @abstract
33
+ def proxied?
34
+ raise NotImplementedError
35
+ end
36
+
9
37
  # @return [Hash]
10
38
  def completion_item
11
39
  @completion_item ||= {
@@ -34,12 +62,12 @@ module Solargraph
34
62
  end
35
63
  end
36
64
 
37
- # @return [Array<Hash>]
65
+ # @return [::Array<Hash>]
38
66
  def signature_help
39
67
  []
40
68
  end
41
69
 
42
- # @return [String]
70
+ # @return [String, nil]
43
71
  def detail
44
72
  # This property is not cached in an instance variable because it can
45
73
  # change when pins get proxied.
@@ -57,12 +85,14 @@ module Solargraph
57
85
  @link_documentation ||= generate_link
58
86
  end
59
87
 
88
+ # @return [String, nil]
60
89
  def text_documentation
61
- this_path = path || return_type.tag
90
+ this_path = path || name || return_type.tag
62
91
  return nil if this_path == 'undefined'
63
92
  escape_brackets this_path
64
93
  end
65
94
 
95
+ # @return [void]
66
96
  def reset_conversions
67
97
  @completion_item = nil
68
98
  @resolve_completion_item = nil
@@ -73,11 +103,12 @@ module Solargraph
73
103
 
74
104
  private
75
105
 
76
- # @return [String]
106
+ # @return [String, nil]
77
107
  def generate_link
78
- this_path = path || return_type.tag
108
+ this_path = path || name || return_type.tag
79
109
  return nil if this_path == 'undefined'
80
110
  return nil if this_path.nil? || this_path == 'undefined'
111
+ return this_path if path.nil?
81
112
  "[#{escape_brackets(this_path).gsub('_', '\\\\_')}](solargraph:/document?query=#{CGI.escape(this_path)})"
82
113
  end
83
114
 
@@ -11,8 +11,9 @@ module Solargraph
11
11
  # given closure/scope, and the delegated method will then be resolved
12
12
  # to a method pin on that type.
13
13
  #
14
- # @param resolved_method [Method] an already resolved method pin.
15
- # @param receiver [Source::Chain] the source code used to resolve the receiver for this delegated method.
14
+ # @param method [Method, nil] an already resolved method pin.
15
+ # @param receiver [Source::Chain, nil] the source code used to resolve the receiver for this delegated method.
16
+ # @param name [String]
16
17
  # @param receiver_method_name [String] the method name that will be called on the receiver (defaults to :name).
17
18
  def initialize(method: nil, receiver: nil, name: method&.name, receiver_method_name: name, **splat)
18
19
  raise ArgumentError, 'either :method or :receiver is required' if (method && receiver) || (!method && !receiver)
@@ -37,6 +38,7 @@ module Solargraph
37
38
  end
38
39
  end
39
40
 
41
+ # @param api_map [ApiMap]
40
42
  def resolvable?(api_map)
41
43
  resolve_method(api_map)
42
44
  !!@resolved_method
@@ -79,6 +81,7 @@ module Solargraph
79
81
  # helper to print a source chain as code, probably not 100% correct.
80
82
  #
81
83
  # @param chain [Source::Chain]
84
+ # @return [String]
82
85
  def print_chain(chain)
83
86
  out = +''
84
87
  chain.links.each_with_index do |link, index|
@@ -91,6 +94,7 @@ module Solargraph
91
94
  end
92
95
  out << link.word
93
96
  end
97
+ out
94
98
  end
95
99
  end
96
100
  end
@@ -38,23 +38,20 @@ module Solargraph
38
38
  end
39
39
 
40
40
  def to_s
41
- return "\n```ruby\n#{@plaintext}#{@plaintext.end_with?("\n") ? '' : "\n"}```\n\n" if code?
42
- ReverseMarkdown.convert unescape_brackets(Kramdown::Document.new(escape_brackets(@plaintext), input: 'GFM').to_html)
41
+ return to_code if code?
42
+ to_markdown
43
43
  end
44
44
 
45
45
  private
46
46
 
47
- # @param text [String]
48
47
  # @return [String]
49
- def escape_brackets text
50
- # text.gsub(/(\[[^\]]*\])([^\(]|\z)/, '!!!^\1^!!!\2')
51
- text.gsub('[', '!!!!b').gsub(']', 'e!!!!')
48
+ def to_code
49
+ "\n```ruby\n#{Documenting.normalize_indentation(@plaintext)}#{@plaintext.end_with?("\n") ? '' : "\n"}```\n\n"
52
50
  end
53
51
 
54
- # @param text [String]
55
52
  # @return [String]
56
- def unescape_brackets text
57
- text.gsub('!!!!b', '[').gsub('e!!!!', ']')
53
+ def to_markdown
54
+ ReverseMarkdown.convert Kramdown::Document.new(@plaintext, input: 'GFM').to_html
58
55
  end
59
56
  end
60
57
 
@@ -65,40 +62,36 @@ module Solargraph
65
62
  # line and at least two spaces of indentation. This is a common
66
63
  # convention in Ruby core documentation, e.g., String#split.
67
64
  sections = [DocSection.new(false)]
68
- normalize_indentation(docstring.to_s).gsub(/\t/, ' ').lines.each do |l|
69
- if l.strip.empty?
70
- sections.last.concat l
71
- else
72
- if (l =~ /^ [^\s]/ && sections.last.plaintext =~ /(\r?\n[ \t]*?){2,}$/) || (l.start_with?(' ') && sections.last.code?)
73
- # Code block
74
- sections.push DocSection.new(true) unless sections.last.code?
75
- sections.last.concat l[2..-1]
76
- else
77
- # Regular documentation
78
- sections.push DocSection.new(false) if sections.last.code?
79
- sections.last.concat l
80
- end
65
+ Documenting.normalize_indentation(Documenting.strip_html_comments(docstring.to_s.gsub("\t", ' '))).lines.each do |l|
66
+ if l.start_with?(' ')
67
+ # Code block
68
+ sections.push DocSection.new(true) unless sections.last.code?
69
+ elsif sections.last.code?
70
+ # Regular documentation
71
+ sections.push DocSection.new(false)
81
72
  end
73
+ sections.last.concat l
82
74
  end
83
75
  sections.map(&:to_s).join.strip
84
76
  end
85
77
  end
86
78
 
87
- private
88
-
89
79
  # @param text [String]
90
80
  # @return [String]
91
- def normalize_indentation text
92
- text.lines.map { |l| remove_odd_spaces(l) }.join
81
+ def self.strip_html_comments text
82
+ text.gsub(/<!--([\s\S]*?)-->/, '').strip
93
83
  end
94
84
 
95
- # @param line [String]
85
+ # @param text [String]
96
86
  # @return [String]
97
- def remove_odd_spaces line
98
- return line unless line.start_with?(' ')
99
- spaces = line.match(/^ +/)[0].length
100
- return line unless spaces.odd?
101
- line[1..-1]
87
+ def self.normalize_indentation text
88
+ left = text.lines.map do |line|
89
+ match = line.match(/^ +/)
90
+ next 0 unless match
91
+ match[0].length
92
+ end.min
93
+ return text if left.nil? || left.zero?
94
+ text.lines.map { |line| line[left..] }.join
102
95
  end
103
96
  end
104
97
  end
@@ -3,25 +3,29 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class InstanceVariable < BaseVariable
6
+ # @return [ComplexType]
6
7
  def binder
7
8
  closure.binder
8
9
  end
9
10
 
11
+ # @return [::Symbol]
10
12
  def scope
11
13
  closure.binder.scope
12
14
  end
13
15
 
16
+ # @return [ComplexType]
14
17
  def context
15
18
  @context ||= begin
16
19
  result = super
17
20
  if scope == :class
18
- ComplexType.parse("Class<#{result.namespace}>")
21
+ ComplexType.parse("::Class<#{result.rooted_namespace}>")
19
22
  else
20
- ComplexType.parse("#{result.namespace}")
23
+ result.reduce_class_type
21
24
  end
22
25
  end
23
26
  end
24
27
 
28
+ # @param other [InstanceVariable]
25
29
  def nearly? other
26
30
  super && binder == other.binder
27
31
  end
@@ -6,12 +6,16 @@ module Solargraph
6
6
  # @return [Range]
7
7
  attr_reader :presence
8
8
 
9
+ # @param assignment [AST::Node, nil]
10
+ # @param presence [Range, nil]
11
+ # @param splat [Hash]
9
12
  def initialize assignment: nil, presence: nil, **splat
10
13
  super(**splat)
11
14
  @assignment = assignment
12
15
  @presence = presence
13
16
  end
14
17
 
18
+ # @param pin [self]
15
19
  def try_merge! pin
16
20
  return false unless super
17
21
  @presence = pin.presence
@@ -21,11 +25,16 @@ module Solargraph
21
25
  # @param other_closure [Pin::Closure]
22
26
  # @param other_loc [Location]
23
27
  def visible_at?(other_closure, other_loc)
24
- return true if location.filename == other_loc.filename &&
28
+ location.filename == other_loc.filename &&
25
29
  presence.include?(other_loc.range.start) &&
26
30
  match_named_closure(other_closure, closure)
27
31
  end
28
32
 
33
+ # @return [String]
34
+ def to_rbs
35
+ (name || '(anon)') + ' ' + (return_type&.to_rbs || 'untyped')
36
+ end
37
+
29
38
  private
30
39
 
31
40
  # @param tag1 [String]
@@ -40,6 +49,9 @@ module Solargraph
40
49
  (['', 'Class<>'].include?(tag1) && ['', 'Class<>'].include?(tag2))
41
50
  end
42
51
 
52
+ # @param needle [Pin::Base]
53
+ # @param haystack [Pin::Base]
54
+ # @return [Boolean]
43
55
  def match_named_closure needle, haystack
44
56
  return true if needle == haystack || haystack.is_a?(Pin::Block)
45
57
  cursor = haystack