solargraph 0.58.0 → 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.gitattributes +2 -0
  4. data/.github/workflows/linting.yml +6 -5
  5. data/.github/workflows/plugins.yml +48 -35
  6. data/.github/workflows/rspec.yml +15 -28
  7. data/.github/workflows/typecheck.yml +3 -2
  8. data/.gitignore +1 -0
  9. data/.rubocop.yml +38 -6
  10. data/.rubocop_todo.yml +53 -966
  11. data/CHANGELOG.md +24 -0
  12. data/Gemfile +3 -1
  13. data/README.md +3 -3
  14. data/Rakefile +26 -23
  15. data/bin/solargraph +9 -8
  16. data/lib/solargraph/api_map/cache.rb +110 -110
  17. data/lib/solargraph/api_map/constants.rb +288 -279
  18. data/lib/solargraph/api_map/index.rb +204 -193
  19. data/lib/solargraph/api_map/source_to_yard.rb +110 -97
  20. data/lib/solargraph/api_map/store.rb +395 -384
  21. data/lib/solargraph/api_map.rb +1029 -945
  22. data/lib/solargraph/bench.rb +44 -45
  23. data/lib/solargraph/complex_type/conformance.rb +176 -0
  24. data/lib/solargraph/complex_type/type_methods.rb +240 -228
  25. data/lib/solargraph/complex_type/unique_type.rb +641 -482
  26. data/lib/solargraph/complex_type.rb +557 -444
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
  29. data/lib/solargraph/convention/data_definition.rb +108 -105
  30. data/lib/solargraph/convention/gemfile.rb +15 -15
  31. data/lib/solargraph/convention/gemspec.rb +23 -23
  32. data/lib/solargraph/convention/rakefile.rb +17 -17
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
  35. data/lib/solargraph/convention/struct_definition.rb +168 -164
  36. data/lib/solargraph/convention.rb +78 -78
  37. data/lib/solargraph/converters/dd.rb +19 -17
  38. data/lib/solargraph/converters/dl.rb +17 -15
  39. data/lib/solargraph/converters/dt.rb +17 -15
  40. data/lib/solargraph/converters/misc.rb +3 -1
  41. data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
  42. data/lib/solargraph/diagnostics/rubocop.rb +119 -118
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
  44. data/lib/solargraph/diagnostics/type_check.rb +56 -55
  45. data/lib/solargraph/diagnostics/update_errors.rb +37 -41
  46. data/lib/solargraph/doc_map.rb +438 -439
  47. data/lib/solargraph/equality.rb +34 -34
  48. data/lib/solargraph/gem_pins.rb +98 -98
  49. data/lib/solargraph/language_server/error_codes.rb +20 -20
  50. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  51. data/lib/solargraph/language_server/host/dispatch.rb +130 -130
  52. data/lib/solargraph/language_server/host/message_worker.rb +113 -112
  53. data/lib/solargraph/language_server/host/sources.rb +100 -99
  54. data/lib/solargraph/language_server/host.rb +886 -878
  55. data/lib/solargraph/language_server/message/base.rb +97 -97
  56. data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
  57. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
  58. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +108 -114
  59. data/lib/solargraph/language_server/message/extended/document.rb +24 -23
  60. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  61. data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
  62. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  63. data/lib/solargraph/language_server/message/initialize.rb +197 -191
  64. data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
  65. data/lib/solargraph/language_server/message/text_document/definition.rb +49 -40
  66. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
  67. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +36 -26
  68. data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
  69. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  70. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
  71. data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
  72. data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
  73. data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
  74. data/lib/solargraph/language_server/message/text_document/type_definition.rb +33 -25
  75. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
  76. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
  77. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
  78. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +33 -23
  79. data/lib/solargraph/language_server/message.rb +94 -94
  80. data/lib/solargraph/language_server/request.rb +29 -27
  81. data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
  82. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  83. data/lib/solargraph/library.rb +702 -683
  84. data/lib/solargraph/location.rb +85 -82
  85. data/lib/solargraph/logging.rb +55 -37
  86. data/lib/solargraph/page.rb +92 -92
  87. data/lib/solargraph/parser/comment_ripper.rb +84 -69
  88. data/lib/solargraph/parser/flow_sensitive_typing.rb +471 -255
  89. data/lib/solargraph/parser/node_processor/base.rb +122 -92
  90. data/lib/solargraph/parser/node_processor.rb +63 -62
  91. data/lib/solargraph/parser/parser_gem/class_methods.rb +165 -149
  92. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  93. data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
  94. data/lib/solargraph/parser/parser_gem/node_methods.rb +507 -486
  95. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
  96. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
  97. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
  98. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +45 -46
  99. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
  100. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
  101. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
  102. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +42 -40
  103. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
  104. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
  105. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
  106. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  107. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
  108. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
  109. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +51 -52
  110. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +302 -291
  111. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  112. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  113. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
  114. data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
  115. data/lib/solargraph/parser/parser_gem.rb +14 -12
  116. data/lib/solargraph/parser/region.rb +75 -69
  117. data/lib/solargraph/parser/snippet.rb +19 -17
  118. data/lib/solargraph/parser.rb +25 -23
  119. data/lib/solargraph/pin/base.rb +773 -729
  120. data/lib/solargraph/pin/base_variable.rb +375 -126
  121. data/lib/solargraph/pin/block.rb +127 -104
  122. data/lib/solargraph/pin/breakable.rb +15 -9
  123. data/lib/solargraph/pin/callable.rb +275 -231
  124. data/lib/solargraph/pin/closure.rb +69 -72
  125. data/lib/solargraph/pin/common.rb +97 -79
  126. data/lib/solargraph/pin/compound_statement.rb +55 -0
  127. data/lib/solargraph/pin/constant.rb +43 -45
  128. data/lib/solargraph/pin/conversions.rb +129 -123
  129. data/lib/solargraph/pin/delegated_method.rb +131 -120
  130. data/lib/solargraph/pin/documenting.rb +116 -114
  131. data/lib/solargraph/pin/instance_variable.rb +38 -34
  132. data/lib/solargraph/pin/keyword.rb +16 -20
  133. data/lib/solargraph/pin/local_variable.rb +31 -75
  134. data/lib/solargraph/pin/method.rb +724 -672
  135. data/lib/solargraph/pin/method_alias.rb +42 -34
  136. data/lib/solargraph/pin/namespace.rb +122 -115
  137. data/lib/solargraph/pin/parameter.rb +339 -275
  138. data/lib/solargraph/pin/proxy_type.rb +42 -39
  139. data/lib/solargraph/pin/reference/override.rb +47 -47
  140. data/lib/solargraph/pin/reference/superclass.rb +17 -15
  141. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  142. data/lib/solargraph/pin/reference.rb +59 -39
  143. data/lib/solargraph/pin/search.rb +62 -61
  144. data/lib/solargraph/pin/signature.rb +64 -61
  145. data/lib/solargraph/pin/symbol.rb +54 -53
  146. data/lib/solargraph/pin/until.rb +16 -18
  147. data/lib/solargraph/pin/while.rb +16 -18
  148. data/lib/solargraph/pin.rb +46 -44
  149. data/lib/solargraph/pin_cache.rb +248 -245
  150. data/lib/solargraph/position.rb +139 -119
  151. data/lib/solargraph/range.rb +113 -112
  152. data/lib/solargraph/rbs_map/conversions.rb +952 -823
  153. data/lib/solargraph/rbs_map/core_fills.rb +91 -84
  154. data/lib/solargraph/rbs_map/core_map.rb +65 -58
  155. data/lib/solargraph/rbs_map/stdlib_map.rb +71 -43
  156. data/lib/solargraph/rbs_map.rb +207 -163
  157. data/lib/solargraph/server_methods.rb +16 -16
  158. data/lib/solargraph/shell.rb +555 -352
  159. data/lib/solargraph/source/chain/array.rb +39 -37
  160. data/lib/solargraph/source/chain/call.rb +377 -337
  161. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  162. data/lib/solargraph/source/chain/constant.rb +30 -26
  163. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  164. data/lib/solargraph/source/chain/hash.rb +37 -34
  165. data/lib/solargraph/source/chain/if.rb +30 -28
  166. data/lib/solargraph/source/chain/instance_variable.rb +36 -13
  167. data/lib/solargraph/source/chain/link.rb +99 -109
  168. data/lib/solargraph/source/chain/literal.rb +51 -48
  169. data/lib/solargraph/source/chain/or.rb +29 -23
  170. data/lib/solargraph/source/chain/q_call.rb +13 -11
  171. data/lib/solargraph/source/chain/variable.rb +15 -13
  172. data/lib/solargraph/source/chain/z_super.rb +28 -30
  173. data/lib/solargraph/source/chain.rb +304 -291
  174. data/lib/solargraph/source/change.rb +89 -82
  175. data/lib/solargraph/source/cursor.rb +172 -166
  176. data/lib/solargraph/source/encoding_fixes.rb +22 -23
  177. data/lib/solargraph/source/source_chainer.rb +218 -194
  178. data/lib/solargraph/source/updater.rb +59 -55
  179. data/lib/solargraph/source.rb +522 -498
  180. data/lib/solargraph/source_map/clip.rb +245 -226
  181. data/lib/solargraph/source_map/data.rb +37 -34
  182. data/lib/solargraph/source_map/mapper.rb +286 -259
  183. data/lib/solargraph/source_map.rb +224 -212
  184. data/lib/solargraph/type_checker/problem.rb +34 -32
  185. data/lib/solargraph/type_checker/rules.rb +157 -84
  186. data/lib/solargraph/type_checker.rb +888 -814
  187. data/lib/solargraph/version.rb +5 -5
  188. data/lib/solargraph/workspace/config.rb +258 -255
  189. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  190. data/lib/solargraph/workspace/require_paths.rb +98 -97
  191. data/lib/solargraph/workspace.rb +242 -220
  192. data/lib/solargraph/yard_map/helpers.rb +49 -44
  193. data/lib/solargraph/yard_map/mapper/to_method.rb +136 -130
  194. data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
  195. data/lib/solargraph/yard_map/mapper.rb +84 -79
  196. data/lib/solargraph/yard_map.rb +17 -18
  197. data/lib/solargraph/yard_tags.rb +20 -20
  198. data/lib/solargraph/yardoc.rb +90 -87
  199. data/lib/solargraph.rb +128 -105
  200. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  201. data/rbs/fills/tuple/tuple.rbs +28 -0
  202. data/rbs/shims/ast/0/node.rbs +5 -0
  203. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  204. data/rbs_collection.yaml +1 -1
  205. data/solargraph.gemspec +37 -35
  206. metadata +52 -51
  207. data/lib/solargraph/type_checker/checks.rb +0 -124
  208. data/lib/solargraph/type_checker/param_def.rb +0 -37
  209. data/lib/solargraph/yard_map/to_method.rb +0 -89
  210. data/sig/shims/ast/0/node.rbs +0 -5
  211. /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
  212. /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
  213. /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
  214. /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
  215. /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
  216. /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
  217. /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
  218. /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
  219. /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
@@ -1,226 +1,245 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class SourceMap
5
- # A static analysis tool for obtaining definitions, Completions,
6
- # signatures, and type inferences from a Cursor.
7
- #
8
- class Clip
9
- # @param api_map [ApiMap]
10
- # @param cursor [Source::Cursor]
11
- def initialize api_map, cursor
12
- @api_map = api_map
13
- @cursor = cursor
14
- closure_pin = closure
15
- closure_pin.rebind(api_map) if closure_pin.is_a?(Pin::Block) && !Solargraph::Range.from_node(closure_pin.receiver).contain?(cursor.range.start)
16
- end
17
-
18
- # @return [Array<Pin::Base>] Relevant pins for infering the type of the Cursor's position
19
- def define
20
- return [] if cursor.comment? || cursor.chain.literal?
21
- result = cursor.chain.define(api_map, closure, locals)
22
- result.concat file_global_methods
23
- result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
24
- result
25
- end
26
-
27
- # @return [Array<Pin::Base>]
28
- def types
29
- infer.namespaces.map { |namespace| api_map.get_path_pins(namespace) }.flatten
30
- end
31
-
32
- # @return [Completion]
33
- def complete
34
- return package_completions([]) if !source_map.source.parsed? || cursor.string?
35
- return package_completions(api_map.get_symbols) if cursor.chain.literal? && cursor.chain.links.last.word == '<Symbol>'
36
- return Completion.new([], cursor.range) if cursor.chain.literal?
37
- if cursor.comment?
38
- tag_complete
39
- else
40
- code_complete
41
- end
42
- end
43
-
44
- # @return [Array<Pin::Method>]
45
- def signify
46
- return [] unless cursor.argument?
47
- chain = Parser.chain(cursor.recipient_node, cursor.filename)
48
- chain.define(api_map, context_pin, locals).select { |pin| pin.is_a?(Pin::Method) }
49
- end
50
-
51
- # @return [ComplexType]
52
- def infer
53
- result = cursor.chain.infer(api_map, closure, locals)
54
- if result.tag == 'Class'
55
- # HACK: Exception to return BasicObject from Class#new
56
- dfn = cursor.chain.define(api_map, closure, locals).first
57
- return ComplexType.try_parse('::BasicObject') if dfn && dfn.path == 'Class#new'
58
- end
59
- # should receive result with selfs resolved from infer()
60
- Solargraph.assert_or_log(:clip_infer_self, 'Received selfy inference') if result.selfy?
61
- result
62
- end
63
-
64
- # Get an array of all the locals that are visible from the cursors's
65
- # position. Locals can be local variables, method parameters, or block
66
- # parameters. The array starts with the nearest local pin.
67
- #
68
- # @return [::Array<Solargraph::Pin::LocalVariable>]
69
- def locals
70
- @locals ||= source_map.locals_at(location)
71
- end
72
-
73
- # @return [::Array<String>]
74
- def gates
75
- closure.gates
76
- end
77
-
78
- # @param phrase [String]
79
- # @return [Array<Solargraph::Pin::Base>]
80
- def translate phrase
81
- chain = Parser.chain(Parser.parse(phrase))
82
- chain.define(api_map, closure, locals)
83
- end
84
-
85
- private
86
-
87
- # @return [ApiMap]
88
- attr_reader :api_map
89
-
90
- # @return [Source::Cursor]
91
- attr_reader :cursor
92
-
93
- # @return [SourceMap]
94
- def source_map
95
- @source_map ||= api_map.source_map(cursor.filename)
96
- end
97
-
98
- # @return [Location]
99
- def location
100
- Location.new(source_map.filename, Solargraph::Range.new(cursor.position, cursor.position))
101
- end
102
-
103
- # @return [Solargraph::Pin::Closure]
104
- def closure
105
- @closure ||= source_map.locate_closure_pin(cursor.node_position.line, cursor.node_position.character)
106
- end
107
-
108
- # The context at the current position.
109
- #
110
- # @return [Pin::Base]
111
- def context_pin
112
- @context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
113
- end
114
-
115
- # @return [Array<Pin::KeywordParam>]
116
- def complete_keyword_parameters
117
- return [] unless cursor.argument? && cursor.chain.links.one? && cursor.word =~ /^[a-z0-9_]*:?$/
118
- pins = signify
119
- result = []
120
- done = []
121
- pins.each do |pin|
122
- pin.parameters.each do |param|
123
- next if done.include?(param.name)
124
- done.push param.name
125
- next unless param.keyword?
126
- result.push Pin::KeywordParam.new(pin.location, "#{param.name}:")
127
- end
128
- if !pin.parameters.empty? && pin.parameters.last.kwrestarg?
129
- pin.docstring.tags(:param).each do |tag|
130
- next if done.include?(tag.name)
131
- done.push tag.name
132
- result.push Pin::KeywordParam.new(pin.location, "#{tag.name}:")
133
- end
134
- end
135
- end
136
- result
137
- end
138
-
139
- # @param result [Enumerable<Pin::Base>]
140
- # @return [Completion]
141
- def package_completions result
142
- frag_start = cursor.start_of_word.to_s.downcase
143
- filtered = result.uniq(&:name).select { |s|
144
- s.name.downcase.start_with?(frag_start) &&
145
- (!s.is_a?(Pin::Method) || s.name.match(/^[a-z0-9_]+(\!|\?|=)?$/i))
146
- }
147
- Completion.new(filtered, cursor.range)
148
- end
149
-
150
- # @return [Completion]
151
- def tag_complete
152
- result = []
153
- match = source_map.code[0..cursor.offset-1].match(/[\[<, ]([a-z0-9_:]*)\z/i)
154
- if match
155
- full = match[1]
156
- if full.include?('::')
157
- if full.end_with?('::')
158
- result.concat api_map.get_constants(full[0..-3], *gates)
159
- else
160
- result.concat api_map.get_constants(full.split('::')[0..-2].join('::'), *gates)
161
- end
162
- else
163
- result.concat api_map.get_constants('', full.end_with?('::') ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
164
- end
165
- end
166
- package_completions(result)
167
- end
168
-
169
- # @return [Completion]
170
- def code_complete
171
- result = []
172
- result.concat complete_keyword_parameters
173
- if cursor.chain.constant? || cursor.start_of_constant?
174
- full = cursor.chain.links.first.word
175
- type = if cursor.chain.undefined?
176
- cursor.chain.base.infer(api_map, context_pin, locals)
177
- else
178
- if full.include?('::') && cursor.chain.links.length == 1
179
- ComplexType.try_parse(full.split('::')[0..-2].join('::'))
180
- elsif cursor.chain.links.length > 1
181
- ComplexType.try_parse(full)
182
- else
183
- ComplexType::UNDEFINED
184
- end
185
- end
186
- if type.undefined?
187
- if full.include?('::')
188
- result.concat api_map.get_constants(full, *gates)
189
- else
190
- result.concat api_map.get_constants('', cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
191
- end
192
- else
193
- result.concat api_map.get_constants(type.namespace, cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
194
- end
195
- else
196
- type = cursor.chain.base.infer(api_map, closure, locals)
197
- result.concat api_map.get_complex_type_methods(type, closure.binder.namespace, cursor.chain.links.length == 1)
198
- if cursor.chain.links.length == 1
199
- if cursor.word.start_with?('@@')
200
- return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
201
- elsif cursor.word.start_with?('@')
202
- return package_completions(api_map.get_instance_variable_pins(closure.binder.namespace, closure.binder.scope))
203
- elsif cursor.word.start_with?('$')
204
- return package_completions(api_map.get_global_variable_pins)
205
- end
206
- result.concat locals
207
- result.concat file_global_methods unless closure.binder.namespace.empty?
208
- result.concat api_map.get_constants(context_pin.context.namespace, *gates)
209
- result.concat api_map.get_methods(closure.binder.namespace, scope: closure.binder.scope, visibility: [:public, :private, :protected])
210
- result.concat api_map.get_methods('Kernel')
211
- result.concat api_map.keyword_pins.to_a
212
- end
213
- end
214
- package_completions(result)
215
- end
216
-
217
- # @return [Array<Pin::Base>]
218
- def file_global_methods
219
- return [] if cursor.word.empty?
220
- source_map.pins.select do |pin|
221
- pin.is_a?(Pin::Method) && pin.namespace == '' && pin.name.start_with?(cursor.word)
222
- end
223
- end
224
- end
225
- end
226
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class SourceMap
5
+ # A static analysis tool for obtaining definitions, Completions,
6
+ # signatures, and type inferences from a Cursor.
7
+ #
8
+ class Clip
9
+ # @param api_map [ApiMap]
10
+ # @param cursor [Source::Cursor]
11
+ def initialize api_map, cursor
12
+ @api_map = api_map
13
+ @cursor = cursor
14
+ closure_pin = closure
15
+ # @sg-ignore Need to add nil check here
16
+ if closure_pin.is_a?(Pin::Block) && !Solargraph::Range.from_node(closure_pin.receiver).contain?(cursor.range.start)
17
+ closure_pin.rebind(api_map)
18
+ end
19
+ end
20
+
21
+ # @return [Array<Pin::Base>] Relevant pins for infering the type of the Cursor's position
22
+ def define
23
+ return [] if cursor.comment? || cursor.chain.literal?
24
+ result = cursor.chain.define(api_map, closure, locals)
25
+ result.concat file_global_methods
26
+ if result.empty?
27
+ result.concat((source_map.pins + source_map.locals).select do |p|
28
+ # @sg-ignore Need to add nil check here
29
+ p.name == cursor.word && p.location.range.contain?(cursor.position)
30
+ end)
31
+ end
32
+ result
33
+ end
34
+
35
+ # @return [Array<Pin::Base>]
36
+ def types
37
+ infer.namespaces.map { |namespace| api_map.get_path_pins(namespace) }.flatten
38
+ end
39
+
40
+ # @return [Completion]
41
+ def complete
42
+ return package_completions([]) if !source_map.source.parsed? || cursor.string?
43
+ if cursor.chain.literal? && cursor.chain.links.last.word == '<Symbol>'
44
+ return package_completions(api_map.get_symbols)
45
+ end
46
+ return Completion.new([], cursor.range) if cursor.chain.literal?
47
+ if cursor.comment?
48
+ tag_complete
49
+ else
50
+ code_complete
51
+ end
52
+ end
53
+
54
+ # @return [Array<Pin::Method>]
55
+ def signify
56
+ return [] unless cursor.argument?
57
+ chain = Parser.chain(cursor.recipient_node, cursor.filename)
58
+ chain.define(api_map, context_pin, locals).select { |pin| pin.is_a?(Pin::Method) }
59
+ end
60
+
61
+ # @return [ComplexType]
62
+ def infer
63
+ result = cursor.chain.infer(api_map, closure, locals)
64
+ if result.tag == 'Class'
65
+ # HACK: Exception to return BasicObject from Class#new
66
+ dfn = cursor.chain.define(api_map, closure, locals).first
67
+ return ComplexType.try_parse('::BasicObject') if dfn && dfn.path == 'Class#new'
68
+ end
69
+ # should receive result with selfs resolved from infer()
70
+ Solargraph.assert_or_log(:clip_infer_self, 'Received selfy inference') if result.selfy?
71
+ result
72
+ end
73
+
74
+ # Get an array of all the locals that are visible from the cursors's
75
+ # position. Locals can be local variables, method parameters, or block
76
+ # parameters. The array starts with the nearest local pin.
77
+ #
78
+ # @return [::Array<Solargraph::Pin::LocalVariable>]
79
+ def locals
80
+ @locals ||= source_map.locals_at(location)
81
+ end
82
+
83
+ # @return [::Array<String>]
84
+ def gates
85
+ closure.gates
86
+ end
87
+
88
+ # @param phrase [String]
89
+ # @return [Array<Solargraph::Pin::Base>]
90
+ def translate phrase
91
+ chain = Parser.chain(Parser.parse(phrase, cursor.filename, cursor.position.line))
92
+ chain.define(api_map, closure, locals)
93
+ end
94
+
95
+ private
96
+
97
+ # @return [ApiMap]
98
+ attr_reader :api_map
99
+
100
+ # @return [Source::Cursor]
101
+ attr_reader :cursor
102
+
103
+ # @return [SourceMap]
104
+ def source_map
105
+ # @sg-ignore Need to add nil check here
106
+ @source_map ||= api_map.source_map(cursor.filename)
107
+ end
108
+
109
+ # @return [Location]
110
+ def location
111
+ Location.new(source_map.filename, Solargraph::Range.new(cursor.position, cursor.position))
112
+ end
113
+
114
+ # @return [Solargraph::Pin::Closure]
115
+ def closure
116
+ @closure ||= source_map.locate_closure_pin(cursor.node_position.line, cursor.node_position.character)
117
+ end
118
+
119
+ # The context at the current position.
120
+ #
121
+ # @return [Pin::Base]
122
+ def context_pin
123
+ @context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
124
+ end
125
+
126
+ # @return [Array<Pin::KeywordParam>]
127
+ def complete_keyword_parameters
128
+ return [] unless cursor.argument? && cursor.chain.links.one? && cursor.word =~ /^[a-z0-9_]*:?$/
129
+ pins = signify
130
+ result = []
131
+ done = []
132
+ pins.each do |pin|
133
+ pin.parameters.each do |param|
134
+ next if done.include?(param.name)
135
+ done.push param.name
136
+ next unless param.keyword?
137
+ result.push Pin::KeywordParam.new(pin.location, "#{param.name}:")
138
+ end
139
+ next unless !pin.parameters.empty? && pin.parameters.last.kwrestarg?
140
+ pin.docstring.tags(:param).each do |tag|
141
+ next if done.include?(tag.name)
142
+ done.push tag.name
143
+ result.push Pin::KeywordParam.new(pin.location, "#{tag.name}:")
144
+ end
145
+ end
146
+ result
147
+ end
148
+
149
+ # @param result [Enumerable<Pin::Base>]
150
+ # @return [Completion]
151
+ def package_completions result
152
+ frag_start = cursor.start_of_word.to_s.downcase
153
+ filtered = result.uniq(&:name).select do |s|
154
+ s.name.downcase.start_with?(frag_start) &&
155
+ (!s.is_a?(Pin::Method) || s.name.match(/^[a-z0-9_]+(!|\?|=)?$/i))
156
+ end
157
+ Completion.new(filtered, cursor.range)
158
+ end
159
+
160
+ # @return [Completion]
161
+ def tag_complete
162
+ result = []
163
+ # @sg-ignore Need to add nil check here
164
+ match = source_map.code[0..(cursor.offset - 1)].match(/[\[<, ]([a-z0-9_:]*)\z/i)
165
+ if match
166
+ # @sg-ignore Need to add nil check here
167
+ full = match[1]
168
+ # @sg-ignore Need to add nil check here
169
+ if full.include?('::')
170
+ # @sg-ignore Need to add nil check here
171
+ if full.end_with?('::')
172
+ # @sg-ignore Need to add nil check here
173
+ result.concat api_map.get_constants(full[0..-3], *gates)
174
+ else
175
+ # @sg-ignore Need to add nil check here
176
+ result.concat api_map.get_constants(full.split('::')[0..-2].join('::'), *gates)
177
+ end
178
+ else
179
+ # @sg-ignore Need to add nil check here
180
+ result.concat api_map.get_constants('', full.end_with?('::') ? '' : context_pin.full_context.namespace, *gates) # .select { |pin| pin.name.start_with?(full) }
181
+ end
182
+ end
183
+ package_completions(result)
184
+ end
185
+
186
+ # @return [Completion]
187
+ def code_complete
188
+ result = []
189
+ result.concat complete_keyword_parameters
190
+ if cursor.chain.constant? || cursor.start_of_constant?
191
+ full = cursor.chain.links.first.word
192
+ type = if cursor.chain.undefined?
193
+ cursor.chain.base.infer(api_map, context_pin, locals)
194
+ elsif full.include?('::') && cursor.chain.links.length == 1
195
+ # @sg-ignore Need to add nil check here
196
+ ComplexType.try_parse(full.split('::')[0..-2].join('::'))
197
+ elsif cursor.chain.links.length > 1
198
+ ComplexType.try_parse(full)
199
+ else
200
+ ComplexType::UNDEFINED
201
+ end
202
+ if type.undefined?
203
+ if full.include?('::')
204
+ result.concat api_map.get_constants(full, *gates)
205
+ else
206
+ result.concat api_map.get_constants('', cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates) # .select { |pin| pin.name.start_with?(full) }
207
+ end
208
+ else
209
+ result.concat api_map.get_constants(type.namespace,
210
+ cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
211
+ end
212
+ else
213
+ type = cursor.chain.base.infer(api_map, closure, locals)
214
+ result.concat api_map.get_complex_type_methods(type, closure.binder.namespace, cursor.chain.links.length == 1)
215
+ if cursor.chain.links.length == 1
216
+ if cursor.word.start_with?('@@')
217
+ return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
218
+ elsif cursor.word.start_with?('@')
219
+ return package_completions(api_map.get_instance_variable_pins(closure.full_context.namespace,
220
+ closure.context.scope))
221
+ elsif cursor.word.start_with?('$')
222
+ return package_completions(api_map.get_global_variable_pins)
223
+ end
224
+ result.concat locals
225
+ result.concat file_global_methods unless closure.binder.namespace.empty?
226
+ result.concat api_map.get_constants(context_pin.context.namespace, *gates)
227
+ result.concat api_map.get_methods(closure.binder.namespace, scope: closure.binder.scope,
228
+ visibility: %i[public private protected])
229
+ result.concat api_map.get_methods('Kernel')
230
+ result.concat api_map.keyword_pins.to_a
231
+ end
232
+ end
233
+ package_completions(result)
234
+ end
235
+
236
+ # @return [Array<Pin::Base>]
237
+ def file_global_methods
238
+ return [] if cursor.word.empty?
239
+ source_map.pins.select do |pin|
240
+ pin.is_a?(Pin::Method) && pin.namespace == '' && pin.name.start_with?(cursor.word)
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end
@@ -1,34 +1,37 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class SourceMap
5
- class Data
6
- # @param source [Solargraph::Source]
7
- def initialize source
8
- @source = source
9
- end
10
-
11
- # @return [Array<Solargraph::Pin::Base>]
12
- def pins
13
- generate
14
- @pins || []
15
- end
16
-
17
- # @return [Array<Solargraph::LocalVariable>]
18
- def locals
19
- generate
20
- @locals || []
21
- end
22
-
23
- private
24
-
25
- # @return [void]
26
- def generate
27
- return if @generated
28
-
29
- @generated = true
30
- @pins, @locals = Mapper.map(@source)
31
- end
32
- end
33
- end
34
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class SourceMap
5
+ class Data
6
+ # @param source [Solargraph::Source]
7
+ def initialize source
8
+ @source = source
9
+ end
10
+
11
+ # @sg-ignore Translate to something flow sensitive typing understands
12
+ # @return [Array<Solargraph::Pin::Base>]
13
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1100
14
+ def pins
15
+ generate
16
+ @pins || []
17
+ end
18
+
19
+ # @sg-ignore Translate to something flow sensitive typing understands
20
+ # @return [Array<Solargraph::Pin::LocalVariable>]
21
+ def locals
22
+ generate
23
+ @locals || []
24
+ end
25
+
26
+ private
27
+
28
+ # @return [void]
29
+ def generate
30
+ return if @generated
31
+
32
+ @generated = true
33
+ @pins, @locals = Mapper.map(@source)
34
+ end
35
+ end
36
+ end
37
+ end