solargraph 0.40.1 → 0.41.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +15 -0
- data/SPONSORS.md +1 -0
- data/lib/.rubocop.yml +1 -1
- 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/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/legacy/node_methods.rb +4 -0
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -1
- data/lib/solargraph/parser/rubyvm/node_methods.rb +9 -2
- 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 +49 -39
- 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
- data/solargraph.gemspec +1 -1
- metadata +4 -4
@@ -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
|
@@ -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.gsub(':', '\\:') unless pin.is_a?(Pin::Namespace) || pin.detail.nil?
|
20
|
+
parts.push "`" + pin.detail.gsub(':', '\\:') + "`" 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
|