solargraph 0.26.1 → 0.27.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 +5 -2
- data/lib/solargraph/api_map.rb +236 -234
- data/lib/solargraph/api_map/store.rb +18 -53
- data/lib/solargraph/bundle.rb +22 -0
- data/lib/solargraph/complex_type.rb +9 -5
- data/lib/solargraph/complex_type/type_methods.rb +113 -0
- data/lib/solargraph/complex_type/unique_type.rb +35 -0
- data/lib/solargraph/core_fills.rb +1 -0
- data/lib/solargraph/diagnostics.rb +6 -4
- data/lib/solargraph/diagnostics/base.rb +3 -0
- data/lib/solargraph/diagnostics/require_not_found.rb +2 -1
- data/lib/solargraph/diagnostics/rubocop.rb +21 -6
- data/lib/solargraph/diagnostics/type_not_defined.rb +4 -3
- data/lib/solargraph/diagnostics/update_errors.rb +18 -0
- data/lib/solargraph/language_server/host.rb +90 -222
- data/lib/solargraph/language_server/host/cataloger.rb +68 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +85 -0
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +35 -24
- data/lib/solargraph/language_server/message/text_document/completion.rb +6 -8
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +1 -1
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +0 -1
- data/lib/solargraph/language_server/transport/socket.rb +4 -6
- data/lib/solargraph/language_server/transport/stdio.rb +4 -6
- data/lib/solargraph/library.rb +152 -99
- data/lib/solargraph/live_map.rb +1 -1
- data/lib/solargraph/location.rb +28 -0
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/pin/attribute.rb +26 -12
- data/lib/solargraph/pin/base.rb +15 -35
- data/lib/solargraph/pin/base_variable.rb +7 -15
- data/lib/solargraph/pin/block.rb +5 -9
- data/lib/solargraph/pin/block_parameter.rb +9 -7
- data/lib/solargraph/pin/conversions.rb +5 -5
- data/lib/solargraph/pin/duck_method.rb +1 -1
- data/lib/solargraph/pin/instance_variable.rb +0 -4
- data/lib/solargraph/pin/keyword.rb +4 -0
- data/lib/solargraph/pin/localized.rb +5 -3
- data/lib/solargraph/pin/method.rb +11 -0
- data/lib/solargraph/pin/namespace.rb +7 -3
- data/lib/solargraph/pin/proxy_type.rb +3 -7
- data/lib/solargraph/pin/reference.rb +2 -2
- data/lib/solargraph/pin/symbol.rb +1 -1
- data/lib/solargraph/pin/yard_pin/method.rb +2 -2
- data/lib/solargraph/pin/yard_pin/namespace.rb +16 -7
- data/lib/solargraph/position.rb +103 -0
- data/lib/solargraph/range.rb +70 -0
- data/lib/solargraph/source.rb +159 -328
- data/lib/solargraph/source/chain.rb +38 -55
- data/lib/solargraph/source/chain/call.rb +47 -29
- data/lib/solargraph/source/chain/class_variable.rb +2 -2
- data/lib/solargraph/source/chain/constant.rb +3 -3
- data/lib/solargraph/source/chain/definition.rb +7 -3
- data/lib/solargraph/source/chain/global_variable.rb +1 -1
- data/lib/solargraph/source/chain/head.rb +22 -9
- data/lib/solargraph/source/chain/instance_variable.rb +2 -2
- data/lib/solargraph/source/chain/link.rb +4 -4
- data/lib/solargraph/source/chain/literal.rb +1 -1
- data/lib/solargraph/source/chain/variable.rb +2 -2
- data/lib/solargraph/source/change.rb +0 -6
- data/lib/solargraph/source/cursor.rb +161 -0
- data/lib/solargraph/source/encoding_fixes.rb +1 -1
- data/lib/solargraph/source/node_chainer.rb +28 -21
- data/lib/solargraph/source/node_methods.rb +1 -1
- data/lib/solargraph/source/source_chainer.rb +217 -0
- data/lib/solargraph/source_map.rb +138 -0
- data/lib/solargraph/source_map/clip.rb +123 -0
- data/lib/solargraph/{source → source_map}/completion.rb +3 -3
- data/lib/solargraph/{source → source_map}/mapper.rb +143 -41
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +13 -20
- data/lib/solargraph/yard_map.rb +77 -48
- metadata +17 -11
- data/lib/solargraph/basic_type.rb +0 -33
- data/lib/solargraph/basic_type_methods.rb +0 -111
- data/lib/solargraph/source/call_chainer.rb +0 -273
- data/lib/solargraph/source/fragment.rb +0 -342
- data/lib/solargraph/source/location.rb +0 -23
- data/lib/solargraph/source/position.rb +0 -95
- data/lib/solargraph/source/range.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46fca036521e6830f95550138d35e1c504cec3f75c04b45ff9ce3cf06cbafc30
|
4
|
+
data.tar.gz: 32fd1c0b308a3c5b89f00bbd4b8f804aba057d8277ccafb5505f7e787dca3fb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '07263532728a958734568023619dedbd8b2fcc1c5b84aa9a4432c4af8c247f5cf47343861ee15ef8b377371c35ed96e05367d34781fbb49b1dcf120cc5f1893b'
|
7
|
+
data.tar.gz: 1bc3fddcfc98cee8f0287b46e1792f4ff87c51c45bc6ed1281e88ea8473470ef062eebe2e3ac112d63d639c647015c702072840732464b271f68574cf329cf66
|
data/lib/solargraph.rb
CHANGED
@@ -24,8 +24,12 @@ module Solargraph
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
autoload :Position, 'solargraph/position'
|
28
|
+
autoload :Range, 'solargraph/range'
|
29
|
+
autoload :Location, 'solargraph/location'
|
27
30
|
autoload :Shell, 'solargraph/shell'
|
28
31
|
autoload :Source, 'solargraph/source'
|
32
|
+
autoload :SourceMap, 'solargraph/source_map'
|
29
33
|
autoload :ApiMap, 'solargraph/api_map'
|
30
34
|
autoload :YardMap, 'solargraph/yard_map'
|
31
35
|
autoload :Pin, 'solargraph/pin'
|
@@ -38,9 +42,8 @@ module Solargraph
|
|
38
42
|
autoload :Page, 'solargraph/page'
|
39
43
|
autoload :Library, 'solargraph/library'
|
40
44
|
autoload :Diagnostics, 'solargraph/diagnostics'
|
41
|
-
autoload :BasicTypeMethods, 'solargraph/basic_type_methods'
|
42
|
-
autoload :BasicType, 'solargraph/basic_type'
|
43
45
|
autoload :ComplexType, 'solargraph/complex_type'
|
46
|
+
autoload :Bundle, 'solargraph/bundle'
|
44
47
|
|
45
48
|
YARDOC_PATH = File.join(File.realpath(File.dirname(__FILE__)), '..', 'yardoc')
|
46
49
|
YARD_EXTENSION_FILE = File.join(File.realpath(File.dirname(__FILE__)), 'yard-solargraph.rb')
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'set'
|
3
|
-
require 'time'
|
4
3
|
|
5
4
|
module Solargraph
|
6
5
|
# An aggregate provider for information about workspaces, sources, gems, and
|
@@ -12,132 +11,147 @@ module Solargraph
|
|
12
11
|
autoload :Store, 'solargraph/api_map/store'
|
13
12
|
|
14
13
|
include Solargraph::ApiMap::SourceToYard
|
15
|
-
include CoreFills
|
16
|
-
|
17
|
-
# The workspace to analyze and process.
|
18
|
-
#
|
19
|
-
# @return [Solargraph::Workspace]
|
20
|
-
attr_reader :workspace
|
21
14
|
|
22
15
|
# Get a LiveMap associated with the current workspace.
|
23
16
|
#
|
24
17
|
# @return [Solargraph::LiveMap]
|
25
18
|
attr_reader :live_map
|
26
19
|
|
27
|
-
# @param workspace [Solargraph::Workspace]
|
28
|
-
def initialize workspace = Solargraph::Workspace.new(nil)
|
29
|
-
@workspace = workspace
|
30
|
-
require_extensions
|
31
|
-
@virtual_source = nil
|
32
|
-
@sources = workspace.sources
|
33
|
-
refresh_store_and_maps
|
34
|
-
end
|
35
|
-
|
36
|
-
# Create an ApiMap with a workspace in the specified directory.
|
37
|
-
#
|
38
|
-
# @param directory [String]
|
39
|
-
# @return [ApiMap]
|
40
|
-
def self.load directory
|
41
|
-
self.new(Solargraph::Workspace.new(directory))
|
42
|
-
end
|
43
|
-
|
44
|
-
# @return [Array<Solargraph::Pin::Base>]
|
45
|
-
def pins
|
46
|
-
store.pins
|
47
|
-
end
|
48
|
-
|
49
20
|
# @return [Array<String>]
|
50
|
-
|
51
|
-
@domains ||= []
|
52
|
-
end
|
21
|
+
attr_reader :unresolved_requires
|
53
22
|
|
54
|
-
#
|
23
|
+
# @param pins [Array<Solargraph::Pin::Base>]
|
24
|
+
# @param yard_map [YardMap]
|
25
|
+
# def initialize workspace = Solargraph::Workspace.new(nil)
|
26
|
+
def initialize pins: []
|
27
|
+
# @todo Extensions don't work yet
|
28
|
+
# require_extensions
|
29
|
+
@source_map_hash = {}
|
30
|
+
@cache = Cache.new
|
31
|
+
@mutex = Mutex.new
|
32
|
+
index pins
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param pins [Array<Pin::Base>]
|
36
|
+
# @return [self]
|
37
|
+
def index pins
|
38
|
+
@mutex.synchronize {
|
39
|
+
@source_map_hash.clear
|
40
|
+
@cache.clear
|
41
|
+
@store = Store.new(pins + YardMap.new.pins)
|
42
|
+
@unresolved_requires = []
|
43
|
+
}
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param source [Source]
|
48
|
+
# @return [self]
|
49
|
+
def map source
|
50
|
+
catalog Bundle.new(sources: [source])
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
# Catalog a workspace. Additional sources that need to be mapped can be
|
55
|
+
# included in an optional array.
|
55
56
|
#
|
56
|
-
# @
|
57
|
-
|
58
|
-
|
59
|
-
@
|
60
|
-
|
57
|
+
# @param bundle [Bundle]
|
58
|
+
# @return [self]
|
59
|
+
def catalog bundle
|
60
|
+
# @todo This can be more efficient. We don't need to remap sources that
|
61
|
+
# are already here.
|
62
|
+
# all_sources = (workspace.sources + others).uniq
|
63
|
+
new_map_hash = {}
|
64
|
+
unmerged = false
|
65
|
+
bundle.sources.each do |source|
|
66
|
+
if source_map_hash.has_key?(source.filename)
|
67
|
+
if source_map_hash[source.filename].code == source.code
|
68
|
+
new_map_hash[source.filename] = source_map_hash[source.filename]
|
69
|
+
else
|
70
|
+
map = Solargraph::SourceMap.map(source)
|
71
|
+
if source_map_hash[source.filename].try_merge!(map)
|
72
|
+
new_map_hash[source.filename] = source_map_hash[source.filename]
|
73
|
+
else
|
74
|
+
new_map_hash[source.filename] = map
|
75
|
+
unmerged = true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
else
|
79
|
+
map = Solargraph::SourceMap.map(source)
|
80
|
+
new_map_hash[source.filename] = map
|
81
|
+
unmerged = true
|
82
|
+
end
|
61
83
|
end
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
domains.uniq!
|
82
|
-
if workspace.has_source?(source)
|
83
|
-
@sources = workspace.sources
|
84
|
-
@virtual_source = nil
|
85
|
-
else
|
86
|
-
@virtual_source = source
|
87
|
-
@sources = workspace.sources
|
88
|
-
unless @virtual_source.nil?
|
89
|
-
@sources.push @virtual_source
|
90
|
-
process_virtual
|
84
|
+
return self unless unmerged
|
85
|
+
pins = []
|
86
|
+
reqs = []
|
87
|
+
# @param map [SourceMap]
|
88
|
+
new_map_hash.values.each do |map|
|
89
|
+
pins.concat map.pins
|
90
|
+
reqs.concat map.requires.map(&:name)
|
91
|
+
end
|
92
|
+
reqs.concat bundle.required
|
93
|
+
unless bundle.load_paths.empty?
|
94
|
+
reqs.delete_if do |r|
|
95
|
+
result = false
|
96
|
+
bundle.load_paths.each do |l|
|
97
|
+
if new_map_hash.keys.include?(File.join(l, "#{r}.rb"))
|
98
|
+
result = true
|
99
|
+
break
|
100
|
+
end
|
101
|
+
end
|
102
|
+
result
|
91
103
|
end
|
92
104
|
end
|
93
|
-
|
105
|
+
bundle.yard_map.change(reqs)
|
106
|
+
new_store = Store.new(pins + bundle.yard_map.pins)
|
107
|
+
@mutex.synchronize {
|
108
|
+
@cache.clear
|
109
|
+
@source_map_hash = new_map_hash
|
110
|
+
@store = new_store
|
111
|
+
@unresolved_requires = bundle.yard_map.unresolved_requires
|
112
|
+
}
|
113
|
+
self
|
94
114
|
end
|
95
115
|
|
96
|
-
# Create a Source from the code and filename, and virtualize the result.
|
97
|
-
# This method can be useful for directly testing the ApiMap. In practice,
|
98
|
-
# applications should use a Library to synchronize the ApiMap to a
|
99
|
-
# workspace.
|
100
|
-
#
|
101
|
-
# @param code [String]
|
102
116
|
# @param filename [String]
|
103
|
-
# @
|
104
|
-
|
105
|
-
|
106
|
-
|
117
|
+
# @param position [Position]
|
118
|
+
# @return [Source::Cursor]
|
119
|
+
def cursor_at filename, position
|
120
|
+
raise "File not found: #{filename}" unless source_map_hash.has_key?(filename)
|
121
|
+
source_map_hash[filename].cursor_at(position)
|
107
122
|
end
|
108
123
|
|
109
|
-
#
|
110
|
-
# performing the refresh unless the `force` parameter is true.
|
124
|
+
# Get a clip by filename and position.
|
111
125
|
#
|
112
|
-
# @param
|
113
|
-
# @
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
refresh_store_and_maps
|
118
|
-
else
|
119
|
-
update_store_and_maps
|
120
|
-
end
|
121
|
-
true
|
126
|
+
# @param filename [String]
|
127
|
+
# @param position [Position]
|
128
|
+
# @return [SourceMap::Clip]
|
129
|
+
def clip_at filename, position
|
130
|
+
SourceMap::Clip.new(self, cursor_at(filename, position))
|
122
131
|
end
|
123
132
|
|
124
|
-
#
|
125
|
-
# the last time the map was processed.
|
133
|
+
# Create an ApiMap with a workspace in the specified directory.
|
126
134
|
#
|
127
|
-
# @
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
135
|
+
# @param directory [String]
|
136
|
+
# @return [ApiMap]
|
137
|
+
def self.load directory
|
138
|
+
# @todo How should this work?
|
139
|
+
api_map = self.new #(Solargraph::Workspace.new(directory))
|
140
|
+
workspace = Solargraph::Workspace.new(directory)
|
141
|
+
api_map.catalog Bundle.new(sources: workspace.sources)
|
142
|
+
api_map
|
143
|
+
end
|
144
|
+
|
145
|
+
# @return [Array<Solargraph::Pin::Base>]
|
146
|
+
def pins
|
147
|
+
store.pins
|
134
148
|
end
|
135
149
|
|
136
150
|
# An array of suggestions based on Ruby keywords (`if`, `end`, etc.).
|
137
151
|
#
|
138
152
|
# @return [Array<Solargraph::Pin::Keyword>]
|
139
153
|
def self.keywords
|
140
|
-
@keywords ||= KEYWORDS.map{ |s|
|
154
|
+
@keywords ||= CoreFills::KEYWORDS.map{ |s|
|
141
155
|
Pin::Keyword.new(s)
|
142
156
|
}.freeze
|
143
157
|
end
|
@@ -190,34 +204,26 @@ module Solargraph
|
|
190
204
|
# Get a fully qualified namespace name. This method will start the search
|
191
205
|
# in the specified context until it finds a match for the name.
|
192
206
|
#
|
193
|
-
# @param namespace [String] The namespace to match
|
207
|
+
# @param namespace [String, nil] The namespace to match
|
194
208
|
# @param context [String] The context to search
|
195
209
|
# @return [String]
|
196
210
|
def qualify namespace, context = ''
|
197
211
|
# @todo The return for self might work better elsewhere
|
212
|
+
return nil if namespace.nil?
|
198
213
|
return qualify(context) if namespace == 'self'
|
199
214
|
cached = cache.get_qualified_namespace(namespace, context)
|
200
215
|
return cached.clone unless cached.nil?
|
201
|
-
result = inner_qualify(namespace, context, [])
|
216
|
+
# result = inner_qualify(namespace, context, [])
|
217
|
+
# result = result[2..-1] if !result.nil? && result.start_with?('::')
|
218
|
+
if namespace.start_with?('::')
|
219
|
+
result = inner_qualify(namespace[2..-1], '', [])
|
220
|
+
else
|
221
|
+
result = inner_qualify(namespace, context, [])
|
222
|
+
end
|
202
223
|
cache.set_qualified_namespace(namespace, context, result)
|
203
224
|
result
|
204
225
|
end
|
205
226
|
|
206
|
-
def fragment_at(location)
|
207
|
-
@sources.each do |source|
|
208
|
-
return source.fragment_at(location.range.start.line, location.range.start.column) if source.filename == location.filename
|
209
|
-
end
|
210
|
-
nil
|
211
|
-
end
|
212
|
-
|
213
|
-
# @deprecated Use #qualify instead
|
214
|
-
# @param namespace [String]
|
215
|
-
# @param context [String]
|
216
|
-
# @return [String]
|
217
|
-
def find_fully_qualified_namespace namespace, context = ''
|
218
|
-
qualify namespace, context
|
219
|
-
end
|
220
|
-
|
221
227
|
# Get an array of instance variable pins defined in specified namespace
|
222
228
|
# and scope.
|
223
229
|
#
|
@@ -225,7 +231,14 @@ module Solargraph
|
|
225
231
|
# @param scope [Symbol] :instance or :class
|
226
232
|
# @return [Array<Solargraph::Pin::InstanceVariable>]
|
227
233
|
def get_instance_variable_pins(namespace, scope = :instance)
|
228
|
-
|
234
|
+
result = []
|
235
|
+
result.concat store.get_instance_variables(namespace, scope)
|
236
|
+
sc = qualify(store.get_superclass(namespace), namespace)
|
237
|
+
until sc.nil?
|
238
|
+
result.concat store.get_instance_variables(sc, scope)
|
239
|
+
sc = qualify(store.get_superclass(sc), sc)
|
240
|
+
end
|
241
|
+
result
|
229
242
|
end
|
230
243
|
|
231
244
|
# Get an array of class variable pins for a namespace.
|
@@ -241,21 +254,10 @@ module Solargraph
|
|
241
254
|
store.get_symbols
|
242
255
|
end
|
243
256
|
|
244
|
-
# @todo Make this better
|
245
|
-
def get_source filename
|
246
|
-
@sources.each do |s|
|
247
|
-
return s if s.filename == filename
|
248
|
-
end
|
249
|
-
nil
|
250
|
-
end
|
251
|
-
|
252
257
|
# @return [Array<Solargraph::Pin::GlobalVariable>]
|
253
258
|
def get_global_variable_pins
|
254
|
-
|
255
|
-
|
256
|
-
globals.concat s.global_variable_pins
|
257
|
-
end
|
258
|
-
globals
|
259
|
+
# @todo Slow version
|
260
|
+
pins.select{|p| p.kind == Pin::GLOBAL_VARIABLE}
|
259
261
|
end
|
260
262
|
|
261
263
|
# Get an array of methods available in a particular context.
|
@@ -271,21 +273,22 @@ module Solargraph
|
|
271
273
|
result = []
|
272
274
|
skip = []
|
273
275
|
if fqns == ''
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
276
|
+
# @todo Implement domains
|
277
|
+
# domains.each do |domain|
|
278
|
+
# type = ComplexType.parse(domain).first
|
279
|
+
# result.concat inner_get_methods(type.name, type.scope, [:public], deep, skip)
|
280
|
+
# end
|
278
281
|
result.concat inner_get_methods(fqns, :class, visibility, deep, skip)
|
279
282
|
result.concat inner_get_methods(fqns, :instance, visibility, deep, skip)
|
280
283
|
result.concat inner_get_methods('Kernel', :instance, visibility, deep, skip)
|
281
284
|
else
|
282
285
|
result.concat inner_get_methods(fqns, scope, visibility, deep, skip)
|
283
286
|
end
|
284
|
-
live = live_map.get_methods(fqns, '', scope.to_s, visibility.include?(:private))
|
285
|
-
unless live.empty?
|
286
|
-
|
287
|
-
|
288
|
-
end
|
287
|
+
# live = live_map.get_methods(fqns, '', scope.to_s, visibility.include?(:private))
|
288
|
+
# unless live.empty?
|
289
|
+
# exist = result.map(&:name)
|
290
|
+
# result.concat live.reject{|p| exist.include?(p.name)}
|
291
|
+
# end
|
289
292
|
cache.set_methods(fqns, scope, visibility, deep, result)
|
290
293
|
result
|
291
294
|
end
|
@@ -296,21 +299,17 @@ module Solargraph
|
|
296
299
|
# @param context [String]
|
297
300
|
# @return [Array<Solargraph::Pin::Base>]
|
298
301
|
def get_complex_type_methods type, context = '', internal = false
|
299
|
-
return [] if type.undefined?
|
302
|
+
return [] if type.undefined? || type.void?
|
300
303
|
result = []
|
301
304
|
if type.duck_type?
|
302
305
|
type.select(&:duck_type?).each do |t|
|
303
306
|
result.push Pin::DuckMethod.new(nil, t.tag[1..-1])
|
304
307
|
end
|
305
308
|
else
|
306
|
-
unless type.nil?
|
309
|
+
unless type.nil? || type.name == 'void'
|
307
310
|
namespace = qualify(type.namespace, context)
|
308
|
-
if ['Class', 'Module'].include?(namespace) and !type.subtypes.empty?
|
309
|
-
subtype = qualify(type.subtypes.first.name, context)
|
310
|
-
result.concat get_methods(subtype, scope: :class)
|
311
|
-
end
|
312
311
|
visibility = [:public]
|
313
|
-
if namespace == context
|
312
|
+
if namespace == context || super_and_sub?(namespace, context)
|
314
313
|
visibility.push :protected
|
315
314
|
visibility.push :private if internal
|
316
315
|
end
|
@@ -333,9 +332,9 @@ module Solargraph
|
|
333
332
|
# @param scope [Symbol] :instance or :class
|
334
333
|
# @return [Array<Solargraph::Pin::Base>]
|
335
334
|
def get_method_stack fqns, name, scope: :instance
|
336
|
-
# @todo
|
335
|
+
# @todo This cache is still causing problems.
|
337
336
|
# cached = cache.get_method_stack(fqns, name, scope)
|
338
|
-
# return cached
|
337
|
+
# return cached unless cached.nil?
|
339
338
|
result = get_methods(fqns, scope: scope, visibility: [:private, :protected, :public]).select{|p| p.name == name}
|
340
339
|
# cache.set_method_stack(fqns, name, scope, result)
|
341
340
|
result
|
@@ -343,19 +342,29 @@ module Solargraph
|
|
343
342
|
|
344
343
|
# Get an array of all suggestions that match the specified path.
|
345
344
|
#
|
345
|
+
# @deprecated Use #get_path_pins instead.
|
346
|
+
#
|
346
347
|
# @param path [String] The path to find
|
347
348
|
# @return [Array<Solargraph::Pin::Base>]
|
348
349
|
def get_path_suggestions path
|
349
350
|
return [] if path.nil?
|
350
351
|
result = []
|
351
352
|
result.concat store.get_path_pins(path)
|
352
|
-
if result.empty?
|
353
|
-
|
354
|
-
|
355
|
-
end
|
353
|
+
# if result.empty?
|
354
|
+
# lp = live_map.get_path_pin(path)
|
355
|
+
# result.push lp unless lp.nil?
|
356
|
+
# end
|
356
357
|
result
|
357
358
|
end
|
358
359
|
|
360
|
+
# Get an array of pins that match the specified path.
|
361
|
+
#
|
362
|
+
# @param path [String]
|
363
|
+
# @return [Array<Pin::Base>]
|
364
|
+
def get_path_pins path
|
365
|
+
get_path_suggestions(path)
|
366
|
+
end
|
367
|
+
|
359
368
|
# Get a list of documented paths that match the query.
|
360
369
|
#
|
361
370
|
# @example
|
@@ -364,11 +373,10 @@ module Solargraph
|
|
364
373
|
# @param query [String] The text to match
|
365
374
|
# @return [Array<String>]
|
366
375
|
def search query
|
367
|
-
rake_yard(store)
|
368
|
-
@yard_stale = false
|
376
|
+
rake_yard(store)
|
369
377
|
found = []
|
370
378
|
code_object_paths.each do |k|
|
371
|
-
if found.empty?
|
379
|
+
if found.empty? || (query.include?('.') || query.include?('#')) || !(k.include?('.') || k.include?('#'))
|
372
380
|
found.push k if k.downcase.include?(query.downcase)
|
373
381
|
end
|
374
382
|
end
|
@@ -383,8 +391,7 @@ module Solargraph
|
|
383
391
|
# @param path [String] The path to find
|
384
392
|
# @return [Array<YARD::CodeObject::Base>]
|
385
393
|
def document path
|
386
|
-
rake_yard(store)
|
387
|
-
@yard_stale = false
|
394
|
+
rake_yard(store)
|
388
395
|
docs = []
|
389
396
|
docs.push code_object_at(path) unless code_object_at(path).nil?
|
390
397
|
docs
|
@@ -396,74 +403,68 @@ module Solargraph
|
|
396
403
|
# @return [Array<Pin::Base>]
|
397
404
|
def query_symbols query
|
398
405
|
result = []
|
399
|
-
|
406
|
+
source_map_hash.values.each do |s|
|
400
407
|
result.concat s.query_symbols(query)
|
401
408
|
end
|
402
409
|
result
|
403
410
|
end
|
404
411
|
|
405
|
-
# @param location [Solargraph::
|
412
|
+
# @param location [Solargraph::Location]
|
406
413
|
# @return [Solargraph::Pin::Base]
|
407
414
|
def locate_pin location
|
408
|
-
|
409
|
-
|
410
|
-
return pin unless pin.nil?
|
411
|
-
end
|
412
|
-
nil
|
415
|
+
return nil if location.nil? || !source_map_hash.has_key?(location.filename)
|
416
|
+
source_map_hash[location.filename].locate_pin(location)
|
413
417
|
end
|
414
418
|
|
415
|
-
# @
|
416
|
-
|
417
|
-
|
419
|
+
# @raise [FileNotFoundError] if the cursor's file is not in the ApiMap
|
420
|
+
# @param cursor [Source::Cursor]
|
421
|
+
# @return [SourceMap::Clip]
|
422
|
+
def clip cursor
|
423
|
+
raise FileNotFoundError, "ApiMap did not catalog #{cursor.filename}" unless source_map_hash.has_key?(cursor.filename)
|
424
|
+
SourceMap::Clip.new(self, cursor)
|
418
425
|
end
|
419
426
|
|
420
|
-
|
421
|
-
|
422
|
-
# @
|
423
|
-
|
424
|
-
|
427
|
+
# Get an array of document symbols from a file.
|
428
|
+
#
|
429
|
+
# @param filename [String]
|
430
|
+
# @return [Array<Pin::Symbol>]
|
431
|
+
def document_symbols filename
|
432
|
+
return [] unless source_map_hash.has_key?(filename) # @todo Raise error?
|
433
|
+
source_map_hash[filename].document_symbols
|
425
434
|
end
|
426
435
|
|
427
|
-
#
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
436
|
+
# Get a source map by filename.
|
437
|
+
#
|
438
|
+
# @param filename [String]
|
439
|
+
# @return [SourceMap]
|
440
|
+
def source_map filename
|
441
|
+
raise FileNotFoundError, "Source map for `#{filename}` not found" unless source_map_hash.has_key?(filename)
|
442
|
+
source_map_hash[filename]
|
434
443
|
end
|
435
444
|
|
436
|
-
|
437
|
-
def update_store_and_maps
|
438
|
-
@yard_stale = true
|
439
|
-
store.remove *(current_workspace_sources.reject{ |s| workspace.sources.include?(s) })
|
440
|
-
@sources = workspace.sources
|
441
|
-
@sources.push @virtual_source unless @virtual_source.nil?
|
442
|
-
store.update *(@sources.select{ |s| @stime.nil? or s.stime > @stime })
|
443
|
-
store.update_yard(yard_map.pins) if yard_map.change(required)
|
444
|
-
cache.clear
|
445
|
-
@stime = Time.now
|
446
|
-
end
|
445
|
+
private
|
447
446
|
|
448
|
-
#
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
447
|
+
# A hash of source maps with filename keys.
|
448
|
+
#
|
449
|
+
# @return [Hash{String => SourceMap}]
|
450
|
+
def source_map_hash
|
451
|
+
@mutex.synchronize {
|
452
|
+
@source_map_hash
|
453
|
+
}
|
455
454
|
end
|
456
455
|
|
457
|
-
# @
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
456
|
+
# @return [ApiMap::Store]
|
457
|
+
def store
|
458
|
+
@mutex.synchronize {
|
459
|
+
@store
|
460
|
+
}
|
462
461
|
end
|
463
462
|
|
464
463
|
# @return [Solargraph::ApiMap::Cache]
|
465
464
|
def cache
|
466
|
-
@
|
465
|
+
@mutex.synchronize {
|
466
|
+
@cache
|
467
|
+
}
|
467
468
|
end
|
468
469
|
|
469
470
|
# @param fqns [String] A fully qualified namespace
|
@@ -471,34 +472,41 @@ module Solargraph
|
|
471
472
|
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
472
473
|
# @param deep [Boolean]
|
473
474
|
# @param skip [Array<String>]
|
475
|
+
# @param no_core [Boolean] Skip core classes if true
|
474
476
|
# @return [Array<Pin::Base>]
|
475
|
-
def inner_get_methods fqns, scope, visibility, deep, skip
|
477
|
+
def inner_get_methods fqns, scope, visibility, deep, skip, no_core = false
|
478
|
+
return [] if no_core && fqns =~ /^(Object|BasicObject|Class|Module|Kernel)$/
|
476
479
|
reqstr = "#{fqns}|#{scope}|#{visibility.sort}|#{deep}"
|
477
480
|
return [] if skip.include?(reqstr)
|
478
481
|
skip.push reqstr
|
479
482
|
result = []
|
480
|
-
result.concat store.get_attrs(fqns, scope)
|
481
483
|
result.concat store.get_methods(fqns, scope: scope, visibility: visibility)
|
482
484
|
if deep
|
483
485
|
sc = store.get_superclass(fqns)
|
484
486
|
unless sc.nil?
|
485
|
-
fqsc = qualify(sc, fqns)
|
486
|
-
result.concat inner_get_methods(fqsc, scope, visibility, true, skip) unless fqsc.nil?
|
487
|
+
fqsc = qualify(sc, fqns.split('::')[0..-2].join('::'))
|
488
|
+
result.concat inner_get_methods(fqsc, scope, visibility, true, skip, true) unless fqsc.nil?
|
487
489
|
end
|
488
490
|
if scope == :instance
|
489
|
-
store.get_includes(fqns).each do |im|
|
491
|
+
store.get_includes(fqns).reverse.each do |im|
|
490
492
|
fqim = qualify(im, fqns)
|
491
|
-
result.concat inner_get_methods(fqim, scope, visibility, deep, skip) unless fqim.nil?
|
493
|
+
result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
|
492
494
|
end
|
493
|
-
result.concat inner_get_methods('Object', :instance, [:public], deep, skip)
|
495
|
+
result.concat inner_get_methods('Object', :instance, [:public], deep, skip, no_core)
|
494
496
|
else
|
495
|
-
store.get_extends(fqns).each do |em|
|
497
|
+
store.get_extends(fqns).reverse.each do |em|
|
496
498
|
fqem = qualify(em, fqns)
|
497
|
-
result.concat inner_get_methods(fqem, :instance, visibility, deep, skip) unless fqem.nil?
|
499
|
+
result.concat inner_get_methods(fqem, :instance, visibility, deep, skip, true) unless fqem.nil?
|
498
500
|
end
|
499
|
-
|
500
|
-
|
501
|
-
|
501
|
+
unless no_core || fqns.empty?
|
502
|
+
type = get_namespace_type(fqns)
|
503
|
+
result.concat inner_get_methods('Class', :instance, visibility, deep, skip, no_core) if type == :class
|
504
|
+
result.concat inner_get_methods('Module', :instance,visibility, deep, skip, no_core)
|
505
|
+
end
|
506
|
+
end
|
507
|
+
store.domains(fqns).each do |d|
|
508
|
+
dt = ComplexType.parse(d)
|
509
|
+
result.concat inner_get_methods(dt.namespace, dt.scope, [:public], deep, skip)
|
502
510
|
end
|
503
511
|
end
|
504
512
|
result
|
@@ -517,7 +525,7 @@ module Solargraph
|
|
517
525
|
fqis = qualify(is, fqns)
|
518
526
|
result.concat inner_get_constants(fqis, [:public], skip) unless fqis.nil?
|
519
527
|
end
|
520
|
-
result.concat live_map.get_constants(fqns)
|
528
|
+
# result.concat live_map.get_constants(fqns)
|
521
529
|
result
|
522
530
|
end
|
523
531
|
|
@@ -538,11 +546,6 @@ module Solargraph
|
|
538
546
|
@path_macros ||= {}
|
539
547
|
end
|
540
548
|
|
541
|
-
# @return [Array<Solargraph::Source>]
|
542
|
-
def current_workspace_sources
|
543
|
-
@sources - [@virtual_source]
|
544
|
-
end
|
545
|
-
|
546
549
|
# @param name [String]
|
547
550
|
# @param root [String]
|
548
551
|
# @param skip [Array<String>]
|
@@ -571,7 +574,7 @@ module Solargraph
|
|
571
574
|
return name if store.namespace_exists?(name)
|
572
575
|
end
|
573
576
|
end
|
574
|
-
live_map.get_fqns(name, root)
|
577
|
+
# live_map.get_fqns(name, root)
|
575
578
|
end
|
576
579
|
|
577
580
|
# Get the namespace's type (Class or Module).
|
@@ -585,13 +588,6 @@ module Solargraph
|
|
585
588
|
pin.type
|
586
589
|
end
|
587
590
|
|
588
|
-
# Get a YardMap associated with the current workspace.
|
589
|
-
#
|
590
|
-
# @return [Solargraph::YardMap]
|
591
|
-
def yard_map
|
592
|
-
@yard_map ||= Solargraph::YardMap.new(required: required, workspace: workspace)
|
593
|
-
end
|
594
|
-
|
595
591
|
# Sort an array of pins to put nil or undefined variables last.
|
596
592
|
#
|
597
593
|
# @param pins [Array<Solargraph::Pin::Base>]
|
@@ -600,7 +596,7 @@ module Solargraph
|
|
600
596
|
result = []
|
601
597
|
nil_pins = []
|
602
598
|
pins.each do |pin|
|
603
|
-
if pin.variable?
|
599
|
+
if pin.variable? && pin.nil_assignment?
|
604
600
|
nil_pins.push pin
|
605
601
|
else
|
606
602
|
result.push pin
|
@@ -609,11 +605,17 @@ module Solargraph
|
|
609
605
|
result + nil_pins
|
610
606
|
end
|
611
607
|
|
608
|
+
# Check if a class is a superclass of another class.
|
609
|
+
#
|
610
|
+
# @param sup [String] The superclass
|
611
|
+
# @param sub [String] The subclass
|
612
|
+
# @return [Boolean]
|
612
613
|
def super_and_sub?(sup, sub)
|
613
|
-
|
614
|
+
fqsup = qualify(sup)
|
615
|
+
cls = qualify(store.get_superclass(sub), sub)
|
614
616
|
until cls.nil?
|
615
|
-
return true if cls ==
|
616
|
-
cls = store.get_superclass(cls)
|
617
|
+
return true if cls == fqsup
|
618
|
+
cls = qualify(store.get_superclass(cls), cls)
|
617
619
|
end
|
618
620
|
false
|
619
621
|
end
|