solargraph 0.30.2 → 0.31.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.
- checksums.yaml +4 -4
- data/lib/solargraph.rb +7 -0
- data/lib/solargraph/api_map.rb +31 -38
- data/lib/solargraph/api_map/store.rb +7 -1
- data/lib/solargraph/diagnostics/require_not_found.rb +2 -1
- data/lib/solargraph/language_server/host.rb +34 -83
- data/lib/solargraph/language_server/host/cataloger.rb +17 -7
- data/lib/solargraph/language_server/host/diagnoser.rb +19 -10
- data/lib/solargraph/language_server/host/dispatch.rb +110 -0
- data/lib/solargraph/language_server/host/sources.rb +100 -1
- data/lib/solargraph/language_server/message/base.rb +15 -11
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
- data/lib/solargraph/language_server/message/initialize.rb +32 -27
- data/lib/solargraph/language_server/message/text_document/completion.rb +1 -8
- data/lib/solargraph/language_server/transport/adapter.rb +26 -15
- data/lib/solargraph/language_server/transport/data_reader.rb +2 -2
- data/lib/solargraph/library.rb +30 -58
- data/lib/solargraph/live_map.rb +1 -1
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/pin/base.rb +1 -1
- data/lib/solargraph/pin/base_method.rb +1 -1
- data/lib/solargraph/pin/method.rb +1 -1
- data/lib/solargraph/pin/method_alias.rb +15 -4
- data/lib/solargraph/plugin/process.rb +1 -1
- data/lib/solargraph/position.rb +1 -2
- data/lib/solargraph/server_methods.rb +1 -0
- data/lib/solargraph/shell.rb +0 -28
- data/lib/solargraph/source.rb +116 -20
- data/lib/solargraph/source/encoding_fixes.rb +1 -1
- data/lib/solargraph/source/source_chainer.rb +16 -8
- data/lib/solargraph/source_map.rb +11 -2
- data/lib/solargraph/source_map/clip.rb +1 -1
- data/lib/solargraph/source_map/mapper.rb +8 -5
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +3 -0
- data/lib/solargraph/workspace.rb +17 -14
- data/lib/solargraph/workspace/config.rb +1 -1
- data/lib/solargraph/yard_map.rb +6 -5
- data/lib/solargraph/yard_map/core_docs.rb +68 -18
- data/lib/solargraph/yard_map/core_gen.rb +47 -0
- data/lib/yard-coregen.rb +16 -0
- data/lib/yard-solargraph.rb +10 -1
- metadata +21 -4
@@ -4,13 +4,6 @@ module Solargraph
|
|
4
4
|
module TextDocument
|
5
5
|
class Completion < Base
|
6
6
|
def process
|
7
|
-
inner_process
|
8
|
-
end
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
# @return [void]
|
13
|
-
def inner_process
|
14
7
|
filename = uri_to_file(params['textDocument']['uri'])
|
15
8
|
line = params['position']['line']
|
16
9
|
col = params['position']['character']
|
@@ -39,7 +32,7 @@ module Solargraph
|
|
39
32
|
items: items
|
40
33
|
)
|
41
34
|
rescue InvalidOffsetError => e
|
42
|
-
|
35
|
+
Logging.logger.info "Completion ignored invalid offset: #{filename}, line #{line}, character #{col}"
|
43
36
|
set_result empty_result
|
44
37
|
end
|
45
38
|
end
|
@@ -4,20 +4,20 @@ module Solargraph
|
|
4
4
|
# A common module for running language servers in Backport.
|
5
5
|
#
|
6
6
|
module Adapter
|
7
|
+
@@timer_is_running = false
|
8
|
+
|
7
9
|
def opening
|
8
10
|
@host = Solargraph::LanguageServer::Host.new
|
11
|
+
@host.start
|
9
12
|
@data_reader = Solargraph::LanguageServer::Transport::DataReader.new
|
10
13
|
@data_reader.set_message_handler do |message|
|
11
14
|
process message
|
12
15
|
end
|
13
|
-
|
16
|
+
start_timer
|
14
17
|
end
|
15
18
|
|
16
|
-
def
|
17
|
-
|
18
|
-
message.send_response
|
19
|
-
tmp = @host.flush
|
20
|
-
write tmp unless tmp.empty?
|
19
|
+
def closing
|
20
|
+
@host.stop
|
21
21
|
end
|
22
22
|
|
23
23
|
# @param data [String]
|
@@ -27,19 +27,30 @@ module Solargraph
|
|
27
27
|
|
28
28
|
private
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
# @param request [String]
|
31
|
+
# @return [void]
|
32
|
+
def process request
|
33
|
+
message = @host.receive(request)
|
34
|
+
message.send_response
|
35
|
+
tmp = @host.flush
|
36
|
+
write tmp unless tmp.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
def start_timer
|
40
|
+
Backport.prepare_interval 0.1 do |server|
|
34
41
|
if @host.stopped?
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
42
|
+
server.stop
|
43
|
+
shutdown
|
44
|
+
else
|
45
|
+
tmp = @host.flush
|
46
|
+
write tmp unless tmp.empty?
|
40
47
|
end
|
41
48
|
end
|
42
49
|
end
|
50
|
+
|
51
|
+
def shutdown
|
52
|
+
Backport.stop unless @host.options['transport'] == 'external'
|
53
|
+
end
|
43
54
|
end
|
44
55
|
end
|
45
56
|
end
|
@@ -52,8 +52,8 @@ module Solargraph
|
|
52
52
|
msg = JSON.parse(@buffer)
|
53
53
|
@message_handler.call msg unless @message_handler.nil?
|
54
54
|
rescue JSON::ParserError => e
|
55
|
-
|
56
|
-
|
55
|
+
Solargraph::Logging.logger.info "Failed to parse request: #{e.message}"
|
56
|
+
Solargraph::Logging.logger.debug "Buffer: #{@buffer}"
|
57
57
|
ensure
|
58
58
|
@buffer.clear
|
59
59
|
@in_header = true
|
data/lib/solargraph/library.rb
CHANGED
@@ -20,6 +20,11 @@ module Solargraph
|
|
20
20
|
@catalog_mutex = Mutex.new
|
21
21
|
end
|
22
22
|
|
23
|
+
def inspect
|
24
|
+
# Let's not deal with insane data dumps in spec failures
|
25
|
+
to_s
|
26
|
+
end
|
27
|
+
|
23
28
|
# True if the ApiMap is up to date with the library's workspace and open
|
24
29
|
# files.
|
25
30
|
#
|
@@ -28,23 +33,6 @@ module Solargraph
|
|
28
33
|
@synchronized
|
29
34
|
end
|
30
35
|
|
31
|
-
# Open a file in the library. Opening a file will make it available for
|
32
|
-
# checkout and merge it into the workspace if applicable.
|
33
|
-
#
|
34
|
-
# @deprecated The library should not be responsible for this. Instead, it
|
35
|
-
# should accept a source and determine whether or not to merge it.
|
36
|
-
#
|
37
|
-
# @param filename [String]
|
38
|
-
# @param text [String]
|
39
|
-
# @param version [Integer]
|
40
|
-
# @return [void]
|
41
|
-
def open filename, text, version
|
42
|
-
logger.warn "Library#open is deprecated"
|
43
|
-
source = Solargraph::Source.load_string(text, filename, version)
|
44
|
-
merge source
|
45
|
-
attach source
|
46
|
-
end
|
47
|
-
|
48
36
|
# Open a file from disk and try to merge it into the workspace.
|
49
37
|
#
|
50
38
|
# @param filename [String]
|
@@ -60,7 +48,7 @@ module Solargraph
|
|
60
48
|
# library will include it in the ApiMap while it's attached. Only one
|
61
49
|
# source can be attached to the library at a time.
|
62
50
|
#
|
63
|
-
# @param source [Source]
|
51
|
+
# @param source [Source, nil]
|
64
52
|
# @return [void]
|
65
53
|
def attach source
|
66
54
|
mutex.synchronize do
|
@@ -78,6 +66,16 @@ module Solargraph
|
|
78
66
|
end
|
79
67
|
alias open? attached?
|
80
68
|
|
69
|
+
# Detach the specified file if it is currently attached to the library.
|
70
|
+
#
|
71
|
+
# @param filename [String]
|
72
|
+
# @return [Boolean] True if the specified file was detached
|
73
|
+
def detach filename
|
74
|
+
return false if @current.nil? || @current.filename != filename
|
75
|
+
attach nil
|
76
|
+
true
|
77
|
+
end
|
78
|
+
|
81
79
|
# True if the specified file is included in the workspace (but not
|
82
80
|
# necessarily open).
|
83
81
|
#
|
@@ -130,11 +128,10 @@ module Solargraph
|
|
130
128
|
# @param filename [String]
|
131
129
|
# @return [void]
|
132
130
|
def delete filename
|
131
|
+
detach filename
|
133
132
|
mutex.synchronize do
|
134
|
-
|
135
|
-
@
|
136
|
-
workspace.remove filename
|
137
|
-
# catalog
|
133
|
+
result = workspace.remove(filename)
|
134
|
+
@synchronized = !result if synchronized?
|
138
135
|
end
|
139
136
|
end
|
140
137
|
|
@@ -206,7 +203,7 @@ module Solargraph
|
|
206
203
|
return [] if pins.empty?
|
207
204
|
result = []
|
208
205
|
pins.uniq.each do |pin|
|
209
|
-
(workspace.sources + (@current ? [@current] : [])).uniq.each do |source|
|
206
|
+
(workspace.sources + (@current ? [@current] : [])).uniq(&:filename).each do |source|
|
210
207
|
found = source.references(pin.name)
|
211
208
|
found.select! do |loc|
|
212
209
|
referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character)
|
@@ -223,7 +220,7 @@ module Solargraph
|
|
223
220
|
end)
|
224
221
|
end
|
225
222
|
end
|
226
|
-
result
|
223
|
+
result.uniq
|
227
224
|
end
|
228
225
|
|
229
226
|
# Get the pin at the specified location or nil if the pin does not exist.
|
@@ -256,7 +253,10 @@ module Solargraph
|
|
256
253
|
checked = read(filename)
|
257
254
|
@synchronized = (checked == @current) if synchronized?
|
258
255
|
@current = checked
|
259
|
-
|
256
|
+
# Cataloging is necessary to avoid FileNotFoundErrors when the file is
|
257
|
+
# not in the workspace. Otherwise it should be safe to defer
|
258
|
+
# synchronization.
|
259
|
+
catalog unless workspace.has_file?(filename)
|
260
260
|
@current
|
261
261
|
end
|
262
262
|
|
@@ -303,30 +303,6 @@ module Solargraph
|
|
303
303
|
api_map.get_path_suggestions(path)
|
304
304
|
end
|
305
305
|
|
306
|
-
# Update a source in the library from the provided updater.
|
307
|
-
#
|
308
|
-
# @note This method will not update the library's ApiMap. See
|
309
|
-
# Library#synchronized? and Library#catalog for more information.
|
310
|
-
#
|
311
|
-
# @deprecated The library should not be responsible for this. Instead, it
|
312
|
-
# should accept a source and determine whether or not to merge it.
|
313
|
-
#
|
314
|
-
# @raise [FileNotFoundError] if the updater's file is not available.
|
315
|
-
# @param updater [Solargraph::Source::Updater]
|
316
|
-
# @return [void]
|
317
|
-
def update updater
|
318
|
-
logger.warn 'Library#update is deprecated'
|
319
|
-
mutex.synchronize do
|
320
|
-
if workspace.has_file?(updater.filename)
|
321
|
-
workspace.synchronize!(updater)
|
322
|
-
@current = workspace.source(updater.filename) if @current && @current.filename == updater.filename
|
323
|
-
elsif @current && @current.filename == updater.filename
|
324
|
-
@current = @current.synchronize(updater)
|
325
|
-
end
|
326
|
-
@synchronized = false
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
306
|
# Get the current text of a file in the library.
|
331
307
|
#
|
332
308
|
# @param filename [String]
|
@@ -366,25 +342,21 @@ module Solargraph
|
|
366
342
|
logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
|
367
343
|
api_map.catalog bundle
|
368
344
|
@synchronized = true
|
345
|
+
logger.info "Catalog complete (#{api_map.pins.length} pins)"
|
369
346
|
end
|
370
347
|
end
|
371
348
|
|
372
349
|
# Get an array of foldable ranges for the specified file.
|
373
350
|
#
|
351
|
+
# @deprecated The library should not need to handle folding ranges. The
|
352
|
+
# source itself has all the information it needs.
|
353
|
+
#
|
374
354
|
# @param filename [String]
|
375
355
|
# @return [Array<Range>]
|
376
356
|
def folding_ranges filename
|
377
357
|
read(filename).folding_ranges
|
378
358
|
end
|
379
359
|
|
380
|
-
# @deprecated Libraries are no longer responsible for tracking open files.
|
381
|
-
#
|
382
|
-
# @return [Array<Source>]
|
383
|
-
def open_sources
|
384
|
-
logger.warn 'Library#open_sources is deprecated'
|
385
|
-
@current ? [@current] : []
|
386
|
-
end
|
387
|
-
|
388
360
|
# Create a library from a directory.
|
389
361
|
#
|
390
362
|
# @param directory [String] The path to be used for the workspace
|
@@ -403,7 +375,7 @@ module Solargraph
|
|
403
375
|
result = nil
|
404
376
|
mutex.synchronize do
|
405
377
|
result = workspace.merge(source)
|
406
|
-
@synchronized = result if synchronized?
|
378
|
+
@synchronized = !result if synchronized?
|
407
379
|
end
|
408
380
|
result
|
409
381
|
end
|
data/lib/solargraph/live_map.rb
CHANGED
data/lib/solargraph/pin.rb
CHANGED
data/lib/solargraph/pin/base.rb
CHANGED
@@ -167,7 +167,7 @@ module Solargraph
|
|
167
167
|
# @param api_map [ApiMap]
|
168
168
|
# @return [ComplexType]
|
169
169
|
def infer api_map
|
170
|
-
|
170
|
+
Solargraph::Logging.logger.warn "WARNING: Pin #infer methods are deprecated. Use #typify or #probe instead."
|
171
171
|
type = typify(api_map)
|
172
172
|
return type unless type.undefined?
|
173
173
|
probe api_map
|
@@ -82,7 +82,7 @@ module Solargraph
|
|
82
82
|
|
83
83
|
# @deprecated Use #typify and/or #probe instead
|
84
84
|
def infer api_map
|
85
|
-
|
85
|
+
Solargraph::Logging.logger.warn 'WARNING: Pin #infer methods are deprecated. Use #typify or #probe instead.'
|
86
86
|
type = typify(api_map)
|
87
87
|
return type unless type.undefined?
|
88
88
|
probe api_map
|
@@ -1,19 +1,30 @@
|
|
1
1
|
module Solargraph
|
2
2
|
module Pin
|
3
3
|
# Use this class to track method aliases for later remapping. Common
|
4
|
-
# examples are aliases for superclass methods or
|
5
|
-
# modules.
|
4
|
+
# examples that defer mapping are aliases for superclass methods or
|
5
|
+
# methods from included modules.
|
6
6
|
#
|
7
|
-
class MethodAlias <
|
7
|
+
class MethodAlias < Base
|
8
|
+
attr_reader :scope
|
9
|
+
|
8
10
|
attr_reader :original
|
9
11
|
|
10
12
|
def initialize location, namespace, name, scope, original
|
11
13
|
# @todo Determine how to handle these parameters. Among other things,
|
12
14
|
# determine if the visibility is defined by the location of the
|
13
15
|
# alias call or the original method.
|
14
|
-
super(location, namespace, name, ''
|
16
|
+
super(location, namespace, name, '')
|
17
|
+
@scope = scope
|
15
18
|
@original = original
|
16
19
|
end
|
20
|
+
|
21
|
+
def kind
|
22
|
+
Pin::METHOD_ALIAS
|
23
|
+
end
|
24
|
+
|
25
|
+
def path
|
26
|
+
@path ||= namespace + (scope == :instance ? '#' : '.') + name
|
27
|
+
end
|
17
28
|
end
|
18
29
|
end
|
19
30
|
end
|
@@ -48,7 +48,7 @@ module Solargraph
|
|
48
48
|
require p
|
49
49
|
@required.push p
|
50
50
|
rescue Exception => e
|
51
|
-
|
51
|
+
Solargraph::Logging.logger.info "Failed to require #{p}: #{e.message}"
|
52
52
|
errors.push "Failed to require #{p}: #{e.class} #{e.message}"
|
53
53
|
end
|
54
54
|
end
|
data/lib/solargraph/position.rb
CHANGED
@@ -44,7 +44,6 @@ module Solargraph
|
|
44
44
|
column = position.character
|
45
45
|
text.lines.each do |l|
|
46
46
|
line_length = l.length
|
47
|
-
char_length = l.chomp.length
|
48
47
|
if feed == line
|
49
48
|
result += column
|
50
49
|
break
|
@@ -85,7 +84,7 @@ module Solargraph
|
|
85
84
|
cursor += line_length
|
86
85
|
line += 1
|
87
86
|
end
|
88
|
-
character = 0 if character.nil? and offset
|
87
|
+
character = 0 if character.nil? and (cursor - offset).between?(0, 1)
|
89
88
|
raise InvalidOffsetError if character.nil?
|
90
89
|
Position.new(line, character)
|
91
90
|
end
|
data/lib/solargraph/shell.rb
CHANGED
@@ -48,34 +48,6 @@ module Solargraph
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
desc 'suggest', 'Get code suggestions for the provided input'
|
52
|
-
long_desc <<-LONGDESC
|
53
|
-
Analyze a Ruby file and output a list of code suggestions in JSON format.
|
54
|
-
LONGDESC
|
55
|
-
option :line, type: :numeric, aliases: :l, desc: 'Zero-based line number', required: true
|
56
|
-
option :column, type: :numeric, aliases: [:c, :col], desc: 'Zero-based column number', required: true
|
57
|
-
option :filename, type: :string, aliases: :f, desc: 'File name', required: false
|
58
|
-
def suggest(*filenames)
|
59
|
-
STDERR.puts "WARNING: The `solargraph suggest` command is a candidate for deprecation. It will either change drastically or not exist in a future version."
|
60
|
-
# HACK: The ARGV array needs to be manipulated for ARGF.read to work
|
61
|
-
ARGV.clear
|
62
|
-
ARGV.concat filenames
|
63
|
-
text = ARGF.read
|
64
|
-
filename = options[:filename] || filenames[0]
|
65
|
-
begin
|
66
|
-
code_map = CodeMap.new(code: text, filename: filename)
|
67
|
-
offset = code_map.get_offset(options[:line], options[:column])
|
68
|
-
sugg = code_map.suggest_at(offset, filtered: true)
|
69
|
-
result = { "status" => "ok", "suggestions" => sugg }.to_json
|
70
|
-
STDOUT.puts result
|
71
|
-
rescue Exception => e
|
72
|
-
STDERR.puts e
|
73
|
-
STDERR.puts e.backtrace.join("\n")
|
74
|
-
result = { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
|
75
|
-
STDOUT.puts result
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
51
|
desc 'config [DIRECTORY]', 'Create or overwrite a default configuration file'
|
80
52
|
option :extensions, type: :boolean, aliases: :e, desc: 'Add installed extensions', default: true
|
81
53
|
def config(directory = '.')
|
data/lib/solargraph/source.rb
CHANGED
@@ -18,6 +18,9 @@ module Solargraph
|
|
18
18
|
include EncodingFixes
|
19
19
|
include NodeMethods
|
20
20
|
|
21
|
+
# @return [String]
|
22
|
+
attr_reader :filename
|
23
|
+
|
21
24
|
# @return [String]
|
22
25
|
attr_reader :code
|
23
26
|
|
@@ -27,9 +30,6 @@ module Solargraph
|
|
27
30
|
# @return [Array<Parser::Source::Comment>]
|
28
31
|
attr_reader :comments
|
29
32
|
|
30
|
-
# @return [String]
|
31
|
-
attr_reader :filename
|
32
|
-
|
33
33
|
# @todo Deprecate?
|
34
34
|
# @return [Integer]
|
35
35
|
attr_reader :version
|
@@ -64,10 +64,16 @@ module Solargraph
|
|
64
64
|
end
|
65
65
|
|
66
66
|
# @param range [Solargraph::Range]
|
67
|
+
# @return [String]
|
67
68
|
def at range
|
68
69
|
from_to range.start.line, range.start.character, range.ending.line, range.ending.character
|
69
70
|
end
|
70
71
|
|
72
|
+
# @param l1 [Integer]
|
73
|
+
# @param c1 [Integer]
|
74
|
+
# @param l2 [Integer]
|
75
|
+
# @param c2 [Integer]
|
76
|
+
# @return [String]
|
71
77
|
def from_to l1, c1, l2, c2
|
72
78
|
b = Solargraph::Position.line_char_to_offset(@code, l1, c1)
|
73
79
|
e = Solargraph::Position.line_char_to_offset(@code, l2, c2)
|
@@ -97,8 +103,53 @@ module Solargraph
|
|
97
103
|
stack
|
98
104
|
end
|
99
105
|
|
106
|
+
# Start synchronizing the source. This method updates the code without
|
107
|
+
# parsing a new AST. The resulting Source object will be marked not
|
108
|
+
# synchronized (#synchronized? == false).
|
109
|
+
#
|
110
|
+
# @param updater [Source::Updater]
|
111
|
+
# @return [Source]
|
112
|
+
def start_synchronize updater
|
113
|
+
raise 'Invalid synchronization' unless updater.filename == filename
|
114
|
+
real_code = updater.write(@code)
|
115
|
+
src = Source.allocate
|
116
|
+
src.filename = filename
|
117
|
+
src.code = real_code
|
118
|
+
src.version = updater.version
|
119
|
+
src.parsed = parsed?
|
120
|
+
src.repaired = updater.repair(@repaired)
|
121
|
+
src.synchronized = false
|
122
|
+
src.node = @node
|
123
|
+
src.comments = @comments
|
124
|
+
src.error_ranges = error_ranges
|
125
|
+
src.last_updater = updater
|
126
|
+
src
|
127
|
+
end
|
128
|
+
|
129
|
+
# Finish synchronizing a source that was updated via #start_synchronize.
|
130
|
+
# This method returns self if the source is already synchronized. Otherwise
|
131
|
+
# it parses the AST and returns a new synchronized Source.
|
132
|
+
#
|
133
|
+
# @return [Source]
|
134
|
+
def finish_synchronize
|
135
|
+
return self if synchronized?
|
136
|
+
synced = Source.new(@code, filename)
|
137
|
+
if synced.parsed?
|
138
|
+
synced.version = version
|
139
|
+
return synced
|
140
|
+
end
|
141
|
+
synced = Source.new(@repaired, filename)
|
142
|
+
synced.error_ranges.concat (error_ranges + last_updater.changes.map(&:range))
|
143
|
+
synced.code = @code
|
144
|
+
synced.synchronized = true
|
145
|
+
synced.version = version
|
146
|
+
synced
|
147
|
+
end
|
148
|
+
|
149
|
+
# Synchronize the Source with an update. This method applies changes to the
|
150
|
+
# code, parses the new code's AST, and returns the resulting Source object.
|
151
|
+
#
|
100
152
|
# @param updater [Source::Updater]
|
101
|
-
# @param reparse [Boolean]
|
102
153
|
# @return [Source]
|
103
154
|
def synchronize updater
|
104
155
|
raise 'Invalid synchronization' unless updater.filename == filename
|
@@ -177,11 +228,9 @@ module Solargraph
|
|
177
228
|
@error_ranges ||= []
|
178
229
|
end
|
179
230
|
|
231
|
+
# @param node [Parser::AST::Node]
|
232
|
+
# @return [String]
|
180
233
|
def code_for(node)
|
181
|
-
# @todo Using node locations on code with converted EOLs seems
|
182
|
-
# slightly more efficient than calculating offsets.
|
183
|
-
# b = node.location.expression.begin.begin_pos
|
184
|
-
# e = node.location.expression.end.end_pos
|
185
234
|
b = Position.line_char_to_offset(@code, node.location.line, node.location.column)
|
186
235
|
e = Position.line_char_to_offset(@code, node.location.last_line, node.location.last_column)
|
187
236
|
frag = code[b..e-1].to_s
|
@@ -191,8 +240,10 @@ module Solargraph
|
|
191
240
|
# @param node [Parser::AST::Node]
|
192
241
|
# @return [String]
|
193
242
|
def comments_for node
|
194
|
-
|
195
|
-
|
243
|
+
stringified_comments[node.loc.line] ||= begin
|
244
|
+
arr = associated_comments[node.loc.line]
|
245
|
+
arr ? stringify_comment_array(arr) : nil
|
246
|
+
end
|
196
247
|
end
|
197
248
|
|
198
249
|
# A location representing the file in its entirety.
|
@@ -219,11 +270,16 @@ module Solargraph
|
|
219
270
|
@folding_ranges ||= begin
|
220
271
|
result = []
|
221
272
|
inner_folding_ranges node, result
|
222
|
-
result.concat
|
273
|
+
result.concat foldable_comment_block_ranges
|
223
274
|
result
|
224
275
|
end
|
225
276
|
end
|
226
277
|
|
278
|
+
def synchronized?
|
279
|
+
@synchronized = true if @synchronized.nil?
|
280
|
+
@synchronized
|
281
|
+
end
|
282
|
+
|
227
283
|
private
|
228
284
|
|
229
285
|
# @param top [Parser::AST::Node]
|
@@ -249,7 +305,7 @@ module Solargraph
|
|
249
305
|
@associated_comments ||= begin
|
250
306
|
result = {}
|
251
307
|
Parser::Source::Comment.associate_locations(node, comments).each_pair do |loc, all|
|
252
|
-
block = all
|
308
|
+
block = all #.select{ |l| l.document? || code.lines[l.loc.line].strip.start_with?('#')}
|
253
309
|
next if block.empty?
|
254
310
|
result[loc.line] ||= []
|
255
311
|
result[loc.line].concat block
|
@@ -266,6 +322,7 @@ module Solargraph
|
|
266
322
|
ctxt = ''
|
267
323
|
num = nil
|
268
324
|
started = false
|
325
|
+
last_line = nil
|
269
326
|
comments.each { |l|
|
270
327
|
# Trim the comment and minimum leading whitespace
|
271
328
|
p = l.text.gsub(/^#/, '')
|
@@ -276,11 +333,21 @@ module Solargraph
|
|
276
333
|
cur = p.index(/[^ ]/)
|
277
334
|
num = cur if cur < num
|
278
335
|
end
|
336
|
+
# Include blank lines between comments
|
337
|
+
ctxt += ("\n" * (l.loc.first_line - last_line - 1)) unless last_line.nil?
|
279
338
|
ctxt += "#{p[num..-1]}\n" if started
|
339
|
+
last_line = l.loc.last_line
|
280
340
|
}
|
281
341
|
ctxt
|
282
342
|
end
|
283
343
|
|
344
|
+
# A hash of line numbers and their associated comments.
|
345
|
+
#
|
346
|
+
# @return [Hash{Integer => Array<String>}]
|
347
|
+
def stringified_comments
|
348
|
+
@stringified_comments ||= {}
|
349
|
+
end
|
350
|
+
|
284
351
|
# @return [Array<Range>]
|
285
352
|
def string_ranges
|
286
353
|
@string_ranges ||= string_ranges_in(@node)
|
@@ -293,7 +360,12 @@ module Solargraph
|
|
293
360
|
end
|
294
361
|
end
|
295
362
|
|
296
|
-
|
363
|
+
# Get an array of foldable comment block ranges. Blocks are excluded if
|
364
|
+
# they are less than 3 lines long.
|
365
|
+
#
|
366
|
+
# @return [Array<Range>]
|
367
|
+
def foldable_comment_block_ranges
|
368
|
+
return [] unless synchronized?
|
297
369
|
result = []
|
298
370
|
grouped = []
|
299
371
|
# @param cmnt [Parser::Source::Comment]
|
@@ -304,13 +376,17 @@ module Solargraph
|
|
304
376
|
if grouped.empty? || cmnt.loc.expression.line == grouped.last.loc.expression.line + 1
|
305
377
|
grouped.push cmnt
|
306
378
|
else
|
307
|
-
result.push Range.from_to(grouped.first.loc.expression.line, 0, grouped.last.loc.expression.line, 0) unless grouped.
|
379
|
+
result.push Range.from_to(grouped.first.loc.expression.line, 0, grouped.last.loc.expression.line, 0) unless grouped.length < 3
|
308
380
|
grouped = [cmnt]
|
309
381
|
end
|
310
382
|
else
|
311
|
-
|
383
|
+
unless grouped.length < 3
|
384
|
+
result.push Range.from_to(grouped.first.loc.expression.line, 0, grouped.last.loc.expression.line, 0)
|
385
|
+
end
|
386
|
+
grouped.clear
|
312
387
|
end
|
313
388
|
end
|
389
|
+
result.push Range.from_to(grouped.first.loc.expression.line, 0, grouped.last.loc.expression.line, 0) unless grouped.length < 3
|
314
390
|
result
|
315
391
|
end
|
316
392
|
|
@@ -339,12 +415,13 @@ module Solargraph
|
|
339
415
|
end
|
340
416
|
end
|
341
417
|
|
418
|
+
# @param name [String]
|
419
|
+
# @param top [AST::Node]
|
420
|
+
# @return [Array<AST::Node>]
|
342
421
|
def inner_node_references name, top
|
343
422
|
result = []
|
344
|
-
if top.
|
345
|
-
if top.children.any?{|c| c.to_s == name}
|
346
|
-
result.push top
|
347
|
-
end
|
423
|
+
if top.is_a?(AST::Node)
|
424
|
+
result.push top if top.children.any? { |c| c.to_s == name }
|
348
425
|
top.children.each { |c| result.concat inner_node_references(name, c) }
|
349
426
|
end
|
350
427
|
result
|
@@ -352,18 +429,36 @@ module Solargraph
|
|
352
429
|
|
353
430
|
protected
|
354
431
|
|
432
|
+
# @return [String]
|
433
|
+
attr_writer :filename
|
434
|
+
|
355
435
|
# @return [Integer]
|
356
436
|
attr_writer :version
|
357
437
|
|
358
438
|
# @return [String]
|
359
439
|
attr_writer :code
|
360
440
|
|
441
|
+
# @return [Parser::AST::Node]
|
442
|
+
attr_writer :node
|
443
|
+
|
444
|
+
# @return [Array<Range>]
|
445
|
+
attr_writer :error_ranges
|
446
|
+
|
361
447
|
# @return [String]
|
362
448
|
attr_accessor :repaired
|
363
449
|
|
364
450
|
# @return [Boolean]
|
365
451
|
attr_writer :parsed
|
366
452
|
|
453
|
+
# @return [Array<Parser::Source::Comment>]
|
454
|
+
attr_writer :comments
|
455
|
+
|
456
|
+
# @return [Boolean]
|
457
|
+
attr_writer :synchronized
|
458
|
+
|
459
|
+
# @return [Source::Updater]
|
460
|
+
attr_accessor :last_updater
|
461
|
+
|
367
462
|
class << self
|
368
463
|
# @param filename [String]
|
369
464
|
# @return [Solargraph::Source]
|
@@ -392,7 +487,8 @@ module Solargraph
|
|
392
487
|
end
|
393
488
|
|
394
489
|
# @param code [String]
|
395
|
-
# @param filename [String]
|
490
|
+
# @param filename [String, nil]
|
491
|
+
# @param line [Integer]
|
396
492
|
# @return [Parser::AST::Node]
|
397
493
|
def parse code, filename = nil, line = 0
|
398
494
|
buffer = Parser::Source::Buffer.new(filename, line)
|