solargraph 0.17.4 → 0.18.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 +16 -12
- data/lib/solargraph/api_map.rb +516 -588
- data/lib/solargraph/api_map/completion.rb +16 -0
- data/lib/solargraph/api_map/source_to_yard.rb +2 -2
- data/lib/solargraph/language_server.rb +12 -0
- data/lib/solargraph/language_server/completion_item_kinds.rb +31 -0
- data/lib/solargraph/language_server/error_codes.rb +16 -0
- data/lib/solargraph/language_server/host.rb +305 -0
- data/lib/solargraph/language_server/message.rb +70 -0
- data/lib/solargraph/language_server/message/base.rb +64 -0
- data/lib/solargraph/language_server/message/cancel_request.rb +11 -0
- data/lib/solargraph/language_server/message/client.rb +5 -0
- data/lib/solargraph/language_server/message/client/register_capability.rb +13 -0
- data/lib/solargraph/language_server/message/completion_item.rb +9 -0
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +23 -0
- data/lib/solargraph/language_server/message/exit_notification.rb +12 -0
- data/lib/solargraph/language_server/message/extended.rb +15 -0
- data/lib/solargraph/language_server/message/extended/document.rb +18 -0
- data/lib/solargraph/language_server/message/extended/search.rb +18 -0
- data/lib/solargraph/language_server/message/initialize.rb +39 -0
- data/lib/solargraph/language_server/message/initialized.rb +10 -0
- data/lib/solargraph/language_server/message/method_not_found.rb +14 -0
- data/lib/solargraph/language_server/message/method_not_implemented.rb +12 -0
- data/lib/solargraph/language_server/message/shutdown.rb +11 -0
- data/lib/solargraph/language_server/message/text_document.rb +21 -0
- data/lib/solargraph/language_server/message/text_document/base.rb +17 -0
- data/lib/solargraph/language_server/message/text_document/completion.rb +69 -0
- data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
- data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
- data/lib/solargraph/language_server/message/text_document/did_close.rb +12 -0
- data/lib/solargraph/language_server/message/text_document/did_open.rb +13 -0
- data/lib/solargraph/language_server/message/text_document/did_save.rb +15 -0
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +31 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +36 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +19 -0
- data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +29 -0
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +23 -0
- data/lib/solargraph/language_server/message/workspace.rb +11 -0
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +9 -0
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +30 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +31 -0
- data/lib/solargraph/language_server/symbol_kinds.rb +32 -0
- data/lib/solargraph/language_server/transport.rb +7 -0
- data/lib/solargraph/language_server/transport/socket.rb +66 -0
- data/lib/solargraph/language_server/uri_helpers.rb +21 -0
- data/lib/solargraph/library.rb +225 -0
- data/lib/solargraph/live_map.rb +1 -1
- data/lib/solargraph/page.rb +61 -0
- data/lib/solargraph/pin.rb +7 -0
- data/lib/solargraph/pin/attribute.rb +9 -0
- data/lib/solargraph/pin/base.rb +76 -6
- data/lib/solargraph/pin/base_variable.rb +29 -7
- data/lib/solargraph/pin/block_parameter.rb +53 -0
- data/lib/solargraph/pin/constant.rb +6 -2
- data/lib/solargraph/pin/conversions.rb +65 -0
- data/lib/solargraph/pin/directed/attribute.rb +4 -0
- data/lib/solargraph/pin/directed/method.rb +6 -1
- data/lib/solargraph/pin/helper.rb +35 -0
- data/lib/solargraph/pin/keyword.rb +22 -0
- data/lib/solargraph/pin/local_variable.rb +0 -1
- data/lib/solargraph/pin/method.rb +55 -2
- data/lib/solargraph/pin/method_parameter.rb +19 -0
- data/lib/solargraph/pin/namespace.rb +7 -2
- data/lib/solargraph/pin/parameter.rb +23 -0
- data/lib/solargraph/pin/plugin/method.rb +3 -2
- data/lib/solargraph/pin/yard_object.rb +101 -0
- data/lib/solargraph/server.rb +82 -135
- data/lib/solargraph/shell.rb +20 -1
- data/lib/solargraph/source.rb +709 -0
- data/lib/solargraph/source/flawed_builder.rb +10 -0
- data/lib/solargraph/source/fragment.rb +319 -0
- data/lib/solargraph/source/position.rb +26 -0
- data/lib/solargraph/source/range.rb +39 -0
- data/lib/solargraph/suggestion.rb +29 -4
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +105 -0
- data/lib/solargraph/{api_map → workspace}/config.rb +1 -1
- data/lib/solargraph/yard_map.rb +59 -37
- metadata +168 -5
- data/lib/solargraph/api_map/source.rb +0 -470
- data/lib/solargraph/code_map.rb +0 -868
@@ -0,0 +1,13 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module LanguageServer
|
3
|
+
module Message
|
4
|
+
module TextDocument
|
5
|
+
class DidOpen < Base
|
6
|
+
def process
|
7
|
+
host.open params['textDocument']['uri'], params['textDocument']['text'], params['textDocument']['version']
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module LanguageServer
|
3
|
+
module Message
|
4
|
+
module TextDocument
|
5
|
+
class DidSave < Base
|
6
|
+
def process
|
7
|
+
STDERR.puts "TODO: TextDocument saved"
|
8
|
+
# host.open params['textDocument']
|
9
|
+
# publish_diagnostics
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Solargraph::LanguageServer::Message::TextDocument::DocumentSymbol < Solargraph::LanguageServer::Message::Base
|
2
|
+
include Solargraph::LanguageServer::UriHelpers
|
3
|
+
|
4
|
+
def process
|
5
|
+
pins = host.library.file_symbols(uri_to_file(params['textDocument']['uri']))
|
6
|
+
info = pins.map do |pin|
|
7
|
+
parts = pin.location.split(':')
|
8
|
+
char = parts.pop.to_i
|
9
|
+
line = parts.pop.to_i
|
10
|
+
filename = parts.join(':')
|
11
|
+
{
|
12
|
+
name: pin.path,
|
13
|
+
kind: Solargraph::LanguageServer::SymbolKinds::NAMESPACE,
|
14
|
+
location: {
|
15
|
+
uri: file_to_uri(filename),
|
16
|
+
range: {
|
17
|
+
start: {
|
18
|
+
line: line,
|
19
|
+
character: char
|
20
|
+
},
|
21
|
+
end: {
|
22
|
+
line: line,
|
23
|
+
character: char
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
set_result info
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module LanguageServer
|
5
|
+
module Message
|
6
|
+
module TextDocument
|
7
|
+
class Formatting < Base
|
8
|
+
def process
|
9
|
+
filename = uri_to_file(params['textDocument']['uri'])
|
10
|
+
original = host.read_text(params['textDocument']['uri'])
|
11
|
+
cmd = "rubocop -a -f fi -s #{Shellwords.escape(filename)}"
|
12
|
+
o, e, s = Open3.capture3(cmd, stdin_data: original)
|
13
|
+
formatted = o.lines[2..-1].join
|
14
|
+
set_result(
|
15
|
+
[
|
16
|
+
{
|
17
|
+
range: {
|
18
|
+
start: {
|
19
|
+
line: 0,
|
20
|
+
character: 0
|
21
|
+
},
|
22
|
+
end: {
|
23
|
+
line: original.lines.length,
|
24
|
+
character: 0
|
25
|
+
}
|
26
|
+
},
|
27
|
+
newText: formatted
|
28
|
+
}
|
29
|
+
]
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Solargraph::LanguageServer::Message::TextDocument
|
4
|
+
class Hover < Base
|
5
|
+
def process
|
6
|
+
filename = uri_to_file(params['textDocument']['uri'])
|
7
|
+
line = params['position']['line']
|
8
|
+
col = params['position']['character']
|
9
|
+
suggestions = host.library.definitions_at(filename, line, col)
|
10
|
+
contents = suggestions.map(&:hover)
|
11
|
+
set_result(
|
12
|
+
contents: {
|
13
|
+
kind: 'markdown',
|
14
|
+
value: contents.join("\n\n")
|
15
|
+
}
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module LanguageServer
|
3
|
+
module Message
|
4
|
+
module TextDocument
|
5
|
+
class OnTypeFormatting < Base
|
6
|
+
def process
|
7
|
+
src = host.library.checkout(uri_to_file(params['textDocument']['uri']))
|
8
|
+
offset = src.get_offset(params['position']['line'], params['position']['character'])
|
9
|
+
if src.string_at?(offset-1) and params['ch'] == '{' and src.code[offset-2,2] == '#{'
|
10
|
+
set_result(
|
11
|
+
[
|
12
|
+
{
|
13
|
+
range: {
|
14
|
+
start: params['position'],
|
15
|
+
end: params['position']
|
16
|
+
},
|
17
|
+
newText: '}'
|
18
|
+
}
|
19
|
+
]
|
20
|
+
)
|
21
|
+
else
|
22
|
+
set_result []
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module LanguageServer
|
3
|
+
module Message
|
4
|
+
module TextDocument
|
5
|
+
class SignatureHelp < TextDocument::Base
|
6
|
+
def process
|
7
|
+
filename = uri_to_file(params['textDocument']['uri'])
|
8
|
+
line = params['position']['line']
|
9
|
+
col = params['position']['character']
|
10
|
+
suggestions = host.library.signatures_at(filename, line, col)
|
11
|
+
info = []
|
12
|
+
suggestions.each do |s|
|
13
|
+
info.push s.signature_help
|
14
|
+
end
|
15
|
+
set_result({
|
16
|
+
signatures: info
|
17
|
+
})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module LanguageServer
|
3
|
+
module Message
|
4
|
+
module Workspace
|
5
|
+
autoload :DidChangeWatchedFiles, 'solargraph/language_server/message/workspace/did_change_watched_files'
|
6
|
+
autoload :WorkspaceSymbol, 'solargraph/language_server/message/workspace/workspace_symbol'
|
7
|
+
autoload :DidChangeConfiguration, 'solargraph/language_server/message/workspace/did_change_configuration'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Solargraph::LanguageServer::Message::Workspace
|
4
|
+
class DidChangeWatchedFiles < Solargraph::LanguageServer::Message::Base
|
5
|
+
CREATED = 1
|
6
|
+
CHANGED = 2
|
7
|
+
DELETED = 3
|
8
|
+
|
9
|
+
include Solargraph::LanguageServer::UriHelpers
|
10
|
+
|
11
|
+
def process
|
12
|
+
params['changes'].each do |change|
|
13
|
+
if change['type'] == CREATED
|
14
|
+
STDERR.puts "TODO: Need to handle a created file?"
|
15
|
+
# host.create change['uri']
|
16
|
+
elsif change['type'] == CHANGED
|
17
|
+
# @todo Should this check if the source is already loaded in the source?
|
18
|
+
# Possibly out of sync with the disk?
|
19
|
+
# host.workspace.handle_changed filename
|
20
|
+
# host.api_map.refresh
|
21
|
+
STDERR.puts "TODO: Workspace changed"
|
22
|
+
elsif change['type'] == DELETED
|
23
|
+
host.delete change['uri']
|
24
|
+
else
|
25
|
+
# @todo Handle error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Solargraph::LanguageServer::Message::Workspace::WorkspaceSymbol < Solargraph::LanguageServer::Message::Base
|
2
|
+
include Solargraph::LanguageServer::UriHelpers
|
3
|
+
|
4
|
+
def process
|
5
|
+
pins = host.library.query_symbols(params['query'])
|
6
|
+
info = pins.map do |pin|
|
7
|
+
parts = pin.location.split(':')
|
8
|
+
char = parts.pop.to_i
|
9
|
+
line = parts.pop.to_i
|
10
|
+
filename = parts.join(':')
|
11
|
+
{
|
12
|
+
name: pin.path,
|
13
|
+
kind: Solargraph::LanguageServer::SymbolKinds::NAMESPACE,
|
14
|
+
location: {
|
15
|
+
uri: file_to_uri(filename),
|
16
|
+
range: {
|
17
|
+
start: {
|
18
|
+
line: line,
|
19
|
+
character: char
|
20
|
+
},
|
21
|
+
end: {
|
22
|
+
line: line,
|
23
|
+
character: char
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
set_result info
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module LanguageServer
|
3
|
+
module SymbolKinds
|
4
|
+
FILE = 1;
|
5
|
+
MODULE = 2;
|
6
|
+
NAMESPACE = 3;
|
7
|
+
PACKAGE = 4;
|
8
|
+
CLASS = 5;
|
9
|
+
METHOD = 6;
|
10
|
+
PROPERTY = 7;
|
11
|
+
FIELD = 8;
|
12
|
+
CONSTRUCTOR = 9;
|
13
|
+
ENUM = 10;
|
14
|
+
INTERFACE = 11;
|
15
|
+
FUNCTION = 12;
|
16
|
+
VARIABLE = 13;
|
17
|
+
CONSTANT = 14;
|
18
|
+
STRING = 15;
|
19
|
+
NUMBER = 16;
|
20
|
+
BOOLEAN = 17;
|
21
|
+
ARRAY = 18;
|
22
|
+
OBJECT = 19;
|
23
|
+
KEY = 20;
|
24
|
+
NULL = 21;
|
25
|
+
ENUM_MEMBER = 22;
|
26
|
+
STRUCT = 23;
|
27
|
+
EVENT = 24;
|
28
|
+
OPERATOR = 25;
|
29
|
+
TYPE_PARAMETER = 26;
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module LanguageServer
|
5
|
+
module Transport
|
6
|
+
# A module for running language servers in EventMachine.
|
7
|
+
#
|
8
|
+
module Socket
|
9
|
+
def post_init
|
10
|
+
@in_header = true
|
11
|
+
@content_length = 0
|
12
|
+
@buffer = ''
|
13
|
+
@host = Solargraph::LanguageServer::Host.new
|
14
|
+
EventMachine.add_periodic_timer 0.1 do
|
15
|
+
tmp = @host.flush
|
16
|
+
send_data tmp unless tmp.empty?
|
17
|
+
EventMachine.stop if @host.stopped?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def process request
|
22
|
+
Thread.new do
|
23
|
+
message = @host.start(request)
|
24
|
+
message.send
|
25
|
+
tmp = @host.flush
|
26
|
+
send_data tmp unless tmp.empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param data [String]
|
31
|
+
def receive_data data
|
32
|
+
data.each_char do |char|
|
33
|
+
@buffer.concat char
|
34
|
+
if @in_header
|
35
|
+
if @buffer.end_with?("\r\n\r\n")
|
36
|
+
@in_header = false
|
37
|
+
@buffer.each_line do |line|
|
38
|
+
parts = line.split(':').map(&:strip)
|
39
|
+
if parts[0] == 'Content-Length'
|
40
|
+
@content_length = parts[1].to_i
|
41
|
+
break
|
42
|
+
end
|
43
|
+
end
|
44
|
+
@buffer.clear
|
45
|
+
end
|
46
|
+
else
|
47
|
+
if @buffer.bytesize == @content_length
|
48
|
+
begin
|
49
|
+
process JSON.parse(@buffer)
|
50
|
+
rescue Exception => e
|
51
|
+
STDERR.puts "Failed to parse request: #{e.message}"
|
52
|
+
STDERR.puts e.backtrace.inspect
|
53
|
+
STDERR.puts "Buffer: #{@buffer}"
|
54
|
+
ensure
|
55
|
+
@buffer.clear
|
56
|
+
@in_header = true
|
57
|
+
@content_length = 0
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module LanguageServer
|
3
|
+
module UriHelpers
|
4
|
+
# Convert a file URI to a path.
|
5
|
+
#
|
6
|
+
# @param uri [String]
|
7
|
+
# @return [String]
|
8
|
+
def uri_to_file uri
|
9
|
+
URI.decode(uri).sub(/^file\:\/\//, '').sub(/^\/([a-z]\:)/i, '\1')
|
10
|
+
end
|
11
|
+
|
12
|
+
# Convert a file path to a URI.
|
13
|
+
#
|
14
|
+
# @param file [String]
|
15
|
+
# @return [String]
|
16
|
+
def file_to_uri file
|
17
|
+
"file://#{URI.encode(file.gsub(/^([a-z]\:)/i, '/\1'))}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
module Solargraph
|
2
|
+
# A library handles coordination between a Workspace and an ApiMap.
|
3
|
+
#
|
4
|
+
class Library
|
5
|
+
class FileNotFoundError < Exception; end
|
6
|
+
|
7
|
+
# @param workspace [Solargraph::Workspace]
|
8
|
+
def initialize workspace = Solargraph::Workspace.new(nil)
|
9
|
+
@workspace = workspace
|
10
|
+
api_map
|
11
|
+
end
|
12
|
+
|
13
|
+
# Open a file in the library. Opening a file will make it available for
|
14
|
+
# checkout and merge it into the workspace if applicable.
|
15
|
+
#
|
16
|
+
# @param filename [String]
|
17
|
+
# @param text [String]
|
18
|
+
# @param version [Integer]
|
19
|
+
def open filename, text, version
|
20
|
+
source = Solargraph::Source.load_string(text, filename)
|
21
|
+
source.version = version
|
22
|
+
source_hash[filename] = source
|
23
|
+
workspace.merge source
|
24
|
+
api_map.refresh
|
25
|
+
end
|
26
|
+
|
27
|
+
# Create a file source to be added to the workspace. The source is ignored
|
28
|
+
# if the workspace is not configured to include the file.
|
29
|
+
#
|
30
|
+
# @param filename [String]
|
31
|
+
# @param text [String] The contents of the file
|
32
|
+
# @return [Boolean] True if the file was added to the workspace.
|
33
|
+
def create filename, text
|
34
|
+
result = false
|
35
|
+
if workspace.would_merge?(filename)
|
36
|
+
source = Solargraph::Source.load_string(text, filename)
|
37
|
+
if workspace.merge(source)
|
38
|
+
source_hash[filename] = source
|
39
|
+
api_map.refresh
|
40
|
+
result = true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
result
|
44
|
+
end
|
45
|
+
|
46
|
+
# Delete a file from the library. Deleting a file will make it unavailable
|
47
|
+
# for checkout and optionally remove it from the workspace unless the
|
48
|
+
# workspace configuration determines that it should still exist.
|
49
|
+
#
|
50
|
+
# @param filename [String]
|
51
|
+
def delete filename
|
52
|
+
source = source_hash[filename]
|
53
|
+
return if source.nil?
|
54
|
+
source_hash.delete filename
|
55
|
+
workspace.remove source
|
56
|
+
api_map.refresh
|
57
|
+
end
|
58
|
+
|
59
|
+
# Close a file in the library. Closing a file will make it unavailable for
|
60
|
+
# checkout although it may still exist in the workspace.
|
61
|
+
#
|
62
|
+
# @param filename [String]
|
63
|
+
def close filename
|
64
|
+
source_hash.delete filename
|
65
|
+
end
|
66
|
+
|
67
|
+
# Get completion suggestions at the specified file and location.
|
68
|
+
#
|
69
|
+
# @param filename [String] The file to analyze
|
70
|
+
# @param line [Integer] The zero-based line number
|
71
|
+
# @param column [Integer] The zero-based column number
|
72
|
+
# @return [ApiMap::Completion]
|
73
|
+
def completions_at filename, line, column
|
74
|
+
# @type [Solargraph::Source]
|
75
|
+
source = nil
|
76
|
+
source = read(filename)
|
77
|
+
fragment = Solargraph::Source::Fragment.new(source, source.get_offset(line, column))
|
78
|
+
api_map.complete(fragment)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Get definition suggestions for the expression at the specified file and
|
82
|
+
# location.
|
83
|
+
#
|
84
|
+
# @param filename [String] The file to analyze
|
85
|
+
# @param line [Integer] The zero-based line number
|
86
|
+
# @param column [Integer] The zero-based column number
|
87
|
+
# @return [Array<Solargraph::Pin::Base>]
|
88
|
+
def definitions_at filename, line, column
|
89
|
+
source = read(filename)
|
90
|
+
fragment = Solargraph::Source::Fragment.new(source, source.get_offset(line, column))
|
91
|
+
result = api_map.define(fragment)
|
92
|
+
result
|
93
|
+
end
|
94
|
+
|
95
|
+
# Get signature suggestions for the method at the specified file and
|
96
|
+
# location.
|
97
|
+
#
|
98
|
+
# @param filename [String] The file to analyze
|
99
|
+
# @param line [Integer] The zero-based line number
|
100
|
+
# @param column [Integer] The zero-based column number
|
101
|
+
# @return [Array<Solargraph::Pin::Base>]
|
102
|
+
def signatures_at filename, line, column
|
103
|
+
source = read(filename)
|
104
|
+
fragment = Solargraph::Source::Fragment.new(source, signature_index_before(source, source.get_offset(line, column)))
|
105
|
+
api_map.define(fragment).select{|pin| pin.method?}
|
106
|
+
end
|
107
|
+
|
108
|
+
# Get the pin at the specified location or nil if the pin does not exist.
|
109
|
+
#
|
110
|
+
# @return [Solargraph::Pin::Base]
|
111
|
+
def locate_pin location
|
112
|
+
api_map.locate_pin location
|
113
|
+
end
|
114
|
+
|
115
|
+
# Get an array of pins that match a path.
|
116
|
+
#
|
117
|
+
# @param path [String]
|
118
|
+
# @return [Array<Solargraph::Pin::Base>]
|
119
|
+
def get_path_pins path
|
120
|
+
api_map.get_path_suggestions(path)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Check a file out of the library. If the file is not part of the
|
124
|
+
# workspace, the ApiMap will virtualize it for mapping purposes. If
|
125
|
+
# filename is nil, any source currently checked out of the library
|
126
|
+
# will be removed from the ApiMap. Only one file can be checked out
|
127
|
+
# (virtualized) at a time.
|
128
|
+
#
|
129
|
+
# @raise [FileNotFoundError] if the file is not in the library.
|
130
|
+
#
|
131
|
+
# @param filename [String]
|
132
|
+
# @return [Source]
|
133
|
+
def checkout filename
|
134
|
+
if filename.nil?
|
135
|
+
api_map.virtualize nil
|
136
|
+
nil
|
137
|
+
else
|
138
|
+
read filename
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def refresh force = false
|
143
|
+
api_map.refresh force
|
144
|
+
end
|
145
|
+
|
146
|
+
def document query
|
147
|
+
api_map.document query
|
148
|
+
end
|
149
|
+
|
150
|
+
def search query
|
151
|
+
api_map.search query
|
152
|
+
end
|
153
|
+
|
154
|
+
def query_symbols query
|
155
|
+
api_map.query_symbols query
|
156
|
+
end
|
157
|
+
|
158
|
+
def file_symbols filename
|
159
|
+
read(filename).all_symbols
|
160
|
+
end
|
161
|
+
|
162
|
+
def path_pins path
|
163
|
+
api_map.get_path_suggestions(path)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Get the current text of a file in the library.
|
167
|
+
#
|
168
|
+
# @param filename [String]
|
169
|
+
# @return [String]
|
170
|
+
def read_text filename
|
171
|
+
source = read(filename)
|
172
|
+
source.code
|
173
|
+
end
|
174
|
+
|
175
|
+
# Create a library from a directory.
|
176
|
+
#
|
177
|
+
# @param directory [String] The path to be used for the workspace
|
178
|
+
# @return [Solargraph::Library]
|
179
|
+
def self.load directory
|
180
|
+
Solargraph::Library.new(Solargraph::Workspace.new(directory))
|
181
|
+
end
|
182
|
+
|
183
|
+
private
|
184
|
+
|
185
|
+
# @return [Hash<String, Solargraph::Source>]
|
186
|
+
def source_hash
|
187
|
+
@source_hash ||= {}
|
188
|
+
end
|
189
|
+
|
190
|
+
# @return [Solargraph::ApiMap]
|
191
|
+
def api_map
|
192
|
+
@api_map ||= Solargraph::ApiMap.new(workspace)
|
193
|
+
end
|
194
|
+
|
195
|
+
# @return [Solargraph::Workspace]
|
196
|
+
def workspace
|
197
|
+
@workspace
|
198
|
+
end
|
199
|
+
|
200
|
+
# @return [Solargraph::Source]
|
201
|
+
def read filename
|
202
|
+
source = source_hash[filename]
|
203
|
+
raise FileNotFoundError, "Source not found for #{filename}" if source.nil?
|
204
|
+
api_map.virtualize source
|
205
|
+
source
|
206
|
+
end
|
207
|
+
|
208
|
+
def signature_index_before source, index
|
209
|
+
open_parens = 0
|
210
|
+
cursor = index - 1
|
211
|
+
while cursor >= 0
|
212
|
+
break if cursor < 0
|
213
|
+
if source.code[cursor] == ')'
|
214
|
+
open_parens -= 1
|
215
|
+
elsif source.code[cursor] == '('
|
216
|
+
open_parens += 1
|
217
|
+
end
|
218
|
+
break if open_parens == 1
|
219
|
+
cursor -= 1
|
220
|
+
end
|
221
|
+
cursor = 0 if cursor < 0
|
222
|
+
cursor
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|