solargraph 0.40.2 → 0.41.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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/README.md +15 -0
  4. data/SPONSORS.md +1 -0
  5. data/lib/.rubocop.yml +2 -2
  6. data/lib/solargraph.rb +8 -7
  7. data/lib/solargraph/api_map.rb +52 -75
  8. data/lib/solargraph/api_map/store.rb +5 -0
  9. data/lib/solargraph/bench.rb +19 -18
  10. data/lib/solargraph/compat.rb +15 -1
  11. data/lib/solargraph/diagnostics/rubocop.rb +10 -2
  12. data/lib/solargraph/diagnostics/rubocop_helpers.rb +19 -20
  13. data/lib/solargraph/language_server/host.rb +74 -1
  14. data/lib/solargraph/language_server/host/diagnoser.rb +9 -1
  15. data/lib/solargraph/language_server/message/completion_item/resolve.rb +1 -0
  16. data/lib/solargraph/language_server/message/extended/environment.rb +3 -3
  17. data/lib/solargraph/language_server/message/initialize.rb +30 -35
  18. data/lib/solargraph/language_server/message/text_document/formatting.rb +68 -18
  19. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
  20. data/lib/solargraph/library.rb +94 -21
  21. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -1
  22. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +11 -12
  23. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +1 -6
  24. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +1 -1
  25. data/lib/solargraph/source.rb +1 -1
  26. data/lib/solargraph/source/chain/head.rb +0 -16
  27. data/lib/solargraph/source/source_chainer.rb +1 -0
  28. data/lib/solargraph/source_map/mapper.rb +0 -5
  29. data/lib/solargraph/type_checker.rb +25 -22
  30. data/lib/solargraph/type_checker/checks.rb +9 -5
  31. data/lib/solargraph/type_checker/rules.rb +5 -1
  32. data/lib/solargraph/version.rb +1 -1
  33. data/lib/solargraph/workspace/config.rb +19 -3
  34. data/lib/solargraph/yard_map/core_fills.rb +1 -0
  35. metadata +2 -2
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'observer'
4
4
  require 'set'
5
+ require 'securerandom'
5
6
 
6
7
  module Solargraph
7
8
  module LanguageServer
@@ -192,7 +193,7 @@ module Solargraph
192
193
  def diagnose uri
193
194
  if sources.include?(uri)
194
195
  library = library_for(uri)
195
- if library.synchronized?
196
+ if library.mapped? && library.synchronized?
196
197
  logger.info "Diagnosing #{uri}"
197
198
  begin
198
199
  results = library.diagnose uri_to_file(uri)
@@ -277,6 +278,7 @@ module Solargraph
277
278
  begin
278
279
  lib = Solargraph::Library.load(path, name)
279
280
  libraries.push lib
281
+ async_library_map lib
280
282
  rescue WorkspaceTooLargeError => e
281
283
  send_notification 'window/showMessage', {
282
284
  'type' => Solargraph::LanguageServer::MessageTypes::WARNING,
@@ -494,6 +496,11 @@ module Solargraph
494
496
  library.read_text(filename)
495
497
  end
496
498
 
499
+ def formatter_config uri
500
+ library = library_for(uri)
501
+ library.workspace.config.formatter
502
+ end
503
+
497
504
  # @param uri [String]
498
505
  # @param line [Integer]
499
506
  # @param column [Integer]
@@ -626,6 +633,7 @@ module Solargraph
626
633
 
627
634
  # @return [void]
628
635
  def catalog
636
+ return unless libraries.all?(&:mapped?)
629
637
  libraries.each(&:catalog)
630
638
  end
631
639
 
@@ -736,6 +744,71 @@ module Solargraph
736
744
  def prepare_rename?
737
745
  client_capabilities['rename'] && client_capabilities['rename']['prepareSupport']
738
746
  end
747
+
748
+ def client_supports_progress?
749
+ client_capabilities['window'] && client_capabilities['window']['workDoneProgress']
750
+ end
751
+
752
+ # @param library [Library]
753
+ # @return [void]
754
+ def async_library_map library
755
+ return if library.mapped?
756
+ Thread.new do
757
+ if client_supports_progress?
758
+ uuid = SecureRandom.uuid
759
+ send_request 'window/workDoneProgress/create', {
760
+ token: uuid
761
+ } do |response|
762
+ do_async_library_map library, response.nil? ? uuid : nil
763
+ end
764
+ else
765
+ do_async_library_map library
766
+ end
767
+ end
768
+ end
769
+
770
+ def do_async_library_map library, uuid = nil
771
+ total = library.workspace.sources.length
772
+ if uuid
773
+ send_notification '$/progress', {
774
+ token: uuid,
775
+ value: {
776
+ kind: 'begin',
777
+ title: "Mapping workspace",
778
+ message: "0/#{total} files",
779
+ cancellable: false,
780
+ percentage: 0
781
+ }
782
+ }
783
+ end
784
+ pct = 0
785
+ mod = 10
786
+ while library.next_map
787
+ next unless uuid
788
+ cur = ((library.source_map_hash.keys.length.to_f / total.to_f) * 100).to_i
789
+ if cur > pct && cur % mod == 0
790
+ pct = cur
791
+ send_notification '$/progress', {
792
+ token: uuid,
793
+ value: {
794
+ kind: 'report',
795
+ cancellable: false,
796
+ message: "#{library.source_map_hash.keys.length}/#{total} files",
797
+ percentage: pct
798
+ }
799
+ }
800
+ end
801
+ end
802
+ if uuid
803
+ send_notification '$/progress', {
804
+ token: uuid,
805
+ value: {
806
+ kind: 'end',
807
+ message: 'Mapping complete'
808
+ }
809
+ }
810
+ end
811
+ end
739
812
  end
740
813
  end
741
814
  end
@@ -62,7 +62,15 @@ module Solargraph
62
62
  end
63
63
  current = mutex.synchronize { queue.shift }
64
64
  return if queue.include?(current)
65
- host.diagnose current
65
+ begin
66
+ host.diagnose current
67
+ rescue InvalidOffsetError
68
+ # @todo This error can occur when the Source is out of sync with
69
+ # with the ApiMap. It's probably not the best way to handle it,
70
+ # but it's quick and easy.
71
+ Logging.logger.warn "Deferring diagnosis due to invalid offset: #{current}"
72
+ mutex.synchronize { queue.push current }
73
+ end
66
74
  end
67
75
 
68
76
  private
@@ -21,6 +21,7 @@ module Solargraph
21
21
  docs = pins
22
22
  .reject { |pin| pin.documentation.empty? && pin.return_type.undefined? }
23
23
  result = params
24
+ .transform_keys(&:to_sym)
24
25
  .merge(pins.first.resolve_completion_item)
25
26
  .merge(documentation: markup_content(join_docs(docs)))
26
27
  result[:detail] = pins.first.detail
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Make sure the environment page can report RuboCop's version
4
- require 'rubocop'
5
-
6
3
  module Solargraph
7
4
  module LanguageServer
8
5
  module Message
@@ -12,6 +9,9 @@ module Solargraph
12
9
  #
13
10
  class Environment < Base
14
11
  def process
12
+ # Make sure the environment page can report RuboCop's version
13
+ require 'rubocop'
14
+
15
15
  page = Solargraph::Page.new(host.options['viewsPath'])
16
16
  content = page.render('environment', layout: true, locals: { config: host.options, folders: host.folders })
17
17
  set_result(
@@ -1,49 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'benchmark'
4
-
5
3
  module Solargraph
6
4
  module LanguageServer
7
5
  module Message
8
6
  class Initialize < Base
9
7
  def process
10
- bm = Benchmark.measure {
11
- host.configure params['initializationOptions']
12
- host.client_capabilities = params['capabilities']
13
- if support_workspace_folders?
14
- host.prepare_folders params['workspaceFolders']
15
- elsif params['rootUri']
16
- host.prepare UriHelpers.uri_to_file(params['rootUri'])
17
- else
18
- host.prepare params['rootPath']
19
- end
20
- result = {
21
- capabilities: {
22
- textDocumentSync: 2, # @todo What should this be?
23
- workspace: {
24
- workspaceFolders: {
25
- supported: true,
26
- changeNotifications: true
27
- }
8
+ host.configure params['initializationOptions']
9
+ host.client_capabilities = params['capabilities']
10
+ if support_workspace_folders?
11
+ host.prepare_folders params['workspaceFolders']
12
+ elsif params['rootUri']
13
+ host.prepare UriHelpers.uri_to_file(params['rootUri'])
14
+ else
15
+ host.prepare params['rootPath']
16
+ end
17
+ result = {
18
+ capabilities: {
19
+ textDocumentSync: 2, # @todo What should this be?
20
+ workspace: {
21
+ workspaceFolders: {
22
+ supported: true,
23
+ changeNotifications: true
28
24
  }
29
25
  }
30
26
  }
31
- result[:capabilities].merge! static_completion unless dynamic_registration_for?('textDocument', 'completion')
32
- result[:capabilities].merge! static_signature_help unless dynamic_registration_for?('textDocument', 'signatureHelp')
33
- # result[:capabilities].merge! static_on_type_formatting unless dynamic_registration_for?('textDocument', 'onTypeFormatting')
34
- result[:capabilities].merge! static_hover unless dynamic_registration_for?('textDocument', 'hover')
35
- result[:capabilities].merge! static_document_formatting unless dynamic_registration_for?('textDocument', 'formatting')
36
- result[:capabilities].merge! static_document_symbols unless dynamic_registration_for?('textDocument', 'documentSymbol')
37
- result[:capabilities].merge! static_definitions unless dynamic_registration_for?('textDocument', 'definition')
38
- result[:capabilities].merge! static_rename unless dynamic_registration_for?('textDocument', 'rename')
39
- result[:capabilities].merge! static_references unless dynamic_registration_for?('textDocument', 'references')
40
- result[:capabilities].merge! static_workspace_symbols unless dynamic_registration_for?('workspace', 'symbol')
41
- result[:capabilities].merge! static_folding_range unless dynamic_registration_for?('textDocument', 'foldingRange')
42
- # @todo Temporarily disabled
43
- # result[:capabilities].merge! static_code_action unless dynamic_registration_for?('textDocument', 'codeAction')
44
- set_result result
45
27
  }
46
- Solargraph.logger.unknown "Solargraph initialized (#{bm.real} seconds)"
28
+ result[:capabilities].merge! static_completion unless dynamic_registration_for?('textDocument', 'completion')
29
+ result[:capabilities].merge! static_signature_help unless dynamic_registration_for?('textDocument', 'signatureHelp')
30
+ # result[:capabilities].merge! static_on_type_formatting unless dynamic_registration_for?('textDocument', 'onTypeFormatting')
31
+ result[:capabilities].merge! static_hover unless dynamic_registration_for?('textDocument', 'hover')
32
+ result[:capabilities].merge! static_document_formatting unless dynamic_registration_for?('textDocument', 'formatting')
33
+ result[:capabilities].merge! static_document_symbols unless dynamic_registration_for?('textDocument', 'documentSymbol')
34
+ result[:capabilities].merge! static_definitions unless dynamic_registration_for?('textDocument', 'definition')
35
+ result[:capabilities].merge! static_rename unless dynamic_registration_for?('textDocument', 'rename')
36
+ result[:capabilities].merge! static_references unless dynamic_registration_for?('textDocument', 'references')
37
+ result[:capabilities].merge! static_workspace_symbols unless dynamic_registration_for?('workspace', 'symbol')
38
+ result[:capabilities].merge! static_folding_range unless dynamic_registration_for?('textDocument', 'foldingRange')
39
+ # @todo Temporarily disabled
40
+ # result[:capabilities].merge! static_code_action unless dynamic_registration_for?('textDocument', 'codeAction')
41
+ set_result result
47
42
  end
48
43
 
49
44
  private
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rubocop'
4
3
  require 'securerandom'
5
4
  require 'tmpdir'
6
5
 
@@ -12,28 +11,79 @@ module Solargraph
12
11
  include Solargraph::Diagnostics::RubocopHelpers
13
12
 
14
13
  def process
15
- filename = uri_to_file(params['textDocument']['uri'])
16
- Dir.mktmpdir do |tempdir|
17
- tempfile = File.join(tempdir, File.basename(filename))
18
- rubocop_file = Diagnostics::RubocopHelpers.find_rubocop_file(filename)
19
- original = host.read_text(params['textDocument']['uri'])
20
- File.write tempfile, original
21
- begin
22
- args = ['-a', '-f', 'fi', tempfile]
23
- args.unshift('-c', fix_drive_letter(rubocop_file)) unless rubocop_file.nil?
24
- options, paths = RuboCop::Options.new.parse(args)
25
- store = RuboCop::ConfigStore.new
26
- redirect_stdout { RuboCop::Runner.new(options, store).run(paths) }
27
- result = File.read(tempfile)
28
- format original, result
29
- rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
30
- set_error(Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}")
31
- end
14
+ file_uri = params['textDocument']['uri']
15
+ config = config_for(file_uri)
16
+ original = host.read_text(file_uri)
17
+ args = cli_args(file_uri, config)
18
+
19
+ require_rubocop(config['version'])
20
+ options, paths = RuboCop::Options.new.parse(args)
21
+ options[:stdin] = original
22
+ corrections = redirect_stdout do
23
+ RuboCop::Runner.new(options, RuboCop::ConfigStore.new).run(paths)
32
24
  end
25
+ result = options[:stdin]
26
+
27
+ log_corrections(corrections)
28
+
29
+ format original, result
30
+ rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
31
+ set_error(Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}")
33
32
  end
34
33
 
35
34
  private
36
35
 
36
+ def log_corrections(corrections)
37
+ corrections = corrections&.strip
38
+ return if corrections&.empty?
39
+
40
+ Solargraph.logger.info('Formatting result:')
41
+ corrections.each_line do |line|
42
+ next if line.strip.empty?
43
+ Solargraph.logger.info(line.strip)
44
+ end
45
+ end
46
+
47
+ def config_for(file_uri)
48
+ conf = host.formatter_config(file_uri)
49
+ return {} unless conf.is_a?(Hash)
50
+
51
+ conf['rubocop'] || {}
52
+ end
53
+
54
+ def cli_args file_uri, config
55
+ file = UriHelpers.uri_to_file(file_uri)
56
+ args = [
57
+ config['cops'] == 'all' ? '--auto-correct-all' : '--auto-correct',
58
+ '--cache', 'false',
59
+ '--format', formatter_class(config).name,
60
+ ]
61
+
62
+ ['except', 'only'].each do |arg|
63
+ cops = cop_list(config[arg])
64
+ args += ["--#{arg}", cops] if cops
65
+ end
66
+
67
+ args += config['extra_args'] if config['extra_args']
68
+ args + [file]
69
+ end
70
+
71
+ def formatter_class(config)
72
+ if self.class.const_defined?('BlankRubocopFormatter')
73
+ BlankRubocopFormatter
74
+ else
75
+ require_rubocop(config['version'])
76
+ klass = Class.new(::RuboCop::Formatter::BaseFormatter)
77
+ self.class.const_set 'BlankRubocopFormatter', klass
78
+ end
79
+ end
80
+
81
+ def cop_list(value)
82
+ value = value.join(',') if value.respond_to?(:join)
83
+ return nil if value == '' || !value.is_a?(String)
84
+ value
85
+ end
86
+
37
87
  # @param original [String]
38
88
  # @param result [String]
39
89
  # @return [void]
@@ -17,7 +17,7 @@ module Solargraph
17
17
  if !this_link.nil? && this_link != last_link
18
18
  parts.push this_link
19
19
  end
20
- parts.push pin.detail.gsub(':', '\\:') unless pin.is_a?(Pin::Namespace) || pin.detail.nil?
20
+ parts.push "`#{pin.detail}`" unless pin.is_a?(Pin::Namespace) || pin.detail.nil?
21
21
  parts.push pin.documentation unless pin.documentation.nil? || pin.documentation.empty?
22
22
  unless parts.empty?
23
23
  data = parts.join("\n\n")
@@ -20,9 +20,7 @@ module Solargraph
20
20
  def initialize workspace = Solargraph::Workspace.new, name = nil
21
21
  @workspace = workspace
22
22
  @name = name
23
- api_map.catalog bench
24
- @synchronized = true
25
- @catalog_mutex = Mutex.new
23
+ @synchronized = false
26
24
  end
27
25
 
28
26
  def inspect
@@ -48,9 +46,13 @@ module Solargraph
48
46
  # @return [void]
49
47
  def attach source
50
48
  mutex.synchronize do
51
- @synchronized = (@current == source) if synchronized?
49
+ if @current && @current.filename != source.filename && source_map_hash.key?(@current.filename) && !workspace.has_file?(@current.filename)
50
+ source_map_hash.delete @current.filename
51
+ @synchronized = false
52
+ end
52
53
  @current = source
53
- catalog
54
+ maybe_map @current
55
+ api_map.catalog bench unless synchronized?
54
56
  end
55
57
  end
56
58
 
@@ -110,9 +112,9 @@ module Solargraph
110
112
  mutex.synchronize do
111
113
  next if File.directory?(filename) || !File.exist?(filename)
112
114
  next unless contain?(filename) || open?(filename) || workspace.would_merge?(filename)
113
- @synchronized = false
114
115
  source = Solargraph::Source.load_string(File.read(filename), filename)
115
116
  workspace.merge(source)
117
+ maybe_map source
116
118
  result = true
117
119
  end
118
120
  result
@@ -158,6 +160,8 @@ module Solargraph
158
160
  position = Position.new(line, column)
159
161
  cursor = Source::Cursor.new(read(filename), position)
160
162
  api_map.clip(cursor).complete
163
+ rescue FileNotFoundError => e
164
+ handle_file_not_found filename, e
161
165
  end
162
166
 
163
167
  # Get definition suggestions for the expression at the specified file and
@@ -186,6 +190,8 @@ module Solargraph
186
190
  else
187
191
  api_map.clip(cursor).define.map { |pin| pin.realize(api_map) }
188
192
  end
193
+ rescue FileNotFoundError => e
194
+ handle_file_not_found(filename, e)
189
195
  end
190
196
 
191
197
  # Get signature suggestions for the method at the specified file and
@@ -260,14 +266,12 @@ module Solargraph
260
266
  # @param query [String]
261
267
  # @return [Array<YARD::CodeObjects::Base>]
262
268
  def document query
263
- catalog
264
269
  api_map.document query
265
270
  end
266
271
 
267
272
  # @param query [String]
268
273
  # @return [Array<String>]
269
274
  def search query
270
- catalog
271
275
  api_map.search query
272
276
  end
273
277
 
@@ -276,7 +280,6 @@ module Solargraph
276
280
  # @param query [String]
277
281
  # @return [Array<Pin::Base>]
278
282
  def query_symbols query
279
- catalog
280
283
  api_map.query_symbols query
281
284
  end
282
285
 
@@ -295,10 +298,13 @@ module Solargraph
295
298
  # @param path [String]
296
299
  # @return [Array<Solargraph::Pin::Base>]
297
300
  def path_pins path
298
- catalog
299
301
  api_map.get_path_suggestions(path)
300
302
  end
301
303
 
304
+ def source_maps
305
+ source_map_hash.values
306
+ end
307
+
302
308
  # Get the current text of a file in the library.
303
309
  #
304
310
  # @param filename [String]
@@ -318,7 +324,6 @@ module Solargraph
318
324
  # be an option to do so.
319
325
  #
320
326
  return [] unless open?(filename)
321
- catalog
322
327
  result = []
323
328
  source = read(filename)
324
329
  repargs = {}
@@ -346,7 +351,7 @@ module Solargraph
346
351
  #
347
352
  # @return [void]
348
353
  def catalog
349
- @catalog_mutex.synchronize do
354
+ mutex.synchronize do
350
355
  break if synchronized?
351
356
  logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
352
357
  api_map.catalog bench
@@ -355,6 +360,17 @@ module Solargraph
355
360
  end
356
361
  end
357
362
 
363
+ def bench
364
+ source_maps = @current ? [@current] : []
365
+ source_maps.concat source_map_hash.values
366
+ Bench.new(
367
+ source_maps: source_maps,
368
+ load_paths: workspace.require_paths,
369
+ gemnames: workspace.gemnames,
370
+ directory: workspace.directory
371
+ )
372
+ end
373
+
358
374
  # Get an array of foldable ranges for the specified file.
359
375
  #
360
376
  # @deprecated The library should not need to handle folding ranges. The
@@ -381,14 +397,49 @@ module Solargraph
381
397
  # @param source [Source]
382
398
  # @return [Boolean] True if the source was merged into the workspace.
383
399
  def merge source
400
+ Logging.logger.debug "Merging source: #{source.filename}"
384
401
  result = false
385
402
  mutex.synchronize do
386
403
  result = workspace.merge(source)
387
- @synchronized = !result if synchronized?
404
+ maybe_map source
388
405
  end
406
+ # catalog
389
407
  result
390
408
  end
391
409
 
410
+ def source_map_hash
411
+ @source_map_hash ||= {}
412
+ end
413
+
414
+ def mapped?
415
+ (workspace.filenames - source_map_hash.keys).empty?
416
+ end
417
+
418
+ def next_map
419
+ return false if mapped?
420
+ mutex.synchronize do
421
+ @synchronized = false
422
+ src = workspace.sources.find { |s| !source_map_hash.key?(s.filename) }
423
+ if src
424
+ Logging.logger.debug "Mapping #{src.filename}"
425
+ source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
426
+ else
427
+ false
428
+ end
429
+ end
430
+ end
431
+
432
+ def map!
433
+ workspace.sources.each do |src|
434
+ source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
435
+ end
436
+ self
437
+ end
438
+
439
+ def pins
440
+ @pins ||= []
441
+ end
442
+
392
443
  private
393
444
 
394
445
  # @return [Mutex]
@@ -401,14 +452,6 @@ module Solargraph
401
452
  @api_map ||= Solargraph::ApiMap.new
402
453
  end
403
454
 
404
- # @return [Bench]
405
- def bench
406
- Bench.new(
407
- workspace: workspace,
408
- opened: @current ? [@current] : []
409
- )
410
- end
411
-
412
455
  # Get the source for an open file or create a new source if the file
413
456
  # exists on disk. Sources created from disk are not added to the open
414
457
  # workspace files, i.e., the version on disk remains the authoritative
@@ -422,5 +465,35 @@ module Solargraph
422
465
  raise FileNotFoundError, "File not found: #{filename}" unless workspace.has_file?(filename)
423
466
  workspace.source(filename)
424
467
  end
468
+
469
+ def handle_file_not_found filename, error
470
+ if workspace.source(filename)
471
+ Solargraph.logger.debug "#{filename} is not cataloged in the ApiMap"
472
+ nil
473
+ else
474
+ raise error
475
+ end
476
+ end
477
+
478
+ def maybe_map source
479
+ if source_map_hash.key?(source.filename)
480
+ return if source_map_hash[source.filename].code == source.code &&
481
+ source_map_hash[source.filename].source.synchronized? &&
482
+ source.synchronized?
483
+ if source.synchronized?
484
+ new_map = Solargraph::SourceMap.map(source)
485
+ unless source_map_hash[source.filename].try_merge!(new_map)
486
+ source_map_hash[source.filename] = new_map
487
+ @synchronized = false
488
+ end
489
+ else
490
+ # @todo Smelly instance variable access
491
+ source_map_hash[source.filename].instance_variable_set(:@source, source)
492
+ end
493
+ else
494
+ source_map_hash[source.filename] = Solargraph::SourceMap.map(source)
495
+ @synchronized = false
496
+ end
497
+ end
425
498
  end
426
499
  end