solargraph 0.47.2 → 0.54.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/.github/FUNDING.yml +1 -0
- data/.github/workflows/plugins.yml +40 -0
- data/.github/workflows/rspec.yml +4 -8
- data/.github/workflows/typecheck.yml +34 -0
- data/.yardopts +2 -2
- data/CHANGELOG.md +166 -3
- data/LICENSE +1 -1
- data/README.md +19 -16
- data/SPONSORS.md +2 -9
- data/lib/solargraph/api_map/cache.rb +50 -20
- data/lib/solargraph/api_map/source_to_yard.rb +17 -10
- data/lib/solargraph/api_map/store.rb +68 -15
- data/lib/solargraph/api_map.rb +238 -112
- data/lib/solargraph/bench.rb +3 -2
- data/lib/solargraph/cache.rb +77 -0
- data/lib/solargraph/complex_type/type_methods.rb +116 -35
- data/lib/solargraph/complex_type/unique_type.rb +261 -33
- data/lib/solargraph/complex_type.rb +149 -30
- data/lib/solargraph/convention/rakefile.rb +17 -0
- data/lib/solargraph/convention.rb +2 -3
- data/lib/solargraph/converters/dd.rb +5 -0
- data/lib/solargraph/converters/dl.rb +3 -0
- data/lib/solargraph/converters/dt.rb +3 -0
- data/lib/solargraph/diagnostics/rubocop.rb +23 -8
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/diagnostics.rb +2 -2
- data/lib/solargraph/doc_map.rb +187 -0
- data/lib/solargraph/gem_pins.rb +72 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
- data/lib/solargraph/language_server/host/dispatch.rb +22 -5
- data/lib/solargraph/language_server/host/message_worker.rb +4 -0
- data/lib/solargraph/language_server/host/sources.rb +8 -65
- data/lib/solargraph/language_server/host.rb +88 -93
- data/lib/solargraph/language_server/message/base.rb +1 -1
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
- data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
- data/lib/solargraph/language_server/message/initialize.rb +27 -0
- data/lib/solargraph/language_server/message/initialized.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +4 -1
- data/lib/solargraph/language_server/message/text_document/formatting.rb +5 -4
- data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
- data/lib/solargraph/language_server/message/text_document.rb +1 -1
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
- data/lib/solargraph/language_server/message.rb +1 -0
- data/lib/solargraph/language_server/progress.rb +118 -0
- data/lib/solargraph/language_server/transport/adapter.rb +16 -1
- data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
- data/lib/solargraph/language_server.rb +1 -0
- data/lib/solargraph/library.rb +231 -104
- data/lib/solargraph/location.rb +1 -0
- data/lib/solargraph/page.rb +6 -0
- data/lib/solargraph/parser/comment_ripper.rb +4 -0
- data/lib/solargraph/parser/node_methods.rb +47 -7
- data/lib/solargraph/parser/node_processor/base.rb +11 -1
- data/lib/solargraph/parser/node_processor.rb +1 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
- data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +57 -41
- data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +53 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +14 -4
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/cvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/def_node.rb +7 -20
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +47 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +42 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +7 -5
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
- data/lib/solargraph/parser/parser_gem.rb +12 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +9 -10
- data/lib/solargraph/pin/base.rb +69 -11
- data/lib/solargraph/pin/base_variable.rb +40 -7
- data/lib/solargraph/pin/block.rb +81 -33
- data/lib/solargraph/pin/closure.rb +17 -2
- data/lib/solargraph/pin/common.rb +7 -3
- data/lib/solargraph/pin/conversions.rb +34 -8
- data/lib/solargraph/pin/delegated_method.rb +101 -0
- data/lib/solargraph/pin/documenting.rb +25 -32
- data/lib/solargraph/pin/instance_variable.rb +4 -0
- data/lib/solargraph/pin/local_variable.rb +13 -1
- data/lib/solargraph/pin/method.rb +273 -17
- data/lib/solargraph/pin/namespace.rb +17 -1
- data/lib/solargraph/pin/parameter.rb +40 -28
- data/lib/solargraph/pin/reference/override.rb +2 -2
- data/lib/solargraph/pin/reference.rb +8 -0
- data/lib/solargraph/pin/search.rb +4 -4
- data/lib/solargraph/pin/signature.rb +143 -0
- data/lib/solargraph/pin.rb +2 -1
- data/lib/solargraph/range.rb +4 -6
- data/lib/solargraph/rbs_map/conversions.rb +607 -0
- data/lib/solargraph/rbs_map/core_fills.rb +50 -0
- data/lib/solargraph/rbs_map/core_map.rb +28 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +33 -0
- data/lib/solargraph/rbs_map.rb +92 -0
- data/lib/solargraph/shell.rb +85 -59
- data/lib/solargraph/source/chain/array.rb +32 -0
- data/lib/solargraph/source/chain/block_symbol.rb +13 -0
- data/lib/solargraph/source/chain/call.rb +125 -61
- data/lib/solargraph/source/chain/constant.rb +15 -1
- data/lib/solargraph/source/chain/if.rb +23 -0
- data/lib/solargraph/source/chain/link.rb +8 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +3 -3
- data/lib/solargraph/source/chain.rb +64 -14
- data/lib/solargraph/source/change.rb +3 -0
- data/lib/solargraph/source/cursor.rb +2 -0
- data/lib/solargraph/source/source_chainer.rb +8 -5
- data/lib/solargraph/source/updater.rb +1 -0
- data/lib/solargraph/source.rb +18 -63
- data/lib/solargraph/source_map/clip.rb +31 -23
- data/lib/solargraph/source_map/mapper.rb +23 -7
- data/lib/solargraph/source_map.rb +36 -11
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker.rb +229 -100
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +2 -2
- data/lib/solargraph/workspace/config.rb +15 -11
- data/lib/solargraph/workspace.rb +41 -17
- data/lib/solargraph/yard_map/cache.rb +6 -0
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +23 -7
- data/lib/solargraph/yard_map/mapper.rb +1 -1
- data/lib/solargraph/yard_map/to_method.rb +11 -4
- data/lib/solargraph/yard_map.rb +1 -443
- data/lib/solargraph/yard_tags.rb +20 -0
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +8 -6
- data/solargraph.gemspec +19 -8
- metadata +164 -99
- data/.travis.yml +0 -19
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- data/lib/solargraph/compat.rb +0 -37
- data/lib/solargraph/convention/rspec.rb +0 -30
- data/lib/solargraph/documentor.rb +0 -76
- data/lib/solargraph/language_server/host/cataloger.rb +0 -56
- data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
- data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/def_node.rb +0 -63
- data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +0 -21
- data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
- data/lib/solargraph/parser/legacy.rb +0 -12
- data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -144
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
- data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -22
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -57
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -21
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -277
- data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +0 -18
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
- data/lib/solargraph/parser/rubyvm.rb +0 -40
- data/lib/solargraph/yard_map/core_docs.rb +0 -170
- data/lib/solargraph/yard_map/core_fills.rb +0 -208
- data/lib/solargraph/yard_map/core_gen.rb +0 -76
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
- data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
- data/lib/yard-solargraph.rb +0 -33
- data/yardoc/2.2.2.tar.gz +0 -0
data/lib/solargraph/library.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'pathname'
|
4
|
+
require 'observer'
|
4
5
|
|
5
6
|
module Solargraph
|
6
7
|
# A Library handles coordination between a Workspace and an ApiMap.
|
7
8
|
#
|
8
9
|
class Library
|
9
10
|
include Logging
|
11
|
+
include Observable
|
10
12
|
|
11
13
|
# @return [Solargraph::Workspace]
|
12
14
|
attr_reader :workspace
|
@@ -17,12 +19,19 @@ module Solargraph
|
|
17
19
|
# @return [Source, nil]
|
18
20
|
attr_reader :current
|
19
21
|
|
22
|
+
# @return [LanguageServer::Progress, nil]
|
23
|
+
attr_reader :cache_progress
|
24
|
+
|
20
25
|
# @param workspace [Solargraph::Workspace]
|
21
26
|
# @param name [String, nil]
|
22
27
|
def initialize workspace = Solargraph::Workspace.new, name = nil
|
23
28
|
@workspace = workspace
|
24
29
|
@name = name
|
25
|
-
@
|
30
|
+
@threads = []
|
31
|
+
# @type [Integer, nil]
|
32
|
+
@total = nil
|
33
|
+
# @type [Source, nil]
|
34
|
+
@current = nil
|
26
35
|
end
|
27
36
|
|
28
37
|
def inspect
|
@@ -35,7 +44,7 @@ module Solargraph
|
|
35
44
|
#
|
36
45
|
# @return [Boolean]
|
37
46
|
def synchronized?
|
38
|
-
|
47
|
+
!mutex.locked?
|
39
48
|
end
|
40
49
|
|
41
50
|
# Attach a source to the library.
|
@@ -47,17 +56,15 @@ module Solargraph
|
|
47
56
|
# @param source [Source, nil]
|
48
57
|
# @return [void]
|
49
58
|
def attach source
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
@external_requires = nil
|
55
|
-
@synchronized = false
|
56
|
-
end
|
57
|
-
@current = source
|
58
|
-
maybe_map @current
|
59
|
-
catalog_inlock
|
59
|
+
if @current && (!source || @current.filename != source.filename) && source_map_hash.key?(@current.filename) && !workspace.has_file?(@current.filename)
|
60
|
+
source_map_hash.delete @current.filename
|
61
|
+
source_map_external_require_hash.delete @current.filename
|
62
|
+
@external_requires = nil
|
60
63
|
end
|
64
|
+
changed = source && @current != source
|
65
|
+
@current = source
|
66
|
+
maybe_map @current
|
67
|
+
catalog if changed
|
61
68
|
end
|
62
69
|
|
63
70
|
# True if the specified file is currently attached.
|
@@ -95,47 +102,37 @@ module Solargraph
|
|
95
102
|
# @param text [String] The contents of the file
|
96
103
|
# @return [Boolean] True if the file was added to the workspace.
|
97
104
|
def create filename, text
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
source = Solargraph::Source.load_string(text, filename)
|
103
|
-
workspace.merge(source)
|
104
|
-
result = true
|
105
|
-
end
|
106
|
-
result
|
105
|
+
return false unless contain?(filename) || open?(filename)
|
106
|
+
source = Solargraph::Source.load_string(text, filename)
|
107
|
+
workspace.merge(source)
|
108
|
+
true
|
107
109
|
end
|
108
110
|
|
109
|
-
# Create
|
111
|
+
# Create file sources from files on disk. A file is ignored if it is
|
110
112
|
# neither open in the library nor included in the workspace.
|
111
113
|
#
|
112
|
-
# @param
|
113
|
-
# @return [Boolean] True if
|
114
|
-
def create_from_disk
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
workspace.merge(source)
|
121
|
-
maybe_map source
|
122
|
-
result = true
|
123
|
-
end
|
114
|
+
# @param filenames [Array<String>]
|
115
|
+
# @return [Boolean] True if at least one file was added to the workspace.
|
116
|
+
def create_from_disk *filenames
|
117
|
+
sources = filenames
|
118
|
+
.reject { |filename| File.directory?(filename) || !File.exist?(filename) }
|
119
|
+
.map { |filename| Solargraph::Source.load_string(File.read(filename), filename) }
|
120
|
+
result = workspace.merge(*sources)
|
121
|
+
sources.each { |source| maybe_map source }
|
124
122
|
result
|
125
123
|
end
|
126
124
|
|
127
|
-
# Delete
|
125
|
+
# Delete files from the library. Deleting a file will make it unavailable
|
128
126
|
# for checkout and optionally remove it from the workspace unless the
|
129
127
|
# workspace configuration determines that it should still exist.
|
130
128
|
#
|
131
|
-
# @param
|
132
|
-
# @return [Boolean] True if
|
133
|
-
def delete
|
134
|
-
detach filename
|
129
|
+
# @param filenames [Array<String>]
|
130
|
+
# @return [Boolean] True if any file was deleted
|
131
|
+
def delete *filenames
|
135
132
|
result = false
|
136
|
-
|
137
|
-
|
138
|
-
|
133
|
+
filenames.each do |filename|
|
134
|
+
detach filename
|
135
|
+
result ||= workspace.remove(filename)
|
139
136
|
end
|
140
137
|
result
|
141
138
|
end
|
@@ -146,11 +143,10 @@ module Solargraph
|
|
146
143
|
# @param filename [String]
|
147
144
|
# @return [void]
|
148
145
|
def close filename
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
146
|
+
return unless @current&.filename == filename
|
147
|
+
|
148
|
+
@current = nil
|
149
|
+
catalog unless workspace.has_file?(filename)
|
154
150
|
end
|
155
151
|
|
156
152
|
# Get completion suggestions at the specified file and location.
|
@@ -158,12 +154,13 @@ module Solargraph
|
|
158
154
|
# @param filename [String] The file to analyze
|
159
155
|
# @param line [Integer] The zero-based line number
|
160
156
|
# @param column [Integer] The zero-based column number
|
161
|
-
# @return [SourceMap::Completion]
|
157
|
+
# @return [SourceMap::Completion, nil]
|
162
158
|
# @todo Take a Location instead of filename/line/column
|
163
159
|
def completions_at filename, line, column
|
160
|
+
sync_catalog
|
164
161
|
position = Position.new(line, column)
|
165
162
|
cursor = Source::Cursor.new(read(filename), position)
|
166
|
-
api_map.clip(cursor).complete
|
163
|
+
mutex.synchronize { api_map.clip(cursor).complete }
|
167
164
|
rescue FileNotFoundError => e
|
168
165
|
handle_file_not_found filename, e
|
169
166
|
end
|
@@ -174,11 +171,12 @@ module Solargraph
|
|
174
171
|
# @param filename [String] The file to analyze
|
175
172
|
# @param line [Integer] The zero-based line number
|
176
173
|
# @param column [Integer] The zero-based column number
|
177
|
-
# @return [Array<Solargraph::Pin::Base
|
174
|
+
# @return [Array<Solargraph::Pin::Base>, nil]
|
178
175
|
# @todo Take filename/position instead of filename/line/column
|
179
176
|
def definitions_at filename, line, column
|
180
177
|
position = Position.new(line, column)
|
181
178
|
cursor = Source::Cursor.new(read(filename), position)
|
179
|
+
sync_catalog
|
182
180
|
if cursor.comment?
|
183
181
|
source = read(filename)
|
184
182
|
offset = Solargraph::Position.to_offset(source.code, Solargraph::Position.new(line, column))
|
@@ -186,18 +184,35 @@ module Solargraph
|
|
186
184
|
rgt = source.code[offset..-1].match(/^([a-z0-9_]*)(:[a-z0-9_:]*)?[\]>, ]/i)
|
187
185
|
if lft && rgt
|
188
186
|
tag = (lft[1] + rgt[1]).sub(/:+$/, '')
|
189
|
-
clip = api_map.clip(cursor)
|
187
|
+
clip = mutex.synchronize { api_map.clip(cursor) }
|
190
188
|
clip.translate tag
|
191
189
|
else
|
192
190
|
[]
|
193
191
|
end
|
194
192
|
else
|
195
|
-
api_map.clip(cursor).define.map { |pin| pin.realize(api_map) }
|
193
|
+
mutex.synchronize { api_map.clip(cursor).define.map { |pin| pin.realize(api_map) } }
|
196
194
|
end
|
197
195
|
rescue FileNotFoundError => e
|
198
196
|
handle_file_not_found(filename, e)
|
199
197
|
end
|
200
198
|
|
199
|
+
# Get type definition suggestions for the expression at the specified file and
|
200
|
+
# location.
|
201
|
+
#
|
202
|
+
# @param filename [String] The file to analyze
|
203
|
+
# @param line [Integer] The zero-based line number
|
204
|
+
# @param column [Integer] The zero-based column number
|
205
|
+
# @return [Array<Solargraph::Pin::Base>, nil]
|
206
|
+
# @todo Take filename/position instead of filename/line/column
|
207
|
+
def type_definitions_at filename, line, column
|
208
|
+
position = Position.new(line, column)
|
209
|
+
cursor = Source::Cursor.new(read(filename), position)
|
210
|
+
sync_catalog
|
211
|
+
mutex.synchronize { api_map.clip(cursor).types }
|
212
|
+
rescue FileNotFoundError => e
|
213
|
+
handle_file_not_found filename, e
|
214
|
+
end
|
215
|
+
|
201
216
|
# Get signature suggestions for the method at the specified file and
|
202
217
|
# location.
|
203
218
|
#
|
@@ -209,7 +224,8 @@ module Solargraph
|
|
209
224
|
def signatures_at filename, line, column
|
210
225
|
position = Position.new(line, column)
|
211
226
|
cursor = Source::Cursor.new(read(filename), position)
|
212
|
-
|
227
|
+
sync_catalog
|
228
|
+
mutex.synchronize { api_map.clip(cursor).signify }
|
213
229
|
end
|
214
230
|
|
215
231
|
# @param filename [String]
|
@@ -220,8 +236,9 @@ module Solargraph
|
|
220
236
|
# @return [Array<Solargraph::Range>]
|
221
237
|
# @todo Take a Location instead of filename/line/column
|
222
238
|
def references_from filename, line, column, strip: false, only: false
|
223
|
-
|
224
|
-
|
239
|
+
sync_catalog
|
240
|
+
cursor = Source::Cursor.new(read(filename), [line, column])
|
241
|
+
clip = mutex.synchronize { api_map.clip(cursor) }
|
225
242
|
pin = clip.define.first
|
226
243
|
return [] unless pin
|
227
244
|
result = []
|
@@ -234,7 +251,19 @@ module Solargraph
|
|
234
251
|
found = source.references(pin.name)
|
235
252
|
found.select! do |loc|
|
236
253
|
referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character).first
|
237
|
-
referenced
|
254
|
+
referenced&.path == pin.path
|
255
|
+
end
|
256
|
+
if pin.path == 'Class#new'
|
257
|
+
caller = cursor.chain.base.infer(api_map, clip.send(:block), clip.locals).first
|
258
|
+
if caller.defined?
|
259
|
+
found.select! do |loc|
|
260
|
+
clip = api_map.clip_at(loc.filename, loc.range.start)
|
261
|
+
other = clip.send(:cursor).chain.base.infer(api_map, clip.send(:block), clip.locals).first
|
262
|
+
caller == other
|
263
|
+
end
|
264
|
+
else
|
265
|
+
found.clear
|
266
|
+
end
|
238
267
|
end
|
239
268
|
# HACK: for language clients that exclude special characters from the start of variable names
|
240
269
|
if strip && match = cursor.word.match(/^[^a-z0-9_]+/i)
|
@@ -254,20 +283,31 @@ module Solargraph
|
|
254
283
|
# @param location [Location]
|
255
284
|
# @return [Array<Solargraph::Pin::Base>]
|
256
285
|
def locate_pins location
|
257
|
-
|
286
|
+
sync_catalog
|
287
|
+
mutex.synchronize { api_map.locate_pins(location).map { |pin| pin.realize(api_map) } }
|
258
288
|
end
|
259
289
|
|
290
|
+
# Match a require reference to a file.
|
291
|
+
#
|
292
|
+
# @param location [Location]
|
293
|
+
# @return [Location, nil]
|
260
294
|
def locate_ref location
|
261
295
|
map = source_map_hash[location.filename]
|
262
296
|
return if map.nil?
|
263
297
|
pin = map.requires.select { |p| p.location.range.contain?(location.range.start) }.first
|
264
298
|
return nil if pin.nil?
|
299
|
+
# @param full [String]
|
300
|
+
return_if_match = proc do |full|
|
301
|
+
if source_map_hash.key?(full)
|
302
|
+
return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0))
|
303
|
+
end
|
304
|
+
end
|
265
305
|
workspace.require_paths.each do |path|
|
266
|
-
full =
|
267
|
-
|
268
|
-
|
306
|
+
full = File.join path, pin.name
|
307
|
+
return_if_match.(full)
|
308
|
+
return_if_match.(full << ".rb")
|
269
309
|
end
|
270
|
-
|
310
|
+
nil
|
271
311
|
rescue FileNotFoundError
|
272
312
|
nil
|
273
313
|
end
|
@@ -275,21 +315,24 @@ module Solargraph
|
|
275
315
|
# Get an array of pins that match a path.
|
276
316
|
#
|
277
317
|
# @param path [String]
|
278
|
-
# @return [
|
318
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
279
319
|
def get_path_pins path
|
280
|
-
|
320
|
+
sync_catalog
|
321
|
+
mutex.synchronize { api_map.get_path_suggestions(path) }
|
281
322
|
end
|
282
323
|
|
283
324
|
# @param query [String]
|
284
|
-
# @return [
|
325
|
+
# @return [Enumerable<YARD::CodeObjects::Base>]
|
285
326
|
def document query
|
286
|
-
|
327
|
+
sync_catalog
|
328
|
+
mutex.synchronize { api_map.document query }
|
287
329
|
end
|
288
330
|
|
289
331
|
# @param query [String]
|
290
332
|
# @return [Array<String>]
|
291
333
|
def search query
|
292
|
-
|
334
|
+
sync_catalog
|
335
|
+
mutex.synchronize { api_map.search query }
|
293
336
|
end
|
294
337
|
|
295
338
|
# Get an array of all symbols in the workspace that match the query.
|
@@ -297,7 +340,8 @@ module Solargraph
|
|
297
340
|
# @param query [String]
|
298
341
|
# @return [Array<Pin::Base>]
|
299
342
|
def query_symbols query
|
300
|
-
|
343
|
+
sync_catalog
|
344
|
+
mutex.synchronize { api_map.query_symbols query }
|
301
345
|
end
|
302
346
|
|
303
347
|
# Get an array of document symbols.
|
@@ -309,15 +353,18 @@ module Solargraph
|
|
309
353
|
# @param filename [String]
|
310
354
|
# @return [Array<Solargraph::Pin::Base>]
|
311
355
|
def document_symbols filename
|
312
|
-
|
356
|
+
sync_catalog
|
357
|
+
mutex.synchronize { api_map.document_symbols(filename) }
|
313
358
|
end
|
314
359
|
|
315
360
|
# @param path [String]
|
316
|
-
# @return [
|
361
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
317
362
|
def path_pins path
|
318
|
-
|
363
|
+
sync_catalog
|
364
|
+
mutex.synchronize { api_map.get_path_suggestions(path) }
|
319
365
|
end
|
320
366
|
|
367
|
+
# @return [Array<SourceMap>]
|
321
368
|
def source_maps
|
322
369
|
source_map_hash.values
|
323
370
|
end
|
@@ -340,10 +387,10 @@ module Solargraph
|
|
340
387
|
# everything in the workspace should get diagnosed, or if there should
|
341
388
|
# be an option to do so.
|
342
389
|
#
|
390
|
+
sync_catalog
|
343
391
|
return [] unless open?(filename)
|
344
392
|
result = []
|
345
393
|
source = read(filename)
|
346
|
-
catalog
|
347
394
|
repargs = {}
|
348
395
|
workspace.config.reporters.each do |line|
|
349
396
|
if line == 'all!'
|
@@ -369,19 +416,23 @@ module Solargraph
|
|
369
416
|
#
|
370
417
|
# @return [void]
|
371
418
|
def catalog
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
419
|
+
@threads.delete_if(&:stop?)
|
420
|
+
@threads.push(Thread.new do
|
421
|
+
sleep 0.05 if RUBY_PLATFORM =~ /mingw/
|
422
|
+
next unless @threads.last == Thread.current
|
423
|
+
|
424
|
+
mutex.synchronize do
|
425
|
+
logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
|
426
|
+
api_map.catalog bench
|
427
|
+
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
|
428
|
+
logger.info "#{api_map.uncached_gemspecs.length} uncached gemspecs"
|
429
|
+
cache_next_gemspec
|
430
|
+
end
|
431
|
+
end)
|
432
|
+
@threads.last.run if RUBY_PLATFORM =~ /mingw/
|
383
433
|
end
|
384
434
|
|
435
|
+
# @return [Bench]
|
385
436
|
def bench
|
386
437
|
Bench.new(
|
387
438
|
source_maps: source_map_hash.values,
|
@@ -417,15 +468,12 @@ module Solargraph
|
|
417
468
|
# @return [Boolean] True if the source was merged into the workspace.
|
418
469
|
def merge source
|
419
470
|
Logging.logger.debug "Merging source: #{source.filename}"
|
420
|
-
result =
|
421
|
-
|
422
|
-
result = workspace.merge(source)
|
423
|
-
maybe_map source
|
424
|
-
end
|
425
|
-
# catalog
|
471
|
+
result = workspace.merge(source)
|
472
|
+
maybe_map source
|
426
473
|
result
|
427
474
|
end
|
428
475
|
|
476
|
+
# @return [Hash{String => SourceMap}]
|
429
477
|
def source_map_hash
|
430
478
|
@source_map_hash ||= {}
|
431
479
|
end
|
@@ -434,22 +482,21 @@ module Solargraph
|
|
434
482
|
(workspace.filenames - source_map_hash.keys).empty?
|
435
483
|
end
|
436
484
|
|
485
|
+
# @return [SourceMap, Boolean]
|
437
486
|
def next_map
|
438
487
|
return false if mapped?
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
else
|
448
|
-
false
|
449
|
-
end
|
488
|
+
src = workspace.sources.find { |s| !source_map_hash.key?(s.filename) }
|
489
|
+
if src
|
490
|
+
Logging.logger.debug "Mapping #{src.filename}"
|
491
|
+
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
492
|
+
find_external_requires(source_map_hash[src.filename])
|
493
|
+
source_map_hash[src.filename]
|
494
|
+
else
|
495
|
+
false
|
450
496
|
end
|
451
497
|
end
|
452
498
|
|
499
|
+
# @return [self]
|
453
500
|
def map!
|
454
501
|
workspace.sources.each do |src|
|
455
502
|
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
@@ -458,28 +505,34 @@ module Solargraph
|
|
458
505
|
self
|
459
506
|
end
|
460
507
|
|
508
|
+
# @return [Array<Solargraph::Pin::Base>]
|
461
509
|
def pins
|
462
510
|
@pins ||= []
|
463
511
|
end
|
464
512
|
|
513
|
+
# @return [Set<String>]
|
465
514
|
def external_requires
|
466
515
|
@external_requires ||= source_map_external_require_hash.values.flatten.to_set
|
467
516
|
end
|
468
517
|
|
469
518
|
private
|
470
519
|
|
520
|
+
# @return [Hash{String => Set<String>}]
|
471
521
|
def source_map_external_require_hash
|
472
522
|
@source_map_external_require_hash ||= {}
|
473
523
|
end
|
474
524
|
|
475
525
|
# @param source_map [SourceMap]
|
526
|
+
# @return [void]
|
476
527
|
def find_external_requires source_map
|
477
528
|
new_set = source_map.requires.map(&:name).to_set
|
478
529
|
# return if new_set == source_map_external_require_hash[source_map.filename]
|
530
|
+
_filenames = nil
|
531
|
+
filenames = ->{ _filenames ||= workspace.filenames.to_set }
|
479
532
|
source_map_external_require_hash[source_map.filename] = new_set.reject do |path|
|
480
533
|
workspace.require_paths.any? do |base|
|
481
|
-
full =
|
482
|
-
|
534
|
+
full = File.join(base, path)
|
535
|
+
filenames[].include?(full) or filenames[].include?(full << ".rb")
|
483
536
|
end
|
484
537
|
end
|
485
538
|
@external_requires = nil
|
@@ -509,6 +562,9 @@ module Solargraph
|
|
509
562
|
workspace.source(filename)
|
510
563
|
end
|
511
564
|
|
565
|
+
# @param filename [String]
|
566
|
+
# @param error [FileNotFoundError]
|
567
|
+
# @return [nil]
|
512
568
|
def handle_file_not_found filename, error
|
513
569
|
if workspace.source(filename)
|
514
570
|
Solargraph.logger.debug "#{filename} is not cataloged in the ApiMap"
|
@@ -518,11 +574,13 @@ module Solargraph
|
|
518
574
|
end
|
519
575
|
end
|
520
576
|
|
577
|
+
# @param source [Source, nil]
|
578
|
+
# @return [void]
|
521
579
|
def maybe_map source
|
522
580
|
return unless source
|
523
581
|
return unless @current == source || workspace.has_file?(source.filename)
|
524
582
|
if source_map_hash.key?(source.filename)
|
525
|
-
return if source_map_hash[source.filename].code == source.code &&
|
583
|
+
return if source_map_hash[source.filename].code == source.code &&
|
526
584
|
source_map_hash[source.filename].source.synchronized? &&
|
527
585
|
source.synchronized?
|
528
586
|
if source.synchronized?
|
@@ -530,7 +588,6 @@ module Solargraph
|
|
530
588
|
unless source_map_hash[source.filename].try_merge!(new_map)
|
531
589
|
source_map_hash[source.filename] = new_map
|
532
590
|
find_external_requires(source_map_hash[source.filename])
|
533
|
-
@synchronized = false
|
534
591
|
end
|
535
592
|
else
|
536
593
|
# @todo Smelly instance variable access
|
@@ -539,8 +596,78 @@ module Solargraph
|
|
539
596
|
else
|
540
597
|
source_map_hash[source.filename] = Solargraph::SourceMap.map(source)
|
541
598
|
find_external_requires(source_map_hash[source.filename])
|
542
|
-
@synchronized = false
|
543
599
|
end
|
544
600
|
end
|
601
|
+
|
602
|
+
# @return [Set<Gem::Specification>]
|
603
|
+
def cache_errors
|
604
|
+
@cache_errors ||= Set.new
|
605
|
+
end
|
606
|
+
|
607
|
+
# @return [void]
|
608
|
+
def cache_next_gemspec
|
609
|
+
return if @cache_progress
|
610
|
+
spec = api_map.uncached_gemspecs.find { |spec| !cache_errors.include?(spec) }
|
611
|
+
return end_cache_progress unless spec
|
612
|
+
|
613
|
+
pending = api_map.uncached_gemspecs.length - cache_errors.length - 1
|
614
|
+
logger.info "Caching #{spec.name} #{spec.version}"
|
615
|
+
Thread.new do
|
616
|
+
cache_pid = Process.spawn(workspace.command_path, 'cache', spec.name, spec.version.to_s)
|
617
|
+
report_cache_progress spec.name, pending
|
618
|
+
Process.wait(cache_pid)
|
619
|
+
logger.info "Cached #{spec.name} #{spec.version}"
|
620
|
+
rescue Errno::EINVAL => _e
|
621
|
+
logger.info "Cached #{spec.name} #{spec.version} with EINVAL"
|
622
|
+
rescue StandardError => e
|
623
|
+
cache_errors.add spec
|
624
|
+
Solargraph.logger.warn "Error caching gemspec #{spec.name} #{spec.version}: [#{e.class}] #{e.message}"
|
625
|
+
ensure
|
626
|
+
end_cache_progress
|
627
|
+
catalog
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
631
|
+
# @param gem_name [String]
|
632
|
+
# @param pending [Integer]
|
633
|
+
# @return [void]
|
634
|
+
def report_cache_progress gem_name, pending
|
635
|
+
@total ||= pending
|
636
|
+
@total = pending if pending > @total
|
637
|
+
finished = @total - pending
|
638
|
+
pct = if @total.zero?
|
639
|
+
0
|
640
|
+
else
|
641
|
+
((finished.to_f / @total.to_f) * 100).to_i
|
642
|
+
end
|
643
|
+
message = "#{gem_name}#{pending > 0 ? " (+#{pending})" : ''}"
|
644
|
+
# "
|
645
|
+
if @cache_progress
|
646
|
+
@cache_progress.report(message, pct)
|
647
|
+
else
|
648
|
+
@cache_progress = LanguageServer::Progress.new('Caching gem')
|
649
|
+
# If we don't send both a begin and a report, the progress notification
|
650
|
+
# might get stuck in the status bar forever
|
651
|
+
@cache_progress.begin(message, pct)
|
652
|
+
changed
|
653
|
+
notify_observers @cache_progress
|
654
|
+
@cache_progress.report(message, pct)
|
655
|
+
end
|
656
|
+
changed
|
657
|
+
notify_observers @cache_progress
|
658
|
+
end
|
659
|
+
|
660
|
+
# @return [void]
|
661
|
+
def end_cache_progress
|
662
|
+
changed if @cache_progress&.finish('done')
|
663
|
+
notify_observers @cache_progress
|
664
|
+
@cache_progress = nil
|
665
|
+
@total = nil
|
666
|
+
end
|
667
|
+
|
668
|
+
def sync_catalog
|
669
|
+
@threads.delete_if(&:stop?)
|
670
|
+
.last&.join
|
671
|
+
end
|
545
672
|
end
|
546
673
|
end
|
data/lib/solargraph/location.rb
CHANGED
data/lib/solargraph/page.rb
CHANGED
@@ -7,6 +7,12 @@ require 'cgi'
|
|
7
7
|
|
8
8
|
module Solargraph
|
9
9
|
class Page
|
10
|
+
# @todo This method directive is necessary because OpenStruct.new confuses
|
11
|
+
# the typechecker.
|
12
|
+
# @!method self.new(locals, render_method)
|
13
|
+
# @param locals[Hash]
|
14
|
+
# @param render_method [Proc]
|
15
|
+
# @return [Binder]
|
10
16
|
class Binder < OpenStruct
|
11
17
|
# @param locals [Hash]
|
12
18
|
# @param render_method [Proc]
|
@@ -3,6 +3,9 @@ require 'ripper'
|
|
3
3
|
module Solargraph
|
4
4
|
module Parser
|
5
5
|
class CommentRipper < Ripper::SexpBuilderPP
|
6
|
+
# @param src [String]
|
7
|
+
# @param filename [String]
|
8
|
+
# @param lineno [Integer]
|
6
9
|
def initialize src, filename = '(ripper)', lineno = 0
|
7
10
|
super
|
8
11
|
@buffer = src
|
@@ -42,6 +45,7 @@ module Solargraph
|
|
42
45
|
result
|
43
46
|
end
|
44
47
|
|
48
|
+
# @return [Hash{Integer => String}]
|
45
49
|
def parse
|
46
50
|
@comments = {}
|
47
51
|
super
|