solargraph 0.54.4 → 0.58.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 (238) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/linting.yml +127 -0
  4. data/.github/workflows/plugins.yml +185 -6
  5. data/.github/workflows/rspec.yml +55 -5
  6. data/.github/workflows/typecheck.yml +8 -3
  7. data/.gitignore +8 -0
  8. data/.overcommit.yml +72 -0
  9. data/.rspec +1 -0
  10. data/.rubocop.yml +66 -0
  11. data/.rubocop_todo.yml +1279 -0
  12. data/.yardopts +1 -0
  13. data/CHANGELOG.md +143 -0
  14. data/README.md +20 -6
  15. data/Rakefile +125 -13
  16. data/bin/solargraph +3 -0
  17. data/lib/solargraph/api_map/cache.rb +110 -109
  18. data/lib/solargraph/api_map/constants.rb +279 -0
  19. data/lib/solargraph/api_map/index.rb +193 -167
  20. data/lib/solargraph/api_map/source_to_yard.rb +97 -88
  21. data/lib/solargraph/api_map/store.rb +384 -241
  22. data/lib/solargraph/api_map.rb +945 -875
  23. data/lib/solargraph/bench.rb +45 -28
  24. data/lib/solargraph/complex_type/type_methods.rb +228 -217
  25. data/lib/solargraph/complex_type/unique_type.rb +482 -386
  26. data/lib/solargraph/complex_type.rb +444 -394
  27. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  28. data/lib/solargraph/convention/base.rb +20 -3
  29. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  30. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  31. data/lib/solargraph/convention/data_definition.rb +105 -0
  32. data/lib/solargraph/convention/gemfile.rb +15 -15
  33. data/lib/solargraph/convention/gemspec.rb +23 -22
  34. data/lib/solargraph/convention/rakefile.rb +17 -17
  35. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
  36. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
  37. data/lib/solargraph/convention/struct_definition.rb +164 -0
  38. data/lib/solargraph/convention.rb +78 -47
  39. data/lib/solargraph/converters/dd.rb +17 -17
  40. data/lib/solargraph/converters/dl.rb +15 -15
  41. data/lib/solargraph/converters/dt.rb +15 -15
  42. data/lib/solargraph/converters/misc.rb +1 -1
  43. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  44. data/lib/solargraph/diagnostics/rubocop.rb +118 -113
  45. data/lib/solargraph/diagnostics/rubocop_helpers.rb +68 -66
  46. data/lib/solargraph/diagnostics/type_check.rb +55 -55
  47. data/lib/solargraph/diagnostics/update_errors.rb +41 -41
  48. data/lib/solargraph/doc_map.rb +439 -188
  49. data/lib/solargraph/environ.rb +9 -2
  50. data/lib/solargraph/equality.rb +34 -33
  51. data/lib/solargraph/gem_pins.rb +98 -72
  52. data/lib/solargraph/language_server/error_codes.rb +20 -20
  53. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  54. data/lib/solargraph/language_server/host/dispatch.rb +130 -128
  55. data/lib/solargraph/language_server/host/message_worker.rb +112 -106
  56. data/lib/solargraph/language_server/host/sources.rb +99 -99
  57. data/lib/solargraph/language_server/host.rb +878 -861
  58. data/lib/solargraph/language_server/message/base.rb +97 -96
  59. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
  60. data/lib/solargraph/language_server/message/completion_item/resolve.rb +60 -60
  61. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +114 -112
  62. data/lib/solargraph/language_server/message/extended/document.rb +23 -20
  63. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  64. data/lib/solargraph/language_server/message/extended/download_core.rb +19 -19
  65. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  66. data/lib/solargraph/language_server/message/initialize.rb +191 -191
  67. data/lib/solargraph/language_server/message/text_document/completion.rb +56 -56
  68. data/lib/solargraph/language_server/message/text_document/definition.rb +40 -38
  69. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
  70. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -26
  71. data/lib/solargraph/language_server/message/text_document/formatting.rb +148 -131
  72. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  73. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
  74. data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
  75. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
  76. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -24
  77. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -24
  78. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +35 -35
  79. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -40
  80. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +26 -24
  81. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  82. data/lib/solargraph/language_server/message.rb +94 -94
  83. data/lib/solargraph/language_server/progress.rb +8 -0
  84. data/lib/solargraph/language_server/request.rb +27 -24
  85. data/lib/solargraph/language_server/transport/data_reader.rb +74 -74
  86. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  87. data/lib/solargraph/library.rb +683 -662
  88. data/lib/solargraph/location.rb +82 -58
  89. data/lib/solargraph/logging.rb +37 -27
  90. data/lib/solargraph/page.rb +92 -89
  91. data/lib/solargraph/parser/comment_ripper.rb +69 -56
  92. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
  93. data/lib/solargraph/parser/node_processor/base.rb +92 -87
  94. data/lib/solargraph/parser/node_processor.rb +62 -45
  95. data/lib/solargraph/parser/parser_gem/class_methods.rb +149 -157
  96. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -18
  97. data/lib/solargraph/parser/parser_gem/node_chainer.rb +166 -164
  98. data/lib/solargraph/parser/parser_gem/node_methods.rb +486 -495
  99. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  100. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
  101. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +59 -57
  102. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +15 -15
  103. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -43
  104. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
  105. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  106. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +53 -50
  107. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +37 -36
  108. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  109. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
  110. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +40 -38
  111. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +29 -28
  112. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +59 -53
  113. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
  114. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -0
  115. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -16
  116. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +38 -36
  117. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +52 -42
  118. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +291 -259
  119. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
  120. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  121. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  122. data/lib/solargraph/parser/parser_gem/node_processors.rb +70 -56
  123. data/lib/solargraph/parser/parser_gem.rb +12 -12
  124. data/lib/solargraph/parser/region.rb +69 -66
  125. data/lib/solargraph/parser/snippet.rb +17 -15
  126. data/lib/solargraph/parser.rb +23 -22
  127. data/lib/solargraph/pin/base.rb +729 -378
  128. data/lib/solargraph/pin/base_variable.rb +126 -118
  129. data/lib/solargraph/pin/block.rb +104 -101
  130. data/lib/solargraph/pin/breakable.rb +9 -0
  131. data/lib/solargraph/pin/callable.rb +231 -147
  132. data/lib/solargraph/pin/closure.rb +72 -57
  133. data/lib/solargraph/pin/common.rb +79 -70
  134. data/lib/solargraph/pin/constant.rb +45 -43
  135. data/lib/solargraph/pin/conversions.rb +123 -123
  136. data/lib/solargraph/pin/delegated_method.rb +120 -101
  137. data/lib/solargraph/pin/documenting.rb +114 -98
  138. data/lib/solargraph/pin/instance_variable.rb +34 -34
  139. data/lib/solargraph/pin/keyword.rb +20 -15
  140. data/lib/solargraph/pin/local_variable.rb +75 -67
  141. data/lib/solargraph/pin/method.rb +672 -527
  142. data/lib/solargraph/pin/method_alias.rb +34 -31
  143. data/lib/solargraph/pin/namespace.rb +115 -107
  144. data/lib/solargraph/pin/parameter.rb +275 -212
  145. data/lib/solargraph/pin/proxy_type.rb +39 -29
  146. data/lib/solargraph/pin/reference/override.rb +47 -29
  147. data/lib/solargraph/pin/reference/require.rb +2 -2
  148. data/lib/solargraph/pin/reference/superclass.rb +15 -10
  149. data/lib/solargraph/pin/reference.rb +39 -22
  150. data/lib/solargraph/pin/search.rb +61 -56
  151. data/lib/solargraph/pin/signature.rb +61 -17
  152. data/lib/solargraph/pin/singleton.rb +1 -1
  153. data/lib/solargraph/pin/symbol.rb +53 -47
  154. data/lib/solargraph/pin/until.rb +18 -0
  155. data/lib/solargraph/pin/while.rb +18 -0
  156. data/lib/solargraph/pin.rb +44 -41
  157. data/lib/solargraph/pin_cache.rb +245 -0
  158. data/lib/solargraph/position.rb +132 -107
  159. data/lib/solargraph/range.rb +112 -98
  160. data/lib/solargraph/rbs_map/conversions.rb +823 -646
  161. data/lib/solargraph/rbs_map/core_fills.rb +84 -50
  162. data/lib/solargraph/rbs_map/core_map.rb +58 -28
  163. data/lib/solargraph/rbs_map/stdlib_map.rb +43 -33
  164. data/lib/solargraph/rbs_map.rb +163 -93
  165. data/lib/solargraph/server_methods.rb +16 -16
  166. data/lib/solargraph/shell.rb +363 -269
  167. data/lib/solargraph/source/chain/array.rb +37 -33
  168. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  169. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  170. data/lib/solargraph/source/chain/call.rb +337 -303
  171. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  172. data/lib/solargraph/source/chain/constant.rb +26 -89
  173. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  174. data/lib/solargraph/source/chain/hash.rb +34 -33
  175. data/lib/solargraph/source/chain/head.rb +1 -1
  176. data/lib/solargraph/source/chain/if.rb +28 -28
  177. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  178. data/lib/solargraph/source/chain/link.rb +109 -98
  179. data/lib/solargraph/source/chain/literal.rb +48 -28
  180. data/lib/solargraph/source/chain/or.rb +23 -23
  181. data/lib/solargraph/source/chain/q_call.rb +11 -11
  182. data/lib/solargraph/source/chain/variable.rb +13 -13
  183. data/lib/solargraph/source/chain/z_super.rb +30 -30
  184. data/lib/solargraph/source/chain.rb +291 -252
  185. data/lib/solargraph/source/change.rb +82 -82
  186. data/lib/solargraph/source/cursor.rb +166 -167
  187. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  188. data/lib/solargraph/source/source_chainer.rb +194 -194
  189. data/lib/solargraph/source/updater.rb +55 -55
  190. data/lib/solargraph/source.rb +498 -495
  191. data/lib/solargraph/source_map/clip.rb +226 -232
  192. data/lib/solargraph/source_map/data.rb +34 -30
  193. data/lib/solargraph/source_map/mapper.rb +259 -255
  194. data/lib/solargraph/source_map.rb +212 -217
  195. data/lib/solargraph/type_checker/checks.rb +124 -120
  196. data/lib/solargraph/type_checker/param_def.rb +37 -35
  197. data/lib/solargraph/type_checker/problem.rb +32 -32
  198. data/lib/solargraph/type_checker/rules.rb +84 -62
  199. data/lib/solargraph/type_checker.rb +814 -672
  200. data/lib/solargraph/version.rb +5 -5
  201. data/lib/solargraph/views/_method.erb +10 -10
  202. data/lib/solargraph/views/_namespace.erb +3 -3
  203. data/lib/solargraph/views/document.erb +10 -10
  204. data/lib/solargraph/workspace/config.rb +255 -239
  205. data/lib/solargraph/workspace/require_paths.rb +97 -0
  206. data/lib/solargraph/workspace.rb +220 -239
  207. data/lib/solargraph/yard_map/helpers.rb +44 -16
  208. data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
  209. data/lib/solargraph/yard_map/mapper/to_method.rb +130 -94
  210. data/lib/solargraph/yard_map/mapper/to_namespace.rb +31 -28
  211. data/lib/solargraph/yard_map/mapper.rb +79 -78
  212. data/lib/solargraph/yard_map/to_method.rb +89 -86
  213. data/lib/solargraph/yard_tags.rb +20 -20
  214. data/lib/solargraph/yardoc.rb +87 -52
  215. data/lib/solargraph.rb +105 -72
  216. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  217. data/rbs/fills/open3/0/open3.rbs +172 -0
  218. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  219. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  220. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  221. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  222. data/rbs/fills/tuple/tuple.rbs +149 -0
  223. data/rbs/shims/ast/0/node.rbs +5 -0
  224. data/rbs/shims/ast/2.4/.rbs_meta.yaml +9 -0
  225. data/rbs/shims/ast/2.4/ast.rbs +73 -0
  226. data/rbs/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  227. data/rbs/shims/parser/3.2.0.1/manifest.yaml +7 -0
  228. data/rbs/shims/parser/3.2.0.1/parser.rbs +201 -0
  229. data/rbs/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  230. data/rbs/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  231. data/rbs/shims/thor/1.2.0.1/manifest.yaml +7 -0
  232. data/rbs/shims/thor/1.2.0.1/thor.rbs +17 -0
  233. data/rbs_collection.yaml +19 -0
  234. data/solargraph.gemspec +27 -5
  235. metadata +215 -18
  236. data/lib/.rubocop.yml +0 -22
  237. data/lib/solargraph/cache.rb +0 -77
  238. data/lib/solargraph/parser/node_methods.rb +0 -83
@@ -0,0 +1,255 @@
1
+ module Solargraph
2
+ module Parser
3
+ class FlowSensitiveTyping
4
+ include Solargraph::Parser::NodeMethods
5
+
6
+ # @param locals [Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
7
+ # @param enclosing_breakable_pin [Solargraph::Pin::Breakable, nil]
8
+ def initialize(locals, enclosing_breakable_pin = nil)
9
+ @locals = locals
10
+ @enclosing_breakable_pin = enclosing_breakable_pin
11
+ end
12
+
13
+ # @param and_node [Parser::AST::Node]
14
+ # @param true_ranges [Array<Range>]
15
+ #
16
+ # @return [void]
17
+ def process_and(and_node, true_ranges = [])
18
+ # @type [Parser::AST::Node]
19
+ lhs = and_node.children[0]
20
+ # @type [Parser::AST::Node]
21
+ rhs = and_node.children[1]
22
+
23
+ before_rhs_loc = rhs.location.expression.adjust(begin_pos: -1)
24
+ before_rhs_pos = Position.new(before_rhs_loc.line, before_rhs_loc.column)
25
+
26
+ rhs_presence = Range.new(before_rhs_pos,
27
+ get_node_end_position(rhs))
28
+ process_isa(lhs, true_ranges + [rhs_presence])
29
+ end
30
+
31
+ # @param if_node [Parser::AST::Node]
32
+ #
33
+ # @return [void]
34
+ def process_if(if_node)
35
+ #
36
+ # See if we can refine a type based on the result of 'if foo.nil?'
37
+ #
38
+ # [3] pry(main)> require 'parser/current'; Parser::CurrentRuby.parse("if foo.is_a? Baz; then foo; else bar; end")
39
+ # => s(:if,
40
+ # s(:send,
41
+ # s(:send, nil, :foo), :is_a?,
42
+ # s(:const, nil, :Baz)),
43
+ # s(:send, nil, :foo),
44
+ # s(:send, nil, :bar))
45
+ # [4] pry(main)>
46
+ conditional_node = if_node.children[0]
47
+ # @type [Parser::AST::Node]
48
+ then_clause = if_node.children[1]
49
+ # @type [Parser::AST::Node]
50
+ else_clause = if_node.children[2]
51
+
52
+ true_ranges = []
53
+ if always_breaks?(else_clause)
54
+ unless enclosing_breakable_pin.nil?
55
+ rest_of_breakable_body = Range.new(get_node_end_position(if_node),
56
+ get_node_end_position(enclosing_breakable_pin.node))
57
+ true_ranges << rest_of_breakable_body
58
+ end
59
+ end
60
+
61
+ unless then_clause.nil?
62
+ #
63
+ # Add specialized locals for the then clause range
64
+ #
65
+ before_then_clause_loc = then_clause.location.expression.adjust(begin_pos: -1)
66
+ before_then_clause_pos = Position.new(before_then_clause_loc.line, before_then_clause_loc.column)
67
+ true_ranges << Range.new(before_then_clause_pos,
68
+ get_node_end_position(then_clause))
69
+ end
70
+
71
+ process_conditional(conditional_node, true_ranges)
72
+ end
73
+
74
+ class << self
75
+ include Logging
76
+ end
77
+
78
+ # Find a variable pin by name and where it is used.
79
+ #
80
+ # Resolves our most specific view of this variable's type by
81
+ # preferring pins created by flow-sensitive typing when we have
82
+ # them based on the Closure and Location.
83
+ #
84
+ # @param pins [Array<Pin::LocalVariable>]
85
+ # @param name [String]
86
+ # @param closure [Pin::Closure]
87
+ # @param location [Location]
88
+ #
89
+ # @return [Array<Pin::LocalVariable>]
90
+ def self.visible_pins(pins, name, closure, location)
91
+ logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location})" }
92
+ pins_with_name = pins.select { |p| p.name == name }
93
+ if pins_with_name.empty?
94
+ logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location}) => [] - no pins with name" }
95
+ return []
96
+ end
97
+ pins_with_specific_visibility = pins.select { |p| p.name == name && p.presence && p.visible_at?(closure, location) }
98
+ if pins_with_specific_visibility.empty?
99
+ logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location}) => #{pins_with_name} - no pins with specific visibility" }
100
+ return pins_with_name
101
+ end
102
+ visible_pins_specific_to_this_closure = pins_with_specific_visibility.select { |p| p.closure == closure }
103
+ if visible_pins_specific_to_this_closure.empty?
104
+ logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location}) => #{pins_with_specific_visibility} - no visible pins specific to this closure (#{closure})}" }
105
+ return pins_with_specific_visibility
106
+ end
107
+ flow_defined_pins = pins_with_specific_visibility.select { |p| p.presence_certain? }
108
+ if flow_defined_pins.empty?
109
+ logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location}) => #{visible_pins_specific_to_this_closure} - no flow-defined pins" }
110
+ return visible_pins_specific_to_this_closure
111
+ end
112
+
113
+ logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location}) => #{flow_defined_pins}" }
114
+
115
+ flow_defined_pins
116
+ end
117
+
118
+ include Logging
119
+
120
+ private
121
+
122
+ # @param pin [Pin::LocalVariable]
123
+ # @param downcast_type_name [String]
124
+ # @param presence [Range]
125
+ #
126
+ # @return [void]
127
+ def add_downcast_local(pin, downcast_type_name, presence)
128
+ # @todo Create pin#update method
129
+ new_pin = Solargraph::Pin::LocalVariable.new(
130
+ location: pin.location,
131
+ closure: pin.closure,
132
+ name: pin.name,
133
+ assignment: pin.assignment,
134
+ comments: pin.comments,
135
+ presence: presence,
136
+ return_type: ComplexType.try_parse(downcast_type_name),
137
+ presence_certain: true,
138
+ source: :flow_sensitive_typing
139
+ )
140
+ locals.push(new_pin)
141
+ end
142
+
143
+ # @param facts_by_pin [Hash{Pin::LocalVariable => Array<Hash{Symbol => String}>}]
144
+ # @param presences [Array<Range>]
145
+ #
146
+ # @return [void]
147
+ def process_facts(facts_by_pin, presences)
148
+ #
149
+ # Add specialized locals for the rest of the block
150
+ #
151
+ facts_by_pin.each_pair do |pin, facts|
152
+ facts.each do |fact|
153
+ downcast_type_name = fact.fetch(:type)
154
+ presences.each do |presence|
155
+ add_downcast_local(pin, downcast_type_name, presence)
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ # @param conditional_node [Parser::AST::Node]
162
+ # @param true_ranges [Array<Range>]
163
+ #
164
+ # @return [void]
165
+ def process_conditional(conditional_node, true_ranges)
166
+ if conditional_node.type == :send
167
+ process_isa(conditional_node, true_ranges)
168
+ elsif conditional_node.type == :and
169
+ process_and(conditional_node, true_ranges)
170
+ end
171
+ end
172
+
173
+ # @param isa_node [Parser::AST::Node]
174
+ # @return [Array(String, String), nil]
175
+ def parse_isa(isa_node)
176
+ return unless isa_node&.type == :send && isa_node.children[1] == :is_a?
177
+ # Check if conditional node follows this pattern:
178
+ # s(:send,
179
+ # s(:send, nil, :foo), :is_a?,
180
+ # s(:const, nil, :Baz)),
181
+ isa_receiver = isa_node.children[0]
182
+ isa_type_name = type_name(isa_node.children[2])
183
+ return unless isa_type_name
184
+
185
+ # check if isa_receiver looks like this:
186
+ # s(:send, nil, :foo)
187
+ # and set variable_name to :foo
188
+ if isa_receiver&.type == :send && isa_receiver.children[0].nil? && isa_receiver.children[1].is_a?(Symbol)
189
+ variable_name = isa_receiver.children[1].to_s
190
+ end
191
+ # or like this:
192
+ # (lvar :repr)
193
+ variable_name = isa_receiver.children[0].to_s if isa_receiver&.type == :lvar
194
+ return unless variable_name
195
+
196
+ [isa_type_name, variable_name]
197
+ end
198
+
199
+ # @param variable_name [String]
200
+ # @param position [Position]
201
+ #
202
+ # @return [Solargraph::Pin::LocalVariable, nil]
203
+ def find_local(variable_name, position)
204
+ pins = locals.select { |pin| pin.name == variable_name && pin.presence.include?(position) }
205
+ return unless pins.length == 1
206
+ pins.first
207
+ end
208
+
209
+ # @param isa_node [Parser::AST::Node]
210
+ # @param true_presences [Array<Range>]
211
+ #
212
+ # @return [void]
213
+ def process_isa(isa_node, true_presences)
214
+ isa_type_name, variable_name = parse_isa(isa_node)
215
+ return if variable_name.nil? || variable_name.empty?
216
+ isa_position = Range.from_node(isa_node).start
217
+
218
+ pin = find_local(variable_name, isa_position)
219
+ return unless pin
220
+
221
+ if_true = {}
222
+ if_true[pin] ||= []
223
+ if_true[pin] << { type: isa_type_name }
224
+ process_facts(if_true, true_presences)
225
+ end
226
+
227
+ # @param node [Parser::AST::Node]
228
+ #
229
+ # @return [String, nil]
230
+ def type_name(node)
231
+ # e.g.,
232
+ # s(:const, nil, :Baz)
233
+ return unless node&.type == :const
234
+ module_node = node.children[0]
235
+ class_node = node.children[1]
236
+
237
+ return class_node.to_s if module_node.nil?
238
+
239
+ module_type_name = type_name(module_node)
240
+ return unless module_type_name
241
+
242
+ "#{module_type_name}::#{class_node}"
243
+ end
244
+
245
+ # @param clause_node [Parser::AST::Node]
246
+ def always_breaks?(clause_node)
247
+ clause_node&.type == :break
248
+ end
249
+
250
+ attr_reader :locals
251
+
252
+ attr_reader :enclosing_breakable_pin
253
+ end
254
+ end
255
+ end
@@ -1,87 +1,92 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Parser
5
- module NodeProcessor
6
- class Base
7
- # @return [Parser::AST::Node]
8
- attr_reader :node
9
-
10
- # @return [Region]
11
- attr_reader :region
12
-
13
- # @return [Array<Pin::Base>]
14
- attr_reader :pins
15
-
16
- # @return [Array<Pin::BaseVariable>]
17
- attr_reader :locals
18
-
19
- # @param node [Parser::AST::Node]
20
- # @param region [Region]
21
- # @param pins [Array<Pin::Base>]
22
- # @param locals [Array<Pin::LocalVariable>]
23
- def initialize node, region, pins, locals
24
- @node = node
25
- @region = region
26
- @pins = pins
27
- @locals = locals
28
- @processed_children = false
29
- end
30
-
31
- # Subclasses should override this method to generate new pins.
32
- #
33
- # @return [void]
34
- def process
35
- process_children
36
- end
37
-
38
- private
39
-
40
- # @param subregion [Region]
41
- # @return [void]
42
- def process_children subregion = region
43
- return if @processed_children
44
- @processed_children = true
45
- node.children.each do |child|
46
- next unless Parser.is_ast_node?(child)
47
- NodeProcessor.process(child, subregion, pins, locals)
48
- end
49
- end
50
-
51
- # @param node [Parser::AST::Node]
52
- # @return [Solargraph::Location]
53
- def get_node_location(node)
54
- range = Parser.node_range(node)
55
- Location.new(region.filename, range)
56
- end
57
-
58
- # @param node [Parser::AST::Node]
59
- # @return [String, nil]
60
- def comments_for(node)
61
- region.source.comments_for(node)
62
- end
63
-
64
- # @param position [Solargraph::Position]
65
- # @return [Pin::Closure, nil]
66
- def named_path_pin position
67
- pins.select{|pin| pin.is_a?(Pin::Closure) && pin.path && !pin.path.empty? && pin.location.range.contain?(position)}.last
68
- end
69
-
70
- # @todo Candidate for deprecation
71
- # @param position [Solargraph::Position]
72
- # @return [Pin::Closure, nil]
73
- def block_pin position
74
- # @todo determine if this can return a Pin::Block
75
- pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
76
- end
77
-
78
- # @todo Candidate for deprecation
79
- # @param position [Solargraph::Position]
80
- # @return [Pin::Closure, nil]
81
- def closure_pin position
82
- pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
83
- end
84
- end
85
- end
86
- end
87
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module NodeProcessor
6
+ class Base
7
+ # @return [Parser::AST::Node]
8
+ attr_reader :node
9
+
10
+ # @return [Region]
11
+ attr_reader :region
12
+
13
+ # @return [Array<Pin::Base>]
14
+ attr_reader :pins
15
+
16
+ # @return [Array<Pin::LocalVariable>]
17
+ attr_reader :locals
18
+
19
+ # @param node [Parser::AST::Node]
20
+ # @param region [Region]
21
+ # @param pins [Array<Pin::Base>]
22
+ # @param locals [Array<Pin::LocalVariable>]
23
+ def initialize node, region, pins, locals
24
+ @node = node
25
+ @region = region
26
+ @pins = pins
27
+ @locals = locals
28
+ @processed_children = false
29
+ end
30
+
31
+ # Subclasses should override this method to generate new pins.
32
+ #
33
+ # @return [Boolean] continue processing the next processor of the same node type.
34
+ # @return [void] In case there is only one processor registered for the node type, it can be void.
35
+ def process
36
+ process_children
37
+
38
+ true
39
+ end
40
+
41
+ private
42
+
43
+ # @param subregion [Region]
44
+ # @return [void]
45
+ def process_children subregion = region
46
+ return if @processed_children
47
+ @processed_children = true
48
+ node.children.each do |child|
49
+ next unless Parser.is_ast_node?(child)
50
+ NodeProcessor.process(child, subregion, pins, locals)
51
+ end
52
+ end
53
+
54
+ # @param node [Parser::AST::Node]
55
+ # @return [Solargraph::Location]
56
+ def get_node_location(node)
57
+ range = Parser.node_range(node)
58
+ Location.new(region.filename, range)
59
+ end
60
+
61
+ # @param node [Parser::AST::Node]
62
+ # @return [String, nil]
63
+ def comments_for(node)
64
+ region.source.comments_for(node)
65
+ end
66
+
67
+ # @param position [Solargraph::Position]
68
+ # @return [Pin::Closure, nil]
69
+ def named_path_pin position
70
+ pins.select do |pin|
71
+ pin.is_a?(Pin::Closure) && pin.path && !pin.path.empty? && pin.location.range.contain?(position)
72
+ end.last
73
+ end
74
+
75
+ # @todo Candidate for deprecation
76
+ # @param position [Solargraph::Position]
77
+ # @return [Pin::Closure, nil]
78
+ def block_pin position
79
+ # @todo determine if this can return a Pin::Block
80
+ pins.select { |pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position) }.last
81
+ end
82
+
83
+ # @todo Candidate for deprecation
84
+ # @param position [Solargraph::Position]
85
+ # @return [Pin::Closure, nil]
86
+ def closure_pin position
87
+ pins.select { |pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position) }.last
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -1,45 +1,62 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Parser
5
- # The processor classes used by SourceMap::Mapper to generate pins from
6
- # parser nodes.
7
- #
8
- module NodeProcessor
9
- autoload :Base, 'solargraph/parser/node_processor/base'
10
-
11
- class << self
12
- # @type [Hash<Symbol, Class<NodeProcessor::Base>>]
13
- @@processors ||= {}
14
-
15
- # Register a processor for a node type.
16
- #
17
- # @param type [Symbol]
18
- # @param cls [Class<NodeProcessor::Base>]
19
- # @return [Class<NodeProcessor::Base>]
20
- def register type, cls
21
- @@processors[type] = cls
22
- end
23
- end
24
-
25
- # @param node [Parser::AST::Node]
26
- # @param region [Region]
27
- # @param pins [Array<Pin::Base>]
28
- # @param locals [Array<Pin::BaseVariable>]
29
- # @return [Array(Array<Pin::Base>, Array<Pin::Base>)]
30
- def self.process node, region = Region.new, pins = [], locals = []
31
- if pins.empty?
32
- pins.push Pin::Namespace.new(
33
- location: region.source.location,
34
- name: ''
35
- )
36
- end
37
- return [pins, locals] unless Parser.is_ast_node?(node)
38
- klass = @@processors[node.type] || NodeProcessor::Base
39
- processor = klass.new(node, region, pins, locals)
40
- processor.process
41
- [processor.pins, processor.locals]
42
- end
43
- end
44
- end
45
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ # The processor classes used by SourceMap::Mapper to generate pins from
6
+ # parser nodes.
7
+ #
8
+ module NodeProcessor
9
+ autoload :Base, 'solargraph/parser/node_processor/base'
10
+
11
+ class << self
12
+ # @type [Hash{Symbol => Array<Class<NodeProcessor::Base>>}]
13
+ @@processors ||= {}
14
+
15
+ # Register a processor for a node type. You can register multiple processors for the same type.
16
+ # If a node processor returns true, it will skip the next processor of the same node type.
17
+ #
18
+ # @param type [Symbol]
19
+ # @param cls [Class<NodeProcessor::Base>]
20
+ # @return [Array<Class<NodeProcessor::Base>>]
21
+ def register type, cls
22
+ @@processors[type] ||= []
23
+ @@processors[type] << cls
24
+ end
25
+
26
+ # @param type [Symbol]
27
+ # @param cls [Class<NodeProcessor::Base>]
28
+ #
29
+ # @return [void]
30
+ def deregister type, cls
31
+ @@processors[type].delete(cls)
32
+ end
33
+ end
34
+
35
+ # @param node [Parser::AST::Node]
36
+ # @param region [Region]
37
+ # @param pins [Array<Pin::Base>]
38
+ # @param locals [Array<Pin::BaseVariable>]
39
+ # @return [Array(Array<Pin::Base>, Array<Pin::Base>)]
40
+ def self.process node, region = Region.new, pins = [], locals = []
41
+ if pins.empty?
42
+ pins.push Pin::Namespace.new(
43
+ location: region.source.location,
44
+ name: '',
45
+ source: :parser,
46
+ )
47
+ end
48
+ return [pins, locals] unless Parser.is_ast_node?(node)
49
+ node_processor_classes = @@processors[node.type] || [NodeProcessor::Base]
50
+
51
+ node_processor_classes.each do |klass|
52
+ processor = klass.new(node, region, pins, locals)
53
+ process_next = processor.process
54
+
55
+ break unless process_next
56
+ end
57
+
58
+ [pins, locals]
59
+ end
60
+ end
61
+ end
62
+ end