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
@@ -1,232 +1,226 @@
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
- block.rebind(api_map) if block.is_a?(Pin::Block)
15
- end
16
-
17
- # @return [Array<Pin::Base>] Relevant pins for infering the type of the Cursor's position
18
- def define
19
- return [] if cursor.comment? || cursor.chain.literal?
20
- result = cursor.chain.define(api_map, block, locals)
21
- result.concat file_global_methods
22
- result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
23
- result
24
- end
25
-
26
- # @return [Array<Pin::Base>]
27
- def types
28
- infer.namespaces.map { |namespace| api_map.get_path_pins(namespace) }.flatten
29
- end
30
-
31
- # @return [Completion]
32
- def complete
33
- return package_completions([]) if !source_map.source.parsed? || cursor.string?
34
- return package_completions(api_map.get_symbols) if cursor.chain.literal? && cursor.chain.links.last.word == '<Symbol>'
35
- return Completion.new([], cursor.range) if cursor.chain.literal?
36
- if cursor.comment?
37
- tag_complete
38
- else
39
- code_complete
40
- end
41
- end
42
-
43
- # @return [Array<Pin::Method>]
44
- def signify
45
- return [] unless cursor.argument?
46
- chain = Parser.chain(cursor.recipient_node, cursor.filename)
47
- chain.define(api_map, context_pin, locals).select { |pin| pin.is_a?(Pin::Method) }
48
- end
49
-
50
- # @return [ComplexType]
51
- def infer
52
- result = cursor.chain.infer(api_map, block, locals)
53
- if result.tag == 'Class'
54
- # HACK: Exception to return BasicObject from Class#new
55
- dfn = cursor.chain.define(api_map, block, locals).first
56
- return ComplexType.try_parse('::BasicObject') if dfn && dfn.path == 'Class#new'
57
- end
58
- return result unless result.tag == 'self'
59
- cursor.chain.base.infer(api_map, block, locals)
60
- end
61
-
62
- # Get an array of all the locals that are visible from the cursors's
63
- # position. Locals can be local variables, method parameters, or block
64
- # parameters. The array starts with the nearest local pin.
65
- #
66
- # @return [::Array<Solargraph::Pin::Base>]
67
- def locals
68
- @locals ||= source_map.locals_at(location)
69
- end
70
-
71
- # @return [::Array<String>]
72
- def gates
73
- block.gates
74
- end
75
-
76
- def in_block?
77
- return @in_block unless @in_block.nil?
78
- @in_block = begin
79
- tree = cursor.source.tree_at(cursor.position.line, cursor.position.column)
80
- Parser.is_ast_node?(tree[1]) && [:block, :ITER].include?(tree[1].type)
81
- end
82
- end
83
-
84
- # @param phrase [String]
85
- # @return [Array<Solargraph::Pin::Base>]
86
- def translate phrase
87
- chain = Parser.chain(Parser.parse(phrase))
88
- chain.define(api_map, block, locals)
89
- end
90
-
91
- private
92
-
93
- # @return [ApiMap]
94
- attr_reader :api_map
95
-
96
- # @return [Source::Cursor]
97
- attr_reader :cursor
98
-
99
- # @return [SourceMap]
100
- def source_map
101
- @source_map ||= api_map.source_map(cursor.filename)
102
- end
103
-
104
- # @return [Location]
105
- def location
106
- Location.new(source_map.filename, Solargraph::Range.new(cursor.position, cursor.position))
107
- end
108
-
109
- # @return [Solargraph::Pin::Closure]
110
- def block
111
- @block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
112
- end
113
-
114
- # The context at the current position.
115
- #
116
- # @return [Pin::Base]
117
- def context_pin
118
- @context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
119
- end
120
-
121
- # @return [Array<Pin::KeywordParam>]
122
- def complete_keyword_parameters
123
- return [] unless cursor.argument? && cursor.chain.links.one? && cursor.word =~ /^[a-z0-9_]*:?$/
124
- pins = signify
125
- result = []
126
- done = []
127
- pins.each do |pin|
128
- pin.parameters.each do |param|
129
- next if done.include?(param.name)
130
- done.push param.name
131
- next unless param.keyword?
132
- result.push Pin::KeywordParam.new(pin.location, "#{param.name}:")
133
- end
134
- if !pin.parameters.empty? && pin.parameters.last.kwrestarg?
135
- pin.docstring.tags(:param).each do |tag|
136
- next if done.include?(tag.name)
137
- done.push tag.name
138
- result.push Pin::KeywordParam.new(pin.location, "#{tag.name}:")
139
- end
140
- end
141
- end
142
- result
143
- end
144
-
145
- # @param result [Enumerable<Pin::Base>]
146
- # @return [Completion]
147
- def package_completions result
148
- frag_start = cursor.start_of_word.to_s.downcase
149
- filtered = result.uniq(&:name).select { |s|
150
- s.name.downcase.start_with?(frag_start) &&
151
- (!s.is_a?(Pin::Method) || s.name.match(/^[a-z0-9_]+(\!|\?|=)?$/i))
152
- }
153
- Completion.new(filtered, cursor.range)
154
- end
155
-
156
- # @return [Completion]
157
- def tag_complete
158
- result = []
159
- match = source_map.code[0..cursor.offset-1].match(/[\[<, ]([a-z0-9_:]*)\z/i)
160
- if match
161
- full = match[1]
162
- if full.include?('::')
163
- if full.end_with?('::')
164
- result.concat api_map.get_constants(full[0..-3], *gates)
165
- else
166
- result.concat api_map.get_constants(full.split('::')[0..-2].join('::'), *gates)
167
- end
168
- else
169
- result.concat api_map.get_constants('', full.end_with?('::') ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
170
- end
171
- end
172
- package_completions(result)
173
- end
174
-
175
- # @return [Completion]
176
- def code_complete
177
- result = []
178
- result.concat complete_keyword_parameters
179
- if cursor.chain.constant? || cursor.start_of_constant?
180
- full = cursor.chain.links.first.word
181
- type = if cursor.chain.undefined?
182
- cursor.chain.base.infer(api_map, context_pin, locals)
183
- else
184
- if full.include?('::') && cursor.chain.links.length == 1
185
- ComplexType.try_parse(full.split('::')[0..-2].join('::'))
186
- elsif cursor.chain.links.length > 1
187
- ComplexType.try_parse(full)
188
- else
189
- ComplexType::UNDEFINED
190
- end
191
- end
192
- if type.undefined?
193
- if full.include?('::')
194
- result.concat api_map.get_constants(full, *gates)
195
- else
196
- result.concat api_map.get_constants('', cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
197
- end
198
- else
199
- result.concat api_map.get_constants(type.namespace, cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
200
- end
201
- else
202
- type = cursor.chain.base.infer(api_map, block, locals)
203
- result.concat api_map.get_complex_type_methods(type, block.binder.namespace, cursor.chain.links.length == 1)
204
- if cursor.chain.links.length == 1
205
- if cursor.word.start_with?('@@')
206
- return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
207
- elsif cursor.word.start_with?('@')
208
- return package_completions(api_map.get_instance_variable_pins(block.binder.namespace, block.binder.scope))
209
- elsif cursor.word.start_with?('$')
210
- return package_completions(api_map.get_global_variable_pins)
211
- end
212
- result.concat locals
213
- result.concat file_global_methods unless block.binder.namespace.empty?
214
- result.concat api_map.get_constants(context_pin.context.namespace, *gates)
215
- result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
216
- result.concat api_map.get_methods('Kernel')
217
- result.concat api_map.keyword_pins.to_a
218
- end
219
- end
220
- package_completions(result)
221
- end
222
-
223
- # @return [Array<Pin::Base>]
224
- def file_global_methods
225
- return [] if cursor.word.empty?
226
- source_map.pins.select do |pin|
227
- pin.is_a?(Pin::Method) && pin.namespace == '' && pin.name.start_with?(cursor.word)
228
- end
229
- end
230
- end
231
- end
232
- 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
+ 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,30 +1,34 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class SourceMap
5
- class Data
6
- def initialize source
7
- @source = source
8
- end
9
-
10
- def pins
11
- generate
12
- @pins || []
13
- end
14
-
15
- def locals
16
- generate
17
- @locals || []
18
- end
19
-
20
- private
21
-
22
- def generate
23
- return if @generated
24
-
25
- @generated = true
26
- @pins, @locals = Mapper.map(@source)
27
- end
28
- end
29
- end
30
- 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
+ # @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