solargraph 0.17.4 → 0.18.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 +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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ccb588fb1b726e174fc3e8d569a92f1e8ae0c9d
|
4
|
+
data.tar.gz: 0ec8f37bcd32ecde24d4f56a80bd6db81d559c13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71df1903bd21f4a7e762068d23ff09c5d5c1a078e63eec46ce04b5500d9e27fcda2ff8a921c16ce3a4b7d6379cc8ac582ea48a9d36fc6e4f1e8ed8282d9e77fa
|
7
|
+
data.tar.gz: 4e1fe48e17648c06a5ca4bf513fc46856ae848746844a1db6f2d21ee281f8c664a44ddbf7b1dd01e47ec80abbb8eba77c742853086a1d43d66e7a9b218c21a12
|
data/lib/solargraph.rb
CHANGED
@@ -3,18 +3,22 @@ require 'rubygems/package'
|
|
3
3
|
require 'yard-solargraph'
|
4
4
|
|
5
5
|
module Solargraph
|
6
|
-
autoload :Shell,
|
7
|
-
autoload :
|
8
|
-
autoload :
|
9
|
-
autoload :NodeMethods,
|
10
|
-
autoload :Suggestion,
|
11
|
-
autoload :Server,
|
12
|
-
autoload :YardMap,
|
13
|
-
autoload :Pin,
|
14
|
-
autoload :LiveMap,
|
15
|
-
autoload :ServerMethods,
|
16
|
-
autoload :Plugin,
|
17
|
-
autoload :CoreFills,
|
6
|
+
autoload :Shell, 'solargraph/shell'
|
7
|
+
autoload :Source, 'solargraph/source'
|
8
|
+
autoload :ApiMap, 'solargraph/api_map'
|
9
|
+
autoload :NodeMethods, 'solargraph/node_methods'
|
10
|
+
autoload :Suggestion, 'solargraph/suggestion'
|
11
|
+
autoload :Server, 'solargraph/server'
|
12
|
+
autoload :YardMap, 'solargraph/yard_map'
|
13
|
+
autoload :Pin, 'solargraph/pin'
|
14
|
+
autoload :LiveMap, 'solargraph/live_map'
|
15
|
+
autoload :ServerMethods, 'solargraph/server_methods'
|
16
|
+
autoload :Plugin, 'solargraph/plugin'
|
17
|
+
autoload :CoreFills, 'solargraph/core_fills'
|
18
|
+
autoload :LanguageServer, 'solargraph/language_server'
|
19
|
+
autoload :Workspace, 'solargraph/workspace'
|
20
|
+
autoload :Page, 'solargraph/page'
|
21
|
+
autoload :Library, 'solargraph/library'
|
18
22
|
|
19
23
|
YARDOC_PATH = File.join(File.realpath(File.dirname(__FILE__)), '..', 'yardoc')
|
20
24
|
YARD_EXTENSION_FILE = File.join(File.realpath(File.dirname(__FILE__)), 'yard-solargraph.rb')
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -1,67 +1,37 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'parser/current'
|
3
|
-
require 'thread'
|
4
2
|
require 'set'
|
3
|
+
require 'time'
|
5
4
|
|
6
5
|
module Solargraph
|
7
6
|
class ApiMap
|
8
|
-
autoload :Config, 'solargraph/api_map/config'
|
9
|
-
autoload :Source, 'solargraph/api_map/source'
|
10
7
|
autoload :Cache, 'solargraph/api_map/cache'
|
11
8
|
autoload :SourceToYard, 'solargraph/api_map/source_to_yard'
|
12
|
-
|
9
|
+
autoload :Completion, 'solargraph/api_map/completion'
|
13
10
|
|
14
11
|
include NodeMethods
|
15
12
|
include Solargraph::ApiMap::SourceToYard
|
16
13
|
include CoreFills
|
17
14
|
|
18
|
-
# The
|
19
|
-
# additional files to parse and analyze.
|
15
|
+
# The workspace to analyze and process.
|
20
16
|
#
|
21
|
-
# @return [
|
17
|
+
# @return [Solargraph::Workspace]
|
22
18
|
attr_reader :workspace
|
23
19
|
|
24
|
-
# @param workspace [
|
20
|
+
# @param workspace [Solargraph::Workspace]
|
25
21
|
def initialize workspace = nil
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
# @todo Deprecate strings for the workspace parameter
|
23
|
+
workspace = Solargraph::Workspace.new(workspace) if workspace.kind_of?(String)
|
24
|
+
workspace = Solargraph::Workspace.new(nil) if workspace.nil?
|
25
|
+
@workspace = workspace
|
29
26
|
require_extensions
|
30
|
-
unless @workspace.nil?
|
31
|
-
workspace_files.concat config.calculated
|
32
|
-
workspace_files.each do |wf|
|
33
|
-
begin
|
34
|
-
@@source_cache[wf] ||= Source.load(wf)
|
35
|
-
rescue Parser::SyntaxError, EncodingError => e
|
36
|
-
STDERR.puts "Failed to load #{wf}: #{e.message}"
|
37
|
-
@@source_cache[wf] = Source.virtual('', wf)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
@sources = {}
|
42
27
|
@virtual_source = nil
|
43
|
-
@virtual_filename = nil
|
44
|
-
@stale = true
|
45
28
|
@yard_stale = true
|
46
|
-
|
29
|
+
process_maps
|
47
30
|
yard_map
|
48
31
|
end
|
49
32
|
|
50
|
-
|
51
|
-
|
52
|
-
# if it exists.
|
53
|
-
#
|
54
|
-
# @return [Solargraph::ApiMap::Config]
|
55
|
-
def config reload = false
|
56
|
-
@config = ApiMap::Config.new(@workspace) if @config.nil? or reload
|
57
|
-
@config
|
58
|
-
end
|
59
|
-
|
60
|
-
# An array of all workspace files included in the map.
|
61
|
-
#
|
62
|
-
# @return[Array<String>]
|
63
|
-
def workspace_files
|
64
|
-
@workspace_files ||= []
|
33
|
+
def self.load directory
|
34
|
+
self.new(Solargraph::Workspace.new(directory))
|
65
35
|
end
|
66
36
|
|
67
37
|
# An array of required paths in the workspace.
|
@@ -71,67 +41,81 @@ module Solargraph
|
|
71
41
|
@required ||= []
|
72
42
|
end
|
73
43
|
|
74
|
-
# Get a YardMap associated with the current
|
44
|
+
# Get a YardMap associated with the current workspace.
|
75
45
|
#
|
76
46
|
# @return [Solargraph::YardMap]
|
77
47
|
def yard_map
|
78
|
-
refresh
|
48
|
+
# refresh
|
79
49
|
if @yard_map.nil? || @yard_map.required.to_set != required.to_set
|
80
50
|
@yard_map = Solargraph::YardMap.new(required: required, workspace: workspace)
|
81
51
|
end
|
82
52
|
@yard_map
|
83
53
|
end
|
84
54
|
|
85
|
-
# Get a LiveMap associated with the current
|
55
|
+
# Get a LiveMap associated with the current workspace.
|
86
56
|
#
|
87
57
|
# @return [Solargraph::LiveMap]
|
88
58
|
def live_map
|
89
59
|
@live_map ||= Solargraph::LiveMap.new(self)
|
90
60
|
end
|
91
61
|
|
92
|
-
#
|
93
|
-
#
|
62
|
+
# Declare a virtual source that will be included in the map regardless of
|
63
|
+
# whether it's in the workspace.
|
94
64
|
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
true
|
105
|
-
end
|
106
|
-
end
|
107
|
-
if filename.nil? or filename.end_with?('.rb') or filename.end_with?('.erb')
|
108
|
-
eliminate @virtual_filename unless @virtual_source.nil? or @virtual_filename == filename or workspace_files.include?(@virtual_filename)
|
109
|
-
@virtual_filename = filename
|
110
|
-
@virtual_source = Source.fix(code, filename, cursor)
|
111
|
-
unless filename.nil? or workspace_files.include?(filename)
|
112
|
-
current_files = @workspace_files
|
113
|
-
@workspace_files = config(true).calculated
|
114
|
-
(current_files - @workspace_files).each { |f| eliminate f }
|
115
|
-
end
|
116
|
-
process_virtual
|
65
|
+
# If the source is in the workspace, virtualizing it has no effect. Only
|
66
|
+
# one source can be virtualized at a time.
|
67
|
+
#
|
68
|
+
# @param [Solargraph::Source]
|
69
|
+
def virtualize source
|
70
|
+
eliminate @virtual_source unless @virtual_source.nil?
|
71
|
+
if workspace.has_source?(source)
|
72
|
+
@sources = workspace.sources
|
73
|
+
@virtual_source = nil
|
117
74
|
else
|
118
|
-
|
119
|
-
|
75
|
+
@virtual_source = source
|
76
|
+
@sources = workspace.sources
|
77
|
+
unless @virtual_source.nil?
|
78
|
+
@sources.push @virtual_source
|
79
|
+
process_virtual
|
120
80
|
end
|
121
81
|
end
|
122
|
-
@virtual_source
|
123
82
|
end
|
124
83
|
|
125
|
-
# @
|
126
|
-
def append_source code, filename
|
127
|
-
|
84
|
+
# @todo Candidate for deprecation
|
85
|
+
def append_source code, filename = nil
|
86
|
+
source = Source.load_string(code, filename)
|
87
|
+
virtualize source
|
128
88
|
end
|
129
89
|
|
130
90
|
# Refresh the ApiMap.
|
131
91
|
#
|
132
92
|
# @param force [Boolean] Perform a refresh even if the map is not "stale."
|
133
93
|
def refresh force = false
|
134
|
-
|
94
|
+
return unless @force or changed?
|
95
|
+
if force
|
96
|
+
process_maps
|
97
|
+
else
|
98
|
+
current_workspace_sources.reject{|s| workspace.sources.include?(s)}.each do |source|
|
99
|
+
eliminate source
|
100
|
+
end
|
101
|
+
@sources = workspace.sources
|
102
|
+
@sources.push @virtual_source unless @virtual_source.nil?
|
103
|
+
cache.clear
|
104
|
+
namespace_map.clear
|
105
|
+
@sources.each do |s|
|
106
|
+
s.namespace_nodes.each_pair do |k, v|
|
107
|
+
namespace_map[k] ||= []
|
108
|
+
namespace_map[k].concat v
|
109
|
+
end
|
110
|
+
end
|
111
|
+
@sources.each do |source|
|
112
|
+
if @stime.nil? or source.stime > @stime
|
113
|
+
eliminate source
|
114
|
+
map_source source
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
@stime = Time.new
|
135
119
|
end
|
136
120
|
|
137
121
|
# True if a workspace file has been created, modified, or deleted since
|
@@ -139,15 +123,10 @@ module Solargraph
|
|
139
123
|
#
|
140
124
|
# @return [Boolean]
|
141
125
|
def changed?
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
current.each do |f|
|
147
|
-
if !File.exist?(f) or File.mtime(f) != source_file_mtime(f)
|
148
|
-
return true
|
149
|
-
end
|
150
|
-
end
|
126
|
+
return true if current_workspace_sources.length != workspace.sources.length
|
127
|
+
return true if @stime.nil?
|
128
|
+
return true if workspace.stime > @stime
|
129
|
+
return true if !@virtual_source.nil? and @virtual_source.stime > @stime
|
151
130
|
false
|
152
131
|
end
|
153
132
|
|
@@ -156,17 +135,17 @@ module Solargraph
|
|
156
135
|
# @param node [AST::Node]
|
157
136
|
# @return [YARD::Docstring]
|
158
137
|
def get_docstring_for node
|
159
|
-
|
160
|
-
return nil if
|
161
|
-
|
138
|
+
source = get_source_for(node)
|
139
|
+
return nil if source.nil?
|
140
|
+
source.docstring_for(node)
|
162
141
|
end
|
163
142
|
|
164
143
|
# An array of suggestions based on Ruby keywords (`if`, `end`, etc.).
|
165
144
|
#
|
166
|
-
# @return [Array<Solargraph::
|
145
|
+
# @return [Array<Solargraph::Pin::Keyword>]
|
167
146
|
def self.keywords
|
168
147
|
@keyword_suggestions ||= KEYWORDS.map{ |s|
|
169
|
-
|
148
|
+
Pin::Keyword.new(s)
|
170
149
|
}.freeze
|
171
150
|
end
|
172
151
|
|
@@ -174,7 +153,7 @@ module Solargraph
|
|
174
153
|
#
|
175
154
|
# @return [Array<String>]
|
176
155
|
def namespaces
|
177
|
-
refresh
|
156
|
+
# refresh
|
178
157
|
namespace_map.keys
|
179
158
|
end
|
180
159
|
|
@@ -203,8 +182,9 @@ module Solargraph
|
|
203
182
|
#
|
204
183
|
# @param namespace [String] The namespace to match
|
205
184
|
# @param context [String] The context to search
|
206
|
-
# @return [Array<Solargraph::
|
185
|
+
# @return [Array<Solargraph::Pin::Base>]
|
207
186
|
def get_constants namespace, context = ''
|
187
|
+
namespace ||= ''
|
208
188
|
skip = []
|
209
189
|
result = []
|
210
190
|
if context.empty?
|
@@ -222,7 +202,19 @@ module Solargraph
|
|
222
202
|
parts.pop
|
223
203
|
end
|
224
204
|
end
|
225
|
-
result.map{|pin| Suggestion.pull(pin)}
|
205
|
+
# result.map{|pin| Suggestion.pull(pin)}
|
206
|
+
result
|
207
|
+
end
|
208
|
+
|
209
|
+
def find_fully_qualified_type namespace_type, context_type = ''
|
210
|
+
namespace, scope = extract_namespace_and_scope(namespace_type)
|
211
|
+
context = extract_namespace(context_type)
|
212
|
+
fqns = find_fully_qualified_namespace(namespace, context)
|
213
|
+
subtypes = get_subtypes(namespace_type)
|
214
|
+
fqns = "#{fqns}<#{subtypes.join(', ')}>" unless subtypes.empty?
|
215
|
+
return fqns if scope == :instance
|
216
|
+
type = get_namespace_type(fqns)
|
217
|
+
"#{type == :class ? 'Class<' : 'Module<'}#{fqns}>"
|
226
218
|
end
|
227
219
|
|
228
220
|
# Get a fully qualified namespace name. This method will start the search
|
@@ -232,7 +224,8 @@ module Solargraph
|
|
232
224
|
# @param root [String] The context to search
|
233
225
|
# @return [String]
|
234
226
|
def find_fully_qualified_namespace name, root = '', skip = []
|
235
|
-
refresh
|
227
|
+
# refresh
|
228
|
+
return nil if name.nil?
|
236
229
|
return nil if skip.include?(root)
|
237
230
|
skip.push root
|
238
231
|
if name == ''
|
@@ -244,11 +237,14 @@ module Solargraph
|
|
244
237
|
else
|
245
238
|
if (root == '')
|
246
239
|
return name unless namespace_map[name].nil?
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
240
|
+
im = @namespace_includes['']
|
241
|
+
unless im.nil?
|
242
|
+
im.each do |i|
|
243
|
+
reroot = "#{root == '' ? '' : root + '::'}#{i}"
|
244
|
+
recname = find_fully_qualified_namespace name.to_s, reroot, skip
|
245
|
+
return recname unless recname.nil?
|
246
|
+
end
|
247
|
+
end
|
252
248
|
else
|
253
249
|
roots = root.to_s.split('::')
|
254
250
|
while roots.length > 0
|
@@ -257,10 +253,13 @@ module Solargraph
|
|
257
253
|
roots.pop
|
258
254
|
end
|
259
255
|
return name unless namespace_map[name].nil?
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
256
|
+
im = @namespace_includes['']
|
257
|
+
unless im.nil?
|
258
|
+
im.each do |i|
|
259
|
+
recname = find_fully_qualified_namespace name, i, skip
|
260
|
+
return recname unless recname.nil?
|
261
|
+
end
|
262
|
+
end
|
264
263
|
end
|
265
264
|
end
|
266
265
|
result = yard_map.find_fully_qualified_namespace(name, root)
|
@@ -277,134 +276,71 @@ module Solargraph
|
|
277
276
|
# @param scope [Symbol] :instance or :class
|
278
277
|
# @return [Array<Solargraph::Pin::InstanceVariable>]
|
279
278
|
def get_instance_variable_pins(namespace, scope = :instance)
|
280
|
-
|
281
|
-
(@ivar_pins[namespace] || []).select{ |pin| pin.scope == scope }
|
279
|
+
suggest_unique_variables (@ivar_pins[namespace] || []).select{ |pin| pin.scope == scope }
|
282
280
|
end
|
283
281
|
|
284
|
-
# Get an array of
|
285
|
-
# namespace and scope.
|
282
|
+
# Get an array of class variable pins for a namespace.
|
286
283
|
#
|
287
284
|
# @param namespace [String] A fully qualified namespace
|
288
|
-
# @param scope [Symbol] :instance or :class
|
289
|
-
# @return [Array<Solargraph::Suggestion>]
|
290
|
-
def get_instance_variables(namespace, scope = :instance)
|
291
|
-
refresh
|
292
|
-
result = []
|
293
|
-
ip = @ivar_pins[namespace]
|
294
|
-
unless ip.nil?
|
295
|
-
result.concat suggest_unique_variables(ip.select{ |pin| pin.scope == scope })
|
296
|
-
end
|
297
|
-
result
|
298
|
-
end
|
299
|
-
|
300
285
|
# @return [Array<Solargraph::Pin::ClassVariable>]
|
301
286
|
def get_class_variable_pins(namespace)
|
302
|
-
|
303
|
-
@cvar_pins[namespace] || []
|
304
|
-
end
|
305
|
-
|
306
|
-
# @return [Array<Solargraph::Suggestion>]
|
307
|
-
def get_class_variables(namespace)
|
308
|
-
refresh
|
309
|
-
result = []
|
310
|
-
cp = @cvar_pins[namespace]
|
311
|
-
unless cp.nil?
|
312
|
-
result.concat suggest_unique_variables(cp)
|
313
|
-
end
|
314
|
-
result
|
287
|
+
suggest_unique_variables(@cvar_pins[namespace] || [])
|
315
288
|
end
|
316
289
|
|
317
|
-
# @return [Array<Solargraph::Pin::
|
290
|
+
# @return [Array<Solargraph::Pin::Base>]
|
318
291
|
def get_symbols
|
319
|
-
refresh
|
320
|
-
@symbol_pins
|
292
|
+
# refresh
|
293
|
+
@symbol_pins
|
321
294
|
end
|
322
295
|
|
323
296
|
# @return [String]
|
324
297
|
def get_filename_for(node)
|
325
|
-
@sources.each do |
|
298
|
+
@sources.each do |source|
|
326
299
|
return source.filename if source.include?(node)
|
327
300
|
end
|
328
301
|
nil
|
329
302
|
end
|
330
303
|
|
331
|
-
# @return [Solargraph::
|
304
|
+
# @return [Solargraph::Source]
|
332
305
|
def get_source_for(node)
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
nil
|
337
|
-
end
|
338
|
-
|
339
|
-
# @return [String]
|
340
|
-
def infer_instance_variable(var, namespace, scope)
|
341
|
-
refresh
|
342
|
-
pins = @ivar_pins[namespace]
|
343
|
-
return nil if pins.nil?
|
344
|
-
pin = pins.select{|p| p.name == var and p.scope == scope}.first
|
345
|
-
return nil if pin.nil?
|
346
|
-
type = nil
|
347
|
-
type = find_fully_qualified_namespace(pin.return_type, pin.namespace) unless pin.return_type.nil?
|
348
|
-
if type.nil?
|
349
|
-
zparts = resolve_node_signature(pin.assignment_node).split('.')
|
350
|
-
ztype = infer_signature_type(zparts[0..-2].join('.'), namespace, scope: :instance, call_node: pin.assignment_node)
|
351
|
-
type = get_return_type_from_macro(ztype, zparts[-1], pin.assignment_node, :instance, [:public, :private, :protected])
|
306
|
+
matches = []
|
307
|
+
@sources.each do |source|
|
308
|
+
matches.push source if source.include?(node)
|
352
309
|
end
|
353
|
-
|
354
|
-
end
|
355
|
-
|
356
|
-
# @return [String]
|
357
|
-
def infer_class_variable(var, namespace)
|
358
|
-
refresh
|
359
|
-
fqns = find_fully_qualified_namespace(namespace)
|
360
|
-
pins = @cvar_pins[fqns]
|
361
|
-
return nil if pins.nil?
|
362
|
-
pin = pins.select{|p| p.name == var}.first
|
363
|
-
return nil if pin.nil? or pin.return_type.nil?
|
364
|
-
find_fully_qualified_namespace(pin.return_type, pin.namespace)
|
365
|
-
end
|
366
|
-
|
367
|
-
# @return [Array<Solargraph::Suggestion>]
|
368
|
-
def get_global_variables
|
369
|
-
globals = []
|
370
|
-
@sources.values.each do |s|
|
371
|
-
globals.concat s.global_variable_pins
|
372
|
-
end
|
373
|
-
suggest_unique_variables globals
|
310
|
+
matches.first
|
374
311
|
end
|
375
312
|
|
376
313
|
# @return [Array<Solargraph::Pin::GlobalVariable>]
|
377
314
|
def get_global_variable_pins
|
378
315
|
globals = []
|
379
|
-
@sources.
|
316
|
+
@sources.each do |s|
|
380
317
|
globals.concat s.global_variable_pins
|
381
318
|
end
|
382
319
|
globals
|
383
320
|
end
|
384
321
|
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
if
|
393
|
-
|
394
|
-
# Avoid infinite loops from variable assignments that reference themselves
|
395
|
-
return nil if node.children[name_i].to_s == sig.split('.').first
|
396
|
-
type = infer_signature_type(sig, namespace, call_node: node.children[sig_i])
|
397
|
-
end
|
398
|
-
cache.set_assignment_node_type(node, namespace, type)
|
399
|
-
type
|
322
|
+
def get_type_methods type, context = ''
|
323
|
+
return [] if type.nil?
|
324
|
+
namespace, scope = extract_namespace_and_scope(type)
|
325
|
+
base = extract_namespace(context)
|
326
|
+
fqns = find_fully_qualified_namespace(namespace, base)
|
327
|
+
return [] if fqns.nil?
|
328
|
+
visibility = [:public]
|
329
|
+
visibility.push :private, :protected if fqns == base
|
330
|
+
get_methods fqns, scope: scope, visibility: visibility
|
400
331
|
end
|
401
332
|
|
402
|
-
def
|
403
|
-
return [] unless node.type == :send
|
333
|
+
def get_methods fqns, scope: :instance, visibility: [:public], deep: true
|
404
334
|
result = []
|
405
|
-
|
406
|
-
|
335
|
+
if fqns == ''
|
336
|
+
skip = []
|
337
|
+
result.concat inner_get_methods(fqns, :class, visibility, deep, skip)
|
338
|
+
result.concat inner_get_methods(fqns, :instance, visibility, deep, skip)
|
339
|
+
result.concat inner_get_methods('Kernel', :instance, visibility, deep, skip)
|
340
|
+
else
|
341
|
+
result.concat inner_get_methods(fqns, scope, visibility, deep, [])
|
407
342
|
end
|
343
|
+
# result.each{|pin| pin.resolve(self)}
|
408
344
|
result
|
409
345
|
end
|
410
346
|
|
@@ -419,222 +355,199 @@ module Solargraph
|
|
419
355
|
# @param scope [Symbol] :class or :instance
|
420
356
|
# @return [String]
|
421
357
|
def infer_signature_type signature, namespace, scope: :class, call_node: nil
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
fqns = find_fully_qualified_namespace(signature, namespace)
|
431
|
-
unless fqns.nil? or fqns.empty?
|
432
|
-
type = (get_namespace_type(fqns) == :class ? 'Class' : 'Module')
|
433
|
-
return "#{type}<#{fqns}>"
|
358
|
+
return nil if signature.start_with?('.')
|
359
|
+
# inner_infer_signature_type signature, namespace, scope, call_node, true
|
360
|
+
base, rest = signature.split('.', 2)
|
361
|
+
if base == 'self'
|
362
|
+
if rest.nil?
|
363
|
+
combine_type(namespace, scope)
|
364
|
+
else
|
365
|
+
inner_infer_signature_type(rest, namespace, scope, call_node, false)
|
434
366
|
end
|
435
|
-
end
|
436
|
-
result = nil
|
437
|
-
if namespace.end_with?('#class')
|
438
|
-
result = infer_signature_type signature, namespace[0..-7], scope: (scope == :class ? :instance : :class), call_node: call_node
|
439
367
|
else
|
440
|
-
|
441
|
-
if
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
368
|
+
pins = infer_signature_pins(base, namespace, scope, call_node)
|
369
|
+
return nil if pins.empty?
|
370
|
+
pin = pins.first
|
371
|
+
if rest.nil?
|
372
|
+
pin.resolve self
|
373
|
+
pin.return_type
|
374
|
+
elsif pin.signature.nil? or pin.signature.empty?
|
375
|
+
if pin.path.nil?
|
376
|
+
pin.resolve self
|
377
|
+
fqtype = find_fully_qualified_type(pin.return_type, namespace)
|
378
|
+
return nil if fqtype.nil?
|
379
|
+
subns, subsc = extract_namespace_and_scope(fqtype)
|
380
|
+
inner_infer_signature_type(rest, subns, subsc, call_node, true)
|
452
381
|
else
|
453
|
-
|
382
|
+
inner_infer_signature_type(rest, pin.path, scope, call_node, true)
|
454
383
|
end
|
455
384
|
else
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
type = inner_infer_signature_type(parts[0], namespace, scope: scope, call_node: call_node)
|
460
|
-
if parts.length < 2
|
461
|
-
if type.nil? and !parts.length.nil?
|
462
|
-
path = "#{clean_namespace_string(namespace)}#{scope == :class ? '.' : '#'}#{parts[0]}"
|
463
|
-
subtypes = get_subtypes(namespace)
|
464
|
-
type = subtypes[0] if METHODS_RETURNING_SUBTYPES.include?(path)
|
465
|
-
end
|
466
|
-
result = type
|
467
|
-
else
|
468
|
-
result = inner_infer_signature_type(parts[1], type, scope: :instance, call_node: call_node)
|
469
|
-
end
|
470
|
-
else
|
471
|
-
result = inner_infer_signature_type(parts[1], type, scope: :class, call_node: call_node)
|
472
|
-
end
|
473
|
-
result = type if result == 'self'
|
385
|
+
subtype = inner_infer_signature_type(pin.signature, namespace, scope, call_node, true)
|
386
|
+
subns, subsc = extract_namespace_and_scope(subtype)
|
387
|
+
inner_infer_signature_type(rest, subns, subsc, call_node, false)
|
474
388
|
end
|
475
389
|
end
|
476
|
-
cache.set_signature_type signature, namespace, scope, result
|
477
|
-
result
|
478
390
|
end
|
479
391
|
|
480
|
-
#
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
end
|
494
|
-
type
|
495
|
-
end
|
496
|
-
|
497
|
-
# Get an array of singleton methods that are available in the specified
|
498
|
-
# namespace.
|
499
|
-
#
|
500
|
-
# @return [Array<Solargraph::Suggestion>]
|
501
|
-
def get_methods(namespace, root = '', visibility: [:public])
|
502
|
-
refresh
|
503
|
-
namespace = clean_namespace_string(namespace)
|
504
|
-
fqns = find_fully_qualified_namespace(namespace, root)
|
505
|
-
meths = []
|
506
|
-
skip = []
|
507
|
-
meths.concat inner_get_methods(namespace, root, skip, visibility)
|
508
|
-
yard_meths = yard_map.get_methods(fqns, '', visibility: visibility)
|
509
|
-
if yard_meths.any?
|
510
|
-
meths.concat yard_meths
|
511
|
-
else
|
512
|
-
type = get_namespace_type(fqns)
|
513
|
-
if type == :class
|
514
|
-
meths.concat yard_map.get_instance_methods('Class')
|
392
|
+
# @return [ApiMap::Completion]
|
393
|
+
def complete fragment
|
394
|
+
return Completion.new([], fragment.whole_word_range) if fragment.string? or fragment.comment?
|
395
|
+
result = []
|
396
|
+
if fragment.base.empty?
|
397
|
+
if fragment.signature.start_with?('@@')
|
398
|
+
result.concat get_class_variable_pins(fragment.namespace)
|
399
|
+
elsif fragment.signature.start_with?('@')
|
400
|
+
result.concat get_instance_variable_pins(fragment.namespace, fragment.scope)
|
401
|
+
elsif fragment.signature.start_with?('$')
|
402
|
+
result.concat get_global_variable_pins
|
403
|
+
elsif fragment.signature.start_with?(':') and !fragment.signature.start_with?('::')
|
404
|
+
result.concat get_symbols
|
515
405
|
else
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
unless news.empty?
|
521
|
-
if @method_pins[fqns]
|
522
|
-
inits = @method_pins[fqns].select{|p| p.name == 'initialize'}
|
523
|
-
meths -= news unless inits.empty?
|
524
|
-
inits.each do |pin|
|
525
|
-
meths.push Suggestion.new('new', kind: pin.kind, docstring: pin.docstring, detail: pin.namespace, arguments: pin.parameters, path: pin.path)
|
406
|
+
unless fragment.signature.include?('::')
|
407
|
+
result.concat fragment.local_variable_pins
|
408
|
+
result.concat get_type_methods(fragment.namespace, fragment.namespace)
|
409
|
+
result.concat ApiMap.keywords
|
526
410
|
end
|
411
|
+
result.concat get_constants(fragment.base, fragment.namespace)
|
527
412
|
end
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
413
|
+
else
|
414
|
+
if fragment.signature.include?('::') and !fragment.signature.include?('.')
|
415
|
+
result.concat get_constants(fragment.base, fragment.namespace)
|
416
|
+
else
|
417
|
+
type = infer_signature_type(fragment.base, fragment.namespace, scope: fragment.scope, call_node: fragment.node)
|
418
|
+
result.concat get_type_methods(type)
|
532
419
|
end
|
533
420
|
end
|
534
|
-
|
535
|
-
|
536
|
-
next if strings.include?(ls.to_s)
|
537
|
-
meths.push ls
|
538
|
-
end
|
539
|
-
meths
|
421
|
+
filtered = result.uniq(&:identifier).select{|s| s.kind != Solargraph::LanguageServer::CompletionItemKinds::METHOD or s.name.match(/^[a-z0-9_]*(\!|\?|=)?$/i)}.sort_by.with_index{ |x, idx| [x.name, idx] }
|
422
|
+
Completion.new(filtered, fragment.whole_word_range)
|
540
423
|
end
|
541
424
|
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
end
|
552
|
-
meths = []
|
553
|
-
meths += inner_get_instance_methods(namespace, root, [], visibility) #unless has_yardoc?
|
554
|
-
fqns = find_fully_qualified_namespace(namespace, root)
|
555
|
-
yard_meths = yard_map.get_instance_methods(fqns, '', visibility: visibility)
|
556
|
-
if yard_meths.any?
|
557
|
-
meths.concat yard_meths
|
558
|
-
else
|
559
|
-
type = get_namespace_type(fqns)
|
560
|
-
if type == :class
|
561
|
-
meths += yard_map.get_instance_methods('Object')
|
562
|
-
elsif type == :module
|
563
|
-
meths += yard_map.get_instance_methods('Module')
|
564
|
-
end
|
565
|
-
end
|
566
|
-
if namespace == '' and root == ''
|
567
|
-
config.domains.each do |d|
|
568
|
-
meths.concat get_instance_methods(d)
|
425
|
+
def define fragment
|
426
|
+
return [] if fragment.string? or fragment.comment?
|
427
|
+
pins = infer_signature_pins fragment.whole_signature, fragment.namespace, fragment.scope, fragment.node
|
428
|
+
return [] if pins.empty?
|
429
|
+
if pins.first.variable?
|
430
|
+
result = []
|
431
|
+
pins.select{|pin| pin.variable?}.each do |pin|
|
432
|
+
pin.resolve self
|
433
|
+
result.concat infer_signature_pins(pin.return_type, fragment.namespace, fragment.scope, fragment.node)
|
569
434
|
end
|
435
|
+
result
|
436
|
+
else
|
437
|
+
pins.reject{|pin| pin.path.nil?}
|
570
438
|
end
|
571
|
-
strings = meths.map(&:to_s)
|
572
|
-
live_map.get_methods(fqns, '', 'class', visibility.include?(:private)).each do |ls|
|
573
|
-
next if strings.include?(ls.to_s)
|
574
|
-
meths.push ls
|
575
|
-
end
|
576
|
-
meths
|
577
439
|
end
|
578
440
|
|
579
|
-
#
|
441
|
+
# Identify the variable, constant, or method call at the fragment's location.
|
580
442
|
#
|
581
|
-
# @param
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
443
|
+
# @param fragment [Solargraph::Source::Fragment]
|
444
|
+
# @return [Array<Solargraph::Pin::Base>]
|
445
|
+
def identify fragment
|
446
|
+
pins = infer_signature_pins(fragment.whole_signature, fragment.namespace, fragment.scope, fragment.node)
|
447
|
+
pins.each { |pin| pin.resolve self }
|
448
|
+
pins
|
449
|
+
end
|
450
|
+
|
451
|
+
def infer_signature_pins signature, namespace, scope, call_node
|
452
|
+
return [] if signature.nil? or signature.empty?
|
453
|
+
base, rest = signature.split('.', 2)
|
454
|
+
if base.start_with?('@@')
|
455
|
+
pin = get_class_variable_pins(namespace).select{|pin| pin.name == base}.first
|
456
|
+
return [] if pin.nil?
|
457
|
+
return [pin] if rest.nil?
|
458
|
+
fqns = find_fully_qualified_namespace(pin.return_type, namespace)
|
459
|
+
return [] if fqns.nil?
|
460
|
+
return inner_infer_signature_pins rest, namespace, scope, call_node, false
|
461
|
+
elsif base.start_with?('@')
|
462
|
+
pin = get_instance_variable_pins(namespace, scope).select{|pin| pin.name == base}.first
|
463
|
+
return [] if pin.nil?
|
464
|
+
pin.resolve self
|
465
|
+
return [pin] if rest.nil?
|
466
|
+
fqtype = find_fully_qualified_type(pin.return_type, namespace)
|
467
|
+
return [] if fqtype.nil?
|
468
|
+
subns, subsc = extract_namespace_and_scope(fqtype)
|
469
|
+
return inner_infer_signature_pins rest, subns, subsc, call_node, false
|
470
|
+
elsif base.start_with?('$')
|
471
|
+
# @todo globals
|
472
|
+
else
|
473
|
+
type = find_fully_qualified_namespace(base, namespace)
|
474
|
+
unless type.nil?
|
475
|
+
if rest.nil?
|
476
|
+
return get_path_suggestions(type)
|
477
|
+
else
|
478
|
+
return inner_infer_signature_pins rest, type, :class, call_node, false
|
479
|
+
end
|
588
480
|
end
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
481
|
+
source = get_source_for(call_node)
|
482
|
+
unless source.nil?
|
483
|
+
lvpins = source.local_variable_pins.select{|pin| pin.name == base and pin.visible_from?(call_node)}
|
484
|
+
unless lvpins.empty?
|
485
|
+
if rest.nil?
|
486
|
+
return lvpins
|
487
|
+
else
|
488
|
+
lvp = lvpins.first
|
489
|
+
lvp.resolve self
|
490
|
+
type = lvp.return_type
|
491
|
+
unless type.nil?
|
492
|
+
fqtype = find_fully_qualified_type(type, namespace)
|
493
|
+
return [] if fqtype.nil?
|
494
|
+
subns, subsc = extract_namespace_and_scope(fqtype)
|
495
|
+
return inner_infer_signature_pins(rest, subns, subsc, call_node, false)
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
599
499
|
end
|
600
|
-
|
601
|
-
# @todo Finish refreshing the map
|
602
|
-
@workspace_files = config(true).calculated
|
500
|
+
return inner_infer_signature_pins signature, namespace, scope, call_node, true
|
603
501
|
end
|
604
502
|
end
|
605
503
|
|
606
|
-
#
|
504
|
+
# Get the namespace's type (Class or Module).
|
607
505
|
#
|
608
|
-
# @
|
609
|
-
|
610
|
-
|
506
|
+
# @param [String] A fully qualified namespace
|
507
|
+
# @return [Symbol] :class, :module, or nil
|
508
|
+
def get_namespace_type fqns
|
509
|
+
pin = @namespace_path_pins[fqns]
|
510
|
+
return yard_map.get_namespace_type(fqns) if pin.nil?
|
511
|
+
pin.first.type
|
512
|
+
end
|
513
|
+
|
514
|
+
def combine_type namespace, scope
|
515
|
+
if scope == :instance
|
516
|
+
namespace
|
517
|
+
else
|
518
|
+
type = get_namespace_type(namespace)
|
519
|
+
"#{type == :class ? 'Class' : 'Module'}<#{namespace}>"
|
520
|
+
end
|
611
521
|
end
|
612
522
|
|
613
523
|
# Get an array of all suggestions that match the specified path.
|
614
524
|
#
|
615
525
|
# @param path [String] The path to find
|
616
|
-
# @return [Array<Solargraph::
|
526
|
+
# @return [Array<Solargraph::Pin::Base>]
|
617
527
|
def get_path_suggestions path
|
618
|
-
|
528
|
+
return [] if path.nil?
|
529
|
+
# refresh
|
619
530
|
result = []
|
620
531
|
if path.include?('#')
|
621
532
|
# It's an instance method
|
622
533
|
parts = path.split('#')
|
623
|
-
result =
|
534
|
+
result = get_methods(parts[0], visibility: [:public, :private, :protected]).select{|s| s.name == parts[1]}
|
624
535
|
elsif path.include?('.')
|
625
536
|
# It's a class method
|
626
537
|
parts = path.split('.')
|
627
|
-
result = get_methods(parts[0],
|
538
|
+
result = get_methods(parts[0], scope: :class, visibility: [:public, :private, :protected]).select{|s| s.name == parts[1]}
|
628
539
|
else
|
629
540
|
# It's a class or module
|
630
541
|
parts = path.split('::')
|
631
542
|
np = @namespace_pins[parts[0..-2].join('::')]
|
632
543
|
unless np.nil?
|
633
|
-
result.concat np.select{|p| p.name == parts.last}
|
544
|
+
result.concat np.select{|p| p.name == parts.last}
|
634
545
|
end
|
635
546
|
result.concat yard_map.objects(path)
|
636
547
|
end
|
637
|
-
|
548
|
+
# @todo Resolve the pins?
|
549
|
+
result.map{|pin| pin.resolve(self); pin}
|
550
|
+
# result
|
638
551
|
end
|
639
552
|
|
640
553
|
# Get a list of documented paths that match the query.
|
@@ -645,8 +558,8 @@ module Solargraph
|
|
645
558
|
# @param query [String] The text to match
|
646
559
|
# @return [Array<String>]
|
647
560
|
def search query
|
648
|
-
refresh
|
649
|
-
rake_yard(@sources
|
561
|
+
# refresh
|
562
|
+
rake_yard(@sources) if @yard_stale
|
650
563
|
@yard_stale = false
|
651
564
|
found = []
|
652
565
|
code_object_paths.each do |k|
|
@@ -665,8 +578,8 @@ module Solargraph
|
|
665
578
|
# @param path [String] The path to find
|
666
579
|
# @return [Array<YARD::CodeObject::Base>]
|
667
580
|
def document path
|
668
|
-
refresh
|
669
|
-
rake_yard(@sources
|
581
|
+
# refresh
|
582
|
+
rake_yard(@sources) if @yard_stale
|
670
583
|
@yard_stale = false
|
671
584
|
docs = []
|
672
585
|
docs.push code_object_at(path) unless code_object_at(path).nil?
|
@@ -674,6 +587,31 @@ module Solargraph
|
|
674
587
|
docs
|
675
588
|
end
|
676
589
|
|
590
|
+
def query_symbols query
|
591
|
+
result = []
|
592
|
+
@sources.each do |s|
|
593
|
+
result.concat s.query_symbols(query)
|
594
|
+
end
|
595
|
+
result
|
596
|
+
end
|
597
|
+
|
598
|
+
def superclass_of fqns
|
599
|
+
found = @superclasses[fqns]
|
600
|
+
return nil if found.nil?
|
601
|
+
find_fully_qualified_namespace(found, fqns)
|
602
|
+
end
|
603
|
+
|
604
|
+
def locate_pin location
|
605
|
+
@sources.each do |source|
|
606
|
+
pin = source.locate_pin(location)
|
607
|
+
unless pin.nil?
|
608
|
+
pin.resolve self
|
609
|
+
return pin
|
610
|
+
end
|
611
|
+
end
|
612
|
+
nil
|
613
|
+
end
|
614
|
+
|
677
615
|
private
|
678
616
|
|
679
617
|
# @return [Hash]
|
@@ -681,15 +619,9 @@ module Solargraph
|
|
681
619
|
@namespace_map ||= {}
|
682
620
|
end
|
683
621
|
|
684
|
-
def clear
|
685
|
-
@stale = false
|
686
|
-
namespace_map.clear
|
687
|
-
path_macros.clear
|
688
|
-
@required = config.required.clone
|
689
|
-
end
|
690
|
-
|
691
622
|
def process_maps
|
692
|
-
|
623
|
+
@sources = workspace.sources
|
624
|
+
@sources.push @virtual_source unless @virtual_source.nil?
|
693
625
|
cache.clear
|
694
626
|
@ivar_pins = {}
|
695
627
|
@cvar_pins = {}
|
@@ -701,25 +633,22 @@ module Solargraph
|
|
701
633
|
@namespace_extends = {}
|
702
634
|
@superclasses = {}
|
703
635
|
@namespace_pins = {}
|
636
|
+
@namespace_path_pins = {}
|
704
637
|
namespace_map.clear
|
705
|
-
@required = config.required.clone
|
706
|
-
@
|
707
|
-
unless @virtual_source.nil?
|
708
|
-
@sources[@virtual_filename] = @virtual_source
|
709
|
-
end
|
710
|
-
@sources.values.each do |s|
|
638
|
+
@required = workspace.config.required.clone
|
639
|
+
@sources.each do |s|
|
711
640
|
s.namespace_nodes.each_pair do |k, v|
|
712
641
|
namespace_map[k] ||= []
|
713
642
|
namespace_map[k].concat v
|
714
643
|
end
|
715
644
|
end
|
716
|
-
@sources.
|
645
|
+
@sources.each do |s|
|
717
646
|
map_source s
|
718
|
-
|
647
|
+
end
|
719
648
|
@required.uniq!
|
720
649
|
live_map.refresh
|
721
|
-
@stale = false
|
722
650
|
@yard_stale = true
|
651
|
+
@stime = Time.now
|
723
652
|
end
|
724
653
|
|
725
654
|
def rebuild_local_yardoc
|
@@ -728,46 +657,30 @@ module Solargraph
|
|
728
657
|
Dir.chdir(workspace) { Process.spawn('yardoc') }
|
729
658
|
end
|
730
659
|
|
731
|
-
def process_workspace_files
|
732
|
-
@sources.clear
|
733
|
-
workspace_files.each do |f|
|
734
|
-
if File.file?(f)
|
735
|
-
begin
|
736
|
-
@@source_cache[f] ||= Source.load(f)
|
737
|
-
@sources[f] = @@source_cache[f]
|
738
|
-
rescue Exception => e
|
739
|
-
STDERR.puts "Failed to load #{f}: #{e.message}"
|
740
|
-
end
|
741
|
-
end
|
742
|
-
end
|
743
|
-
end
|
744
|
-
|
745
660
|
def process_virtual
|
746
661
|
unless @virtual_source.nil?
|
747
662
|
cache.clear
|
748
663
|
namespace_map.clear
|
749
|
-
@sources
|
750
|
-
@sources.values.each do |s|
|
664
|
+
@sources.each do |s|
|
751
665
|
s.namespace_nodes.each_pair do |k, v|
|
752
666
|
namespace_map[k] ||= []
|
753
667
|
namespace_map[k].concat v
|
754
668
|
end
|
755
669
|
end
|
756
|
-
eliminate @virtual_filename
|
757
670
|
map_source @virtual_source
|
758
671
|
end
|
759
672
|
end
|
760
673
|
|
761
|
-
def eliminate
|
674
|
+
def eliminate source
|
762
675
|
[@ivar_pins.values, @cvar_pins.values, @const_pins.values, @method_pins.values, @attr_pins.values, @namespace_pins.values].each do |pinsets|
|
763
676
|
pinsets.each do |pins|
|
764
|
-
pins.delete_if{|pin| pin.filename == filename}
|
677
|
+
pins.delete_if{|pin| pin.filename == source.filename}
|
765
678
|
end
|
766
679
|
end
|
767
|
-
|
680
|
+
@symbol_pins.delete_if{|pin| pin.filename == source.filename}
|
768
681
|
end
|
769
682
|
|
770
|
-
# @param [Solargraph::
|
683
|
+
# @param [Solargraph::Source]
|
771
684
|
def map_source source
|
772
685
|
source.method_pins.each do |pin|
|
773
686
|
@method_pins[pin.namespace] ||= []
|
@@ -790,7 +703,7 @@ module Solargraph
|
|
790
703
|
@const_pins[pin.namespace].push pin
|
791
704
|
end
|
792
705
|
source.symbol_pins.each do |pin|
|
793
|
-
@symbol_pins.push
|
706
|
+
@symbol_pins.push pin
|
794
707
|
end
|
795
708
|
source.namespace_includes.each_pair do |ns, i|
|
796
709
|
@namespace_includes[ns || ''] ||= []
|
@@ -804,6 +717,8 @@ module Solargraph
|
|
804
717
|
@superclasses[cls] = sup
|
805
718
|
end
|
806
719
|
source.namespace_pins.each do |pin|
|
720
|
+
@namespace_path_pins[pin.path] ||= []
|
721
|
+
@namespace_path_pins[pin.path].push pin
|
807
722
|
@namespace_pins[pin.namespace] ||= []
|
808
723
|
@namespace_pins[pin.namespace].push pin
|
809
724
|
end
|
@@ -818,144 +733,60 @@ module Solargraph
|
|
818
733
|
@cache ||= Cache.new
|
819
734
|
end
|
820
735
|
|
821
|
-
def inner_get_methods
|
822
|
-
|
823
|
-
return
|
824
|
-
skip.push
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
unless
|
836
|
-
|
837
|
-
sc_visi.push :protected if root == fqns
|
838
|
-
nfqns = find_fully_qualified_namespace(sc, fqns)
|
839
|
-
meths.concat inner_get_methods('', nfqns, skip, sc_visi)
|
840
|
-
meths.concat yard_map.get_methods(nfqns, '', visibility: sc_visi)
|
841
|
-
end
|
842
|
-
end
|
843
|
-
em = @namespace_extends[fqns]
|
844
|
-
unless em.nil?
|
845
|
-
em.each do |e|
|
846
|
-
meths.concat get_instance_methods(e, fqns, visibility: visibility)
|
847
|
-
end
|
848
|
-
end
|
849
|
-
meths.concat get_instance_methods('', '', visibility: [:public])
|
850
|
-
meths.uniq
|
851
|
-
end
|
852
|
-
|
853
|
-
def inner_get_instance_methods(namespace, root, skip, visibility = [:public])
|
854
|
-
fqns = find_fully_qualified_namespace(namespace, root)
|
855
|
-
meths = []
|
856
|
-
return meths if skip.include?(fqns)
|
857
|
-
skip.push fqns
|
858
|
-
an = @attr_pins[fqns]
|
859
|
-
unless an.nil?
|
860
|
-
an.each do |pin|
|
861
|
-
meths.push pin_to_suggestion(pin)
|
862
|
-
end
|
863
|
-
end
|
864
|
-
mn = @method_pins[fqns]
|
865
|
-
unless mn.nil?
|
866
|
-
mn.select{|pin| visibility.include?(pin.visibility) and pin.scope == :instance }.each do |pin|
|
867
|
-
meths.push pin_to_suggestion(pin)
|
736
|
+
def inner_get_methods fqns, scope, visibility, deep, skip
|
737
|
+
reqstr = "#{fqns}|#{scope}|#{visibility.sort}|#{deep}"
|
738
|
+
return [] if skip.include?(reqstr)
|
739
|
+
skip.push reqstr
|
740
|
+
result = []
|
741
|
+
if scope == :instance
|
742
|
+
aps = @attr_pins[fqns]
|
743
|
+
result.concat aps unless aps.nil?
|
744
|
+
end
|
745
|
+
mps = @method_pins[fqns]
|
746
|
+
result.concat mps.select{|pin| (pin.scope == scope or fqns == '') and visibility.include?(pin.visibility)} unless mps.nil?
|
747
|
+
if fqns != '' and scope == :class and !result.map(&:path).include?("#{fqns}.new")
|
748
|
+
# Create a [Class].new method pin from [Class]#initialize
|
749
|
+
init = inner_get_methods(fqns, :instance, [:private], deep, skip - [fqns]).select{|pin| pin.name == 'initialize'}.first
|
750
|
+
unless init.nil?
|
751
|
+
result.unshift Solargraph::Pin::Directed::Method.new(init.source, init.node, init.namespace, :class, :public, init.docstring, 'new', init.namespace)
|
868
752
|
end
|
869
753
|
end
|
870
|
-
if
|
754
|
+
if deep
|
871
755
|
sc = @superclasses[fqns]
|
872
756
|
unless sc.nil?
|
873
757
|
sc_visi = [:public]
|
874
|
-
sc_visi.push :protected if
|
875
|
-
|
876
|
-
|
877
|
-
meths.concat yard_map.get_instance_methods(nfqns, '', visibility: sc_visi)
|
758
|
+
sc_visi.push :protected if visibility.include?(:protected)
|
759
|
+
sc_fqns = find_fully_qualified_namespace(sc, fqns)
|
760
|
+
result.concat inner_get_methods(sc_fqns, scope, sc_visi, true, skip)
|
878
761
|
end
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
end
|
887
|
-
meths.uniq
|
888
|
-
end
|
889
|
-
|
890
|
-
# Get a fully qualified namespace for the given signature.
|
891
|
-
# The signature should be in the form of a method chain, e.g.,
|
892
|
-
# method1.method2
|
893
|
-
#
|
894
|
-
# @return [String] The fully qualified namespace for the signature's type
|
895
|
-
# or nil if a type could not be determined
|
896
|
-
def inner_infer_signature_type signature, namespace, scope: :instance, top: true, call_node: nil
|
897
|
-
return nil if signature.nil?
|
898
|
-
signature.gsub!(/\.$/, '')
|
899
|
-
if signature.empty?
|
900
|
-
if scope == :class
|
901
|
-
type = get_namespace_type(namespace)
|
902
|
-
if type == :class
|
903
|
-
return "Class<#{namespace}>"
|
904
|
-
else
|
905
|
-
return "Module<#{namespace}>"
|
762
|
+
if scope == :instance
|
763
|
+
im = @namespace_includes[fqns]
|
764
|
+
unless im.nil?
|
765
|
+
im.each do |i|
|
766
|
+
ifqns = find_fully_qualified_namespace(i, fqns)
|
767
|
+
result.concat inner_get_methods(ifqns, scope, visibility, deep, skip)
|
768
|
+
end
|
906
769
|
end
|
907
|
-
|
908
|
-
|
909
|
-
parts = signature.split('.')
|
910
|
-
type = namespace || ''
|
911
|
-
while (parts.length > 0)
|
912
|
-
part = parts.shift
|
913
|
-
if top == true and part == 'self'
|
914
|
-
top = false
|
915
|
-
next
|
916
|
-
end
|
917
|
-
cls_match = type.match(/^Class<([A-Za-z0-9_:]*?)>$/)
|
918
|
-
if cls_match
|
919
|
-
type = cls_match[1]
|
920
|
-
scope = :class
|
921
|
-
end
|
922
|
-
if scope == :class and part == 'new'
|
923
|
-
scope = :instance
|
770
|
+
result.concat yard_map.get_instance_methods(fqns, visibility: visibility)
|
771
|
+
result.concat inner_get_methods('Object', :instance, [:public], deep, skip) unless fqns == 'Object'
|
924
772
|
else
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
tmp = get_instance_methods(namespace, visibility: visibility)
|
931
|
-
else
|
932
|
-
tmp = get_methods(namespace, visibility: visibility)
|
933
|
-
end
|
934
|
-
tmp.concat get_instance_methods('Kernel', visibility: [:public]) if top
|
935
|
-
matches = tmp.select{|s| s.label == part}
|
936
|
-
return nil if matches.empty?
|
937
|
-
matches.each do |m|
|
938
|
-
type = get_return_type_from_macro(namespace, signature, call_node, scope, visibility)
|
939
|
-
if type.nil?
|
940
|
-
if METHODS_RETURNING_SELF.include?(m.path)
|
941
|
-
type = curtype
|
942
|
-
elsif METHODS_RETURNING_SUBTYPES.include?(m.path)
|
943
|
-
subtypes = get_subtypes(namespace)
|
944
|
-
type = subtypes[0]
|
945
|
-
else
|
946
|
-
type = m.return_type
|
947
|
-
end
|
773
|
+
em = @namespace_extends[fqns]
|
774
|
+
unless em.nil?
|
775
|
+
em.each do |e|
|
776
|
+
efqns = find_fully_qualified_namespace(e, fqns)
|
777
|
+
result.concat inner_get_methods(efqns, :instance, visibility, deep, skip)
|
948
778
|
end
|
949
|
-
break unless type.nil?
|
950
779
|
end
|
951
|
-
|
780
|
+
result.concat yard_map.get_methods(fqns, '', visibility: visibility)
|
781
|
+
type = get_namespace_type(fqns)
|
782
|
+
if type == :class
|
783
|
+
result.concat inner_get_methods('Class', :instance, [:public], deep, skip)
|
784
|
+
else
|
785
|
+
result.concat inner_get_methods('Module', :instance, [:public], deep, skip)
|
786
|
+
end
|
952
787
|
end
|
953
|
-
top = false
|
954
|
-
end
|
955
|
-
if scope == :class and !type.nil?
|
956
|
-
type = "Class<#{type}>"
|
957
788
|
end
|
958
|
-
|
789
|
+
result
|
959
790
|
end
|
960
791
|
|
961
792
|
def inner_get_constants fqns, visibility, skip
|
@@ -976,41 +807,33 @@ module Solargraph
|
|
976
807
|
result
|
977
808
|
end
|
978
809
|
|
979
|
-
#
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
#
|
810
|
+
# Extract a namespace from a type.
|
811
|
+
#
|
812
|
+
# @example
|
813
|
+
# extract_namespace('String') => 'String'
|
814
|
+
# extract_namespace('Class<String>') => 'String'
|
815
|
+
#
|
985
816
|
# @return [String]
|
986
|
-
def
|
987
|
-
|
988
|
-
if result == 'Class' and namespace.include?('<')
|
989
|
-
subtype = namespace.match(/<([a-z0-9:_]*)/i)[1]
|
990
|
-
result = "#{subtype}#class"
|
991
|
-
elsif result == 'Module' and namespace.include?('<')
|
992
|
-
subtype = namespace.match(/<([a-z0-9:_]*)/i)[1]
|
993
|
-
result = "#{subtype}#module"
|
994
|
-
end
|
995
|
-
result
|
817
|
+
def extract_namespace type
|
818
|
+
extract_namespace_and_scope(type)[0]
|
996
819
|
end
|
997
820
|
|
998
|
-
#
|
999
|
-
#
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
821
|
+
# Extract a namespace and a scope (:instance or :class) from a type.
|
822
|
+
#
|
823
|
+
# @example
|
824
|
+
# extract_namespace('String') #=> ['String', :instance]
|
825
|
+
# extract_namespace('Class<String>') #=> ['String', :class]
|
826
|
+
# extract_namespace('Module<Enumerable') #=> ['Enumberable', :class]
|
827
|
+
#
|
828
|
+
# @return [Array] The namespace (String) and scope (Symbol).
|
829
|
+
def extract_namespace_and_scope type
|
830
|
+
scope = :instance
|
831
|
+
result = type.to_s.gsub(/<.*$/, '')
|
832
|
+
if (result == 'Class' or result == 'Module') and type.include?('<')
|
833
|
+
result = type.match(/<([a-z0-9:_]*)/i)[1]
|
834
|
+
scope = :class
|
1012
835
|
end
|
1013
|
-
|
836
|
+
[result, scope]
|
1014
837
|
end
|
1015
838
|
|
1016
839
|
def require_extensions
|
@@ -1020,6 +843,7 @@ module Solargraph
|
|
1020
843
|
end
|
1021
844
|
end
|
1022
845
|
|
846
|
+
# @return [Array<Solargraph::Pin::Base>]
|
1023
847
|
def suggest_unique_variables pins
|
1024
848
|
result = []
|
1025
849
|
nil_pins = []
|
@@ -1029,20 +853,20 @@ module Solargraph
|
|
1029
853
|
nil_pins.push pin
|
1030
854
|
else
|
1031
855
|
unless val_names.include?(pin.name)
|
1032
|
-
result.push
|
856
|
+
result.push pin
|
1033
857
|
val_names.push pin.name
|
1034
858
|
end
|
1035
859
|
end
|
1036
860
|
end
|
1037
861
|
nil_pins.reject{|p| val_names.include?(p.name)}.each do |pin|
|
1038
|
-
result.push
|
862
|
+
result.push pin
|
1039
863
|
end
|
1040
864
|
result
|
1041
865
|
end
|
1042
866
|
|
1043
867
|
def source_file_mtime(filename)
|
1044
868
|
# @todo This is naively inefficient.
|
1045
|
-
sources.each do |s|
|
869
|
+
@sources.each do |s|
|
1046
870
|
return s.mtime if s.filename == filename
|
1047
871
|
end
|
1048
872
|
nil
|
@@ -1060,25 +884,6 @@ module Solargraph
|
|
1060
884
|
set.select{|p| p.path == fqns}
|
1061
885
|
end
|
1062
886
|
|
1063
|
-
def get_namespace_nodes(fqns)
|
1064
|
-
return file_nodes if fqns == '' or fqns.nil?
|
1065
|
-
refresh
|
1066
|
-
namespace_map[fqns] || []
|
1067
|
-
end
|
1068
|
-
|
1069
|
-
# @return [Array<String>]
|
1070
|
-
def get_include_strings_from *nodes
|
1071
|
-
arr = []
|
1072
|
-
nodes.each { |node|
|
1073
|
-
next unless node.kind_of?(AST::Node)
|
1074
|
-
arr.push unpack_name(node.children[2]) if (node.type == :send and node.children[1] == :include)
|
1075
|
-
node.children.each { |n|
|
1076
|
-
arr += get_include_strings_from(n) if n.kind_of?(AST::Node) and n.type != :class and n.type != :module and n.type != :sclass
|
1077
|
-
}
|
1078
|
-
}
|
1079
|
-
arr
|
1080
|
-
end
|
1081
|
-
|
1082
887
|
# @todo DRY this method. It's duplicated in CodeMap
|
1083
888
|
def get_subtypes type
|
1084
889
|
return nil if type.nil?
|
@@ -1092,15 +897,28 @@ module Solargraph
|
|
1092
897
|
@path_macros ||= {}
|
1093
898
|
end
|
1094
899
|
|
900
|
+
def get_call_arguments node
|
901
|
+
return get_call_arguments(node.children[1]) if [:ivasgn, :cvasgn, :lvasgn].include?(node.type)
|
902
|
+
return [] unless node.type == :send
|
903
|
+
result = []
|
904
|
+
node.children[2..-1].each do |c|
|
905
|
+
result.push unpack_name(c)
|
906
|
+
end
|
907
|
+
result
|
908
|
+
end
|
909
|
+
|
910
|
+
# @todo This method shouldn't need to calculate the path. In fact, it should work directly off a pin.
|
1095
911
|
def get_return_type_from_macro namespace, signature, call_node, scope, visibility
|
1096
912
|
return nil if signature.empty? or signature.include?('.') or call_node.nil?
|
1097
913
|
path = "#{namespace}#{scope == :class ? '.' : '#'}#{signature}"
|
1098
914
|
macmeth = get_path_suggestions(path).first
|
1099
915
|
type = nil
|
1100
916
|
unless macmeth.nil?
|
917
|
+
macmeths = Suggestion.pull(macmeth)
|
1101
918
|
macro = path_macros[macmeth.path]
|
1102
919
|
macro = macro.first unless macro.nil?
|
1103
|
-
|
920
|
+
# @todo Smelly respond_to? call
|
921
|
+
if macro.nil? and macmeth.respond_to?(:code_object) and !macmeth.code_object.nil? and !macmeth.code_object.base_docstring.nil? and macmeth.code_object.base_docstring.all.include?('@!macro')
|
1104
922
|
all = YARD::Docstring.parser.parse(macmeth.code_object.base_docstring.all).directives
|
1105
923
|
macro = all.select{|m| m.tag.tag_name == 'macro'}.first
|
1106
924
|
end
|
@@ -1115,5 +933,115 @@ module Solargraph
|
|
1115
933
|
end
|
1116
934
|
type
|
1117
935
|
end
|
936
|
+
|
937
|
+
def inner_infer_signature_type signature, namespace, scope, call_node, top
|
938
|
+
namespace ||= ''
|
939
|
+
if cache.has_signature_type?(signature, namespace, scope)
|
940
|
+
return cache.get_signature_type(signature, namespace, scope)
|
941
|
+
end
|
942
|
+
return nil if signature.nil?
|
943
|
+
return namespace if signature.empty? and scope == :instance
|
944
|
+
return nil if signature.empty? # @todo This might need to return Class<namespace>
|
945
|
+
if !signature.include?('.')
|
946
|
+
fqns = find_fully_qualified_namespace(signature, namespace)
|
947
|
+
unless fqns.nil? or fqns.empty?
|
948
|
+
type = (get_namespace_type(fqns) == :class ? 'Class' : 'Module')
|
949
|
+
return "#{type}<#{fqns}>"
|
950
|
+
end
|
951
|
+
end
|
952
|
+
result = nil
|
953
|
+
parts = signature.split('.', 2)
|
954
|
+
type = find_fully_qualified_namespace(parts[0], namespace)
|
955
|
+
if type.nil?
|
956
|
+
# It's a variable or method call
|
957
|
+
if top and parts[0] == 'self'
|
958
|
+
if parts[1].nil?
|
959
|
+
result = namespace
|
960
|
+
else
|
961
|
+
return inner_infer_signature_type(parts[1], namespace, scope, call_node, false)
|
962
|
+
end
|
963
|
+
elsif parts[0] == 'new' and scope == :class
|
964
|
+
scope = :instance
|
965
|
+
if parts[1].nil?
|
966
|
+
result = namespace
|
967
|
+
else
|
968
|
+
result = inner_infer_signature_type(parts[1], namespace, :instance, call_node, false)
|
969
|
+
end
|
970
|
+
else
|
971
|
+
visibility = [:public]
|
972
|
+
visibility.concat [:private, :protected] if top
|
973
|
+
if scope == :instance || namespace == ''
|
974
|
+
tmp = get_methods(extract_namespace(namespace), visibility: visibility)
|
975
|
+
else
|
976
|
+
tmp = get_methods(namespace, visibility: visibility, scope: :class)
|
977
|
+
# tmp = get_type_methods(namespace, (top ? namespace : ''))
|
978
|
+
end
|
979
|
+
tmp.concat get_methods('Kernel', visibility: [:public]) if top
|
980
|
+
matches = tmp.select{|s| s.name == parts[0]}
|
981
|
+
return nil if matches.empty?
|
982
|
+
matches.each do |m|
|
983
|
+
type = get_return_type_from_macro(namespace, signature, call_node, scope, visibility)
|
984
|
+
if type.nil?
|
985
|
+
if METHODS_RETURNING_SELF.include?(m.path)
|
986
|
+
type = curtype
|
987
|
+
elsif METHODS_RETURNING_SUBTYPES.include?(m.path)
|
988
|
+
subtypes = get_subtypes(namespace)
|
989
|
+
type = subtypes[0]
|
990
|
+
elsif !m.return_type.nil?
|
991
|
+
if m.return_type == 'self'
|
992
|
+
type = combine_type(namespace, scope)
|
993
|
+
else
|
994
|
+
type = m.return_type
|
995
|
+
end
|
996
|
+
end
|
997
|
+
end
|
998
|
+
break unless type.nil?
|
999
|
+
end
|
1000
|
+
unless type.nil?
|
1001
|
+
scope = :instance
|
1002
|
+
if parts[1].nil?
|
1003
|
+
result = type
|
1004
|
+
else
|
1005
|
+
subns, subsc = extract_namespace_and_scope(type)
|
1006
|
+
result = inner_infer_signature_type(parts[1], subns, subsc, call_node, false)
|
1007
|
+
end
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
else
|
1011
|
+
return inner_infer_signature_type(parts[1], type, :class, call_node, false)
|
1012
|
+
end
|
1013
|
+
# @todo Assuming `self` only works at the top level
|
1014
|
+
# result = type if result == 'self'
|
1015
|
+
unless result.nil?
|
1016
|
+
if scope == :class
|
1017
|
+
nstype = get_namespace_type(result)
|
1018
|
+
result = "#{nstype == :class ? 'Class<' : 'Module<'}#{result}>"
|
1019
|
+
end
|
1020
|
+
end
|
1021
|
+
cache.set_signature_type signature, namespace, scope, result
|
1022
|
+
result
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
# @todo call_node might be superfluous here. We're already past looking for local variables.
|
1026
|
+
def inner_infer_signature_pins signature, namespace, scope, call_node, top
|
1027
|
+
base, rest = signature.split('.', 2)
|
1028
|
+
type = nil
|
1029
|
+
if rest.nil?
|
1030
|
+
visibility = [:public]
|
1031
|
+
visibility.push :private, :protected if top
|
1032
|
+
methods = []
|
1033
|
+
methods.concat get_methods(namespace, visibility: visibility, scope: scope).select{|pin| pin.name == base}
|
1034
|
+
methods.concat get_methods('Kernel', scope: :instance).select{|pin| pin.name == base} if top
|
1035
|
+
return methods
|
1036
|
+
else
|
1037
|
+
type = inner_infer_signature_type base, namespace, scope, call_node, top
|
1038
|
+
nxt_ns, nxt_scope = extract_namespace_and_scope(type)
|
1039
|
+
return inner_infer_signature_pins rest, nxt_ns, nxt_scope, call_node, false
|
1040
|
+
end
|
1041
|
+
end
|
1042
|
+
|
1043
|
+
def current_workspace_sources
|
1044
|
+
@sources - [@virtual_source]
|
1045
|
+
end
|
1118
1046
|
end
|
1119
1047
|
end
|