solargraph 0.46.0 → 0.47.2

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