jimeh-solargraph 0.40.4.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 (252) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +54 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +24 -0
  6. data/.yardopts +2 -0
  7. data/CHANGELOG.md +1003 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE +21 -0
  10. data/README.md +123 -0
  11. data/Rakefile +25 -0
  12. data/SPONSORS.md +15 -0
  13. data/bin/solargraph +5 -0
  14. data/jimeh-solargraph.gemspec +44 -0
  15. data/lib/.rubocop.yml +21 -0
  16. data/lib/solargraph.rb +67 -0
  17. data/lib/solargraph/api_map.rb +752 -0
  18. data/lib/solargraph/api_map/bundler_methods.rb +27 -0
  19. data/lib/solargraph/api_map/cache.rb +70 -0
  20. data/lib/solargraph/api_map/source_to_yard.rb +81 -0
  21. data/lib/solargraph/api_map/store.rb +256 -0
  22. data/lib/solargraph/bench.rb +30 -0
  23. data/lib/solargraph/compat.rb +23 -0
  24. data/lib/solargraph/complex_type.rb +213 -0
  25. data/lib/solargraph/complex_type/type_methods.rb +127 -0
  26. data/lib/solargraph/complex_type/unique_type.rb +75 -0
  27. data/lib/solargraph/convention.rb +47 -0
  28. data/lib/solargraph/convention/base.rb +33 -0
  29. data/lib/solargraph/convention/gemfile.rb +15 -0
  30. data/lib/solargraph/convention/gemspec.rb +22 -0
  31. data/lib/solargraph/convention/rspec.rb +21 -0
  32. data/lib/solargraph/converters/dd.rb +12 -0
  33. data/lib/solargraph/converters/dl.rb +12 -0
  34. data/lib/solargraph/converters/dt.rb +12 -0
  35. data/lib/solargraph/converters/misc.rb +1 -0
  36. data/lib/solargraph/diagnostics.rb +55 -0
  37. data/lib/solargraph/diagnostics/base.rb +29 -0
  38. data/lib/solargraph/diagnostics/require_not_found.rb +37 -0
  39. data/lib/solargraph/diagnostics/rubocop.rb +90 -0
  40. data/lib/solargraph/diagnostics/rubocop_helpers.rb +45 -0
  41. data/lib/solargraph/diagnostics/severities.rb +15 -0
  42. data/lib/solargraph/diagnostics/type_check.rb +54 -0
  43. data/lib/solargraph/diagnostics/update_errors.rb +41 -0
  44. data/lib/solargraph/documentor.rb +78 -0
  45. data/lib/solargraph/environ.rb +45 -0
  46. data/lib/solargraph/language_server.rb +19 -0
  47. data/lib/solargraph/language_server/completion_item_kinds.rb +35 -0
  48. data/lib/solargraph/language_server/error_codes.rb +20 -0
  49. data/lib/solargraph/language_server/host.rb +746 -0
  50. data/lib/solargraph/language_server/host/cataloger.rb +56 -0
  51. data/lib/solargraph/language_server/host/diagnoser.rb +81 -0
  52. data/lib/solargraph/language_server/host/dispatch.rb +112 -0
  53. data/lib/solargraph/language_server/host/sources.rb +156 -0
  54. data/lib/solargraph/language_server/message.rb +92 -0
  55. data/lib/solargraph/language_server/message/base.rb +85 -0
  56. data/lib/solargraph/language_server/message/cancel_request.rb +13 -0
  57. data/lib/solargraph/language_server/message/client.rb +11 -0
  58. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -0
  59. data/lib/solargraph/language_server/message/completion_item.rb +11 -0
  60. data/lib/solargraph/language_server/message/completion_item/resolve.rb +57 -0
  61. data/lib/solargraph/language_server/message/exit_notification.rb +13 -0
  62. data/lib/solargraph/language_server/message/extended.rb +21 -0
  63. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +100 -0
  64. data/lib/solargraph/language_server/message/extended/document.rb +20 -0
  65. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -0
  66. data/lib/solargraph/language_server/message/extended/download_core.rb +23 -0
  67. data/lib/solargraph/language_server/message/extended/environment.rb +25 -0
  68. data/lib/solargraph/language_server/message/extended/search.rb +20 -0
  69. data/lib/solargraph/language_server/message/initialize.rb +153 -0
  70. data/lib/solargraph/language_server/message/initialized.rb +26 -0
  71. data/lib/solargraph/language_server/message/method_not_found.rb +16 -0
  72. data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -0
  73. data/lib/solargraph/language_server/message/shutdown.rb +13 -0
  74. data/lib/solargraph/language_server/message/text_document.rb +28 -0
  75. data/lib/solargraph/language_server/message/text_document/base.rb +19 -0
  76. data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -0
  77. data/lib/solargraph/language_server/message/text_document/completion.rb +57 -0
  78. data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
  79. data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
  80. data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -0
  81. data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -0
  82. data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -0
  83. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -0
  84. data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -0
  85. data/lib/solargraph/language_server/message/text_document/formatting.rb +105 -0
  86. data/lib/solargraph/language_server/message/text_document/hover.rb +44 -0
  87. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -0
  88. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -0
  89. data/lib/solargraph/language_server/message/text_document/references.rb +16 -0
  90. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -0
  91. data/lib/solargraph/language_server/message/text_document/signature_help.rb +29 -0
  92. data/lib/solargraph/language_server/message/workspace.rb +14 -0
  93. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -0
  94. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +33 -0
  95. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -0
  96. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -0
  97. data/lib/solargraph/language_server/message_types.rb +14 -0
  98. data/lib/solargraph/language_server/request.rb +24 -0
  99. data/lib/solargraph/language_server/symbol_kinds.rb +36 -0
  100. data/lib/solargraph/language_server/transport.rb +13 -0
  101. data/lib/solargraph/language_server/transport/adapter.rb +56 -0
  102. data/lib/solargraph/language_server/transport/data_reader.rb +72 -0
  103. data/lib/solargraph/language_server/uri_helpers.rb +49 -0
  104. data/lib/solargraph/library.rb +426 -0
  105. data/lib/solargraph/location.rb +37 -0
  106. data/lib/solargraph/logging.rb +27 -0
  107. data/lib/solargraph/page.rb +83 -0
  108. data/lib/solargraph/parser.rb +26 -0
  109. data/lib/solargraph/parser/comment_ripper.rb +52 -0
  110. data/lib/solargraph/parser/legacy.rb +12 -0
  111. data/lib/solargraph/parser/legacy/class_methods.rb +109 -0
  112. data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
  113. data/lib/solargraph/parser/legacy/node_chainer.rb +118 -0
  114. data/lib/solargraph/parser/legacy/node_methods.rb +311 -0
  115. data/lib/solargraph/parser/legacy/node_processors.rb +54 -0
  116. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -0
  117. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -0
  118. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -0
  119. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +22 -0
  120. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +25 -0
  121. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -0
  122. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -0
  123. data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -0
  124. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -0
  125. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -0
  126. data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -0
  127. data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -0
  128. data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -0
  129. data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -0
  130. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +21 -0
  131. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +257 -0
  132. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -0
  133. data/lib/solargraph/parser/node_methods.rb +43 -0
  134. data/lib/solargraph/parser/node_processor.rb +43 -0
  135. data/lib/solargraph/parser/node_processor/base.rb +80 -0
  136. data/lib/solargraph/parser/region.rb +66 -0
  137. data/lib/solargraph/parser/rubyvm.rb +40 -0
  138. data/lib/solargraph/parser/rubyvm/class_methods.rb +150 -0
  139. data/lib/solargraph/parser/rubyvm/node_chainer.rb +135 -0
  140. data/lib/solargraph/parser/rubyvm/node_methods.rb +301 -0
  141. data/lib/solargraph/parser/rubyvm/node_processors.rb +62 -0
  142. data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
  143. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +86 -0
  144. data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
  145. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +22 -0
  146. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +22 -0
  147. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
  148. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +64 -0
  149. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +57 -0
  150. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -0
  151. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -0
  152. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -0
  153. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -0
  154. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -0
  155. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -0
  156. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +26 -0
  157. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -0
  158. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -0
  159. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +21 -0
  160. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
  161. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +277 -0
  162. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
  163. data/lib/solargraph/parser/snippet.rb +13 -0
  164. data/lib/solargraph/pin.rb +36 -0
  165. data/lib/solargraph/pin/base.rb +296 -0
  166. data/lib/solargraph/pin/base_variable.rb +84 -0
  167. data/lib/solargraph/pin/block.rb +62 -0
  168. data/lib/solargraph/pin/class_variable.rb +8 -0
  169. data/lib/solargraph/pin/closure.rb +37 -0
  170. data/lib/solargraph/pin/common.rb +70 -0
  171. data/lib/solargraph/pin/constant.rb +43 -0
  172. data/lib/solargraph/pin/conversions.rb +96 -0
  173. data/lib/solargraph/pin/documenting.rb +105 -0
  174. data/lib/solargraph/pin/duck_method.rb +16 -0
  175. data/lib/solargraph/pin/global_variable.rb +8 -0
  176. data/lib/solargraph/pin/instance_variable.rb +30 -0
  177. data/lib/solargraph/pin/keyword.rb +15 -0
  178. data/lib/solargraph/pin/keyword_param.rb +8 -0
  179. data/lib/solargraph/pin/local_variable.rb +21 -0
  180. data/lib/solargraph/pin/localized.rb +43 -0
  181. data/lib/solargraph/pin/method.rb +245 -0
  182. data/lib/solargraph/pin/method_alias.rb +31 -0
  183. data/lib/solargraph/pin/namespace.rb +85 -0
  184. data/lib/solargraph/pin/parameter.rb +206 -0
  185. data/lib/solargraph/pin/proxy_type.rb +29 -0
  186. data/lib/solargraph/pin/reference.rb +14 -0
  187. data/lib/solargraph/pin/reference/extend.rb +10 -0
  188. data/lib/solargraph/pin/reference/include.rb +10 -0
  189. data/lib/solargraph/pin/reference/override.rb +29 -0
  190. data/lib/solargraph/pin/reference/prepend.rb +10 -0
  191. data/lib/solargraph/pin/reference/require.rb +14 -0
  192. data/lib/solargraph/pin/reference/superclass.rb +10 -0
  193. data/lib/solargraph/pin/singleton.rb +11 -0
  194. data/lib/solargraph/pin/symbol.rb +47 -0
  195. data/lib/solargraph/position.rb +100 -0
  196. data/lib/solargraph/range.rb +95 -0
  197. data/lib/solargraph/server_methods.rb +16 -0
  198. data/lib/solargraph/shell.rb +222 -0
  199. data/lib/solargraph/source.rb +537 -0
  200. data/lib/solargraph/source/chain.rb +154 -0
  201. data/lib/solargraph/source/chain/block_variable.rb +13 -0
  202. data/lib/solargraph/source/chain/call.rb +203 -0
  203. data/lib/solargraph/source/chain/class_variable.rb +13 -0
  204. data/lib/solargraph/source/chain/constant.rb +75 -0
  205. data/lib/solargraph/source/chain/global_variable.rb +13 -0
  206. data/lib/solargraph/source/chain/head.rb +35 -0
  207. data/lib/solargraph/source/chain/instance_variable.rb +13 -0
  208. data/lib/solargraph/source/chain/link.rb +67 -0
  209. data/lib/solargraph/source/chain/literal.rb +23 -0
  210. data/lib/solargraph/source/chain/or.rb +23 -0
  211. data/lib/solargraph/source/chain/variable.rb +13 -0
  212. data/lib/solargraph/source/chain/z_super.rb +30 -0
  213. data/lib/solargraph/source/change.rb +79 -0
  214. data/lib/solargraph/source/cursor.rb +164 -0
  215. data/lib/solargraph/source/encoding_fixes.rb +23 -0
  216. data/lib/solargraph/source/source_chainer.rb +190 -0
  217. data/lib/solargraph/source/updater.rb +54 -0
  218. data/lib/solargraph/source_map.rb +188 -0
  219. data/lib/solargraph/source_map/clip.rb +224 -0
  220. data/lib/solargraph/source_map/completion.rb +23 -0
  221. data/lib/solargraph/source_map/mapper.rb +215 -0
  222. data/lib/solargraph/type_checker.rb +503 -0
  223. data/lib/solargraph/type_checker/checks.rb +99 -0
  224. data/lib/solargraph/type_checker/param_def.rb +35 -0
  225. data/lib/solargraph/type_checker/problem.rb +32 -0
  226. data/lib/solargraph/type_checker/rules.rb +57 -0
  227. data/lib/solargraph/version.rb +5 -0
  228. data/lib/solargraph/views/_method.erb +62 -0
  229. data/lib/solargraph/views/_name_type_tag.erb +10 -0
  230. data/lib/solargraph/views/_namespace.erb +24 -0
  231. data/lib/solargraph/views/document.erb +23 -0
  232. data/lib/solargraph/views/environment.erb +58 -0
  233. data/lib/solargraph/views/layout.erb +44 -0
  234. data/lib/solargraph/views/search.erb +11 -0
  235. data/lib/solargraph/workspace.rb +209 -0
  236. data/lib/solargraph/workspace/config.rb +230 -0
  237. data/lib/solargraph/yard_map.rb +435 -0
  238. data/lib/solargraph/yard_map/cache.rb +19 -0
  239. data/lib/solargraph/yard_map/core_docs.rb +170 -0
  240. data/lib/solargraph/yard_map/core_fills.rb +185 -0
  241. data/lib/solargraph/yard_map/core_gen.rb +76 -0
  242. data/lib/solargraph/yard_map/helpers.rb +16 -0
  243. data/lib/solargraph/yard_map/mapper.rb +77 -0
  244. data/lib/solargraph/yard_map/mapper/to_constant.rb +25 -0
  245. data/lib/solargraph/yard_map/mapper/to_method.rb +78 -0
  246. data/lib/solargraph/yard_map/mapper/to_namespace.rb +27 -0
  247. data/lib/solargraph/yard_map/rdoc_to_yard.rb +140 -0
  248. data/lib/solargraph/yard_map/stdlib_fills.rb +43 -0
  249. data/lib/solargraph/yard_map/to_method.rb +79 -0
  250. data/lib/yard-solargraph.rb +30 -0
  251. data/yardoc/2.2.2.tar.gz +0 -0
  252. metadata +564 -0
@@ -0,0 +1,224 @@
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
+ end
15
+
16
+ # @return [Array<Pin::Base>]
17
+ def define
18
+ return [] if cursor.comment? || cursor.chain.literal?
19
+ result = cursor.chain.define(api_map, block, locals)
20
+ result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
21
+ result
22
+ end
23
+
24
+ # @return [Completion]
25
+ def complete
26
+ return package_completions([]) if !source_map.source.parsed? || cursor.string?
27
+ return package_completions(api_map.get_symbols) if cursor.chain.literal? && cursor.chain.links.last.word == '<Symbol>'
28
+ return Completion.new([], cursor.range) if cursor.chain.literal?
29
+ if cursor.comment?
30
+ tag_complete
31
+ else
32
+ code_complete
33
+ end
34
+ end
35
+
36
+ # @return [Array<Pin::Base>]
37
+ def signify
38
+ return [] unless cursor.argument?
39
+ chain = Parser.chain(cursor.recipient_node, cursor.filename)
40
+ chain.define(api_map, context_pin, locals).select { |pin| pin.is_a?(Pin::Method) }
41
+ end
42
+
43
+ # @return [ComplexType]
44
+ def infer
45
+ result = cursor.chain.infer(api_map, block, locals)
46
+ return result unless result.tag == 'self'
47
+ ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).namespace)
48
+ end
49
+
50
+ # Get an array of all the locals that are visible from the cursors's
51
+ # position. Locals can be local variables, method parameters, or block
52
+ # parameters. The array starts with the nearest local pin.
53
+ #
54
+ # @return [Array<Solargraph::Pin::Base>]
55
+ def locals
56
+ loc_pos = context_pin.location.range.contain?(cursor.position) ? cursor.position : context_pin.location.range.ending
57
+ adj_pos = Position.new(loc_pos.line, (loc_pos.column.zero? ? 0 : loc_pos.column - 1))
58
+ @locals ||= source_map.locals.select { |pin|
59
+ pin.visible_from?(block, adj_pos)
60
+ }.reverse
61
+ end
62
+
63
+ def gates
64
+ block.gates
65
+ end
66
+
67
+ def in_block?
68
+ return @in_block unless @in_block.nil?
69
+ @in_block = begin
70
+ tree = cursor.source.tree_at(cursor.position.line, cursor.position.column)
71
+ Parser.is_ast_node?(tree[1]) && [:block, :ITER].include?(tree[1].type)
72
+ end
73
+ end
74
+
75
+ # @param phrase [String]
76
+ # @return [Array<Solargraph::Pin::Base>]
77
+ def translate phrase
78
+ chain = Parser.chain(Parser.parse(phrase))
79
+ chain.define(api_map, block, locals)
80
+ end
81
+
82
+ private
83
+
84
+ # @return [ApiMap]
85
+ attr_reader :api_map
86
+
87
+ # @return [Source::Cursor]
88
+ attr_reader :cursor
89
+
90
+ # @return [SourceMap]
91
+ def source_map
92
+ @source_map ||= api_map.source_map(cursor.filename)
93
+ end
94
+
95
+ # @return [Solargraph::Pin::Base]
96
+ def block
97
+ @block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
98
+ end
99
+
100
+ # The context at the current position.
101
+ #
102
+ # @return [Pin::Base]
103
+ def context_pin
104
+ @context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
105
+ end
106
+
107
+ # @return [Array<Pin::Base>]
108
+ def yielded_self_pins
109
+ return [] unless block.is_a?(Pin::Block) && block.receiver
110
+ chain = Parser.chain(block.receiver, source_map.source.filename)
111
+ receiver_pin = chain.define(api_map, context_pin, locals).first
112
+ return [] if receiver_pin.nil?
113
+ result = []
114
+ ys = receiver_pin.docstring.tag(:yieldpublic)
115
+ unless ys.nil? || ys.types.empty?
116
+ ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
117
+ result.concat api_map.get_complex_type_methods(ysct, '', false)
118
+ end
119
+ result
120
+ end
121
+
122
+ # @return [Array<Pin::KeywordParam]
123
+ def complete_keyword_parameters
124
+ return [] unless cursor.argument? && cursor.chain.links.one? && cursor.word =~ /^[a-z0-9_]*:?$/
125
+ pins = signify
126
+ result = []
127
+ done = []
128
+ pins.each do |pin|
129
+ pin.parameters.each do |param|
130
+ next if done.include?(param.name)
131
+ done.push param.name
132
+ next unless param.keyword?
133
+ result.push Pin::KeywordParam.new(pin.location, "#{param.name}:")
134
+ end
135
+ if !pin.parameters.empty? && pin.parameters.last.kwrestarg?
136
+ pin.docstring.tags(:param).each do |tag|
137
+ next if done.include?(tag.name)
138
+ done.push tag.name
139
+ result.push Pin::KeywordParam.new(pin.location, "#{tag.name}:")
140
+ end
141
+ end
142
+ end
143
+ result
144
+ end
145
+
146
+ # @param result [Array<Pin::Base>]
147
+ # @return [Completion]
148
+ def package_completions result
149
+ frag_start = cursor.start_of_word.to_s.downcase
150
+ filtered = result.uniq(&:name).select { |s|
151
+ s.name.downcase.start_with?(frag_start) &&
152
+ (!s.is_a?(Pin::Method) || s.name.match(/^[a-z0-9_]+(\!|\?|=)?$/i))
153
+ }
154
+ Completion.new(filtered, cursor.range)
155
+ end
156
+
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
+ def code_complete
176
+ result = []
177
+ result.concat complete_keyword_parameters
178
+ if cursor.chain.constant? || cursor.start_of_constant?
179
+ full = cursor.chain.links.first.word
180
+ type = if cursor.chain.undefined?
181
+ cursor.chain.base.infer(api_map, context_pin, locals)
182
+ else
183
+ if full.include?('::') && cursor.chain.links.length == 1
184
+ ComplexType.try_parse(full.split('::')[0..-2].join('::'))
185
+ elsif cursor.chain.links.length > 1
186
+ ComplexType.try_parse(full)
187
+ else
188
+ ComplexType::UNDEFINED
189
+ end
190
+ end
191
+ if type.undefined?
192
+ if full.include?('::')
193
+ result.concat api_map.get_constants(full, *gates)
194
+ else
195
+ result.concat api_map.get_constants('', cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
196
+ end
197
+ else
198
+ result.concat api_map.get_constants(type.namespace, cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
199
+ end
200
+ else
201
+ type = cursor.chain.base.infer(api_map, block, locals)
202
+ result.concat api_map.get_complex_type_methods(type, block.binder.namespace, cursor.chain.links.length == 1)
203
+ if cursor.chain.links.length == 1
204
+ if cursor.word.start_with?('@@')
205
+ return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
206
+ elsif cursor.word.start_with?('@')
207
+ return package_completions(api_map.get_instance_variable_pins(block.binder.namespace, block.binder.scope))
208
+ elsif cursor.word.start_with?('$')
209
+ return package_completions(api_map.get_global_variable_pins)
210
+ end
211
+ result.concat locals
212
+ result.concat api_map.get_constants(context_pin.context.namespace, *gates)
213
+ result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
214
+ result.concat api_map.get_methods('Kernel')
215
+ # result.concat ApiMap.keywords
216
+ result.concat api_map.keyword_pins
217
+ result.concat yielded_self_pins
218
+ end
219
+ end
220
+ package_completions(result)
221
+ end
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class SourceMap
5
+ # The result of a completion request containing the pins that describe
6
+ # completion options and the range to be replaced.
7
+ #
8
+ class Completion
9
+ # @return [Array<Solargraph::Pin::Base>]
10
+ attr_reader :pins
11
+
12
+ # @return [Solargraph::Range]
13
+ attr_reader :range
14
+
15
+ # @param pins [Array<Solargraph::Pin::Base>]
16
+ # @param range [Solargraph::Range]
17
+ def initialize pins, range
18
+ @pins = pins
19
+ @range = range
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,215 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class SourceMap
5
+ # The Mapper generates pins and other data for SourceMaps.
6
+ #
7
+ # This class is used internally by the SourceMap class. Users should not
8
+ # normally need to call it directly.
9
+ #
10
+ class Mapper
11
+ # include Source::NodeMethods
12
+
13
+ private_class_method :new
14
+
15
+ MACRO_REGEXP = /(@\!method|@\!attribute|@\!domain|@\!macro|@\!parse|@\!override)/.freeze
16
+
17
+ # Generate the data.
18
+ #
19
+ # @param source [Source]
20
+ # @return [Array]
21
+ def map source
22
+ @source = source
23
+ @filename = source.filename
24
+ @code = source.code
25
+ @comments = source.comments
26
+ @pins, @locals = Parser.map(source)
27
+ process_comment_directives
28
+ [@pins, @locals]
29
+ # rescue Exception => e
30
+ # Solargraph.logger.warn "Error mapping #{source.filename}: [#{e.class}] #{e.message}"
31
+ # Solargraph.logger.warn e.backtrace.join("\n")
32
+ # [[], []]
33
+ end
34
+
35
+ # @param filename [String]
36
+ # @param code [String]
37
+ # @return [Array]
38
+ def unmap filename, code
39
+ s = Position.new(0, 0)
40
+ e = Position.from_offset(code, code.length)
41
+ location = Location.new(filename, Range.new(s, e))
42
+ [[Pin::Namespace.new(location: location, name: '')], []]
43
+ end
44
+
45
+ class << self
46
+ # @param source [Source]
47
+ # @return [Array]
48
+ def map source
49
+ return new.unmap(source.filename, source.code) unless source.parsed?
50
+ new.map source
51
+ end
52
+ end
53
+
54
+ # @return [Array<Solargraph::Pin::Base>]
55
+ def pins
56
+ @pins ||= []
57
+ end
58
+
59
+ def closure_at(position)
60
+ @pins.select{|pin| pin.is_a?(Pin::Closure) and pin.location.range.contain?(position)}.last
61
+ end
62
+
63
+ def process_comment source_position, comment_position, comment
64
+ return unless comment =~ MACRO_REGEXP
65
+ cmnt = remove_inline_comment_hashes(comment)
66
+ parse = Solargraph::Source.parse_docstring(cmnt)
67
+ last_line = 0
68
+ # @param d [YARD::Tags::Directive]
69
+ parse.directives.each do |d|
70
+ line_num = find_directive_line_number(cmnt, d.tag.tag_name, last_line)
71
+ pos = Solargraph::Position.new(comment_position.line + line_num - 1, comment_position.column)
72
+ process_directive(source_position, pos, d)
73
+ last_line = line_num + 1
74
+ # @todo The below call assumes the topmost comment line. The above
75
+ # process occasionally emits incorrect comment positions due to
76
+ # blank lines in comment blocks, but at least it processes all the
77
+ # directives.
78
+ # process_directive(source_position, comment_position, d)
79
+ end
80
+ end
81
+
82
+ # @param comment [String]
83
+ # @return [Integer]
84
+ def find_directive_line_number comment, tag, start
85
+ # Avoid overruning the index
86
+ return start unless start < comment.lines.length
87
+ num = comment.lines[start..-1].find_index do |line|
88
+ # Legacy method directives might be `@method` instead of `@!method`
89
+ # @todo Legacy syntax should probably emit a warning
90
+ line.include?("@!#{tag}") || (tag == 'method' && line.include?("@#{tag}"))
91
+ end
92
+ num.to_i + start
93
+ end
94
+
95
+ # @param source_position [Position]
96
+ # @param comment_position [Position]
97
+ # @param directive [YARD::Tags::Directive]
98
+ # @return [void]
99
+ def process_directive source_position, comment_position, directive
100
+ docstring = Solargraph::Source.parse_docstring(directive.tag.text).to_docstring
101
+ location = Location.new(@filename, Range.new(comment_position, comment_position))
102
+ case directive.tag.tag_name
103
+ when 'method'
104
+ namespace = closure_at(source_position) || @pins.first
105
+ if namespace.location.range.start.line < comment_position.line
106
+ namespace = closure_at(comment_position)
107
+ end
108
+ begin
109
+ src = Solargraph::Source.load_string("def #{directive.tag.name};end", @source.filename)
110
+ region = Parser::Region.new(source: src, closure: namespace)
111
+ gen_pin = Parser.process_node(src.node, region).first.last
112
+ return if gen_pin.nil?
113
+ # Move the location to the end of the line so it gets recognized
114
+ # as originating from a comment
115
+ shifted = Solargraph::Position.new(comment_position.line, @code.lines[comment_position.line].to_s.chomp.length)
116
+ # @todo: Smelly instance variable access
117
+ gen_pin.instance_variable_set(:@comments, docstring.all.to_s)
118
+ gen_pin.instance_variable_set(:@location, Solargraph::Location.new(@filename, Range.new(shifted, shifted)))
119
+ gen_pin.instance_variable_set(:@explicit, false)
120
+ @pins.push gen_pin
121
+ rescue Parser::SyntaxError => e
122
+ # @todo Handle error in directive
123
+ end
124
+ when 'attribute'
125
+ return if directive.tag.name.nil?
126
+ namespace = closure_at(source_position)
127
+ t = (directive.tag.types.nil? || directive.tag.types.empty?) ? nil : directive.tag.types.flatten.join('')
128
+ if t.nil? || t.include?('r')
129
+ pins.push Solargraph::Pin::Method.new(
130
+ location: location,
131
+ closure: namespace,
132
+ name: directive.tag.name,
133
+ comments: docstring.all.to_s,
134
+ scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
135
+ visibility: :public,
136
+ explicit: false,
137
+ attribute: true
138
+ )
139
+ end
140
+ if t.nil? || t.include?('w')
141
+ pins.push Solargraph::Pin::Method.new(
142
+ location: location,
143
+ closure: namespace,
144
+ name: "#{directive.tag.name}=",
145
+ comments: docstring.all.to_s,
146
+ scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
147
+ visibility: :public,
148
+ attribute: true
149
+ )
150
+ pins.last.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
151
+ if pins.last.return_type.defined?
152
+ pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
153
+ end
154
+ end
155
+ when 'parse'
156
+ begin
157
+ ns = closure_at(source_position)
158
+ src = Solargraph::Source.load_string(directive.tag.text, @source.filename)
159
+ region = Parser::Region.new(source: src, closure: ns)
160
+ # @todo These pins may need to be marked not explicit
161
+ index = @pins.length
162
+ loff = if @code.lines[comment_position.line].strip.end_with?('@!parse')
163
+ comment_position.line + 1
164
+ else
165
+ comment_position.line
166
+ end
167
+ Parser.process_node(src.node, region, @pins)
168
+ @pins[index..-1].each do |p|
169
+ # @todo Smelly instance variable access
170
+ p.location.range.start.instance_variable_set(:@line, p.location.range.start.line + loff)
171
+ p.location.range.ending.instance_variable_set(:@line, p.location.range.ending.line + loff)
172
+ end
173
+ rescue Parser::SyntaxError => e
174
+ # @todo Handle parser errors in !parse directives
175
+ end
176
+ when 'domain'
177
+ namespace = closure_at(source_position)
178
+ namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
179
+ when 'override'
180
+ pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags)
181
+ end
182
+ end
183
+
184
+ def remove_inline_comment_hashes comment
185
+ ctxt = ''
186
+ num = nil
187
+ started = false
188
+ comment.lines.each { |l|
189
+ # Trim the comment and minimum leading whitespace
190
+ p = l.gsub(/^#/, '')
191
+ if num.nil? && !p.strip.empty?
192
+ num = p.index(/[^ ]/)
193
+ started = true
194
+ elsif started && !p.strip.empty?
195
+ cur = p.index(/[^ ]/)
196
+ num = cur if cur < num
197
+ end
198
+ ctxt += "#{p[num..-1]}" if started
199
+ }
200
+ ctxt
201
+ end
202
+
203
+ # @return [void]
204
+ def process_comment_directives
205
+ return unless @code =~ MACRO_REGEXP
206
+ code_lines = @code.lines
207
+ @source.associated_comments.each do |line, comments|
208
+ src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
209
+ com_pos = Position.new(line + 1 - comments.lines.length, 0)
210
+ process_comment(src_pos, com_pos, comments)
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end