solargraph 0.54.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +127 -0
  3. data/.github/workflows/plugins.yml +184 -6
  4. data/.github/workflows/rspec.yml +55 -5
  5. data/.github/workflows/typecheck.yml +8 -3
  6. data/.gitignore +7 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +1279 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +171 -0
  13. data/README.md +20 -6
  14. data/Rakefile +125 -13
  15. data/bin/solargraph +8 -5
  16. data/lib/solargraph/api_map/cache.rb +13 -3
  17. data/lib/solargraph/api_map/constants.rb +279 -0
  18. data/lib/solargraph/api_map/index.rb +193 -0
  19. data/lib/solargraph/api_map/source_to_yard.rb +13 -4
  20. data/lib/solargraph/api_map/store.rb +207 -132
  21. data/lib/solargraph/api_map.rb +394 -261
  22. data/lib/solargraph/bench.rb +18 -1
  23. data/lib/solargraph/complex_type/type_methods.rb +29 -12
  24. data/lib/solargraph/complex_type/unique_type.rb +205 -26
  25. data/lib/solargraph/complex_type.rb +126 -26
  26. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  27. data/lib/solargraph/convention/base.rb +20 -3
  28. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  29. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  30. data/lib/solargraph/convention/data_definition.rb +105 -0
  31. data/lib/solargraph/convention/gemspec.rb +3 -2
  32. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
  33. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
  34. data/lib/solargraph/convention/struct_definition.rb +164 -0
  35. data/lib/solargraph/convention.rb +36 -4
  36. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  37. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  38. data/lib/solargraph/doc_map.rb +316 -64
  39. data/lib/solargraph/environ.rb +9 -2
  40. data/lib/solargraph/equality.rb +34 -0
  41. data/lib/solargraph/gem_pins.rb +64 -38
  42. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  43. data/lib/solargraph/language_server/host/message_worker.rb +54 -5
  44. data/lib/solargraph/language_server/host.rb +36 -18
  45. data/lib/solargraph/language_server/message/base.rb +20 -12
  46. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
  47. data/lib/solargraph/language_server/message/extended/document.rb +5 -2
  48. data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
  49. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  50. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  51. data/lib/solargraph/language_server/message/text_document/definition.rb +5 -3
  52. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
  53. data/lib/solargraph/language_server/message/text_document/formatting.rb +23 -2
  54. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
  55. data/lib/solargraph/language_server/message/text_document/type_definition.rb +4 -3
  56. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  57. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
  58. data/lib/solargraph/language_server/progress.rb +27 -2
  59. data/lib/solargraph/language_server/request.rb +4 -1
  60. data/lib/solargraph/library.rb +83 -73
  61. data/lib/solargraph/location.rb +45 -1
  62. data/lib/solargraph/logging.rb +12 -2
  63. data/lib/solargraph/page.rb +3 -0
  64. data/lib/solargraph/parser/comment_ripper.rb +20 -7
  65. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
  66. data/lib/solargraph/parser/node_processor/base.rb +10 -5
  67. data/lib/solargraph/parser/node_processor.rb +26 -8
  68. data/lib/solargraph/parser/parser_gem/class_methods.rb +10 -18
  69. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  70. data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
  71. data/lib/solargraph/parser/parser_gem/node_methods.rb +10 -19
  72. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  73. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
  74. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +26 -20
  75. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
  76. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
  77. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  78. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
  79. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
  80. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  81. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
  82. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
  83. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
  84. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +14 -2
  85. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
  86. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -0
  87. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
  88. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
  89. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +16 -6
  90. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +64 -32
  91. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
  92. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  93. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  94. data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
  95. data/lib/solargraph/parser/region.rb +4 -1
  96. data/lib/solargraph/parser/snippet.rb +2 -0
  97. data/lib/solargraph/parser.rb +3 -5
  98. data/lib/solargraph/pin/base.rb +417 -42
  99. data/lib/solargraph/pin/base_variable.rb +21 -12
  100. data/lib/solargraph/pin/block.rb +9 -26
  101. data/lib/solargraph/pin/breakable.rb +9 -0
  102. data/lib/solargraph/pin/callable.rb +231 -0
  103. data/lib/solargraph/pin/closure.rb +30 -10
  104. data/lib/solargraph/pin/common.rb +12 -7
  105. data/lib/solargraph/pin/constant.rb +2 -0
  106. data/lib/solargraph/pin/conversions.rb +3 -2
  107. data/lib/solargraph/pin/delegated_method.rb +20 -1
  108. data/lib/solargraph/pin/documenting.rb +16 -0
  109. data/lib/solargraph/pin/instance_variable.rb +2 -2
  110. data/lib/solargraph/pin/keyword.rb +7 -2
  111. data/lib/solargraph/pin/local_variable.rb +15 -7
  112. data/lib/solargraph/pin/method.rb +241 -70
  113. data/lib/solargraph/pin/method_alias.rb +3 -0
  114. data/lib/solargraph/pin/namespace.rb +21 -13
  115. data/lib/solargraph/pin/parameter.rb +94 -32
  116. data/lib/solargraph/pin/proxy_type.rb +17 -7
  117. data/lib/solargraph/pin/reference/override.rb +24 -6
  118. data/lib/solargraph/pin/reference/require.rb +2 -2
  119. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  120. data/lib/solargraph/pin/reference.rb +17 -0
  121. data/lib/solargraph/pin/search.rb +6 -1
  122. data/lib/solargraph/pin/signature.rb +39 -121
  123. data/lib/solargraph/pin/singleton.rb +1 -1
  124. data/lib/solargraph/pin/symbol.rb +8 -2
  125. data/lib/solargraph/pin/until.rb +18 -0
  126. data/lib/solargraph/pin/while.rb +18 -0
  127. data/lib/solargraph/pin.rb +8 -2
  128. data/lib/solargraph/pin_cache.rb +245 -0
  129. data/lib/solargraph/position.rb +19 -0
  130. data/lib/solargraph/range.rb +23 -4
  131. data/lib/solargraph/rbs_map/conversions.rb +315 -99
  132. data/lib/solargraph/rbs_map/core_fills.rb +50 -16
  133. data/lib/solargraph/rbs_map/core_map.rb +41 -11
  134. data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
  135. data/lib/solargraph/rbs_map.rb +87 -16
  136. data/lib/solargraph/shell.rb +117 -17
  137. data/lib/solargraph/source/chain/array.rb +13 -8
  138. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  139. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  140. data/lib/solargraph/source/chain/call.rb +135 -66
  141. data/lib/solargraph/source/chain/constant.rb +3 -66
  142. data/lib/solargraph/source/chain/hash.rb +9 -3
  143. data/lib/solargraph/source/chain/head.rb +1 -1
  144. data/lib/solargraph/source/chain/if.rb +7 -2
  145. data/lib/solargraph/source/chain/link.rb +38 -6
  146. data/lib/solargraph/source/chain/literal.rb +27 -2
  147. data/lib/solargraph/source/chain/or.rb +2 -2
  148. data/lib/solargraph/source/chain/z_super.rb +1 -1
  149. data/lib/solargraph/source/chain.rb +140 -63
  150. data/lib/solargraph/source/change.rb +2 -2
  151. data/lib/solargraph/source/cursor.rb +4 -4
  152. data/lib/solargraph/source/source_chainer.rb +3 -3
  153. data/lib/solargraph/source.rb +110 -89
  154. data/lib/solargraph/source_map/clip.rb +22 -28
  155. data/lib/solargraph/source_map/data.rb +34 -0
  156. data/lib/solargraph/source_map/mapper.rb +11 -7
  157. data/lib/solargraph/source_map.rb +50 -43
  158. data/lib/solargraph/type_checker/checks.rb +4 -0
  159. data/lib/solargraph/type_checker/param_def.rb +2 -0
  160. data/lib/solargraph/type_checker/rules.rb +35 -8
  161. data/lib/solargraph/type_checker.rb +331 -189
  162. data/lib/solargraph/version.rb +1 -1
  163. data/lib/solargraph/views/_method.erb +10 -10
  164. data/lib/solargraph/views/_namespace.erb +3 -3
  165. data/lib/solargraph/views/document.erb +10 -10
  166. data/lib/solargraph/views/environment.erb +3 -5
  167. data/lib/solargraph/workspace/config.rb +25 -5
  168. data/lib/solargraph/workspace/require_paths.rb +97 -0
  169. data/lib/solargraph/workspace.rb +53 -72
  170. data/lib/solargraph/yard_map/helpers.rb +29 -1
  171. data/lib/solargraph/yard_map/mapper/to_constant.rb +8 -5
  172. data/lib/solargraph/yard_map/mapper/to_method.rb +55 -19
  173. data/lib/solargraph/yard_map/mapper/to_namespace.rb +11 -7
  174. data/lib/solargraph/yard_map/mapper.rb +5 -3
  175. data/lib/solargraph/yard_map/to_method.rb +6 -3
  176. data/lib/solargraph/yardoc.rb +45 -10
  177. data/lib/solargraph.rb +35 -1
  178. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  179. data/rbs/fills/open3/0/open3.rbs +172 -0
  180. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  181. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  182. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  183. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  184. data/rbs/fills/tuple/tuple.rbs +149 -0
  185. data/rbs_collection.yaml +19 -0
  186. data/sig/shims/ast/0/node.rbs +5 -0
  187. data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
  188. data/sig/shims/ast/2.4/ast.rbs +73 -0
  189. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  190. data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
  191. data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
  192. data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  193. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  194. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  195. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  196. data/solargraph.gemspec +32 -10
  197. metadata +237 -37
  198. data/lib/.rubocop.yml +0 -22
  199. data/lib/solargraph/cache.rb +0 -77
  200. data/lib/solargraph/parser/node_methods.rb +0 -83
@@ -15,17 +15,26 @@ module Solargraph
15
15
 
16
16
  include EncodingFixes
17
17
 
18
- # @return [String]
18
+ # @return [String, nil]
19
19
  attr_reader :filename
20
20
 
21
21
  # @return [String]
22
- attr_reader :code
22
+ def code
23
+ finalize
24
+ @code
25
+ end
23
26
 
24
- # @return [Parser::AST::Node]
25
- attr_reader :node
27
+ # @return [Parser::AST::Node, nil]
28
+ def node
29
+ finalize
30
+ @node
31
+ end
26
32
 
27
- # @return [Hash{Integer => Array<String>}]
28
- attr_reader :comments
33
+ # @return [Hash{Integer => Solargraph::Parser::Snippet}]
34
+ def comments
35
+ finalize
36
+ @comments
37
+ end
29
38
 
30
39
  # @todo Deprecate?
31
40
  # @return [Integer]
@@ -39,17 +48,6 @@ module Solargraph
39
48
  @repaired = code
40
49
  @filename = filename
41
50
  @version = version
42
- @domains = []
43
- begin
44
- @node, @comments = Solargraph::Parser.parse_with_comments(@code, filename)
45
- @parsed = true
46
- rescue Parser::SyntaxError, EncodingError => e
47
- @node = nil
48
- @comments = {}
49
- @parsed = false
50
- ensure
51
- @code.freeze
52
- end
53
51
  end
54
52
 
55
53
  # @param range [Solargraph::Range]
@@ -64,9 +62,9 @@ module Solargraph
64
62
  # @param c2 [Integer]
65
63
  # @return [String]
66
64
  def from_to l1, c1, l2, c2
67
- b = Solargraph::Position.line_char_to_offset(@code, l1, c1)
68
- e = Solargraph::Position.line_char_to_offset(@code, l2, c2)
69
- @code[b..e-1]
65
+ b = Solargraph::Position.line_char_to_offset(code, l1, c1)
66
+ e = Solargraph::Position.line_char_to_offset(code, l2, c2)
67
+ code[b..e-1]
70
68
  end
71
69
 
72
70
  # Get the nearest node that contains the specified index.
@@ -85,10 +83,9 @@ module Solargraph
85
83
  # @param column [Integer]
86
84
  # @return [Array<AST::Node>]
87
85
  def tree_at(line, column)
88
- # offset = Position.line_char_to_offset(@code, line, column)
89
86
  position = Position.new(line, column)
90
87
  stack = []
91
- inner_tree_at @node, position, stack
88
+ inner_tree_at node, position, stack
92
89
  stack
93
90
  end
94
91
 
@@ -104,68 +101,53 @@ module Solargraph
104
101
  @version = updater.version
105
102
  return self
106
103
  end
107
- synced = Source.new(real_code, filename)
108
- if synced.parsed?
109
- synced.version = updater.version
110
- return synced
104
+ Source.new(@code, filename, updater.version).tap do |src|
105
+ src.repaired = @repaired
106
+ src.error_ranges.concat error_ranges
107
+ src.changes.concat(changes + updater.changes)
111
108
  end
112
- incr_code = updater.repair(@repaired)
113
- synced = Source.new(incr_code, filename)
114
- synced.error_ranges.concat (error_ranges + updater.changes.map(&:range))
115
- synced.code = real_code
116
- synced.version = updater.version
117
- synced
118
109
  end
119
110
 
120
111
  # @param position [Position, Array(Integer, Integer)]
121
112
  # @return [Source::Cursor]
122
113
  def cursor_at position
114
+ finalize
123
115
  Cursor.new(self, position)
124
116
  end
125
117
 
126
118
  # @return [Boolean]
127
119
  def parsed?
120
+ finalize
128
121
  @parsed
129
122
  end
130
123
 
131
124
  def repaired?
132
- @is_repaired ||= (@code != @repaired)
125
+ code != @repaired
133
126
  end
134
127
 
135
128
  # @param position [Position]
136
129
  # @return [Boolean]
137
130
  def string_at? position
138
- if Parser.rubyvm?
139
- string_ranges.each do |range|
140
- if synchronized?
141
- return true if range.include?(position) || range.ending == position
142
- else
143
- return true if last_updater && last_updater.changes.one? && range.contain?(last_updater.changes.first.range.start)
144
- end
145
- end
146
- false
147
- else
148
- return false if Position.to_offset(code, position) >= code.length
149
- string_nodes.each do |node|
150
- range = Range.from_node(node)
151
- next if range.ending.line < position.line
152
- break if range.ending.line > position.line
153
- return true if node.type == :str && range.include?(position) && range.start != position
154
- return true if [:STR, :str].include?(node.type) && range.include?(position) && range.start != position
155
- if node.type == :dstr
156
- inner = node_at(position.line, position.column)
157
- next if inner.nil?
158
- inner_range = Range.from_node(inner)
159
- next unless range.include?(inner_range.ending)
160
- return true if inner.type == :str
161
- inner_code = at(Solargraph::Range.new(inner_range.start, position))
162
- return true if (inner.type == :dstr && inner_range.ending.character <= position.character) && !inner_code.end_with?('}') ||
163
- (inner.type != :dstr && inner_range.ending.line == position.line && position.character <= inner_range.ending.character && inner_code.end_with?('}'))
164
- end
165
- break if range.ending.line > position.line
131
+ return false if Position.to_offset(code, position) >= code.length
132
+ string_nodes.each do |node|
133
+ range = Range.from_node(node)
134
+ next if range.ending.line < position.line
135
+ break if range.ending.line > position.line
136
+ return true if node.type == :str && range.include?(position) && range.start != position
137
+ return true if [:STR, :str].include?(node.type) && range.include?(position) && range.start != position
138
+ if node.type == :dstr
139
+ inner = node_at(position.line, position.column)
140
+ next if inner.nil?
141
+ inner_range = Range.from_node(inner)
142
+ next unless range.include?(inner_range.ending)
143
+ return true if inner.type == :str
144
+ inner_code = at(Solargraph::Range.new(inner_range.start, position))
145
+ return true if (inner.type == :dstr && inner_range.ending.character <= position.character) && !inner_code.end_with?('}') ||
146
+ (inner.type != :dstr && inner_range.ending.line == position.line && position.character <= inner_range.ending.character && inner_code.end_with?('}'))
166
147
  end
167
- false
148
+ break if range.ending.line > position.line
168
149
  end
150
+ false
169
151
  end
170
152
 
171
153
  # @return [::Array<Range>]
@@ -199,8 +181,8 @@ module Solargraph
199
181
  # @return [String]
200
182
  def code_for(node)
201
183
  rng = Range.from_node(node)
202
- b = Position.line_char_to_offset(@code, rng.start.line, rng.start.column)
203
- e = Position.line_char_to_offset(@code, rng.ending.line, rng.ending.column)
184
+ b = Position.line_char_to_offset(code, rng.start.line, rng.start.column)
185
+ e = Position.line_char_to_offset(code, rng.ending.line, rng.ending.column)
204
186
  frag = code[b..e-1].to_s
205
187
  frag.strip.gsub(/,$/, '')
206
188
  end
@@ -225,15 +207,9 @@ module Solargraph
225
207
  Location.new(filename, range)
226
208
  end
227
209
 
228
- FOLDING_NODE_TYPES = if Parser.rubyvm?
229
- %i[
230
- CLASS SCLASS MODULE DEFN DEFS IF WHILE UNLESS ITER STR HASH ARRAY LIST
231
- ].freeze
232
- else
233
- %i[
210
+ FOLDING_NODE_TYPES = %i[
234
211
  class sclass module def defs if str dstr array while unless kwbegin hash block
235
212
  ].freeze
236
- end
237
213
 
238
214
  # Get an array of ranges that can be folded, e.g., the range of a class
239
215
  # definition or an if condition.
@@ -251,8 +227,7 @@ module Solargraph
251
227
  end
252
228
 
253
229
  def synchronized?
254
- @synchronized = true if @synchronized.nil?
255
- @synchronized
230
+ true
256
231
  end
257
232
 
258
233
  # Get a hash of comments grouped by the line numbers of the associated code.
@@ -260,10 +235,12 @@ module Solargraph
260
235
  # @return [Hash{Integer => String}]
261
236
  def associated_comments
262
237
  @associated_comments ||= begin
238
+ # @type [Hash{Integer => String}]
263
239
  result = {}
264
240
  buffer = String.new('')
241
+ # @type [Integer, nil]
265
242
  last = nil
266
- @comments.each_pair do |num, snip|
243
+ comments.each_pair do |num, snip|
267
244
  if !last || num == last + 1
268
245
  buffer.concat "#{snip.text}\n"
269
246
  else
@@ -295,12 +272,9 @@ module Solargraph
295
272
  def inner_folding_ranges top, result = [], parent = nil
296
273
  return unless Parser.is_ast_node?(top)
297
274
  if FOLDING_NODE_TYPES.include?(top.type)
298
- # @todo Smelly exception for hash's first-level array in RubyVM
299
- unless [:ARRAY, :LIST].include?(top.type) && parent == :HASH
300
- range = Range.from_node(top)
301
- if result.empty? || range.start.line > result.last.start.line
302
- result.push range unless range.ending.line - range.start.line < 2
303
- end
275
+ range = Range.from_node(top)
276
+ if result.empty? || range.start.line > result.last.start.line
277
+ result.push range unless range.ending.line - range.start.line < 2
304
278
  end
305
279
  end
306
280
  top.children.each do |child|
@@ -334,19 +308,19 @@ module Solargraph
334
308
 
335
309
  # A hash of line numbers and their associated comments.
336
310
  #
337
- # @return [Hash{Integer => Array<String>}]
311
+ # @return [Hash{Integer => Array<String>, nil}]
338
312
  def stringified_comments
339
313
  @stringified_comments ||= {}
340
314
  end
341
315
 
342
316
  # @return [Array<Parser::AST::Node>]
343
317
  def string_nodes
344
- @string_nodes ||= string_nodes_in(@node)
318
+ @string_nodes ||= string_nodes_in(node)
345
319
  end
346
320
 
347
- # @return [Array<Range>]
321
+ # @return [Array<Solargraph::Range>]
348
322
  def comment_ranges
349
- @comment_ranges ||= @comments.values.map(&:range)
323
+ @comment_ranges ||= comments.values.map(&:range)
350
324
  end
351
325
 
352
326
  # Get an array of foldable comment block ranges. Blocks are excluded if
@@ -402,16 +376,60 @@ module Solargraph
402
376
 
403
377
  protected
404
378
 
379
+ # @return [Array<Change>]
380
+ def changes
381
+ @changes ||= []
382
+ end
383
+
405
384
  # @return [String]
406
385
  attr_writer :filename
407
386
 
408
387
  # @return [Integer]
409
388
  attr_writer :version
410
389
 
390
+ # @return [void]
391
+ def finalize
392
+ return if @finalized && changes.empty?
393
+
394
+ changes.each do |change|
395
+ @code = change.write(@code)
396
+ end
397
+ @finalized = true
398
+ begin
399
+ @node, @comments = Solargraph::Parser.parse_with_comments(@code, filename)
400
+ @parsed = true
401
+ @repaired = @code
402
+ rescue Parser::SyntaxError, EncodingError => e
403
+ @node = nil
404
+ @comments = {}
405
+ @parsed = false
406
+ ensure
407
+ @code.freeze
408
+ end
409
+ if !@parsed && !changes.empty?
410
+ changes.each do |change|
411
+ @repaired = change.repair(@repaired)
412
+ end
413
+ error_ranges.concat(changes.map(&:range))
414
+ begin
415
+ @node, @comments = Solargraph::Parser.parse_with_comments(@repaired, filename)
416
+ @parsed = true
417
+ rescue Parser::SyntaxError, EncodingError => e
418
+ @node = nil
419
+ @comments = {}
420
+ @parsed = false
421
+ end
422
+ elsif @parsed
423
+ error_ranges.clear
424
+ end
425
+ changes.clear
426
+ end
427
+
411
428
  # @param val [String]
412
429
  # @return [String]
413
430
  def code=(val)
414
- @code_lines= nil
431
+ @code_lines = nil
432
+ @finalized = false
415
433
  @code = val
416
434
  end
417
435
 
@@ -422,7 +440,13 @@ module Solargraph
422
440
  attr_writer :error_ranges
423
441
 
424
442
  # @return [String]
425
- attr_accessor :repaired
443
+ attr_writer :repaired
444
+
445
+ # @return [String]
446
+ def repaired
447
+ finalize
448
+ @repaired
449
+ end
426
450
 
427
451
  # @return [Boolean]
428
452
  attr_writer :parsed
@@ -433,9 +457,6 @@ module Solargraph
433
457
  # @return [Boolean]
434
458
  attr_writer :synchronized
435
459
 
436
- # @return [Source::Updater]
437
- attr_accessor :last_updater
438
-
439
460
  private
440
461
 
441
462
  # @return [Array<String>]
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Solargraph
4
4
  class SourceMap
5
- # A static analysis tool for obtaining definitions, completions,
6
- # signatures, and type inferences from a cursor.
5
+ # A static analysis tool for obtaining definitions, Completions,
6
+ # signatures, and type inferences from a Cursor.
7
7
  #
8
8
  class Clip
9
9
  # @param api_map [ApiMap]
@@ -11,13 +11,14 @@ module Solargraph
11
11
  def initialize api_map, cursor
12
12
  @api_map = api_map
13
13
  @cursor = cursor
14
- block.rebind(api_map) if block.is_a?(Pin::Block)
14
+ closure_pin = closure
15
+ closure_pin.rebind(api_map) if closure_pin.is_a?(Pin::Block) && !Solargraph::Range.from_node(closure_pin.receiver).contain?(cursor.range.start)
15
16
  end
16
17
 
17
18
  # @return [Array<Pin::Base>] Relevant pins for infering the type of the Cursor's position
18
19
  def define
19
20
  return [] if cursor.comment? || cursor.chain.literal?
20
- result = cursor.chain.define(api_map, block, locals)
21
+ result = cursor.chain.define(api_map, closure, locals)
21
22
  result.concat file_global_methods
22
23
  result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
23
24
  result
@@ -40,7 +41,7 @@ module Solargraph
40
41
  end
41
42
  end
42
43
 
43
- # @return [Array<Pin::Base>]
44
+ # @return [Array<Pin::Method>]
44
45
  def signify
45
46
  return [] unless cursor.argument?
46
47
  chain = Parser.chain(cursor.recipient_node, cursor.filename)
@@ -49,43 +50,36 @@ module Solargraph
49
50
 
50
51
  # @return [ComplexType]
51
52
  def infer
52
- result = cursor.chain.infer(api_map, block, locals)
53
+ result = cursor.chain.infer(api_map, closure, locals)
53
54
  if result.tag == 'Class'
54
55
  # HACK: Exception to return BasicObject from Class#new
55
- dfn = cursor.chain.define(api_map, block, locals).first
56
- return ComplexType.try_parse('BasicObject') if dfn && dfn.path == 'Class#new'
56
+ dfn = cursor.chain.define(api_map, closure, locals).first
57
+ return ComplexType.try_parse('::BasicObject') if dfn && dfn.path == 'Class#new'
57
58
  end
58
- return result unless result.tag == 'self'
59
- ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).tag)
59
+ # should receive result with selfs resolved from infer()
60
+ Solargraph.assert_or_log(:clip_infer_self, 'Received selfy inference') if result.selfy?
61
+ result
60
62
  end
61
63
 
62
64
  # Get an array of all the locals that are visible from the cursors's
63
65
  # position. Locals can be local variables, method parameters, or block
64
66
  # parameters. The array starts with the nearest local pin.
65
67
  #
66
- # @return [::Array<Solargraph::Pin::Base>]
68
+ # @return [::Array<Solargraph::Pin::LocalVariable>]
67
69
  def locals
68
70
  @locals ||= source_map.locals_at(location)
69
71
  end
70
72
 
71
73
  # @return [::Array<String>]
72
74
  def gates
73
- block.gates
74
- end
75
-
76
- def in_block?
77
- return @in_block unless @in_block.nil?
78
- @in_block = begin
79
- tree = cursor.source.tree_at(cursor.position.line, cursor.position.column)
80
- Parser.is_ast_node?(tree[1]) && [:block, :ITER].include?(tree[1].type)
81
- end
75
+ closure.gates
82
76
  end
83
77
 
84
78
  # @param phrase [String]
85
79
  # @return [Array<Solargraph::Pin::Base>]
86
80
  def translate phrase
87
81
  chain = Parser.chain(Parser.parse(phrase))
88
- chain.define(api_map, block, locals)
82
+ chain.define(api_map, closure, locals)
89
83
  end
90
84
 
91
85
  private
@@ -107,8 +101,8 @@ module Solargraph
107
101
  end
108
102
 
109
103
  # @return [Solargraph::Pin::Closure]
110
- def block
111
- @block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
104
+ def closure
105
+ @closure ||= source_map.locate_closure_pin(cursor.node_position.line, cursor.node_position.character)
112
106
  end
113
107
 
114
108
  # The context at the current position.
@@ -199,20 +193,20 @@ module Solargraph
199
193
  result.concat api_map.get_constants(type.namespace, cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
200
194
  end
201
195
  else
202
- type = cursor.chain.base.infer(api_map, block, locals)
203
- result.concat api_map.get_complex_type_methods(type, block.binder.namespace, cursor.chain.links.length == 1)
196
+ type = cursor.chain.base.infer(api_map, closure, locals)
197
+ result.concat api_map.get_complex_type_methods(type, closure.binder.namespace, cursor.chain.links.length == 1)
204
198
  if cursor.chain.links.length == 1
205
199
  if cursor.word.start_with?('@@')
206
200
  return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
207
201
  elsif cursor.word.start_with?('@')
208
- return package_completions(api_map.get_instance_variable_pins(block.binder.namespace, block.binder.scope))
202
+ return package_completions(api_map.get_instance_variable_pins(closure.binder.namespace, closure.binder.scope))
209
203
  elsif cursor.word.start_with?('$')
210
204
  return package_completions(api_map.get_global_variable_pins)
211
205
  end
212
206
  result.concat locals
213
- result.concat file_global_methods unless block.binder.namespace.empty?
207
+ result.concat file_global_methods unless closure.binder.namespace.empty?
214
208
  result.concat api_map.get_constants(context_pin.context.namespace, *gates)
215
- result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
209
+ result.concat api_map.get_methods(closure.binder.namespace, scope: closure.binder.scope, visibility: [:public, :private, :protected])
216
210
  result.concat api_map.get_methods('Kernel')
217
211
  result.concat api_map.keyword_pins.to_a
218
212
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class SourceMap
5
+ class Data
6
+ # @param source [Solargraph::Source]
7
+ def initialize source
8
+ @source = source
9
+ end
10
+
11
+ # @return [Array<Solargraph::Pin::Base>]
12
+ def pins
13
+ generate
14
+ @pins || []
15
+ end
16
+
17
+ # @return [Array<Solargraph::LocalVariable>]
18
+ def locals
19
+ generate
20
+ @locals || []
21
+ end
22
+
23
+ private
24
+
25
+ # @return [void]
26
+ def generate
27
+ return if @generated
28
+
29
+ @generated = true
30
+ @pins, @locals = Mapper.map(@source)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -41,7 +41,7 @@ module Solargraph
41
41
  s = Position.new(0, 0)
42
42
  e = Position.from_offset(code, code.length)
43
43
  location = Location.new(filename, Range.new(s, e))
44
- [[Pin::Namespace.new(location: location, name: '')], []]
44
+ [[Pin::Namespace.new(location: location, name: '', source: :source_map)], []]
45
45
  end
46
46
 
47
47
  class << self
@@ -55,6 +55,7 @@ module Solargraph
55
55
 
56
56
  # @return [Array<Solargraph::Pin::Base>]
57
57
  def pins
58
+ # @type [Array<Solargraph::Pin::Base>]
58
59
  @pins ||= []
59
60
  end
60
61
 
@@ -140,7 +141,8 @@ module Solargraph
140
141
  scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
141
142
  visibility: :public,
142
143
  explicit: false,
143
- attribute: true
144
+ attribute: true,
145
+ source: :source_map
144
146
  )
145
147
  end
146
148
  if t.nil? || t.include?('w')
@@ -151,16 +153,17 @@ module Solargraph
151
153
  comments: docstring.all.to_s,
152
154
  scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
153
155
  visibility: :public,
154
- attribute: true
156
+ attribute: true,
157
+ source: :source_map
155
158
  )
156
159
  pins.push method_pin
157
- method_pin.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
160
+ method_pin.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last, source: :source_map)
158
161
  if pins.last.return_type.defined?
159
162
  pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
160
163
  end
161
164
  end
162
165
  when 'visibility'
163
- begin
166
+
164
167
  kind = directive.tag.text&.to_sym
165
168
  return unless [:private, :protected, :public].include?(kind)
166
169
 
@@ -179,7 +182,7 @@ module Solargraph
179
182
  pin.instance_variable_set(:@visibility, kind)
180
183
  end
181
184
  end
182
- end
185
+
183
186
  when 'parse'
184
187
  begin
185
188
  ns = closure_at(source_position)
@@ -205,7 +208,8 @@ module Solargraph
205
208
  namespace = closure_at(source_position) || Pin::ROOT_PIN
206
209
  namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
207
210
  when 'override'
208
- pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags)
211
+ pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags,
212
+ source: :source_map)
209
213
  when 'macro'
210
214
  # @todo Handle macros
211
215
  end