solargraph 0.20.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/solargraph.rb +2 -3
- data/lib/solargraph/api_map.rb +6 -6
- data/lib/solargraph/api_map/source_to_yard.rb +1 -1
- data/lib/solargraph/language_server/host.rb +69 -10
- data/lib/solargraph/language_server/message.rb +1 -2
- data/lib/solargraph/language_server/message/initialize.rb +83 -15
- data/lib/solargraph/language_server/message/initialized.rb +7 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -1
- data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +20 -19
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +19 -1
- data/lib/solargraph/language_server/request.rb +1 -1
- data/lib/solargraph/language_server/transport.rb +1 -0
- data/lib/solargraph/language_server/transport/data_reader.rb +66 -0
- data/lib/solargraph/language_server/transport/socket.rb +8 -32
- data/lib/solargraph/library.rb +11 -6
- data/lib/solargraph/page.rb +1 -1
- data/lib/solargraph/pin/base.rb +8 -7
- data/lib/solargraph/pin/method_parameter.rb +2 -15
- data/lib/solargraph/pin/yard_object.rb +1 -1
- data/lib/solargraph/plugin/runtime.rb +0 -2
- data/lib/solargraph/shell.rb +0 -24
- data/lib/solargraph/source.rb +5 -169
- data/lib/solargraph/source/mapper.rb +8 -3
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +3 -3
- data/lib/solargraph/workspace/config.rb +7 -9
- data/lib/solargraph/yard_map.rb +9 -48
- metadata +17 -74
- data/lib/solargraph/server.rb +0 -212
- data/lib/solargraph/suggestion.rb +0 -178
@@ -0,0 +1,66 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module LanguageServer
|
3
|
+
module Transport
|
4
|
+
class DataReader
|
5
|
+
def initialize
|
6
|
+
@in_header = true
|
7
|
+
@content_length = 0
|
8
|
+
@buffer = ''
|
9
|
+
end
|
10
|
+
|
11
|
+
# Declare a block to be executed for each message received from the
|
12
|
+
# client.
|
13
|
+
#
|
14
|
+
# @yieldparam [Hash] The message received from the client
|
15
|
+
def set_message_handler &block
|
16
|
+
@message_handler = block
|
17
|
+
end
|
18
|
+
|
19
|
+
# Process raw data received from the client. The data will be parsed
|
20
|
+
# into messages based on the JSON-RPC protocol. Each message will be
|
21
|
+
# passed to the block declared via set_message_handler. Incomplete data
|
22
|
+
# will be buffered and subsequent data will be appended to the buffer.
|
23
|
+
#
|
24
|
+
# @param data [String]
|
25
|
+
def receive data
|
26
|
+
data.each_char do |char|
|
27
|
+
@buffer.concat char
|
28
|
+
if @in_header
|
29
|
+
prepare_to_parse_message if @buffer.end_with?("\r\n\r\n")
|
30
|
+
else
|
31
|
+
parse_message_from_buffer if @buffer.bytesize == @content_length
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def prepare_to_parse_message
|
39
|
+
@in_header = false
|
40
|
+
@buffer.each_line do |line|
|
41
|
+
parts = line.split(':').map(&:strip)
|
42
|
+
if parts[0] == 'Content-Length'
|
43
|
+
@content_length = parts[1].to_i
|
44
|
+
break
|
45
|
+
end
|
46
|
+
end
|
47
|
+
@buffer.clear
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse_message_from_buffer
|
51
|
+
begin
|
52
|
+
msg = JSON.parse(@buffer)
|
53
|
+
@message_handler.call msg unless @message_handler.nil?
|
54
|
+
rescue JSON::ParserError => e
|
55
|
+
STDERR.puts "Failed to parse request: #{e.message}"
|
56
|
+
STDERR.puts "Buffer: #{@buffer}"
|
57
|
+
ensure
|
58
|
+
@buffer.clear
|
59
|
+
@in_header = true
|
60
|
+
@content_length = 0
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -11,50 +11,26 @@ module Solargraph
|
|
11
11
|
@content_length = 0
|
12
12
|
@buffer = ''
|
13
13
|
@host = Solargraph::LanguageServer::Host.new
|
14
|
+
@data_reader = Solargraph::LanguageServer::Transport::DataReader.new
|
15
|
+
@data_reader.set_message_handler do |message|
|
16
|
+
process message
|
17
|
+
end
|
14
18
|
start_timers
|
15
19
|
end
|
16
20
|
|
17
|
-
def process
|
21
|
+
def process message
|
18
22
|
Thread.new do
|
19
|
-
message = @host.start(
|
23
|
+
message = @host.start(message)
|
20
24
|
message.send
|
21
25
|
tmp = @host.flush
|
22
26
|
send_data tmp unless tmp.empty?
|
23
|
-
GC.start unless
|
27
|
+
GC.start unless message['method'] == 'textDocument/didChange'
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
31
|
# @param data [String]
|
28
32
|
def receive_data data
|
29
|
-
|
30
|
-
@buffer.concat char
|
31
|
-
if @in_header
|
32
|
-
if @buffer.end_with?("\r\n\r\n")
|
33
|
-
@in_header = false
|
34
|
-
@buffer.each_line do |line|
|
35
|
-
parts = line.split(':').map(&:strip)
|
36
|
-
if parts[0] == 'Content-Length'
|
37
|
-
@content_length = parts[1].to_i
|
38
|
-
break
|
39
|
-
end
|
40
|
-
end
|
41
|
-
@buffer.clear
|
42
|
-
end
|
43
|
-
else
|
44
|
-
if @buffer.bytesize == @content_length
|
45
|
-
begin
|
46
|
-
process JSON.parse(@buffer)
|
47
|
-
rescue JSON::ParserError => e
|
48
|
-
STDERR.puts "Failed to parse request: #{e.message}"
|
49
|
-
STDERR.puts "Buffer: #{@buffer}"
|
50
|
-
ensure
|
51
|
-
@buffer.clear
|
52
|
-
@in_header = true
|
53
|
-
@content_length = 0
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
33
|
+
@data_reader.receive data
|
58
34
|
end
|
59
35
|
|
60
36
|
private
|
data/lib/solargraph/library.rb
CHANGED
@@ -162,7 +162,7 @@ module Solargraph
|
|
162
162
|
# will be removed from the ApiMap. Only one file can be checked out
|
163
163
|
# (virtualized) at a time.
|
164
164
|
#
|
165
|
-
# @raise [FileNotFoundError] if the file
|
165
|
+
# @raise [FileNotFoundError] if the file does not exist.
|
166
166
|
#
|
167
167
|
# @param filename [String]
|
168
168
|
# @return [Source]
|
@@ -256,14 +256,19 @@ module Solargraph
|
|
256
256
|
@workspace
|
257
257
|
end
|
258
258
|
|
259
|
-
#
|
259
|
+
# Get the source for an open file or create a new source if the file
|
260
|
+
# exists on disk. Sources created from disk are not added to the open
|
261
|
+
# workspace files, i.e., the version on disk remains the authoritative
|
262
|
+
# version.
|
263
|
+
#
|
264
|
+
# @raise [FileNotFoundError] if the file does not exist
|
260
265
|
# @param filename [String]
|
261
266
|
# @return [Solargraph::Source]
|
262
267
|
def read filename
|
263
|
-
|
264
|
-
|
265
|
-
#
|
266
|
-
|
268
|
+
return source_hash[filename] if open?(filename)
|
269
|
+
return workspace.source(filename) if workspace.has_file?(filename)
|
270
|
+
raise FileNotFoundError, "File not found: #{filename}" unless File.file?(filename)
|
271
|
+
Solargraph::Source.load(filename)
|
267
272
|
end
|
268
273
|
end
|
269
274
|
end
|
data/lib/solargraph/page.rb
CHANGED
data/lib/solargraph/pin/base.rb
CHANGED
@@ -6,20 +6,25 @@ module Solargraph
|
|
6
6
|
include Conversions
|
7
7
|
include Documenting
|
8
8
|
|
9
|
+
# @return [Solargraph::Source::Location]
|
9
10
|
attr_reader :location
|
10
11
|
|
11
12
|
# @return [String]
|
12
13
|
attr_reader :namespace
|
13
14
|
|
15
|
+
# @return [String]
|
14
16
|
attr_reader :name
|
15
17
|
|
18
|
+
# @return [YARD::Docstring]
|
16
19
|
attr_reader :docstring
|
17
20
|
|
18
21
|
# @return [String]
|
19
22
|
attr_reader :return_type
|
20
23
|
|
24
|
+
# @return [Integer]
|
21
25
|
attr_reader :kind
|
22
26
|
|
27
|
+
# @return [String]
|
23
28
|
attr_reader :path
|
24
29
|
|
25
30
|
def initialize location, namespace, name, docstring
|
@@ -29,18 +34,12 @@ module Solargraph
|
|
29
34
|
@docstring = docstring
|
30
35
|
end
|
31
36
|
|
37
|
+
# @return [String]
|
32
38
|
def filename
|
33
39
|
location.filename
|
34
40
|
end
|
35
41
|
|
36
|
-
# @return [String]
|
37
|
-
def path
|
38
|
-
end
|
39
|
-
|
40
42
|
# @return [Integer]
|
41
|
-
def kind
|
42
|
-
end
|
43
|
-
|
44
43
|
def completion_item_kind
|
45
44
|
LanguageServer::CompletionItemKinds::KEYWORD
|
46
45
|
end
|
@@ -49,6 +48,7 @@ module Solargraph
|
|
49
48
|
name.to_s
|
50
49
|
end
|
51
50
|
|
51
|
+
# @return [String]
|
52
52
|
def identifier
|
53
53
|
@identifier ||= "#{path}|#{name}"
|
54
54
|
end
|
@@ -57,6 +57,7 @@ module Solargraph
|
|
57
57
|
false
|
58
58
|
end
|
59
59
|
|
60
|
+
# @return [String]
|
60
61
|
def named_context
|
61
62
|
namespace
|
62
63
|
end
|
@@ -1,20 +1,6 @@
|
|
1
1
|
module Solargraph
|
2
2
|
module Pin
|
3
|
-
class MethodParameter <
|
4
|
-
include Localized
|
5
|
-
|
6
|
-
attr_reader :block
|
7
|
-
|
8
|
-
def initialize location, namespace, name, docstring, block
|
9
|
-
super(location, namespace, name, docstring)
|
10
|
-
@block = block
|
11
|
-
@presence = block.location.range
|
12
|
-
end
|
13
|
-
|
14
|
-
def completion_item_kind
|
15
|
-
Solargraph::LanguageServer::CompletionItemKinds::VARIABLE
|
16
|
-
end
|
17
|
-
|
3
|
+
class MethodParameter < LocalVariable
|
18
4
|
def return_type
|
19
5
|
if @return_type.nil? and !block.docstring.nil?
|
20
6
|
found = nil
|
@@ -25,6 +11,7 @@ module Solargraph
|
|
25
11
|
end
|
26
12
|
@return_type = found.types[0] unless found.nil? or found.types.nil?
|
27
13
|
end
|
14
|
+
super
|
28
15
|
@return_type
|
29
16
|
end
|
30
17
|
end
|
@@ -44,7 +44,6 @@ module Solargraph
|
|
44
44
|
false
|
45
45
|
else
|
46
46
|
if @current_required != api_map.required
|
47
|
-
STDERR.puts "Restarting #{self.class} process"
|
48
47
|
@io.close unless @io.nil? or @io.closed?
|
49
48
|
start_process
|
50
49
|
true
|
@@ -70,7 +69,6 @@ module Solargraph
|
|
70
69
|
unless api_map.nil? or api_map.workspace.nil?
|
71
70
|
dir = api_map.workspace
|
72
71
|
end
|
73
|
-
STDERR.puts "Starting #{self.class} process in #{dir}"
|
74
72
|
Dir.chdir(dir) do
|
75
73
|
@io = IO.popen(executable, 'r+')
|
76
74
|
end
|
data/lib/solargraph/shell.rb
CHANGED
@@ -16,30 +16,6 @@ module Solargraph
|
|
16
16
|
puts Solargraph::VERSION
|
17
17
|
end
|
18
18
|
|
19
|
-
desc 'server', 'Start a Solargraph server'
|
20
|
-
option :port, type: :numeric, aliases: :p, desc: 'The server port', default: 7657
|
21
|
-
option :views, type: :string, aliases: :v, desc: 'The view template directory', default: nil
|
22
|
-
option :files, type: :string, aliases: :f, desc: 'The public files directory', default: nil
|
23
|
-
def server
|
24
|
-
port = options[:port]
|
25
|
-
port = available_port if port.zero?
|
26
|
-
Solargraph::Server.set :port, port
|
27
|
-
Solargraph::Server.set :views, options[:views] unless options[:views].nil?
|
28
|
-
Solargraph::Server.set :public_folder, options[:files] unless options[:files].nil?
|
29
|
-
my_pid = nil
|
30
|
-
Solargraph::Server.run! do
|
31
|
-
# This line should not be necessary with WEBrick
|
32
|
-
#STDERR.puts "Solargraph server pid=#{Process.pid} port=#{port}"
|
33
|
-
my_pid = Process.pid
|
34
|
-
Signal.trap("INT") do
|
35
|
-
Solargraph::Server.stop!
|
36
|
-
end
|
37
|
-
Signal.trap("TERM") do
|
38
|
-
Solargraph::Server.stop!
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
19
|
desc 'socket', 'Run a Solargraph socket server'
|
44
20
|
option :host, type: :string, aliases: :h, desc: 'The server host', default: '127.0.0.1'
|
45
21
|
option :port, type: :numeric, aliases: :p, desc: 'The server port', default: 7658
|
data/lib/solargraph/source.rb
CHANGED
@@ -58,7 +58,7 @@ module Solargraph
|
|
58
58
|
@version = 0
|
59
59
|
begin
|
60
60
|
parse
|
61
|
-
rescue Parser::SyntaxError
|
61
|
+
rescue Parser::SyntaxError, EncodingError
|
62
62
|
hard_fix_node
|
63
63
|
end
|
64
64
|
end
|
@@ -79,7 +79,6 @@ module Solargraph
|
|
79
79
|
|
80
80
|
# @return [Array<String>]
|
81
81
|
def namespaces
|
82
|
-
# @namespaces ||= namespace_pin_map.keys
|
83
82
|
@namespaces ||= pins.select{|pin| pin.kind == Pin::NAMESPACE}.map(&:path)
|
84
83
|
end
|
85
84
|
|
@@ -156,25 +155,6 @@ module Solargraph
|
|
156
155
|
found || pins.first
|
157
156
|
end
|
158
157
|
|
159
|
-
# @return [YARD::Docstring]
|
160
|
-
def docstring_for node
|
161
|
-
return @docstring_hash[node.loc] if node.respond_to?(:loc)
|
162
|
-
nil
|
163
|
-
end
|
164
|
-
|
165
|
-
# @return [String]
|
166
|
-
def code_for node
|
167
|
-
b = node.location.expression.begin.begin_pos
|
168
|
-
e = node.location.expression.end.end_pos
|
169
|
-
frag = code[b..e-1].to_s
|
170
|
-
frag.strip.gsub(/,$/, '')
|
171
|
-
end
|
172
|
-
|
173
|
-
# @param node [Parser::AST::Node]
|
174
|
-
def tree_for node
|
175
|
-
@node_tree[node.object_id] || []
|
176
|
-
end
|
177
|
-
|
178
158
|
# Get the nearest node that contains the specified index.
|
179
159
|
#
|
180
160
|
# @param index [Integer]
|
@@ -203,6 +183,7 @@ module Solargraph
|
|
203
183
|
end
|
204
184
|
|
205
185
|
def inner_tree_at node, offset, stack
|
186
|
+
return if node.nil?
|
206
187
|
stack.unshift node
|
207
188
|
node.children.each do |c|
|
208
189
|
next unless c.is_a?(AST::Node)
|
@@ -214,47 +195,6 @@ module Solargraph
|
|
214
195
|
end
|
215
196
|
end
|
216
197
|
|
217
|
-
# Find the nearest parent node from the specified index. If one or more
|
218
|
-
# types are provided, find the nearest node whose type is in the list.
|
219
|
-
#
|
220
|
-
# @param index [Integer]
|
221
|
-
# @param types [Array<Symbol>]
|
222
|
-
# @return [AST::Node]
|
223
|
-
def parent_node_from(line, column, *types)
|
224
|
-
arr = tree_at(line, column)
|
225
|
-
arr.each { |a|
|
226
|
-
if a.kind_of?(AST::Node) and (types.empty? or types.include?(a.type))
|
227
|
-
return a
|
228
|
-
end
|
229
|
-
}
|
230
|
-
nil
|
231
|
-
end
|
232
|
-
|
233
|
-
# @return [String]
|
234
|
-
def namespace_for node
|
235
|
-
parts = []
|
236
|
-
([node] + (@node_tree[node.object_id] || [])).each do |n|
|
237
|
-
next unless n.kind_of?(AST::Node)
|
238
|
-
if n.type == :class or n.type == :module
|
239
|
-
parts.unshift unpack_name(n.children[0])
|
240
|
-
end
|
241
|
-
end
|
242
|
-
parts.join('::')
|
243
|
-
end
|
244
|
-
|
245
|
-
def path_for node
|
246
|
-
path = namespace_for(node) || ''
|
247
|
-
mp = (method_pins + attribute_pins).select{|p| p.node == node}.first
|
248
|
-
unless mp.nil?
|
249
|
-
path += (mp.scope == :instance ? '#' : '.') + mp.name
|
250
|
-
end
|
251
|
-
path
|
252
|
-
end
|
253
|
-
|
254
|
-
def include? node
|
255
|
-
node_object_ids.include? node.object_id
|
256
|
-
end
|
257
|
-
|
258
198
|
def synchronize updater
|
259
199
|
raise 'Invalid synchronization' unless updater.filename == filename
|
260
200
|
original_code = @code
|
@@ -266,11 +206,11 @@ module Solargraph
|
|
266
206
|
begin
|
267
207
|
parse
|
268
208
|
@fixed = @code
|
269
|
-
rescue Parser::SyntaxError => e
|
209
|
+
rescue Parser::SyntaxError, EncodingError => e
|
270
210
|
@fixed = updater.repair(original_fixed)
|
271
211
|
begin
|
272
212
|
parse
|
273
|
-
rescue Parser::SyntaxError => e
|
213
|
+
rescue Parser::SyntaxError, EncodingError => e
|
274
214
|
hard_fix_node
|
275
215
|
end
|
276
216
|
end
|
@@ -284,7 +224,6 @@ module Solargraph
|
|
284
224
|
|
285
225
|
def all_symbols
|
286
226
|
result = []
|
287
|
-
# result.concat namespace_pin_map.values.flatten
|
288
227
|
result.concat namespace_pins.reject{ |pin| pin.name.empty? }
|
289
228
|
result.concat method_pins
|
290
229
|
result.concat constant_pins
|
@@ -301,14 +240,6 @@ module Solargraph
|
|
301
240
|
Fragment.new(self, line, column)
|
302
241
|
end
|
303
242
|
|
304
|
-
def fragment_for node
|
305
|
-
inside = tree_for(node)
|
306
|
-
return nil if inside.empty?
|
307
|
-
line = node.loc.expression.last_line - 1
|
308
|
-
column = node.loc.expression.last_column
|
309
|
-
Fragment.new(self, line, column, inside)
|
310
|
-
end
|
311
|
-
|
312
243
|
def parsed?
|
313
244
|
@parsed
|
314
245
|
end
|
@@ -337,7 +268,7 @@ module Solargraph
|
|
337
268
|
parser.diagnostics.all_errors_are_fatal = true
|
338
269
|
parser.diagnostics.ignore_warnings = true
|
339
270
|
buffer = Parser::Source::Buffer.new(filename, 1)
|
340
|
-
buffer.source = code.
|
271
|
+
buffer.source = code.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: ' ')
|
341
272
|
parser.parse_with_comments(buffer)
|
342
273
|
end
|
343
274
|
|
@@ -346,59 +277,6 @@ module Solargraph
|
|
346
277
|
@stime = Time.now
|
347
278
|
end
|
348
279
|
|
349
|
-
def associate_comments node, comments
|
350
|
-
return nil if comments.nil?
|
351
|
-
comment_hash = Parser::Source::Comment.associate_locations(node, comments)
|
352
|
-
yard_hash = {}
|
353
|
-
comment_hash.each_pair { |k, v|
|
354
|
-
ctxt = ''
|
355
|
-
num = nil
|
356
|
-
started = false
|
357
|
-
v.each { |l|
|
358
|
-
# Trim the comment and minimum leading whitespace
|
359
|
-
p = l.text.gsub(/^#/, '')
|
360
|
-
if num.nil? and !p.strip.empty?
|
361
|
-
num = p.index(/[^ ]/)
|
362
|
-
started = true
|
363
|
-
elsif started and !p.strip.empty?
|
364
|
-
cur = p.index(/[^ ]/)
|
365
|
-
num = cur if cur < num
|
366
|
-
end
|
367
|
-
if started
|
368
|
-
ctxt += "#{p[num..-1]}\n"
|
369
|
-
end
|
370
|
-
}
|
371
|
-
parse = YARD::Docstring.parser.parse(ctxt)
|
372
|
-
unless parse.directives.empty?
|
373
|
-
@directives[k] ||= []
|
374
|
-
@directives[k].concat parse.directives
|
375
|
-
end
|
376
|
-
yard_hash[k] = parse.to_docstring
|
377
|
-
}
|
378
|
-
yard_hash
|
379
|
-
end
|
380
|
-
|
381
|
-
def find_parent(stack, *types)
|
382
|
-
stack.reverse.each { |p|
|
383
|
-
return p if types.include?(p.type)
|
384
|
-
}
|
385
|
-
nil
|
386
|
-
end
|
387
|
-
|
388
|
-
def node_object_ids
|
389
|
-
@node_object_ids ||= @all_nodes.map(&:object_id)
|
390
|
-
end
|
391
|
-
|
392
|
-
# @return [Hash<String, Solargraph::Pin::Namespace>]
|
393
|
-
def namespace_pin_map
|
394
|
-
@namespace_pin_map ||= {}
|
395
|
-
end
|
396
|
-
|
397
|
-
# @return [Hash<String, Solargraph::Pin::Namespace>]
|
398
|
-
def method_pin_map
|
399
|
-
@method_pin_map ||= {}
|
400
|
-
end
|
401
|
-
|
402
280
|
class << self
|
403
281
|
# @return [Solargraph::Source]
|
404
282
|
def load filename
|
@@ -410,48 +288,6 @@ module Solargraph
|
|
410
288
|
def load_string code, filename = nil
|
411
289
|
Source.new code, filename
|
412
290
|
end
|
413
|
-
|
414
|
-
def fix code, filename = nil, offset = nil
|
415
|
-
tries = 0
|
416
|
-
offset = Source.get_offset(code, offset[0], offset[1]) if offset.kind_of?(Array)
|
417
|
-
pos = nil
|
418
|
-
pos = get_position_at(code, offset) unless offset.nil?
|
419
|
-
stubs = []
|
420
|
-
fixed_position = false
|
421
|
-
tmp = code.sub(/\.(\s*\z)$/, ' \1')
|
422
|
-
begin
|
423
|
-
node, comments = Source.parse(tmp, filename)
|
424
|
-
Source.new(code, node, comments, filename, stubs)
|
425
|
-
rescue Parser::SyntaxError => e
|
426
|
-
if tries < 10
|
427
|
-
tries += 1
|
428
|
-
# Stub periods before the offset to retain the expected node tree
|
429
|
-
if !offset.nil? and ['.', '{', '('].include?(tmp[offset-1])
|
430
|
-
tmp = tmp[0, offset-1] + ';' + tmp[offset..-1]
|
431
|
-
elsif !fixed_position and !offset.nil?
|
432
|
-
fixed_position = true
|
433
|
-
beg = beginning_of_line_from(tmp, offset)
|
434
|
-
tmp = "#{tmp[0, beg]}##{tmp[beg+1..-1]}"
|
435
|
-
stubs.push(pos[0])
|
436
|
-
elsif e.message.include?('token $end')
|
437
|
-
tmp += "\nend"
|
438
|
-
elsif e.message.include?("unexpected `@'")
|
439
|
-
tmp = tmp[0, e.diagnostic.location.begin_pos] + '_' + tmp[e.diagnostic.location.begin_pos+1..-1]
|
440
|
-
end
|
441
|
-
retry
|
442
|
-
end
|
443
|
-
STDERR.puts "Unable to parse file #{filename.nil? ? 'undefined' : filename}: #{e.message}"
|
444
|
-
node, comments = parse(code.gsub(/[^\s]/, ' '), filename)
|
445
|
-
Source.new(code, node, comments, filename)
|
446
|
-
end
|
447
|
-
end
|
448
|
-
|
449
|
-
def beginning_of_line_from str, i
|
450
|
-
while i > 0 and str[i-1] != "\n"
|
451
|
-
i -= 1
|
452
|
-
end
|
453
|
-
i
|
454
|
-
end
|
455
291
|
end
|
456
292
|
end
|
457
293
|
end
|