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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +15 -0
- data/SPONSORS.md +1 -0
- data/lib/.rubocop.yml +2 -2
- data/lib/solargraph.rb +8 -7
- data/lib/solargraph/api_map.rb +52 -75
- data/lib/solargraph/api_map/store.rb +5 -0
- data/lib/solargraph/bench.rb +19 -18
- data/lib/solargraph/compat.rb +15 -1
- data/lib/solargraph/diagnostics/rubocop.rb +10 -2
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +19 -20
- data/lib/solargraph/language_server/host.rb +74 -1
- data/lib/solargraph/language_server/host/diagnoser.rb +9 -1
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +1 -0
- data/lib/solargraph/language_server/message/extended/environment.rb +3 -3
- data/lib/solargraph/language_server/message/initialize.rb +30 -35
- data/lib/solargraph/language_server/message/text_document/formatting.rb +68 -18
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
- data/lib/solargraph/library.rb +94 -21
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -1
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +11 -12
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +1 -6
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +1 -1
- data/lib/solargraph/source.rb +1 -1
- data/lib/solargraph/source/chain/head.rb +0 -16
- data/lib/solargraph/source/source_chainer.rb +1 -0
- data/lib/solargraph/source_map/mapper.rb +0 -5
- data/lib/solargraph/type_checker.rb +25 -22
- data/lib/solargraph/type_checker/checks.rb +9 -5
- data/lib/solargraph/type_checker/rules.rb +5 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +19 -3
- data/lib/solargraph/yard_map/core_fills.rb +1 -0
- 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
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
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")
|
data/lib/solargraph/library.rb
CHANGED
@@ -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
|
-
|
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
|
-
@
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|