solargraph 0.39.7

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/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +28 -0
  5. data/.yardopts +2 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE +21 -0
  8. data/README.md +104 -0
  9. data/Rakefile +14 -0
  10. data/SPONSORS.md +9 -0
  11. data/bin/solargraph +5 -0
  12. data/lib/.rubocop.yml +21 -0
  13. data/lib/solargraph.rb +66 -0
  14. data/lib/solargraph/api_map.rb +745 -0
  15. data/lib/solargraph/api_map/bundler_methods.rb +27 -0
  16. data/lib/solargraph/api_map/cache.rb +66 -0
  17. data/lib/solargraph/api_map/source_to_yard.rb +81 -0
  18. data/lib/solargraph/api_map/store.rb +267 -0
  19. data/lib/solargraph/bundle.rb +26 -0
  20. data/lib/solargraph/complex_type.rb +213 -0
  21. data/lib/solargraph/complex_type/type_methods.rb +127 -0
  22. data/lib/solargraph/complex_type/unique_type.rb +75 -0
  23. data/lib/solargraph/convention.rb +38 -0
  24. data/lib/solargraph/convention/base.rb +25 -0
  25. data/lib/solargraph/convention/gemfile.rb +18 -0
  26. data/lib/solargraph/convention/gemspec.rb +25 -0
  27. data/lib/solargraph/convention/rspec.rb +24 -0
  28. data/lib/solargraph/converters/dd.rb +12 -0
  29. data/lib/solargraph/converters/dl.rb +12 -0
  30. data/lib/solargraph/converters/dt.rb +12 -0
  31. data/lib/solargraph/converters/misc.rb +1 -0
  32. data/lib/solargraph/core_fills.rb +159 -0
  33. data/lib/solargraph/diagnostics.rb +55 -0
  34. data/lib/solargraph/diagnostics/base.rb +29 -0
  35. data/lib/solargraph/diagnostics/require_not_found.rb +37 -0
  36. data/lib/solargraph/diagnostics/rubocop.rb +90 -0
  37. data/lib/solargraph/diagnostics/rubocop_helpers.rb +64 -0
  38. data/lib/solargraph/diagnostics/severities.rb +15 -0
  39. data/lib/solargraph/diagnostics/type_check.rb +54 -0
  40. data/lib/solargraph/diagnostics/update_errors.rb +41 -0
  41. data/lib/solargraph/documentor.rb +76 -0
  42. data/lib/solargraph/environ.rb +40 -0
  43. data/lib/solargraph/language_server.rb +19 -0
  44. data/lib/solargraph/language_server/completion_item_kinds.rb +35 -0
  45. data/lib/solargraph/language_server/error_codes.rb +20 -0
  46. data/lib/solargraph/language_server/host.rb +741 -0
  47. data/lib/solargraph/language_server/host/cataloger.rb +56 -0
  48. data/lib/solargraph/language_server/host/diagnoser.rb +81 -0
  49. data/lib/solargraph/language_server/host/dispatch.rb +112 -0
  50. data/lib/solargraph/language_server/host/sources.rb +156 -0
  51. data/lib/solargraph/language_server/message.rb +92 -0
  52. data/lib/solargraph/language_server/message/base.rb +85 -0
  53. data/lib/solargraph/language_server/message/cancel_request.rb +13 -0
  54. data/lib/solargraph/language_server/message/client.rb +11 -0
  55. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -0
  56. data/lib/solargraph/language_server/message/completion_item.rb +11 -0
  57. data/lib/solargraph/language_server/message/completion_item/resolve.rb +57 -0
  58. data/lib/solargraph/language_server/message/exit_notification.rb +13 -0
  59. data/lib/solargraph/language_server/message/extended.rb +21 -0
  60. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +95 -0
  61. data/lib/solargraph/language_server/message/extended/document.rb +20 -0
  62. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -0
  63. data/lib/solargraph/language_server/message/extended/download_core.rb +23 -0
  64. data/lib/solargraph/language_server/message/extended/environment.rb +25 -0
  65. data/lib/solargraph/language_server/message/extended/search.rb +20 -0
  66. data/lib/solargraph/language_server/message/initialize.rb +153 -0
  67. data/lib/solargraph/language_server/message/initialized.rb +26 -0
  68. data/lib/solargraph/language_server/message/method_not_found.rb +16 -0
  69. data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -0
  70. data/lib/solargraph/language_server/message/shutdown.rb +13 -0
  71. data/lib/solargraph/language_server/message/text_document.rb +28 -0
  72. data/lib/solargraph/language_server/message/text_document/base.rb +19 -0
  73. data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -0
  74. data/lib/solargraph/language_server/message/text_document/completion.rb +57 -0
  75. data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
  76. data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
  77. data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -0
  78. data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -0
  79. data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -0
  80. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -0
  81. data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -0
  82. data/lib/solargraph/language_server/message/text_document/formatting.rb +78 -0
  83. data/lib/solargraph/language_server/message/text_document/hover.rb +44 -0
  84. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -0
  85. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -0
  86. data/lib/solargraph/language_server/message/text_document/references.rb +16 -0
  87. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -0
  88. data/lib/solargraph/language_server/message/text_document/signature_help.rb +29 -0
  89. data/lib/solargraph/language_server/message/workspace.rb +14 -0
  90. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -0
  91. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +33 -0
  92. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -0
  93. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -0
  94. data/lib/solargraph/language_server/message_types.rb +14 -0
  95. data/lib/solargraph/language_server/request.rb +24 -0
  96. data/lib/solargraph/language_server/symbol_kinds.rb +36 -0
  97. data/lib/solargraph/language_server/transport.rb +13 -0
  98. data/lib/solargraph/language_server/transport/adapter.rb +56 -0
  99. data/lib/solargraph/language_server/transport/data_reader.rb +72 -0
  100. data/lib/solargraph/language_server/uri_helpers.rb +49 -0
  101. data/lib/solargraph/library.rb +414 -0
  102. data/lib/solargraph/location.rb +37 -0
  103. data/lib/solargraph/logging.rb +27 -0
  104. data/lib/solargraph/page.rb +83 -0
  105. data/lib/solargraph/parser.rb +26 -0
  106. data/lib/solargraph/parser/comment_ripper.rb +52 -0
  107. data/lib/solargraph/parser/legacy.rb +12 -0
  108. data/lib/solargraph/parser/legacy/class_methods.rb +109 -0
  109. data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
  110. data/lib/solargraph/parser/legacy/node_chainer.rb +118 -0
  111. data/lib/solargraph/parser/legacy/node_methods.rb +300 -0
  112. data/lib/solargraph/parser/legacy/node_processors.rb +54 -0
  113. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -0
  114. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -0
  115. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -0
  116. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +22 -0
  117. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +25 -0
  118. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -0
  119. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -0
  120. data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -0
  121. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -0
  122. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -0
  123. data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -0
  124. data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -0
  125. data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -0
  126. data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -0
  127. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +21 -0
  128. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +234 -0
  129. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -0
  130. data/lib/solargraph/parser/node_methods.rb +43 -0
  131. data/lib/solargraph/parser/node_processor.rb +43 -0
  132. data/lib/solargraph/parser/node_processor/base.rb +77 -0
  133. data/lib/solargraph/parser/region.rb +66 -0
  134. data/lib/solargraph/parser/rubyvm.rb +40 -0
  135. data/lib/solargraph/parser/rubyvm/class_methods.rb +150 -0
  136. data/lib/solargraph/parser/rubyvm/node_chainer.rb +135 -0
  137. data/lib/solargraph/parser/rubyvm/node_methods.rb +284 -0
  138. data/lib/solargraph/parser/rubyvm/node_processors.rb +61 -0
  139. data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
  140. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +62 -0
  141. data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
  142. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +22 -0
  143. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +22 -0
  144. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
  145. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +64 -0
  146. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +57 -0
  147. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -0
  148. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -0
  149. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -0
  150. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -0
  151. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -0
  152. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -0
  153. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +31 -0
  154. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -0
  155. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -0
  156. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +21 -0
  157. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
  158. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +255 -0
  159. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
  160. data/lib/solargraph/parser/snippet.rb +13 -0
  161. data/lib/solargraph/pin.rb +39 -0
  162. data/lib/solargraph/pin/attribute.rb +49 -0
  163. data/lib/solargraph/pin/base.rb +296 -0
  164. data/lib/solargraph/pin/base_method.rb +141 -0
  165. data/lib/solargraph/pin/base_variable.rb +84 -0
  166. data/lib/solargraph/pin/block.rb +48 -0
  167. data/lib/solargraph/pin/class_variable.rb +8 -0
  168. data/lib/solargraph/pin/closure.rb +37 -0
  169. data/lib/solargraph/pin/common.rb +70 -0
  170. data/lib/solargraph/pin/constant.rb +43 -0
  171. data/lib/solargraph/pin/conversions.rb +97 -0
  172. data/lib/solargraph/pin/documenting.rb +110 -0
  173. data/lib/solargraph/pin/duck_method.rb +16 -0
  174. data/lib/solargraph/pin/global_variable.rb +8 -0
  175. data/lib/solargraph/pin/instance_variable.rb +30 -0
  176. data/lib/solargraph/pin/keyword.rb +15 -0
  177. data/lib/solargraph/pin/keyword_param.rb +8 -0
  178. data/lib/solargraph/pin/local_variable.rb +21 -0
  179. data/lib/solargraph/pin/localized.rb +43 -0
  180. data/lib/solargraph/pin/method.rb +111 -0
  181. data/lib/solargraph/pin/method_alias.rb +31 -0
  182. data/lib/solargraph/pin/namespace.rb +85 -0
  183. data/lib/solargraph/pin/parameter.rb +206 -0
  184. data/lib/solargraph/pin/proxy_type.rb +29 -0
  185. data/lib/solargraph/pin/reference.rb +14 -0
  186. data/lib/solargraph/pin/reference/extend.rb +10 -0
  187. data/lib/solargraph/pin/reference/include.rb +10 -0
  188. data/lib/solargraph/pin/reference/override.rb +29 -0
  189. data/lib/solargraph/pin/reference/prepend.rb +10 -0
  190. data/lib/solargraph/pin/reference/require.rb +14 -0
  191. data/lib/solargraph/pin/reference/superclass.rb +10 -0
  192. data/lib/solargraph/pin/singleton.rb +11 -0
  193. data/lib/solargraph/pin/symbol.rb +47 -0
  194. data/lib/solargraph/pin/yard_pin.rb +12 -0
  195. data/lib/solargraph/pin/yard_pin/constant.rb +25 -0
  196. data/lib/solargraph/pin/yard_pin/method.rb +65 -0
  197. data/lib/solargraph/pin/yard_pin/namespace.rb +27 -0
  198. data/lib/solargraph/pin/yard_pin/yard_mixin.rb +26 -0
  199. data/lib/solargraph/position.rb +112 -0
  200. data/lib/solargraph/range.rb +95 -0
  201. data/lib/solargraph/server_methods.rb +16 -0
  202. data/lib/solargraph/shell.rb +221 -0
  203. data/lib/solargraph/source.rb +533 -0
  204. data/lib/solargraph/source/chain.rb +172 -0
  205. data/lib/solargraph/source/chain/block_variable.rb +13 -0
  206. data/lib/solargraph/source/chain/call.rb +203 -0
  207. data/lib/solargraph/source/chain/class_variable.rb +13 -0
  208. data/lib/solargraph/source/chain/constant.rb +75 -0
  209. data/lib/solargraph/source/chain/global_variable.rb +13 -0
  210. data/lib/solargraph/source/chain/head.rb +35 -0
  211. data/lib/solargraph/source/chain/instance_variable.rb +13 -0
  212. data/lib/solargraph/source/chain/link.rb +67 -0
  213. data/lib/solargraph/source/chain/literal.rb +23 -0
  214. data/lib/solargraph/source/chain/or.rb +23 -0
  215. data/lib/solargraph/source/chain/variable.rb +13 -0
  216. data/lib/solargraph/source/chain/z_super.rb +184 -0
  217. data/lib/solargraph/source/change.rb +79 -0
  218. data/lib/solargraph/source/cursor.rb +164 -0
  219. data/lib/solargraph/source/encoding_fixes.rb +23 -0
  220. data/lib/solargraph/source/source_chainer.rb +189 -0
  221. data/lib/solargraph/source/updater.rb +54 -0
  222. data/lib/solargraph/source_map.rb +170 -0
  223. data/lib/solargraph/source_map/clip.rb +190 -0
  224. data/lib/solargraph/source_map/completion.rb +23 -0
  225. data/lib/solargraph/source_map/mapper.rb +199 -0
  226. data/lib/solargraph/stdlib_fills.rb +32 -0
  227. data/lib/solargraph/type_checker.rb +498 -0
  228. data/lib/solargraph/type_checker/checks.rb +95 -0
  229. data/lib/solargraph/type_checker/param_def.rb +35 -0
  230. data/lib/solargraph/type_checker/problem.rb +32 -0
  231. data/lib/solargraph/type_checker/rules.rb +53 -0
  232. data/lib/solargraph/version.rb +5 -0
  233. data/lib/solargraph/views/_method.erb +62 -0
  234. data/lib/solargraph/views/_name_type_tag.erb +10 -0
  235. data/lib/solargraph/views/_namespace.erb +24 -0
  236. data/lib/solargraph/views/document.erb +23 -0
  237. data/lib/solargraph/views/environment.erb +58 -0
  238. data/lib/solargraph/views/layout.erb +44 -0
  239. data/lib/solargraph/views/search.erb +11 -0
  240. data/lib/solargraph/workspace.rb +209 -0
  241. data/lib/solargraph/workspace/config.rb +215 -0
  242. data/lib/solargraph/yard_map.rb +420 -0
  243. data/lib/solargraph/yard_map/cache.rb +19 -0
  244. data/lib/solargraph/yard_map/core_docs.rb +170 -0
  245. data/lib/solargraph/yard_map/core_gen.rb +76 -0
  246. data/lib/solargraph/yard_map/mapper.rb +71 -0
  247. data/lib/solargraph/yard_map/rdoc_to_yard.rb +136 -0
  248. data/lib/yard-solargraph.rb +30 -0
  249. data/solargraph.gemspec +41 -0
  250. data/travis-bundler.rb +11 -0
  251. data/yardoc/2.2.2.tar.gz +0 -0
  252. metadata +575 -0
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module Rubyvm
6
+ module NodeProcessors
7
+ class SclassNode < Parser::NodeProcessor::Base
8
+ def process
9
+ # @todo Temporarily skipping remote metaclasses
10
+ return unless node.children[0].is_a?(RubyVM::AbstractSyntaxTree::Node) && node.children[0].type == :SELF
11
+ pins.push Solargraph::Pin::Singleton.new(
12
+ location: get_node_location(node),
13
+ closure: region.closure
14
+ )
15
+ process_children region.update(visibility: :public, scope: :class, closure: pins.last)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module Rubyvm
6
+ module NodeProcessors
7
+ class ScopeNode < Parser::NodeProcessor::Base
8
+ def process
9
+ process_children region.update(lvars: node.children[0])
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,255 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module Rubyvm
6
+ module NodeProcessors
7
+ class SendNode < Parser::NodeProcessor::Base
8
+ include Rubyvm::NodeMethods
9
+
10
+ def process
11
+ if [:private, :public, :protected].include?(node.children[0])
12
+ if node.type == :FCALL && Parser.is_ast_node?(node.children.last)
13
+ node.children.last.children[0..-2].each do |child|
14
+ # next unless child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
15
+ next unless child.type == :LIT || child.type == :STR
16
+ name = child.children[0].to_s
17
+ matches = pins.select{ |pin| pin.is_a?(Pin::BaseMethod) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
18
+ matches.each do |pin|
19
+ # @todo Smelly instance variable access
20
+ pin.instance_variable_set(:@visibility, node.children[0])
21
+ end
22
+ end
23
+ else
24
+ # @todo Smelly instance variable access
25
+ region.instance_variable_set(:@visibility, node.children[0])
26
+ end
27
+ elsif node.children[0] == :module_function
28
+ process_module_function
29
+ elsif node.children[0] == :require
30
+ process_require
31
+ elsif node.children[0] == :alias_method
32
+ process_alias_method
33
+ elsif node.children[0] == :private_class_method
34
+ # Processing a private class can potentially handle children on its own
35
+ return if process_private_class_method
36
+ elsif [:attr_reader, :attr_writer, :attr_accessor].include?(node.children[0])
37
+ process_attribute
38
+ elsif node.children[0] == :include
39
+ process_include
40
+ elsif node.children[0] == :extend
41
+ process_extend
42
+ elsif node.children[0] == :prepend
43
+ process_prepend
44
+ elsif node.children[0] == :private_constant
45
+ process_private_constant
46
+ elsif node.children[1] == :require && unpack_name(node.children[0]) == 'Bundler'
47
+ pins.push Pin::Reference::Require.new(Solargraph::Location.new(region.filename, Solargraph::Range.from_to(0, 0, 0, 0)), 'bundler/require')
48
+ end
49
+ process_children
50
+ end
51
+
52
+ private
53
+
54
+ # @return [void]
55
+ def process_attribute
56
+ return unless Parser.is_ast_node?(node.children[1])
57
+ node.children[1].children[0..-2].each do |a|
58
+ next unless a.type == :LIT
59
+ loc = get_node_location(node)
60
+ clos = region.closure
61
+ cmnt = comments_for(node)
62
+ if node.children[0] == :attr_reader || node.children[0] == :attr_accessor
63
+ pins.push Solargraph::Pin::Attribute.new(
64
+ location: loc,
65
+ closure: clos,
66
+ name: a.children[0].to_s,
67
+ comments: cmnt,
68
+ access: :reader,
69
+ scope: region.scope || :instance,
70
+ visibility: region.visibility
71
+ )
72
+ end
73
+ if node.children[0] == :attr_writer || node.children[0] == :attr_accessor
74
+ pins.push Solargraph::Pin::Attribute.new(
75
+ location: loc,
76
+ closure: clos,
77
+ name: "#{a.children[0]}=",
78
+ comments: cmnt,
79
+ access: :writer,
80
+ scope: region.scope || :instance,
81
+ visibility: region.visibility
82
+ )
83
+ end
84
+ end
85
+ end
86
+
87
+ # @return [void]
88
+ def process_include
89
+ return unless Parser.is_ast_node?(node.children.last)
90
+ node.children.last.children[0..-2].each do |i|
91
+ next unless [:COLON2, :COLON3, :CONST].include?(i.type)
92
+ pins.push Pin::Reference::Include.new(
93
+ location: get_node_location(i),
94
+ closure: region.closure,
95
+ name: unpack_name(i)
96
+ )
97
+ end
98
+ end
99
+
100
+ # @return [void]
101
+ def process_prepend
102
+ return unless Parser.is_ast_node?(node.children.last)
103
+ node.children.last.children[0..-2].each do |i|
104
+ next unless [:COLON2, :COLON3, :CONST].include?(i.type)
105
+ pins.push Pin::Reference::Prepend.new(
106
+ location: get_node_location(i),
107
+ closure: region.closure,
108
+ name: unpack_name(i)
109
+ )
110
+ end
111
+ end
112
+
113
+ # @return [void]
114
+ def process_extend
115
+ return unless Parser.is_ast_node?(node.children.last)
116
+ node.children.last.children[0..-2].each do |i|
117
+ next unless [:COLON2, :COLON3, :CONST, :SELF].include?(i.type)
118
+ loc = get_node_location(node)
119
+ if i.type == :SELF
120
+ pins.push Pin::Reference::Extend.new(
121
+ location: loc,
122
+ closure: region.closure,
123
+ name: region.closure.full_context.namespace
124
+ )
125
+ else
126
+ pins.push Pin::Reference::Extend.new(
127
+ location: loc,
128
+ closure: region.closure,
129
+ name: unpack_name(i)
130
+ )
131
+ end
132
+ end
133
+ end
134
+
135
+ # @return [void]
136
+ def process_require
137
+ return unless Parser.is_ast_node?(node.children[1])
138
+ node.children[1].children.each do |arg|
139
+ next unless Parser.is_ast_node?(arg)
140
+ if arg.type == :STR
141
+ pins.push Pin::Reference::Require.new(get_node_location(arg), arg.children[0])
142
+ end
143
+ end
144
+ end
145
+
146
+ # @return [void]
147
+ def process_module_function
148
+ if node.type == :VCALL
149
+ # @todo Smelly instance variable access
150
+ region.instance_variable_set(:@visibility, :module_function)
151
+ elsif node.children.last.children[0].type == :DEFN
152
+ NodeProcessor.process node.children.last.children[0], region.update(visibility: :module_function), pins, locals
153
+ else
154
+ node.children.last.children[0..-2].each do |x|
155
+ next unless [:LIT, :STR].include?(x.type)
156
+ cn = x.children[0].to_s
157
+ ref = pins.select{|p| [Solargraph::Pin::Method, Solargraph::Pin::Attribute].include?(p.class) && p.namespace == region.closure.full_context.namespace && p.name == cn}.first
158
+ unless ref.nil?
159
+ pins.delete ref
160
+ mm = Solargraph::Pin::Method.new(
161
+ location: ref.location,
162
+ closure: ref.closure,
163
+ name: ref.name,
164
+ comments: ref.comments,
165
+ scope: :class,
166
+ visibility: :public,
167
+ parameters: ref.parameters,
168
+ node: ref.node
169
+ )
170
+ cm = Solargraph::Pin::Method.new(
171
+ location: ref.location,
172
+ closure: ref.closure,
173
+ name: ref.name,
174
+ comments: ref.comments,
175
+ scope: :instance,
176
+ visibility: :private,
177
+ parameters: ref.parameters,
178
+ node: ref.node)
179
+ pins.push mm, cm
180
+ pins.select{|pin| pin.is_a?(Pin::InstanceVariable) && pin.closure.path == ref.path}.each do |ivar|
181
+ pins.delete ivar
182
+ pins.push Solargraph::Pin::InstanceVariable.new(
183
+ location: ivar.location,
184
+ closure: cm,
185
+ name: ivar.name,
186
+ comments: ivar.comments,
187
+ assignment: ivar.assignment
188
+ # scope: :instance
189
+ )
190
+ pins.push Solargraph::Pin::InstanceVariable.new(
191
+ location: ivar.location,
192
+ closure: mm,
193
+ name: ivar.name,
194
+ comments: ivar.comments,
195
+ assignment: ivar.assignment
196
+ # scope: :class
197
+ )
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ # @return [void]
205
+ def process_private_constant
206
+ node.children.last.children[0..-2].each do |child|
207
+ if [:LIT, :STR].include?(child.type)
208
+ cn = child.children[0].to_s
209
+ ref = pins.select{|p| [Solargraph::Pin::Namespace, Solargraph::Pin::Constant].include?(p.class) && p.namespace == region.closure.full_context.namespace && p.name == cn}.first
210
+ # HACK: Smelly instance variable access
211
+ ref.instance_variable_set(:@visibility, :private) unless ref.nil?
212
+ end
213
+ end
214
+ end
215
+
216
+ # @return [void]
217
+ def process_alias_method
218
+ arr = node.children[1]
219
+ return if arr.nil?
220
+ first = arr.children[0]
221
+ second = arr.children[1]
222
+ return unless first && second && [:LIT, :STR].include?(first.type) && [:LIT, :STR].include?(second.type)
223
+ loc = get_node_location(node)
224
+ pins.push Solargraph::Pin::MethodAlias.new(
225
+ location: get_node_location(node),
226
+ closure: region.closure,
227
+ name: first.children[0].to_s,
228
+ original: second.children[0].to_s,
229
+ scope: region.scope || :instance
230
+ )
231
+ end
232
+
233
+ # @return [Boolean]
234
+ def process_private_class_method
235
+ return false unless Parser.is_ast_node?(node.children.last)
236
+ if node.children.last.children.first.type == :DEFN
237
+ process_children region.update(scope: :class, visibility: :private)
238
+ true
239
+ else
240
+ node.children.last.children[0..-2].each do |child|
241
+ if child.type == :LIT && child.children.first.is_a?(::Symbol)
242
+ sym_name = child.children.first.to_s
243
+ ref = pins.select{|p| [Solargraph::Pin::Method, Solargraph::Pin::Attribute].include?(p.class) && p.namespace == region.closure.full_context.namespace && p.name == sym_name}.first
244
+ # HACK: Smelly instance variable access
245
+ ref.instance_variable_set(:@visibility, :private) unless ref.nil?
246
+ false
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module Rubyvm
6
+ module NodeProcessors
7
+ class SymNode < Parser::NodeProcessor::Base
8
+ def process
9
+ pins.push Solargraph::Pin::Symbol.new(
10
+ get_node_location(node),
11
+ ":#{node.children[0]}"
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ module Solargraph
2
+ module Parser
3
+ class Snippet
4
+ attr_reader :range
5
+ attr_reader :text
6
+
7
+ def initialize range, text
8
+ @range = range
9
+ @text = text
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yard'
4
+
5
+ module Solargraph
6
+ # The namespace for pins used in maps.
7
+ #
8
+ module Pin
9
+ autoload :Common, 'solargraph/pin/common'
10
+ autoload :Conversions, 'solargraph/pin/conversions'
11
+ autoload :Base, 'solargraph/pin/base'
12
+ autoload :BaseMethod, 'solargraph/pin/base_method'
13
+ autoload :Method, 'solargraph/pin/method'
14
+ autoload :MethodAlias, 'solargraph/pin/method_alias'
15
+ autoload :Attribute, 'solargraph/pin/attribute'
16
+ autoload :BaseVariable, 'solargraph/pin/base_variable'
17
+ autoload :InstanceVariable, 'solargraph/pin/instance_variable'
18
+ autoload :ClassVariable, 'solargraph/pin/class_variable'
19
+ autoload :LocalVariable, 'solargraph/pin/local_variable'
20
+ autoload :GlobalVariable, 'solargraph/pin/global_variable'
21
+ autoload :Constant, 'solargraph/pin/constant'
22
+ autoload :Symbol, 'solargraph/pin/symbol'
23
+ autoload :Closure, 'solargraph/pin/closure'
24
+ autoload :Namespace, 'solargraph/pin/namespace'
25
+ autoload :Keyword, 'solargraph/pin/keyword'
26
+ autoload :Parameter, 'solargraph/pin/parameter'
27
+ autoload :Reference, 'solargraph/pin/reference'
28
+ autoload :Documenting, 'solargraph/pin/documenting'
29
+ autoload :Block, 'solargraph/pin/block'
30
+ autoload :Localized, 'solargraph/pin/localized'
31
+ autoload :ProxyType, 'solargraph/pin/proxy_type'
32
+ autoload :DuckMethod, 'solargraph/pin/duck_method'
33
+ autoload :YardPin, 'solargraph/pin/yard_pin'
34
+ autoload :Singleton, 'solargraph/pin/singleton'
35
+ autoload :KeywordParam, 'solargraph/pin/keyword_param'
36
+
37
+ ROOT_PIN = Pin::Namespace.new(type: :class, name: '', closure: nil)
38
+ end
39
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class Attribute < BaseMethod
6
+ # @return [::Symbol] :reader or :writer
7
+ attr_reader :access
8
+
9
+ # @param access [::Symbol] :reader or :writer
10
+ def initialize access: :reader, **splat
11
+ super(**splat)
12
+ @access = access
13
+ if access == :writer
14
+ parameters.push(
15
+ Pin::Parameter.new(name: 'value', decl: :arg, closure: self)
16
+ )
17
+ if return_type.defined?
18
+ docstring.add_tag YARD::Tags::Tag.new(:param, '', return_type.to_s.split(', '), 'value')
19
+ end
20
+ end
21
+ end
22
+
23
+ def completion_item_kind
24
+ Solargraph::LanguageServer::CompletionItemKinds::PROPERTY
25
+ end
26
+
27
+ def symbol_kind
28
+ Solargraph::LanguageServer::SymbolKinds::PROPERTY
29
+ end
30
+
31
+ def path
32
+ @path ||= namespace + (scope == :instance ? '#' : '.') + name
33
+ end
34
+
35
+ def probe api_map
36
+ types = []
37
+ varname = "@#{name.gsub(/=$/, '')}"
38
+ pins = api_map.get_instance_variable_pins(binder.namespace, binder.scope).select { |iv| iv.name == varname }
39
+ pins.each do |pin|
40
+ type = pin.typify(api_map)
41
+ type = pin.probe(api_map) if type.undefined?
42
+ types.push type if type.defined?
43
+ end
44
+ return ComplexType::UNDEFINED if types.empty?
45
+ ComplexType.try_parse(*types.map(&:tag).uniq)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,296 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ # The base class for map pins.
6
+ #
7
+ class Base
8
+ include Common
9
+ include Conversions
10
+ include Documenting
11
+
12
+ # @return [YARD::CodeObjects::Base]
13
+ attr_reader :code_object
14
+
15
+ # @return [Solargraph::Location]
16
+ attr_reader :location
17
+
18
+ # @return [String]
19
+ attr_reader :name
20
+
21
+ # @return [String]
22
+ attr_reader :path
23
+
24
+ # @param location [Solargraph::Location]
25
+ # @param kind [Integer]
26
+ # @param closure [String]
27
+ # @param name [String]
28
+ # @param comments [String]
29
+ def initialize location: nil, closure: nil, name: '', comments: ''
30
+ @location = location
31
+ @closure = closure
32
+ @name = name
33
+ @comments = comments
34
+ end
35
+
36
+ # @return [String]
37
+ def comments
38
+ @comments ||= ''
39
+ end
40
+
41
+ # @return [String]
42
+ def filename
43
+ return nil if location.nil?
44
+ location.filename
45
+ end
46
+
47
+ # @return [Integer]
48
+ def completion_item_kind
49
+ LanguageServer::CompletionItemKinds::KEYWORD
50
+ end
51
+
52
+ # @return [Integer, nil]
53
+ def symbol_kind
54
+ nil
55
+ end
56
+
57
+ def to_s
58
+ name.to_s
59
+ end
60
+
61
+ # @return [Boolean]
62
+ def variable?
63
+ false
64
+ end
65
+
66
+ # Pin equality is determined using the #nearly? method and also
67
+ # requiring both pins to have the same location.
68
+ #
69
+ def == other
70
+ return false unless nearly? other
71
+ comments == other.comments and location == other.location
72
+ end
73
+
74
+ # True if the specified pin is a near match to this one. A near match
75
+ # indicates that the pins contain mostly the same data. Any differences
76
+ # between them should not have an impact on the API surface.
77
+ #
78
+ # @param other [Solargraph::Pin::Base, Object]
79
+ # @return [Boolean]
80
+ def nearly? other
81
+ self.class == other.class &&
82
+ name == other.name &&
83
+ (closure == other.closure || (closure && closure.nearly?(other.closure))) &&
84
+ (comments == other.comments ||
85
+ (((maybe_directives? == false && other.maybe_directives? == false) || compare_directives(directives, other.directives)) &&
86
+ compare_docstring_tags(docstring, other.docstring))
87
+ )
88
+ end
89
+
90
+ # The pin's return type.
91
+ #
92
+ # @return [ComplexType]
93
+ def return_type
94
+ @return_type ||= ComplexType::UNDEFINED
95
+ end
96
+
97
+ # @return [YARD::Docstring]
98
+ def docstring
99
+ parse_comments unless defined?(@docstring)
100
+ @docstring ||= Solargraph::Source.parse_docstring('').to_docstring
101
+ end
102
+
103
+ # @return [Array<YARD::Tags::Directive>]
104
+ def directives
105
+ parse_comments unless defined?(@directives)
106
+ @directives
107
+ end
108
+
109
+ # @return [Array<YARD::Tags::MacroDirective>]
110
+ def macros
111
+ @macros ||= collect_macros
112
+ end
113
+
114
+ # Perform a quick check to see if this pin possibly includes YARD
115
+ # directives. This method does not require parsing the comments.
116
+ #
117
+ # After the comments have been parsed, this method will return false if
118
+ # no directives were found, regardless of whether it previously appeared
119
+ # possible.
120
+ #
121
+ # @return [Boolean]
122
+ def maybe_directives?
123
+ return !@directives.empty? if defined?(@directives)
124
+ @maybe_directives ||= comments.include?('@!')
125
+ end
126
+
127
+ # @return [Boolean]
128
+ def deprecated?
129
+ @deprecated ||= docstring.has_tag?('deprecated')
130
+ end
131
+
132
+ # Get a fully qualified type from the pin's return type.
133
+ #
134
+ # The relative type is determined from YARD documentation (@return,
135
+ # @param, @type, etc.) and its namespaces are fully qualified using the
136
+ # provided ApiMap.
137
+ #
138
+ # @param api_map [ApiMap]
139
+ # @return [ComplexType]
140
+ def typify api_map
141
+ return_type.qualify(api_map, namespace)
142
+ end
143
+
144
+ # Infer the pin's return type via static code analysis.
145
+ #
146
+ # @param api_map [ApiMap]
147
+ # @return [ComplexType]
148
+ def probe api_map
149
+ typify api_map
150
+ end
151
+
152
+ # @deprecated Use #typify and/or #probe instead
153
+ # @param api_map [ApiMap]
154
+ # @return [ComplexType]
155
+ def infer api_map
156
+ Solargraph::Logging.logger.warn "WARNING: Pin #infer methods are deprecated. Use #typify or #probe instead."
157
+ type = typify(api_map)
158
+ return type unless type.undefined?
159
+ probe api_map
160
+ end
161
+
162
+ # Try to merge data from another pin. Merges are only possible if the
163
+ # pins are near matches (see the #nearly? method). The changes should
164
+ # not have any side effects on the API surface.
165
+ #
166
+ # @param pin [Pin::Base] The pin to merge into this one
167
+ # @return [Boolean] True if the pins were merged
168
+ def try_merge! pin
169
+ return false unless nearly?(pin)
170
+ @location = pin.location
171
+ @closure = pin.closure
172
+ return true if comments == pin.comments
173
+ @comments = pin.comments
174
+ @docstring = pin.docstring
175
+ @return_type = pin.return_type
176
+ @documentation = nil
177
+ @deprecated = nil
178
+ reset_conversions
179
+ true
180
+ end
181
+
182
+ def proxied?
183
+ @proxied ||= false
184
+ end
185
+
186
+ def probed?
187
+ @probed ||= false
188
+ end
189
+
190
+ # @param api_map [ApiMap]
191
+ # @return [self]
192
+ def realize api_map
193
+ return self if return_type.defined?
194
+ type = typify(api_map)
195
+ return proxy(type) if type.defined?
196
+ type = probe(api_map)
197
+ return self if type.undefined?
198
+ result = proxy(type)
199
+ result.probed = true
200
+ result
201
+ end
202
+
203
+ # Return a proxy for this pin with the specified return type. Other than
204
+ # the return type and the #proxied? setting, the proxy should be a clone
205
+ # of the original.
206
+ #
207
+ # @param return_type [ComplexType]
208
+ # @return [self]
209
+ def proxy return_type
210
+ result = dup
211
+ result.return_type = return_type
212
+ result.proxied = true
213
+ result
214
+ end
215
+
216
+ def identity
217
+ @identity ||= "#{closure.context.namespace}|#{name}"
218
+ end
219
+
220
+ def inspect
221
+ "#<#{self.class} at #{self.location.inspect}>"
222
+ end
223
+
224
+ protected
225
+
226
+ # @return [Boolean]
227
+ attr_writer :probed
228
+
229
+ # @return [Boolean]
230
+ attr_writer :proxied
231
+
232
+ # @return [ComplexType]
233
+ attr_writer :return_type
234
+
235
+ private
236
+
237
+ # @return [void]
238
+ def parse_comments
239
+ # HACK: Avoid a NoMethodError on nil with empty overload tags
240
+ if comments.nil? || comments.empty? || comments.strip.end_with?('@overload')
241
+ @docstring = nil
242
+ @directives = []
243
+ else
244
+ # HACK: Pass a dummy code object to the parser for plugins that
245
+ # expect it not to be nil
246
+ parse = Solargraph::Source.parse_docstring(comments)
247
+ @docstring = parse.to_docstring
248
+ @directives = parse.directives
249
+ end
250
+ end
251
+
252
+ # True if two docstrings have the same tags, regardless of any other
253
+ # differences.
254
+ #
255
+ # @param d1 [YARD::Docstring]
256
+ # @param d2 [YARD::Docstring]
257
+ # @return [Boolean]
258
+ def compare_docstring_tags d1, d2
259
+ return false if d1.tags.length != d2.tags.length
260
+ d1.tags.each_index do |i|
261
+ return false unless compare_tags(d1.tags[i], d2.tags[i])
262
+ end
263
+ true
264
+ end
265
+
266
+ # @param dir1 [Array<YARD::Tags::Directive>]
267
+ # @param dir2 [Array<YARD::Tags::Directive>]
268
+ # @return [Boolean]
269
+ def compare_directives dir1, dir2
270
+ return false if dir1.length != dir2.length
271
+ dir1.each_index do |i|
272
+ return false unless compare_tags(dir1[i].tag, dir2[i].tag)
273
+ end
274
+ true
275
+ end
276
+
277
+ # @param tag1 [YARD::Tags::Tag]
278
+ # @param tag2 [YARD::Tags::Tag]
279
+ # @return [Boolean]
280
+ def compare_tags tag1, tag2
281
+ tag1.class == tag2.class &&
282
+ tag1.tag_name == tag2.tag_name &&
283
+ tag1.text == tag2.text &&
284
+ tag1.name == tag2.name &&
285
+ tag1.types == tag2.types
286
+ end
287
+
288
+ # @return [Array<YARD::Tags::Handlers::Directive>]
289
+ def collect_macros
290
+ return [] unless maybe_directives?
291
+ parse = Solargraph::Source.parse_docstring(comments)
292
+ parse.directives.select{ |d| d.tag.tag_name == 'macro' }
293
+ end
294
+ end
295
+ end
296
+ end