solargraph 0.46.0 → 0.54.5

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 (279) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/plugins.yml +40 -0
  4. data/.github/workflows/rspec.yml +37 -41
  5. data/.github/workflows/typecheck.yml +34 -0
  6. data/.gitignore +9 -9
  7. data/.rspec +2 -2
  8. data/.yardopts +2 -2
  9. data/CHANGELOG.md +1338 -1115
  10. data/Gemfile +0 -0
  11. data/LICENSE +1 -1
  12. data/README.md +131 -128
  13. data/Rakefile +0 -0
  14. data/SPONSORS.md +10 -18
  15. data/bin/solargraph +0 -0
  16. data/lib/solargraph/api_map/cache.rb +109 -70
  17. data/lib/solargraph/api_map/index.rb +167 -0
  18. data/lib/solargraph/api_map/source_to_yard.rb +88 -81
  19. data/lib/solargraph/api_map/store.rb +260 -256
  20. data/lib/solargraph/api_map.rb +870 -686
  21. data/lib/solargraph/bench.rb +44 -27
  22. data/lib/solargraph/cache.rb +77 -0
  23. data/lib/solargraph/complex_type/type_methods.rb +217 -130
  24. data/lib/solargraph/complex_type/unique_type.rb +386 -75
  25. data/lib/solargraph/complex_type.rb +394 -221
  26. data/lib/solargraph/convention/base.rb +33 -33
  27. data/lib/solargraph/convention/gemfile.rb +15 -15
  28. data/lib/solargraph/convention/gemspec.rb +22 -22
  29. data/lib/solargraph/convention/rakefile.rb +17 -0
  30. data/lib/solargraph/convention.rb +47 -47
  31. data/lib/solargraph/converters/dd.rb +17 -12
  32. data/lib/solargraph/converters/dl.rb +15 -12
  33. data/lib/solargraph/converters/dt.rb +15 -12
  34. data/lib/solargraph/converters/misc.rb +1 -1
  35. data/lib/solargraph/diagnostics/base.rb +29 -29
  36. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  37. data/lib/solargraph/diagnostics/rubocop.rb +113 -98
  38. data/lib/solargraph/diagnostics/rubocop_helpers.rb +66 -63
  39. data/lib/solargraph/diagnostics/severities.rb +15 -15
  40. data/lib/solargraph/diagnostics/type_check.rb +55 -54
  41. data/lib/solargraph/diagnostics/update_errors.rb +41 -41
  42. data/lib/solargraph/diagnostics.rb +55 -55
  43. data/lib/solargraph/doc_map.rb +188 -0
  44. data/lib/solargraph/environ.rb +45 -45
  45. data/lib/solargraph/equality.rb +33 -0
  46. data/lib/solargraph/gem_pins.rb +72 -0
  47. data/lib/solargraph/language_server/completion_item_kinds.rb +35 -35
  48. data/lib/solargraph/language_server/error_codes.rb +20 -20
  49. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  50. data/lib/solargraph/language_server/host/dispatch.rb +128 -111
  51. data/lib/solargraph/language_server/host/message_worker.rb +106 -59
  52. data/lib/solargraph/language_server/host/sources.rb +99 -156
  53. data/lib/solargraph/language_server/host.rb +861 -865
  54. data/lib/solargraph/language_server/message/base.rb +96 -89
  55. data/lib/solargraph/language_server/message/cancel_request.rb +13 -13
  56. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
  57. data/lib/solargraph/language_server/message/client.rb +11 -11
  58. data/lib/solargraph/language_server/message/completion_item/resolve.rb +60 -58
  59. data/lib/solargraph/language_server/message/completion_item.rb +11 -11
  60. data/lib/solargraph/language_server/message/exit_notification.rb +13 -13
  61. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +112 -100
  62. data/lib/solargraph/language_server/message/extended/document.rb +20 -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 -23
  65. data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
  66. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  67. data/lib/solargraph/language_server/message/extended.rb +21 -21
  68. data/lib/solargraph/language_server/message/initialize.rb +191 -162
  69. data/lib/solargraph/language_server/message/initialized.rb +28 -27
  70. data/lib/solargraph/language_server/message/method_not_found.rb +16 -16
  71. data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -14
  72. data/lib/solargraph/language_server/message/shutdown.rb +13 -13
  73. data/lib/solargraph/language_server/message/text_document/base.rb +19 -19
  74. data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -17
  75. data/lib/solargraph/language_server/message/text_document/completion.rb +56 -59
  76. data/lib/solargraph/language_server/message/text_document/definition.rb +38 -38
  77. data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -15
  78. data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -15
  79. data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -15
  80. data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -17
  81. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
  82. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -23
  83. data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -26
  84. data/lib/solargraph/language_server/message/text_document/formatting.rb +131 -126
  85. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -54
  86. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -34
  87. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
  88. data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
  89. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
  90. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -29
  91. data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
  92. data/lib/solargraph/language_server/message/text_document.rb +28 -28
  93. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +35 -30
  94. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -33
  95. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -24
  96. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  97. data/lib/solargraph/language_server/message/workspace.rb +14 -14
  98. data/lib/solargraph/language_server/message.rb +94 -93
  99. data/lib/solargraph/language_server/message_types.rb +14 -14
  100. data/lib/solargraph/language_server/progress.rb +135 -0
  101. data/lib/solargraph/language_server/request.rb +24 -24
  102. data/lib/solargraph/language_server/symbol_kinds.rb +36 -36
  103. data/lib/solargraph/language_server/transport/adapter.rb +68 -53
  104. data/lib/solargraph/language_server/transport/data_reader.rb +74 -72
  105. data/lib/solargraph/language_server/transport.rb +13 -13
  106. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  107. data/lib/solargraph/language_server.rb +20 -19
  108. data/lib/solargraph/library.rb +663 -546
  109. data/lib/solargraph/location.rb +58 -37
  110. data/lib/solargraph/logging.rb +27 -27
  111. data/lib/solargraph/page.rb +89 -83
  112. data/lib/solargraph/parser/comment_ripper.rb +56 -52
  113. data/lib/solargraph/parser/node_methods.rb +83 -43
  114. data/lib/solargraph/parser/node_processor/base.rb +87 -77
  115. data/lib/solargraph/parser/node_processor.rb +45 -43
  116. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +153 -135
  117. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +18 -16
  118. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +164 -148
  119. data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
  120. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +23 -23
  121. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +57 -0
  122. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +15 -15
  123. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +43 -42
  124. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +35 -25
  125. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +23 -23
  126. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/def_node.rb +50 -63
  127. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +36 -36
  128. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +23 -23
  129. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +38 -38
  130. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +28 -28
  131. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
  132. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +39 -39
  133. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +16 -16
  134. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +36 -36
  135. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +42 -0
  136. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +259 -257
  137. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +18 -18
  138. data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
  139. data/lib/solargraph/parser/parser_gem.rb +12 -0
  140. data/lib/solargraph/parser/region.rb +66 -66
  141. data/lib/solargraph/parser/snippet.rb +15 -13
  142. data/lib/solargraph/parser.rb +22 -26
  143. data/lib/solargraph/pin/base.rb +378 -296
  144. data/lib/solargraph/pin/base_variable.rb +118 -84
  145. data/lib/solargraph/pin/block.rb +101 -72
  146. data/lib/solargraph/pin/callable.rb +147 -0
  147. data/lib/solargraph/pin/class_variable.rb +8 -8
  148. data/lib/solargraph/pin/closure.rb +57 -37
  149. data/lib/solargraph/pin/common.rb +70 -70
  150. data/lib/solargraph/pin/constant.rb +43 -43
  151. data/lib/solargraph/pin/conversions.rb +123 -96
  152. data/lib/solargraph/pin/delegated_method.rb +101 -0
  153. data/lib/solargraph/pin/documenting.rb +98 -105
  154. data/lib/solargraph/pin/duck_method.rb +16 -16
  155. data/lib/solargraph/pin/global_variable.rb +8 -8
  156. data/lib/solargraph/pin/instance_variable.rb +34 -30
  157. data/lib/solargraph/pin/keyword.rb +15 -15
  158. data/lib/solargraph/pin/keyword_param.rb +8 -8
  159. data/lib/solargraph/pin/local_variable.rb +67 -55
  160. data/lib/solargraph/pin/method.rb +527 -245
  161. data/lib/solargraph/pin/method_alias.rb +31 -31
  162. data/lib/solargraph/pin/namespace.rb +107 -91
  163. data/lib/solargraph/pin/parameter.rb +212 -201
  164. data/lib/solargraph/pin/proxy_type.rb +29 -29
  165. data/lib/solargraph/pin/reference/extend.rb +10 -10
  166. data/lib/solargraph/pin/reference/include.rb +10 -10
  167. data/lib/solargraph/pin/reference/override.rb +29 -29
  168. data/lib/solargraph/pin/reference/prepend.rb +10 -10
  169. data/lib/solargraph/pin/reference/require.rb +14 -14
  170. data/lib/solargraph/pin/reference/superclass.rb +10 -10
  171. data/lib/solargraph/pin/reference.rb +22 -14
  172. data/lib/solargraph/pin/search.rb +56 -56
  173. data/lib/solargraph/pin/signature.rb +17 -0
  174. data/lib/solargraph/pin/singleton.rb +11 -11
  175. data/lib/solargraph/pin/symbol.rb +47 -47
  176. data/lib/solargraph/pin.rb +41 -37
  177. data/lib/solargraph/position.rb +107 -100
  178. data/lib/solargraph/range.rb +98 -95
  179. data/lib/solargraph/rbs_map/conversions.rb +646 -0
  180. data/lib/solargraph/rbs_map/core_fills.rb +50 -0
  181. data/lib/solargraph/rbs_map/core_map.rb +28 -0
  182. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -0
  183. data/lib/solargraph/rbs_map.rb +93 -0
  184. data/lib/solargraph/server_methods.rb +16 -16
  185. data/lib/solargraph/shell.rb +269 -226
  186. data/lib/solargraph/source/chain/array.rb +33 -0
  187. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  188. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  189. data/lib/solargraph/source/chain/call.rb +303 -204
  190. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  191. data/lib/solargraph/source/chain/constant.rb +89 -75
  192. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  193. data/lib/solargraph/source/chain/hash.rb +33 -28
  194. data/lib/solargraph/source/chain/head.rb +19 -19
  195. data/lib/solargraph/source/chain/if.rb +28 -0
  196. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  197. data/lib/solargraph/source/chain/link.rb +98 -71
  198. data/lib/solargraph/source/chain/literal.rb +28 -23
  199. data/lib/solargraph/source/chain/or.rb +23 -23
  200. data/lib/solargraph/source/chain/q_call.rb +11 -11
  201. data/lib/solargraph/source/chain/variable.rb +13 -13
  202. data/lib/solargraph/source/chain/z_super.rb +30 -30
  203. data/lib/solargraph/source/chain.rb +252 -164
  204. data/lib/solargraph/source/change.rb +82 -79
  205. data/lib/solargraph/source/cursor.rb +167 -164
  206. data/lib/solargraph/source/source_chainer.rb +194 -191
  207. data/lib/solargraph/source/updater.rb +55 -54
  208. data/lib/solargraph/source.rb +495 -522
  209. data/lib/solargraph/source_map/clip.rb +232 -224
  210. data/lib/solargraph/source_map/completion.rb +23 -23
  211. data/lib/solargraph/source_map/data.rb +30 -0
  212. data/lib/solargraph/source_map/mapper.rb +255 -212
  213. data/lib/solargraph/source_map.rb +217 -180
  214. data/lib/solargraph/type_checker/checks.rb +120 -99
  215. data/lib/solargraph/type_checker/param_def.rb +35 -35
  216. data/lib/solargraph/type_checker/problem.rb +32 -32
  217. data/lib/solargraph/type_checker/rules.rb +62 -57
  218. data/lib/solargraph/type_checker.rb +672 -543
  219. data/lib/solargraph/version.rb +5 -5
  220. data/lib/solargraph/views/environment.erb +56 -58
  221. data/lib/solargraph/workspace/config.rb +239 -231
  222. data/lib/solargraph/workspace.rb +239 -215
  223. data/lib/solargraph/yard_map/cache.rb +25 -19
  224. data/lib/solargraph/yard_map/helpers.rb +16 -16
  225. data/lib/solargraph/yard_map/mapper/to_constant.rb +26 -25
  226. data/lib/solargraph/yard_map/mapper/to_method.rb +94 -78
  227. data/lib/solargraph/yard_map/mapper/to_namespace.rb +28 -27
  228. data/lib/solargraph/yard_map/mapper.rb +78 -77
  229. data/lib/solargraph/yard_map/to_method.rb +86 -79
  230. data/lib/solargraph/yard_map.rb +18 -460
  231. data/lib/solargraph/yard_tags.rb +20 -0
  232. data/lib/solargraph/yardoc.rb +52 -0
  233. data/lib/solargraph.rb +72 -69
  234. data/solargraph.gemspec +21 -10
  235. metadata +184 -115
  236. data/.travis.yml +0 -19
  237. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  238. data/lib/solargraph/compat.rb +0 -37
  239. data/lib/solargraph/convention/rspec.rb +0 -30
  240. data/lib/solargraph/documentor.rb +0 -76
  241. data/lib/solargraph/language_server/host/cataloger.rb +0 -56
  242. data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
  243. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  244. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
  245. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  246. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +0 -63
  247. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +0 -21
  248. data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
  249. data/lib/solargraph/parser/legacy.rb +0 -12
  250. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -144
  251. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  252. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
  253. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  254. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  255. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -22
  256. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
  257. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -57
  258. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  259. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  260. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  261. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  262. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  263. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  264. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  265. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  266. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
  267. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -21
  268. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  269. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -277
  270. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +0 -18
  271. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
  272. data/lib/solargraph/parser/rubyvm.rb +0 -40
  273. data/lib/solargraph/yard_map/core_docs.rb +0 -170
  274. data/lib/solargraph/yard_map/core_fills.rb +0 -208
  275. data/lib/solargraph/yard_map/core_gen.rb +0 -76
  276. data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
  277. data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
  278. data/lib/yard-solargraph.rb +0 -33
  279. data/yardoc/2.2.2.tar.gz +0 -0
@@ -1,212 +1,255 @@
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.encode('UTF-8', invalid: :replace, replace: '?') =~ 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
- end
75
- end
76
-
77
- # @param comment [String]
78
- # @return [Integer]
79
- def find_directive_line_number comment, tag, start
80
- # Avoid overruning the index
81
- return start unless start < comment.lines.length
82
- num = comment.lines[start..-1].find_index do |line|
83
- # Legacy method directives might be `@method` instead of `@!method`
84
- # @todo Legacy syntax should probably emit a warning
85
- line.include?("@!#{tag}") || (tag == 'method' && line.include?("@#{tag}"))
86
- end
87
- num.to_i + start
88
- end
89
-
90
- # @param source_position [Position]
91
- # @param comment_position [Position]
92
- # @param directive [YARD::Tags::Directive]
93
- # @return [void]
94
- def process_directive source_position, comment_position, directive
95
- docstring = Solargraph::Source.parse_docstring(directive.tag.text).to_docstring
96
- location = Location.new(@filename, Range.new(comment_position, comment_position))
97
- case directive.tag.tag_name
98
- when 'method'
99
- namespace = closure_at(source_position) || @pins.first
100
- if namespace.location.range.start.line < comment_position.line
101
- namespace = closure_at(comment_position)
102
- end
103
- begin
104
- src = Solargraph::Source.load_string("def #{directive.tag.name};end", @source.filename)
105
- region = Parser::Region.new(source: src, closure: namespace)
106
- gen_pin = Parser.process_node(src.node, region).first.last
107
- return if gen_pin.nil?
108
- # Move the location to the end of the line so it gets recognized
109
- # as originating from a comment
110
- shifted = Solargraph::Position.new(comment_position.line, @code.lines[comment_position.line].to_s.chomp.length)
111
- # @todo: Smelly instance variable access
112
- gen_pin.instance_variable_set(:@comments, docstring.all.to_s)
113
- gen_pin.instance_variable_set(:@location, Solargraph::Location.new(@filename, Range.new(shifted, shifted)))
114
- gen_pin.instance_variable_set(:@explicit, false)
115
- @pins.push gen_pin
116
- rescue Parser::SyntaxError => e
117
- # @todo Handle error in directive
118
- end
119
- when 'attribute'
120
- return if directive.tag.name.nil?
121
- namespace = closure_at(source_position)
122
- t = (directive.tag.types.nil? || directive.tag.types.empty?) ? nil : directive.tag.types.flatten.join('')
123
- if t.nil? || t.include?('r')
124
- pins.push Solargraph::Pin::Method.new(
125
- location: location,
126
- closure: namespace,
127
- name: directive.tag.name,
128
- comments: docstring.all.to_s,
129
- scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
130
- visibility: :public,
131
- explicit: false,
132
- attribute: true
133
- )
134
- end
135
- if t.nil? || t.include?('w')
136
- pins.push Solargraph::Pin::Method.new(
137
- location: location,
138
- closure: namespace,
139
- name: "#{directive.tag.name}=",
140
- comments: docstring.all.to_s,
141
- scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
142
- visibility: :public,
143
- attribute: true
144
- )
145
- pins.last.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
146
- if pins.last.return_type.defined?
147
- pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
148
- end
149
- end
150
- when 'parse'
151
- begin
152
- ns = closure_at(source_position)
153
- src = Solargraph::Source.load_string(directive.tag.text, @source.filename)
154
- region = Parser::Region.new(source: src, closure: ns)
155
- # @todo These pins may need to be marked not explicit
156
- index = @pins.length
157
- loff = if @code.lines[comment_position.line].strip.end_with?('@!parse')
158
- comment_position.line + 1
159
- else
160
- comment_position.line
161
- end
162
- Parser.process_node(src.node, region, @pins)
163
- @pins[index..-1].each do |p|
164
- # @todo Smelly instance variable access
165
- p.location.range.start.instance_variable_set(:@line, p.location.range.start.line + loff)
166
- p.location.range.ending.instance_variable_set(:@line, p.location.range.ending.line + loff)
167
- end
168
- rescue Parser::SyntaxError => e
169
- # @todo Handle parser errors in !parse directives
170
- end
171
- when 'domain'
172
- namespace = closure_at(source_position) || Pin::ROOT_PIN
173
- namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
174
- when 'override'
175
- pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags)
176
- end
177
- end
178
-
179
- def remove_inline_comment_hashes comment
180
- ctxt = ''
181
- num = nil
182
- started = false
183
- comment.lines.each { |l|
184
- # Trim the comment and minimum leading whitespace
185
- p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#/, '')
186
- if num.nil? && !p.strip.empty?
187
- num = p.index(/[^ ]/)
188
- started = true
189
- elsif started && !p.strip.empty?
190
- cur = p.index(/[^ ]/)
191
- num = cur if cur < num
192
- end
193
- ctxt += "#{p[num..-1]}" if started
194
- }
195
- ctxt
196
- end
197
-
198
- # @return [void]
199
- def process_comment_directives
200
- return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~ MACRO_REGEXP
201
- code_lines = @code.lines
202
- @source.associated_comments.each do |line, comments|
203
- src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
204
- com_pos = Position.new(line + 1 - comments.lines.length, 0)
205
- process_comment(src_pos, com_pos, comments)
206
- end
207
- rescue StandardError => e
208
- raise e.class, "Error processing comment directives in #{@filename}: #{e.message}"
209
- end
210
- end
211
- end
212
- end
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
+ DIRECTIVE_REGEXP = /(@\!method|@\!attribute|@\!visibility|@\!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
+ @pins.each { |p| p.source = :code }
28
+ @locals.each { |l| l.source = :code }
29
+ process_comment_directives
30
+ [@pins, @locals]
31
+ # rescue Exception => e
32
+ # Solargraph.logger.warn "Error mapping #{source.filename}: [#{e.class}] #{e.message}"
33
+ # Solargraph.logger.warn e.backtrace.join("\n")
34
+ # [[], []]
35
+ end
36
+
37
+ # @param filename [String]
38
+ # @param code [String]
39
+ # @return [Array]
40
+ def unmap filename, code
41
+ s = Position.new(0, 0)
42
+ e = Position.from_offset(code, code.length)
43
+ location = Location.new(filename, Range.new(s, e))
44
+ [[Pin::Namespace.new(location: location, name: '')], []]
45
+ end
46
+
47
+ class << self
48
+ # @param source [Source]
49
+ # @return [Array]
50
+ def map source
51
+ return new.unmap(source.filename, source.code) unless source.parsed?
52
+ new.map source
53
+ end
54
+ end
55
+
56
+ # @return [Array<Solargraph::Pin::Base>]
57
+ def pins
58
+ @pins ||= []
59
+ end
60
+
61
+ # @param position [Solargraph::Position]
62
+ # @return [Solargraph::Pin::Closure]
63
+ def closure_at(position)
64
+ pins.select{|pin| pin.is_a?(Pin::Closure) and pin.location.range.contain?(position)}.last
65
+ end
66
+
67
+ # @param source_position [Position]
68
+ # @param comment_position [Position]
69
+ # @param comment [String]
70
+ # @return [void]
71
+ def process_comment source_position, comment_position, comment
72
+ return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
73
+ cmnt = remove_inline_comment_hashes(comment)
74
+ parse = Solargraph::Source.parse_docstring(cmnt)
75
+ last_line = 0
76
+ # @param d [YARD::Tags::Directive]
77
+ parse.directives.each do |d|
78
+ line_num = find_directive_line_number(cmnt, d.tag.tag_name, last_line)
79
+ pos = Solargraph::Position.new(comment_position.line + line_num - 1, comment_position.column)
80
+ process_directive(source_position, pos, d)
81
+ last_line = line_num + 1
82
+ end
83
+ end
84
+
85
+ # @param comment [String]
86
+ # @param tag [String]
87
+ # @param start [Integer]
88
+ # @return [Integer]
89
+ def find_directive_line_number comment, tag, start
90
+ # Avoid overruning the index
91
+ return start unless start < comment.lines.length
92
+ num = comment.lines[start..-1].find_index do |line|
93
+ # Legacy method directives might be `@method` instead of `@!method`
94
+ # @todo Legacy syntax should probably emit a warning
95
+ line.include?("@!#{tag}") || (tag == 'method' && line.include?("@#{tag}"))
96
+ end
97
+ num.to_i + start
98
+ end
99
+
100
+ # @param source_position [Position]
101
+ # @param comment_position [Position]
102
+ # @param directive [YARD::Tags::Directive]
103
+ # @return [void]
104
+ def process_directive source_position, comment_position, directive
105
+ docstring = Solargraph::Source.parse_docstring(directive.tag.text).to_docstring
106
+ location = Location.new(@filename, Range.new(comment_position, comment_position))
107
+ case directive.tag.tag_name
108
+ when 'method'
109
+ namespace = closure_at(source_position) || @pins.first
110
+ if namespace.location.range.start.line < comment_position.line
111
+ namespace = closure_at(comment_position)
112
+ end
113
+ begin
114
+ src = Solargraph::Source.load_string("def #{directive.tag.name};end", @source.filename)
115
+ region = Parser::Region.new(source: src, closure: namespace)
116
+ method_gen_pins = Parser.process_node(src.node, region).first.select { |pin| pin.is_a?(Pin::Method) }
117
+ gen_pin = method_gen_pins.last
118
+ return if gen_pin.nil?
119
+ # Move the location to the end of the line so it gets recognized
120
+ # as originating from a comment
121
+ shifted = Solargraph::Position.new(comment_position.line, @code.lines[comment_position.line].to_s.chomp.length)
122
+ # @todo: Smelly instance variable access
123
+ gen_pin.instance_variable_set(:@comments, docstring.all.to_s)
124
+ gen_pin.instance_variable_set(:@location, Solargraph::Location.new(@filename, Range.new(shifted, shifted)))
125
+ gen_pin.instance_variable_set(:@explicit, false)
126
+ @pins.push gen_pin
127
+ rescue Parser::SyntaxError => e
128
+ # @todo Handle error in directive
129
+ end
130
+ when 'attribute'
131
+ return if directive.tag.name.nil?
132
+ namespace = closure_at(source_position)
133
+ t = (directive.tag.types.nil? || directive.tag.types.empty?) ? nil : directive.tag.types.flatten.join('')
134
+ if t.nil? || t.include?('r')
135
+ pins.push Solargraph::Pin::Method.new(
136
+ location: location,
137
+ closure: namespace,
138
+ name: directive.tag.name,
139
+ comments: docstring.all.to_s,
140
+ scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
141
+ visibility: :public,
142
+ explicit: false,
143
+ attribute: true
144
+ )
145
+ end
146
+ if t.nil? || t.include?('w')
147
+ method_pin = Solargraph::Pin::Method.new(
148
+ location: location,
149
+ closure: namespace,
150
+ name: "#{directive.tag.name}=",
151
+ comments: docstring.all.to_s,
152
+ scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
153
+ visibility: :public,
154
+ attribute: true
155
+ )
156
+ pins.push method_pin
157
+ method_pin.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
158
+ if pins.last.return_type.defined?
159
+ pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
160
+ end
161
+ end
162
+ when 'visibility'
163
+ begin
164
+ kind = directive.tag.text&.to_sym
165
+ return unless [:private, :protected, :public].include?(kind)
166
+
167
+ name = directive.tag.name
168
+ closure = closure_at(source_position) || @pins.first
169
+ if closure.location.range.start.line < comment_position.line
170
+ closure = closure_at(comment_position)
171
+ end
172
+ if closure.is_a?(Pin::Method) && no_empty_lines?(comment_position.line, source_position.line)
173
+ # @todo Smelly instance variable access
174
+ closure.instance_variable_set(:@visibility, kind)
175
+ else
176
+ matches = pins.select{ |pin| pin.is_a?(Pin::Method) && pin.name == name && pin.namespace == namespace && pin.context.scope == namespace.is_a?(Pin::Singleton) ? :class : :instance }
177
+ matches.each do |pin|
178
+ # @todo Smelly instance variable access
179
+ pin.instance_variable_set(:@visibility, kind)
180
+ end
181
+ end
182
+ end
183
+ when 'parse'
184
+ begin
185
+ ns = closure_at(source_position)
186
+ src = Solargraph::Source.load_string(directive.tag.text, @source.filename)
187
+ region = Parser::Region.new(source: src, closure: ns)
188
+ # @todo These pins may need to be marked not explicit
189
+ index = @pins.length
190
+ loff = if @code.lines[comment_position.line].strip.end_with?('@!parse')
191
+ comment_position.line + 1
192
+ else
193
+ comment_position.line
194
+ end
195
+ Parser.process_node(src.node, region, @pins)
196
+ @pins[index..-1].each do |p|
197
+ # @todo Smelly instance variable access
198
+ p.location.range.start.instance_variable_set(:@line, p.location.range.start.line + loff)
199
+ p.location.range.ending.instance_variable_set(:@line, p.location.range.ending.line + loff)
200
+ end
201
+ rescue Parser::SyntaxError => e
202
+ # @todo Handle parser errors in !parse directives
203
+ end
204
+ when 'domain'
205
+ namespace = closure_at(source_position) || Pin::ROOT_PIN
206
+ namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
207
+ when 'override'
208
+ pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags)
209
+ when 'macro'
210
+ # @todo Handle macros
211
+ end
212
+ end
213
+
214
+ # @param line1 [Integer]
215
+ # @param line2 [Integer]
216
+ def no_empty_lines?(line1, line2)
217
+ @code.lines[line1..line2].none? { |line| line.strip.empty? }
218
+ end
219
+
220
+ # @param comment [String]
221
+ # @return [String]
222
+ def remove_inline_comment_hashes comment
223
+ ctxt = ''
224
+ num = nil
225
+ started = false
226
+ comment.lines.each { |l|
227
+ # Trim the comment and minimum leading whitespace
228
+ p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#+/, '')
229
+ if num.nil? && !p.strip.empty?
230
+ num = p.index(/[^ ]/)
231
+ started = true
232
+ elsif started && !p.strip.empty?
233
+ cur = p.index(/[^ ]/)
234
+ num = cur if cur < num
235
+ end
236
+ ctxt += "#{p[num..-1]}" if started
237
+ }
238
+ ctxt
239
+ end
240
+
241
+ # @return [void]
242
+ def process_comment_directives
243
+ return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
244
+ code_lines = @code.lines
245
+ @source.associated_comments.each do |line, comments|
246
+ src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
247
+ com_pos = Position.new(line + 1 - comments.lines.length, 0)
248
+ process_comment(src_pos, com_pos, comments)
249
+ end
250
+ rescue StandardError => e
251
+ raise e.class, "Error processing comment directives in #{@filename}: #{e.message}"
252
+ end
253
+ end
254
+ end
255
+ end