solargraph 0.58.3 → 0.59.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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +12 -5
  4. data/.github/workflows/plugins.yml +54 -34
  5. data/.github/workflows/rspec.yml +15 -28
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.rubocop.yml +38 -6
  8. data/.rubocop_todo.yml +53 -966
  9. data/CHANGELOG.md +24 -0
  10. data/Gemfile +3 -1
  11. data/README.md +3 -3
  12. data/Rakefile +26 -23
  13. data/bin/solargraph +2 -1
  14. data/lib/solargraph/api_map/cache.rb +3 -3
  15. data/lib/solargraph/api_map/constants.rb +12 -3
  16. data/lib/solargraph/api_map/index.rb +29 -18
  17. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  18. data/lib/solargraph/api_map/store.rb +40 -30
  19. data/lib/solargraph/api_map.rb +160 -78
  20. data/lib/solargraph/bench.rb +2 -3
  21. data/lib/solargraph/complex_type/conformance.rb +176 -0
  22. data/lib/solargraph/complex_type/type_methods.rb +31 -18
  23. data/lib/solargraph/complex_type/unique_type.rb +221 -63
  24. data/lib/solargraph/complex_type.rb +173 -59
  25. data/lib/solargraph/convention/active_support_concern.rb +111 -111
  26. data/lib/solargraph/convention/base.rb +50 -50
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -1
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  29. data/lib/solargraph/convention/data_definition.rb +5 -2
  30. data/lib/solargraph/convention/gemfile.rb +1 -1
  31. data/lib/solargraph/convention/gemspec.rb +1 -1
  32. data/lib/solargraph/convention/rakefile.rb +1 -1
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  35. data/lib/solargraph/convention/struct_definition.rb +8 -4
  36. data/lib/solargraph/convention.rb +2 -2
  37. data/lib/solargraph/converters/dd.rb +2 -0
  38. data/lib/solargraph/converters/dl.rb +2 -0
  39. data/lib/solargraph/converters/dt.rb +2 -0
  40. data/lib/solargraph/converters/misc.rb +2 -0
  41. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  42. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  44. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  45. data/lib/solargraph/diagnostics/update_errors.rb +4 -8
  46. data/lib/solargraph/diagnostics.rb +55 -55
  47. data/lib/solargraph/doc_map.rb +38 -39
  48. data/lib/solargraph/environ.rb +52 -52
  49. data/lib/solargraph/equality.rb +4 -4
  50. data/lib/solargraph/gem_pins.rb +4 -15
  51. data/lib/solargraph/language_server/error_codes.rb +10 -10
  52. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  53. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  54. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  55. data/lib/solargraph/language_server/host/sources.rb +2 -1
  56. data/lib/solargraph/language_server/host.rb +35 -28
  57. data/lib/solargraph/language_server/message/base.rb +1 -1
  58. data/lib/solargraph/language_server/message/client/register_capability.rb +1 -3
  59. data/lib/solargraph/language_server/message/completion_item/resolve.rb +6 -8
  60. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  61. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  62. data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -7
  63. data/lib/solargraph/language_server/message/extended/download_core.rb +2 -1
  64. data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
  65. data/lib/solargraph/language_server/message/extended/search.rb +1 -1
  66. data/lib/solargraph/language_server/message/initialize.rb +20 -14
  67. data/lib/solargraph/language_server/message/initialized.rb +28 -28
  68. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  69. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  70. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +17 -10
  71. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  72. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  73. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  74. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +13 -6
  75. data/lib/solargraph/language_server/message/text_document/references.rb +17 -10
  76. data/lib/solargraph/language_server/message/text_document/rename.rb +20 -13
  77. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  78. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  79. data/lib/solargraph/language_server/message/text_document.rb +28 -28
  80. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +34 -28
  81. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +38 -30
  82. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +23 -17
  83. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  84. data/lib/solargraph/language_server/message.rb +1 -1
  85. data/lib/solargraph/language_server/progress.rb +143 -143
  86. data/lib/solargraph/language_server/request.rb +4 -2
  87. data/lib/solargraph/language_server/transport/adapter.rb +68 -68
  88. data/lib/solargraph/language_server/transport/data_reader.rb +11 -13
  89. data/lib/solargraph/language_server/uri_helpers.rb +2 -2
  90. data/lib/solargraph/language_server.rb +20 -20
  91. data/lib/solargraph/library.rb +57 -38
  92. data/lib/solargraph/location.rb +17 -14
  93. data/lib/solargraph/logging.rb +22 -4
  94. data/lib/solargraph/page.rb +1 -1
  95. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  96. data/lib/solargraph/parser/flow_sensitive_typing.rb +324 -108
  97. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  98. data/lib/solargraph/parser/node_processor.rb +8 -7
  99. data/lib/solargraph/parser/parser_gem/class_methods.rb +30 -14
  100. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -1
  101. data/lib/solargraph/parser/parser_gem/node_chainer.rb +51 -25
  102. data/lib/solargraph/parser/parser_gem/node_methods.rb +181 -73
  103. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +24 -24
  104. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  105. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  106. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  107. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -12
  108. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +36 -36
  109. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +24 -24
  110. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  111. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +9 -8
  112. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +24 -24
  113. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  114. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  115. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  116. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  117. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +40 -40
  118. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  119. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  120. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  121. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  122. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  123. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  124. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +20 -20
  125. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -1
  126. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  127. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  128. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  129. data/lib/solargraph/parser/parser_gem.rb +2 -0
  130. data/lib/solargraph/parser/region.rb +9 -3
  131. data/lib/solargraph/parser/snippet.rb +3 -1
  132. data/lib/solargraph/parser.rb +2 -0
  133. data/lib/solargraph/pin/base.rb +126 -82
  134. data/lib/solargraph/pin/base_variable.rb +273 -24
  135. data/lib/solargraph/pin/block.rb +29 -6
  136. data/lib/solargraph/pin/breakable.rb +7 -1
  137. data/lib/solargraph/pin/callable.rb +65 -21
  138. data/lib/solargraph/pin/closure.rb +7 -10
  139. data/lib/solargraph/pin/common.rb +24 -6
  140. data/lib/solargraph/pin/compound_statement.rb +55 -0
  141. data/lib/solargraph/pin/constant.rb +3 -5
  142. data/lib/solargraph/pin/conversions.rb +10 -4
  143. data/lib/solargraph/pin/delegated_method.rb +19 -8
  144. data/lib/solargraph/pin/documenting.rb +4 -2
  145. data/lib/solargraph/pin/instance_variable.rb +5 -1
  146. data/lib/solargraph/pin/keyword.rb +0 -4
  147. data/lib/solargraph/pin/local_variable.rb +15 -59
  148. data/lib/solargraph/pin/method.rb +158 -104
  149. data/lib/solargraph/pin/method_alias.rb +8 -0
  150. data/lib/solargraph/pin/namespace.rb +19 -12
  151. data/lib/solargraph/pin/parameter.rb +102 -36
  152. data/lib/solargraph/pin/proxy_type.rb +4 -1
  153. data/lib/solargraph/pin/reference/override.rb +1 -1
  154. data/lib/solargraph/pin/reference/require.rb +14 -14
  155. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  156. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  157. data/lib/solargraph/pin/reference.rb +20 -0
  158. data/lib/solargraph/pin/search.rb +8 -7
  159. data/lib/solargraph/pin/signature.rb +15 -12
  160. data/lib/solargraph/pin/singleton.rb +11 -11
  161. data/lib/solargraph/pin/symbol.rb +2 -1
  162. data/lib/solargraph/pin/until.rb +2 -4
  163. data/lib/solargraph/pin/while.rb +2 -4
  164. data/lib/solargraph/pin.rb +2 -0
  165. data/lib/solargraph/pin_cache.rb +22 -19
  166. data/lib/solargraph/position.rb +17 -10
  167. data/lib/solargraph/range.rb +16 -15
  168. data/lib/solargraph/rbs_map/conversions.rb +367 -231
  169. data/lib/solargraph/rbs_map/core_fills.rb +18 -11
  170. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  171. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  172. data/lib/solargraph/rbs_map.rb +76 -32
  173. data/lib/solargraph/server_methods.rb +1 -1
  174. data/lib/solargraph/shell.rb +258 -66
  175. data/lib/solargraph/source/chain/array.rb +3 -12
  176. data/lib/solargraph/source/chain/block_symbol.rb +13 -13
  177. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  178. data/lib/solargraph/source/chain/call.rb +96 -56
  179. data/lib/solargraph/source/chain/class_variable.rb +1 -1
  180. data/lib/solargraph/source/chain/constant.rb +5 -1
  181. data/lib/solargraph/source/chain/global_variable.rb +1 -1
  182. data/lib/solargraph/source/chain/hash.rb +8 -5
  183. data/lib/solargraph/source/chain/head.rb +19 -19
  184. data/lib/solargraph/source/chain/if.rb +12 -10
  185. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  186. data/lib/solargraph/source/chain/link.rb +12 -22
  187. data/lib/solargraph/source/chain/literal.rb +22 -15
  188. data/lib/solargraph/source/chain/or.rb +10 -4
  189. data/lib/solargraph/source/chain/q_call.rb +2 -0
  190. data/lib/solargraph/source/chain/variable.rb +3 -1
  191. data/lib/solargraph/source/chain/z_super.rb +1 -3
  192. data/lib/solargraph/source/chain.rb +51 -38
  193. data/lib/solargraph/source/change.rb +12 -5
  194. data/lib/solargraph/source/cursor.rb +33 -18
  195. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  196. data/lib/solargraph/source/source_chainer.rb +56 -32
  197. data/lib/solargraph/source/updater.rb +5 -1
  198. data/lib/solargraph/source.rb +59 -35
  199. data/lib/solargraph/source_map/clip.rb +54 -30
  200. data/lib/solargraph/source_map/data.rb +4 -1
  201. data/lib/solargraph/source_map/mapper.rb +69 -42
  202. data/lib/solargraph/source_map.rb +21 -9
  203. data/lib/solargraph/type_checker/problem.rb +3 -1
  204. data/lib/solargraph/type_checker/rules.rb +81 -8
  205. data/lib/solargraph/type_checker.rb +196 -122
  206. data/lib/solargraph/version.rb +1 -1
  207. data/lib/solargraph/workspace/config.rb +14 -11
  208. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  209. data/lib/solargraph/workspace/require_paths.rb +1 -0
  210. data/lib/solargraph/workspace.rb +50 -28
  211. data/lib/solargraph/yard_map/cache.rb +25 -25
  212. data/lib/solargraph/yard_map/helpers.rb +8 -3
  213. data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
  214. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  215. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  216. data/lib/solargraph/yard_map/mapper.rb +13 -8
  217. data/lib/solargraph/yard_map.rb +17 -18
  218. data/lib/solargraph/yard_tags.rb +2 -2
  219. data/lib/solargraph/yardoc.rb +7 -4
  220. data/lib/solargraph.rb +33 -10
  221. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  222. data/rbs/shims/ast/0/node.rbs +1 -1
  223. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  224. data/solargraph.gemspec +37 -35
  225. metadata +41 -42
  226. data/lib/solargraph/type_checker/checks.rb +0 -124
  227. data/lib/solargraph/type_checker/param_def.rb +0 -37
  228. data/lib/solargraph/yard_map/to_method.rb +0 -89
  229. data/rbs/fills/tuple/tuple.rbs +0 -149
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Solargraph
2
4
  class Source
3
5
  class Chain
@@ -5,7 +5,9 @@ module Solargraph
5
5
  class Chain
6
6
  class Variable < Link
7
7
  def resolve api_map, name_pin, locals
8
- api_map.get_instance_variable_pins(name_pin.context.namespace, name_pin.context.scope).select{|p| p.name == word}
8
+ api_map.get_instance_variable_pins(name_pin.context.namespace, name_pin.context.scope).select do |p|
9
+ p.name == word
10
+ end
9
11
  end
10
12
  end
11
13
  end
@@ -11,9 +11,7 @@ module Solargraph
11
11
  attr_reader :arguments
12
12
 
13
13
  # @param word [String]
14
- # @param arguments [::Array<Chain>]
15
14
  # @param with_block [Boolean] True if the chain is inside a block
16
- # @param head [Boolean] True if the call is the start of its chain
17
15
  def initialize word, with_block = false
18
16
  super(word, nil, [], with_block)
19
17
  end
@@ -22,7 +20,7 @@ module Solargraph
22
20
  # @param name_pin [Pin::Base]
23
21
  # @param locals [::Array<Pin::Base>]
24
22
  def resolve api_map, name_pin, locals
25
- return super_pins(api_map, name_pin)
23
+ super_pins(api_map, name_pin)
26
24
  end
27
25
  end
28
26
  end
@@ -48,11 +48,6 @@ module Solargraph
48
48
 
49
49
  attr_reader :node
50
50
 
51
- # @sg-ignore Fix "Not enough arguments to Module#protected"
52
- protected def equality_fields
53
- [links, node]
54
- end
55
-
56
51
  # @param node [Parser::AST::Node, nil]
57
52
  # @param links [::Array<Chain::Link>]
58
53
  # @param splat [Boolean]
@@ -71,6 +66,7 @@ module Solargraph
71
66
 
72
67
  # @return [Chain]
73
68
  def base
69
+ # @sg-ignore Need to add nil check here
74
70
  @base ||= Chain.new(links[0..-2])
75
71
  end
76
72
 
@@ -78,25 +74,25 @@ module Solargraph
78
74
  #
79
75
  # @param api_map [ApiMap]
80
76
  #
81
- # @param name_pin [Pin::Base] A pin
82
- # representing the place in which expression is evaluated (e.g.,
83
- # a Method pin, or a Module or Class pin if not run within a
84
- # method - both in terms of the closure around the chain, as well
85
- # as the self type used for any method calls in head position.
77
+ # @param name_pin [Pin::Base] A pin representing the closure in
78
+ # which expression is evaluated (e.g., a Method pin, or a
79
+ # Module or Class pin if not run within a method - both in
80
+ # terms of the closure around the chain, as well as the self
81
+ # type used for any method calls in head position.
86
82
  #
87
83
  # Requirements for name_pin:
88
84
  #
89
85
  # * name_pin.context: This should be a type representing the
90
- # namespace where we can look up non-local variables and
91
- # method names. If it is a Class<X>, we will look up
92
- # :class scoped methods/variables.
86
+ # namespace where we can look up non-local variables. If
87
+ # it is a Class<X>, we will look up :class scoped
88
+ # instance variables.
93
89
  #
94
90
  # * name_pin.binder: Used for method call lookups only
95
91
  # (Chain::Call links). For method calls as the first
96
92
  # element in the chain, 'name_pin.binder' should be the
97
93
  # same as name_pin.context above. For method calls later
98
- # in the chain (e.g., 'b' in a.b.c), it should represent
99
- # 'a'.
94
+ # in the chain, it changes. (e.g., for 'b' in a.b.c, it
95
+ # should represent the type of 'a').
100
96
  #
101
97
  # @param locals [::Array<Pin::LocalVariable>] Any local
102
98
  # variables / method parameters etc visible by the statement
@@ -113,11 +109,14 @@ module Solargraph
113
109
  #
114
110
  # @todo ProxyType uses 'type' for the binder, but '
115
111
  working_pin = name_pin
112
+ # @sg-ignore Need to add nil check here
116
113
  links[0..-2].each do |link|
117
114
  pins = link.resolve(api_map, working_pin, locals)
118
115
  type = infer_from_definitions(pins, working_pin, api_map, locals)
119
116
  if type.undefined?
120
- logger.debug { "Chain#define(links=#{links.map(&:desc)}, name_pin=#{name_pin.inspect}, locals=#{locals}) => [] - undefined type from #{link.desc}" }
117
+ logger.debug do
118
+ "Chain#define(links=#{links.map(&:desc)}, name_pin=#{name_pin.inspect}, locals=#{locals}) => [] - undefined type from #{link.desc}"
119
+ end
121
120
  return []
122
121
  end
123
122
  # We continue to use the context from the head pin, in case
@@ -126,7 +125,9 @@ module Solargraph
126
125
  # for the binder, as this is chaining off of it, and the
127
126
  # binder is now the lhs of the rhs we are evaluating.
128
127
  working_pin = Pin::ProxyType.anonymous(name_pin.context, binder: type, closure: name_pin, source: :chain)
129
- logger.debug { "Chain#define(links=#{links.map(&:desc)}, name_pin=#{name_pin.inspect}, locals=#{locals}) - after processing #{link.desc}, new working_pin=#{working_pin} with binder #{working_pin.binder}" }
128
+ logger.debug do
129
+ "Chain#define(links=#{links.map(&:desc)}, name_pin=#{name_pin.inspect}, locals=#{locals}) - after processing #{link.desc}, new working_pin=#{working_pin} with binder #{working_pin.binder}"
130
+ end
130
131
  end
131
132
  links.last.last_context = working_pin
132
133
  links.last.resolve(api_map, working_pin, locals)
@@ -138,7 +139,8 @@ module Solargraph
138
139
  # @return [ComplexType]
139
140
  # @sg-ignore
140
141
  def infer api_map, name_pin, locals
141
- cache_key = [node, node&.location, links, name_pin&.return_type, locals]
142
+ # includes binder as it is mutable in Pin::Block
143
+ cache_key = [node, node&.location, links, name_pin&.return_type, name_pin&.binder, locals]
142
144
  if @@inference_invalidation_key == api_map.hash
143
145
  cached = @@inference_cache[cache_key]
144
146
  return cached if cached
@@ -147,23 +149,31 @@ module Solargraph
147
149
  @@inference_cache = {}
148
150
  end
149
151
  out = infer_uncached(api_map, name_pin, locals).downcast_to_literal_if_possible
150
- logger.debug { "Chain#infer() - caching result - cache_key_hash=#{cache_key.hash}, links.map(&:hash)=#{links.map(&:hash)}, links=#{links}, cache_key.map(&:hash) = #{cache_key.map(&:hash)}, cache_key=#{cache_key}" }
152
+ logger.debug do
153
+ "Chain#infer() - caching result - cache_key_hash=#{cache_key.hash}, links.map(&:hash)=#{links.map(&:hash)}, links=#{links}, cache_key.map(&:hash) = #{cache_key.map(&:hash)}, cache_key=#{cache_key}"
154
+ end
151
155
  @@inference_cache[cache_key] = out
152
156
  end
153
157
 
154
158
  # @param api_map [ApiMap]
155
159
  # @param name_pin [Pin::Base]
156
160
  # @param locals [::Array<Pin::LocalVariable>]
157
- # @return [ComplexType]
161
+ # @return [ComplexType, ComplexType::UniqueType]
158
162
  def infer_uncached api_map, name_pin, locals
159
163
  pins = define(api_map, name_pin, locals)
160
164
  if pins.empty?
161
- logger.debug { "Chain#infer_uncached(links=#{links.map(&:desc)}, locals=#{locals.map(&:desc)}) => undefined - no pins" }
165
+ logger.debug do
166
+ "Chain#infer_uncached(links=#{links.map(&:desc)}, locals=#{locals.map(&:desc)}) => undefined - no pins"
167
+ end
162
168
  return ComplexType::UNDEFINED
163
169
  end
164
170
  type = infer_from_definitions(pins, links.last.last_context, api_map, locals)
165
171
  out = maybe_nil(type)
166
- logger.debug { "Chain#infer_uncached(links=#{self.links.map(&:desc)}, locals=#{locals.map(&:desc)}, name_pin=#{name_pin}, name_pin.closure=#{name_pin.closure.inspect}, name_pin.binder=#{name_pin.binder}) => #{out.rooted_tags.inspect}" }
172
+ logger.debug do
173
+ "Chain#infer_uncached(links=#{links.map(&:desc)}, locals=#{locals.map(&:desc)}, " \
174
+ "name_pin=#{name_pin}, name_pin.closure=#{name_pin&.closure&.inspect}, " \
175
+ "name_pin.binder=#{name_pin&.binder}) => #{out.rooted_tags.inspect}"
176
+ end
167
177
  out
168
178
  end
169
179
 
@@ -209,12 +219,12 @@ module Solargraph
209
219
  private
210
220
 
211
221
  # @param pins [::Array<Pin::Base>]
212
- # @param context [Pin::Base]
222
+ # @param name_pin [Pin::Base]
213
223
  # @param api_map [ApiMap]
214
224
  # @param locals [::Enumerable<Pin::LocalVariable>]
215
- # @return [ComplexType]
216
- def infer_from_definitions pins, context, api_map, locals
217
- # @type [::Array<ComplexType>]
225
+ # @return [ComplexType, ComplexType::UniqueType]
226
+ def infer_from_definitions pins, name_pin, api_map, locals
227
+ # @type [::Array<ComplexType, ComplexType::UniqueType>]
218
228
  types = []
219
229
  unresolved_pins = []
220
230
  # @todo this param tag shouldn't be needed to probe the type
@@ -232,7 +242,8 @@ module Solargraph
232
242
  # @todo even at strong, no typechecking complaint
233
243
  # happens when a [Pin::Base,nil] is passed into a method
234
244
  # that accepts only [Pin::Namespace] as an argument
235
- type = type.resolve_generics(pin.closure, context.binder)
245
+ # @sg-ignore Need to add nil check here
246
+ type = type.resolve_generics(pin.closure, name_pin.binder)
236
247
  end
237
248
  types << type
238
249
  else
@@ -241,17 +252,13 @@ module Solargraph
241
252
  end
242
253
 
243
254
  # Limit method inference recursion
244
- if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
245
- return ComplexType::UNDEFINED
246
- end
255
+ return ComplexType::UNDEFINED if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
247
256
 
248
257
  @@inference_depth += 1
249
258
  # @param pin [Pin::Base]
250
259
  unresolved_pins.each do |pin|
251
260
  # Avoid infinite recursion
252
- if @@inference_stack.include?(pin.identity)
253
- next
254
- end
261
+ next if @@inference_stack.include?(pin.identity)
255
262
 
256
263
  @@inference_stack.push(pin.identity)
257
264
  type = pin.probe(api_map)
@@ -271,21 +278,27 @@ module Solargraph
271
278
  else
272
279
  ComplexType.new(types)
273
280
  end
274
- if context.nil? || context.return_type.undefined?
281
+ if name_pin.nil? || name_pin.context.undefined?
275
282
  # up to downstream to resolve self type
276
283
  return type
277
284
  end
278
-
279
- type.self_to_type(context.return_type)
285
+ type.self_to_type(name_pin.context)
280
286
  end
281
287
 
282
- # @param type [ComplexType]
283
- # @return [ComplexType]
288
+ # @param type [ComplexType, ComplexType::UniqueType]
289
+ # @return [ComplexType, ComplexType::UniqueType]
284
290
  def maybe_nil type
285
291
  return type if type.undefined? || type.void? || type.nullable?
286
292
  return type unless nullable?
287
293
  ComplexType.new(type.items + [ComplexType::NIL])
288
294
  end
295
+
296
+ protected
297
+
298
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
299
+ def equality_fields
300
+ [links, node]
301
+ end
289
302
  end
290
303
  end
291
304
  end
@@ -7,13 +7,13 @@ module Solargraph
7
7
  class Change
8
8
  include EncodingFixes
9
9
 
10
- # @return [Range]
10
+ # @return [Range, nil]
11
11
  attr_reader :range
12
12
 
13
13
  # @return [String]
14
14
  attr_reader :new_text
15
15
 
16
- # @param range [Range] The starting and ending positions of the change.
16
+ # @param range [Range, nil] The starting and ending positions of the change.
17
17
  # If nil, the original text will be overwritten.
18
18
  # @param new_text [String] The text to be changed.
19
19
  def initialize range, new_text
@@ -28,12 +28,14 @@ module Solargraph
28
28
  # syntax errors will be repaired.
29
29
  # @return [String] The updated text.
30
30
  def write text, nullable = false
31
- if nullable and !range.nil? and new_text.match(/[.\[{(@$:]$/)
31
+ if nullable && !range.nil? && new_text.match(/[.\[{(@$:]$/)
32
32
  [':', '@'].each do |dupable|
33
33
  next unless new_text == dupable
34
+ # @sg-ignore flow sensitive typing needs to handle attrs
34
35
  offset = Position.to_offset(text, range.start)
35
36
  if text[offset - 1] == dupable
36
37
  p = Position.from_offset(text, offset - 1)
38
+ # @sg-ignore flow sensitive typing needs to handle attrs
37
39
  r = Change.new(Range.new(p, range.start), ' ')
38
40
  text = r.write(text)
39
41
  end
@@ -58,10 +60,13 @@ module Solargraph
58
60
  fixed
59
61
  else
60
62
  result = commit text, fixed
63
+ # @sg-ignore flow sensitive typing needs to handle attrs
61
64
  off = Position.to_offset(text, range.start)
65
+ # @sg-ignore Need to add nil check here
62
66
  match = result[0, off].match(/[.:]+\z/)
63
67
  if match
64
- result = result[0, off].sub(/#{match[0]}\z/, ' ' * match[0].length) + result[off..-1]
68
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
69
+ result = result[0, off].sub(/#{match[0]}\z/, ' ' * match[0].length) + result[off..]
65
70
  end
66
71
  result
67
72
  end
@@ -73,9 +78,11 @@ module Solargraph
73
78
  # @param insert [String]
74
79
  # @return [String]
75
80
  def commit text, insert
81
+ # @sg-ignore Need to add nil check here
76
82
  start_offset = Position.to_offset(text, range.start)
83
+ # @sg-ignore Need to add nil check here
77
84
  end_offset = Position.to_offset(text, range.ending)
78
- (start_offset == 0 ? '' : text[0..start_offset-1].to_s) + normalize(insert) + text[end_offset..-1].to_s
85
+ (start_offset.zero? ? '' : text[0..(start_offset - 1)].to_s) + normalize(insert) + text[end_offset..].to_s
79
86
  end
80
87
  end
81
88
  end
@@ -19,7 +19,7 @@ module Solargraph
19
19
  @position = Position.normalize(position)
20
20
  end
21
21
 
22
- # @return [String]
22
+ # @return [String, nil]
23
23
  def filename
24
24
  source.filename
25
25
  end
@@ -35,13 +35,17 @@ module Solargraph
35
35
  # The part of the word before the current position. Given the text
36
36
  # `foo.bar`, the start_of_word at position(0, 6) is `ba`.
37
37
  #
38
+ # @sg-ignore Need to add nil check here
38
39
  # @return [String]
39
40
  def start_of_word
40
41
  @start_of_word ||= begin
41
- match = source.code[0..offset-1].to_s.match(start_word_pattern)
42
+ match = source.code[0..(offset - 1)].to_s.match(start_word_pattern)
42
43
  result = (match ? match[0] : '')
43
44
  # Including the preceding colon if the word appears to be a symbol
44
- result = ":#{result}" if source.code[0..offset-result.length-1].end_with?(':') and !source.code[0..offset-result.length-1].end_with?('::')
45
+ # @sg-ignore Need to add nil check here
46
+ if source.code[0..(offset - result.length - 1)].end_with?(':') && !source.code[0..(offset - result.length - 1)].end_with?('::')
47
+ result = ":#{result}"
48
+ end
45
49
  result
46
50
  end
47
51
  end
@@ -50,16 +54,17 @@ module Solargraph
50
54
  # `foo.bar`, the end_of_word at position (0,6) is `r`.
51
55
  #
52
56
  # @return [String]
57
+ # @sg-ignore Need to add nil check here
53
58
  def end_of_word
54
59
  @end_of_word ||= begin
55
- match = source.code[offset..-1].to_s.match(end_word_pattern)
60
+ match = source.code[offset..].to_s.match(end_word_pattern)
56
61
  match ? match[0] : ''
57
62
  end
58
63
  end
59
64
 
60
65
  # @return [Boolean]
61
66
  def start_of_constant?
62
- source.code[offset-2, 2] == '::'
67
+ source.code[offset - 2, 2] == '::'
63
68
  end
64
69
 
65
70
  # The range of the word at the current position.
@@ -110,7 +115,17 @@ module Solargraph
110
115
  def recipient
111
116
  @recipient ||= begin
112
117
  node = recipient_node
113
- node ? Cursor.new(source, Range.from_node(node).ending) : nil
118
+ if node.nil?
119
+ nil
120
+ else
121
+ rng = Range.from_node(node)
122
+ if rng
123
+ Cursor.new(source, rng.ending)
124
+ else
125
+ pos = Position.new(position.line, [position.column - 1, 0].max)
126
+ Cursor.new(source, pos)
127
+ end
128
+ end
114
129
  end
115
130
  end
116
131
  alias receiver recipient
@@ -122,18 +137,18 @@ module Solargraph
122
137
 
123
138
  # @return [Position]
124
139
  def node_position
125
- @node_position ||= begin
126
- if start_of_word.empty?
127
- match = source.code[0, offset].match(/\s*(\.|:+)\s*$/)
128
- if match
129
- Position.from_offset(source.code, offset - match[0].length)
130
- else
131
- position
132
- end
133
- else
134
- position
135
- end
136
- end
140
+ @node_position ||= if start_of_word.empty?
141
+ # @sg-ignore Need to add nil check here
142
+ match = source.code[0, offset].match(/\s*(\.|:+)\s*$/)
143
+ if match
144
+ # @sg-ignore Need to add nil check here
145
+ Position.from_offset(source.code, offset - match[0].length)
146
+ else
147
+ position
148
+ end
149
+ else
150
+ position
151
+ end
137
152
  end
138
153
 
139
154
  # @return [Parser::AST::Node, nil]
@@ -10,13 +10,12 @@ module Solargraph
10
10
  # @param string [String]
11
11
  # @return [String]
12
12
  def normalize string
13
- begin
14
- string.dup.force_encoding('UTF-8')
15
- rescue ::Encoding::CompatibilityError, ::Encoding::UndefinedConversionError, ::Encoding::InvalidByteSequenceError => e
16
- # @todo Improve error handling
17
- Solargraph::Logging.logger.warn "Normalize error: #{e.message}"
18
- string
19
- end
13
+ string.dup.force_encoding('UTF-8')
14
+ rescue ::Encoding::CompatibilityError, ::Encoding::UndefinedConversionError,
15
+ ::Encoding::InvalidByteSequenceError => e
16
+ # @todo Improve error handling
17
+ Solargraph::Logging.logger.warn "Normalize error: #{e.message}"
18
+ string
20
19
  end
21
20
  end
22
21
  end
@@ -32,26 +32,47 @@ module Solargraph
32
32
  # @return [Source::Chain]
33
33
  def chain
34
34
  # Special handling for files that end with an integer and a period
35
- return Chain.new([Chain::Literal.new('Integer', Integer(phrase[0..-2])), Chain::UNDEFINED_CALL]) if phrase =~ /^[0-9]+\.$/
36
- return Chain.new([Chain::Literal.new('Symbol', phrase[1..].to_sym)]) if phrase.start_with?(':') && !phrase.start_with?('::')
37
- return SourceChainer.chain(source, Position.new(position.line, position.character + 1)) if end_of_phrase.strip == '::' && source.code[Position.to_offset(source.code, position)].to_s.match?(/[a-z]/i)
35
+ # if phrase =~ /^[0-9]+\.$/
36
+ # return Chain.new([Chain::Literal.new('Integer', Integer(phrase[0..-2])),
37
+ # Chain::UNDEFINED_CALL])
38
+ # end
39
+ if phrase.start_with?(':') && !phrase.start_with?('::')
40
+ return Chain.new([Chain::Literal.new('Symbol',
41
+ # @sg-ignore Need to add nil check here
42
+ phrase[1..].to_sym)])
43
+ end
44
+ if end_of_phrase.strip == '::' && source.code[Position.to_offset(
45
+ source.code, position
46
+ )].to_s.match?(/[a-z]/i)
47
+ return SourceChainer.chain(source,
48
+ Position.new(position.line,
49
+ position.character + 1))
50
+ end
38
51
  begin
39
52
  return Chain.new([]) if phrase.end_with?('..')
53
+ # @type [::Parser::AST::Node, nil]
40
54
  node = nil
55
+ # @type [::Parser::AST::Node, nil]
41
56
  parent = nil
42
57
  if !source.repaired? && source.parsed? && source.synchronized?
43
58
  tree = source.tree_at(position.line, position.column)
44
59
  node, parent = tree[0..2]
45
60
  elsif source.parsed? && source.repaired? && end_of_phrase == '.'
46
61
  node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
47
- node = Parser.parse(fixed_phrase) if node.nil?
62
+ # provide filename and line so that we can look up local variables there later
63
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
48
64
  elsif source.repaired?
49
- node = Parser.parse(fixed_phrase)
65
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line)
50
66
  else
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)}
67
+ unless source.error_ranges.any? do |r|
68
+ r.nil? || r.include?(fixed_position)
69
+ end
70
+ node, parent = source.tree_at(fixed_position.line,
71
+ fixed_position.column)[0..2]
72
+ end
52
73
  # Exception for positions that chain literal nodes in unsynchronized sources
53
74
  node = nil unless source.synchronized? || !Parser.infer_literal_node_type(node).nil?
54
- node = Parser.parse(fixed_phrase) if node.nil?
75
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
55
76
  end
56
77
  rescue Parser::SyntaxError
57
78
  return Chain.new([Chain::UNDEFINED_CALL])
@@ -79,14 +100,16 @@ module Solargraph
79
100
  # @return [Solargraph::Source]
80
101
  attr_reader :source
81
102
 
103
+ # @sg-ignore Need to add nil check here
82
104
  # @return [String]
83
105
  def phrase
84
- @phrase ||= source.code[signature_data..offset-1]
106
+ @phrase ||= source.code[signature_data..(offset - 1)]
85
107
  end
86
108
 
109
+ # @sg-ignore Need to add nil check here
87
110
  # @return [String]
88
111
  def fixed_phrase
89
- @fixed_phrase ||= phrase[0..-(end_of_phrase.length+1)]
112
+ @fixed_phrase ||= phrase[0..-(end_of_phrase.length + 1)]
90
113
  end
91
114
 
92
115
  # @return [Position]
@@ -95,6 +118,7 @@ module Solargraph
95
118
  end
96
119
 
97
120
  # @return [String]
121
+ # @sg-ignore Need to add nil check here
98
122
  def end_of_phrase
99
123
  @end_of_phrase ||= begin
100
124
  match = phrase.match(/\s*(\.{1}|::)\s*$/)
@@ -137,47 +161,47 @@ module Solargraph
137
161
  brackets = 0
138
162
  squares = 0
139
163
  parens = 0
140
- index -=1
164
+ index -= 1
141
165
  in_whitespace = false
142
166
  while index >= 0
143
167
  pos = Position.from_offset(@source.code, index)
144
- break if index > 0 and @source.comment_at?(pos)
145
- break if brackets > 0 or parens > 0 or squares > 0
168
+ break if index.positive? && @source.comment_at?(pos)
169
+ break if brackets.positive? || parens.positive? || squares.positive?
146
170
  char = @source.code[index, 1]
147
171
  break if char.nil? # @todo Is this the right way to handle this?
148
- if brackets.zero? and parens.zero? and squares.zero? and [' ', "\r", "\n", "\t"].include?(char)
172
+ if brackets.zero? && parens.zero? && squares.zero? && [' ', "\r", "\n", "\t"].include?(char)
149
173
  in_whitespace = true
150
174
  else
151
- if brackets.zero? and parens.zero? and squares.zero? and in_whitespace
152
- unless char == '.' or @source.code[index+1..-1].strip.start_with?('.')
153
- old = @source.code[index+1..-1]
154
- nxt = @source.code[index+1..-1].lstrip
155
- index += (@source.code[index+1..-1].length - @source.code[index+1..-1].lstrip.length)
156
- break
157
- end
175
+ # @sg-ignore Need to add nil check here
176
+ if brackets.zero? && parens.zero? && squares.zero? && in_whitespace && !((char == '.') || @source.code[(index + 1)..].strip.start_with?('.'))
177
+ @source.code[(index + 1)..]
178
+ # @sg-ignore Need to add nil check here
179
+ @source.code[(index + 1)..].lstrip
180
+ # @sg-ignore Need to add nil check here
181
+ index += (@source.code[(index + 1)..].length - @source.code[(index + 1)..].lstrip.length)
182
+ break
158
183
  end
159
- if char == ')'
160
- parens -=1
161
- elsif char == ']'
162
- squares -=1
163
- elsif char == '}'
184
+ case char
185
+ when ')'
186
+ parens -= 1
187
+ when ']'
188
+ squares -= 1
189
+ when '}'
164
190
  brackets -= 1
165
- elsif char == '('
191
+ when '('
166
192
  parens += 1
167
- elsif char == '{'
193
+ when '{'
168
194
  brackets += 1
169
- elsif char == '['
195
+ when '['
170
196
  squares += 1
171
197
  end
172
- if brackets.zero? and parens.zero? and squares.zero?
198
+ if brackets.zero? && parens.zero? && squares.zero?
173
199
  break if ['"', "'", ',', ';', '%'].include?(char)
174
200
  break if ['!', '?'].include?(char) && index < offset - 1
175
201
  break if char == '$'
176
202
  if char == '@'
177
203
  index -= 1
178
- if @source.code[index, 1] == '@'
179
- index -= 1
180
- end
204
+ index -= 1 if @source.code[index, 1] == '@'
181
205
  break
182
206
  end
183
207
  elsif parens == 1 || brackets == 1 || squares == 1
@@ -29,14 +29,18 @@ module Solargraph
29
29
 
30
30
  # @param text [String]
31
31
  # @param nullable [Boolean]
32
+ # @sg-ignore changes doesn't mutate @output, so this can never be nil
32
33
  # @return [String]
33
34
  def write text, nullable = false
34
35
  can_nullify = (nullable and changes.length == 1)
35
- return @output if @input == text and can_nullify == @did_nullify
36
+ return @output if (@input == text) && (can_nullify == @did_nullify)
36
37
  @input = text
37
38
  @output = text
38
39
  @did_nullify = can_nullify
39
40
  changes.each do |ch|
41
+ # @sg-ignore Wrong argument type for
42
+ # Solargraph::Source::Change#write: text expected String,
43
+ # received String, nil
40
44
  @output = ch.write(@output, can_nullify)
41
45
  end
42
46
  @output