solargraph 0.41.0 → 0.42.2
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/.travis.yml +0 -5
- data/CHANGELOG.md +24 -0
- data/lib/.rubocop.yml +4 -3
- data/lib/solargraph/api_map.rb +5 -53
- data/lib/solargraph/api_map/bundler_methods.rb +1 -6
- data/lib/solargraph/bench.rb +9 -9
- data/lib/solargraph/diagnostics/type_check.rb +1 -1
- data/lib/solargraph/language_server/host.rb +43 -9
- data/lib/solargraph/language_server/host/diagnoser.rb +9 -1
- data/lib/solargraph/language_server/host/sources.rb +1 -1
- data/lib/solargraph/language_server/message/initialize.rb +7 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
- data/lib/solargraph/language_server/transport/adapter.rb +1 -3
- data/lib/solargraph/library.rb +46 -7
- data/lib/solargraph/pin/local_variable.rb +47 -1
- data/lib/solargraph/shell.rb +4 -0
- data/lib/solargraph/source/chain/call.rb +3 -2
- data/lib/solargraph/source_map.rb +2 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +1 -0
- data/lib/solargraph/yard_map.rb +43 -39
- data/lib/solargraph/yard_map/core_fills.rb +18 -1
- data/solargraph.gemspec +2 -1
- metadata +18 -5
- data/lib/solargraph/pin/localized.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4cd4acd35a7ce8242976cdd2b23d583bbd01392e3d79a16e3b4e181443e4858
|
4
|
+
data.tar.gz: 4cb4f369d97681a43d24a8fc3de14a454721c4334426655e23fffafceeb242c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5918eb0b9797ed3bed1fe97a702761889b4fb5b8280de655820d8a4319eefd651f4958e420b32468aac2ab197f657b8cb1386029654dcbd9b3a30bbdd2ca521b
|
7
|
+
data.tar.gz: 649a461beb8b23b69ae40bb347389602e20b42d0a689752d805beb2c08000a863c24d9e45b39d00ee544d37802be0762d9933a6d4e27b2617249d1443ca582f4
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
## 0.42.2 - June 14, 2021
|
2
|
+
- Improve download-core command output
|
3
|
+
- Ignore missing requests to client responses
|
4
|
+
- Add automatically required gems to YardMap
|
5
|
+
- Use closures to identify local variables
|
6
|
+
|
7
|
+
## 0.42.1 - June 11, 2021
|
8
|
+
- YardMap#change sets new directory (#445)
|
9
|
+
|
10
|
+
## 0.42.0 - June 11, 2021
|
11
|
+
- Improve YardMap efficiency
|
12
|
+
- Bench includes Workspace for cataloging
|
13
|
+
- Initialize confirms static features from options (#436)
|
14
|
+
- Enable simple repairs without incremental sync (#416)
|
15
|
+
- Discard unrecognized client responses
|
16
|
+
- Notify on use of closest match for core (#390)
|
17
|
+
|
18
|
+
## 0.41.2 - June 9, 2021
|
19
|
+
- Rescue InvalidOffset in async diagnosis
|
20
|
+
- Remove erroneous escaping from Hover
|
21
|
+
|
22
|
+
## 0.41.1 - May 31, 2021
|
23
|
+
- ApiMap handles required bundles (#443)
|
24
|
+
|
1
25
|
## 0.41.0 - May 30, 2021
|
2
26
|
- Chain constant at last double colon with more than two nested namespaces
|
3
27
|
- Fill Integer#times return type (#440)
|
data/lib/.rubocop.yml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
AllCops:
|
2
|
+
NewCops: enable
|
3
3
|
Style/MethodDefParentheses:
|
4
4
|
Enabled: false
|
5
5
|
Layout/EmptyLineAfterGuardClause:
|
@@ -10,6 +10,8 @@ Lint/RaiseException:
|
|
10
10
|
Enabled: true
|
11
11
|
Lint/StructNewOverride:
|
12
12
|
Enabled: true
|
13
|
+
Metrics/MethodLength:
|
14
|
+
Max: 25
|
13
15
|
Style/ExponentialNotation:
|
14
16
|
Enabled: true
|
15
17
|
Style/HashEachMethods:
|
@@ -18,4 +20,3 @@ Style/HashTransformKeys:
|
|
18
20
|
Enabled: true
|
19
21
|
Style/HashTransformValues:
|
20
22
|
Enabled: true
|
21
|
-
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -17,7 +17,6 @@ module Solargraph
|
|
17
17
|
autoload :BundlerMethods, 'solargraph/api_map/bundler_methods'
|
18
18
|
|
19
19
|
include SourceToYard
|
20
|
-
include BundlerMethods
|
21
20
|
|
22
21
|
# @return [Array<String>]
|
23
22
|
attr_reader :unresolved_requires
|
@@ -59,30 +58,14 @@ module Solargraph
|
|
59
58
|
implicit.clear
|
60
59
|
@cache.clear
|
61
60
|
@source_map_hash = bench.source_maps.map { |s| [s.filename, s] }.to_h
|
62
|
-
pins =
|
63
|
-
|
64
|
-
local_path_hash.clear
|
61
|
+
pins = bench.source_maps.map(&:pins).flatten
|
62
|
+
external_requires = bench.external_requires
|
65
63
|
source_map_hash.each_value do |map|
|
66
|
-
pins.concat map.pins
|
67
|
-
@required.merge map.requires.map(&:name)
|
68
64
|
implicit.merge map.environ
|
69
65
|
end
|
70
|
-
|
71
|
-
external_requires
|
72
|
-
|
73
|
-
result = bench.load_paths.find do |path|
|
74
|
-
full = Pathname.new(path).join("#{req}.rb").to_s
|
75
|
-
@source_map_hash.key?(full)
|
76
|
-
end
|
77
|
-
if result
|
78
|
-
local_path_hash[req] = Pathname.new(result).join("#{req}.rb").to_s
|
79
|
-
else
|
80
|
-
external_requires.push req unless result
|
81
|
-
end
|
82
|
-
end
|
83
|
-
br = @required.include?('bundler/require') ? bench.gemnames.to_h { |gs| [gs.name, gs] } : {}
|
84
|
-
@required.merge br.keys
|
85
|
-
yard_map.change(external_requires, br, bench.gemnames)
|
66
|
+
external_requires.merge implicit.requires
|
67
|
+
external_requires.merge bench.workspace.config.required
|
68
|
+
yard_map.change(external_requires, bench.workspace.directory, bench.workspace.source_gems)
|
86
69
|
@store = Store.new(yard_map.pins + implicit.pins + pins)
|
87
70
|
@unresolved_requires = yard_map.unresolved_requires
|
88
71
|
@rebindable_method_names = nil
|
@@ -105,11 +88,6 @@ module Solargraph
|
|
105
88
|
@implicit ||= Environ.new
|
106
89
|
end
|
107
90
|
|
108
|
-
# @return [Hash{String => String}]
|
109
|
-
def local_path_hash
|
110
|
-
@local_paths ||= {}
|
111
|
-
end
|
112
|
-
|
113
91
|
# @param filename [String]
|
114
92
|
# @param position [Position, Array(Integer, Integer)]
|
115
93
|
# @return [Source::Cursor]
|
@@ -456,27 +434,6 @@ module Solargraph
|
|
456
434
|
source_map_hash.keys.include?(filename)
|
457
435
|
end
|
458
436
|
|
459
|
-
# True if the specified file is included in the workspace.
|
460
|
-
#
|
461
|
-
# @param filename [String]
|
462
|
-
def workspaced? filename
|
463
|
-
workspace_filenames.include?(filename)
|
464
|
-
end
|
465
|
-
|
466
|
-
# @param location [Location]
|
467
|
-
# @return [Location]
|
468
|
-
def require_reference_at location
|
469
|
-
map = source_map(location.filename)
|
470
|
-
pin = map.requires.select { |p| p.location.range.contain?(location.range.start) }.first
|
471
|
-
return nil if pin.nil?
|
472
|
-
if local_path_hash.key?(pin.name)
|
473
|
-
return Location.new(local_path_hash[pin.name], Solargraph::Range.from_to(0, 0, 0, 0))
|
474
|
-
end
|
475
|
-
yard_map.require_reference(pin.name)
|
476
|
-
rescue FileNotFoundError
|
477
|
-
nil
|
478
|
-
end
|
479
|
-
|
480
437
|
# Check if a class is a superclass of another class.
|
481
438
|
#
|
482
439
|
# @param sup [String] The superclass
|
@@ -508,11 +465,6 @@ module Solargraph
|
|
508
465
|
|
509
466
|
private
|
510
467
|
|
511
|
-
# @return [Array<String>]
|
512
|
-
def workspace_filenames
|
513
|
-
@workspace_filenames ||= []
|
514
|
-
end
|
515
|
-
|
516
468
|
# A hash of source maps with filename keys.
|
517
469
|
#
|
518
470
|
# @return [Hash{String => SourceMap}]
|
@@ -9,7 +9,7 @@ module Solargraph
|
|
9
9
|
# @param directory [String]
|
10
10
|
# @return [Hash]
|
11
11
|
def require_from_bundle directory
|
12
|
-
|
12
|
+
begin
|
13
13
|
Solargraph.logger.info "Loading gems for bundler/require"
|
14
14
|
Documentor.specs_from_bundle(directory)
|
15
15
|
rescue BundleNotFoundError => e
|
@@ -17,11 +17,6 @@ module Solargraph
|
|
17
17
|
{}
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
21
|
-
# @return [void]
|
22
|
-
def reset_require_from_bundle
|
23
|
-
@require_from_bundle = nil
|
24
|
-
end
|
25
20
|
end
|
26
21
|
end
|
27
22
|
end
|
data/lib/solargraph/bench.rb
CHANGED
@@ -3,25 +3,25 @@
|
|
3
3
|
require 'set'
|
4
4
|
|
5
5
|
module Solargraph
|
6
|
-
# A container of source maps and
|
6
|
+
# A container of source maps and workspace data to be cataloged in an ApiMap.
|
7
7
|
#
|
8
8
|
class Bench
|
9
9
|
# @return [Set<SourceMap>]
|
10
10
|
attr_reader :source_maps
|
11
11
|
|
12
|
-
# @return [
|
13
|
-
attr_reader :
|
12
|
+
# @return [Workspace]
|
13
|
+
attr_reader :workspace
|
14
14
|
|
15
15
|
# @return [Set<String>]
|
16
|
-
attr_reader :
|
16
|
+
attr_reader :external_requires
|
17
17
|
|
18
18
|
# @param source_maps [Array<SourceMap>, Set<SourceMap>]
|
19
|
-
# @param
|
20
|
-
# @param
|
21
|
-
def initialize source_maps: [],
|
19
|
+
# @param workspace [Workspace]
|
20
|
+
# @param external_requires [Array<String>, Set<String>]
|
21
|
+
def initialize source_maps: [], workspace: Workspace.new, external_requires: []
|
22
22
|
@source_maps = source_maps.to_set
|
23
|
-
@
|
24
|
-
@
|
23
|
+
@workspace = workspace
|
24
|
+
@external_requires = external_requires.to_set
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -7,7 +7,7 @@ module Solargraph
|
|
7
7
|
#
|
8
8
|
class TypeCheck < Base
|
9
9
|
def diagnose source, api_map
|
10
|
-
return [] unless args.include?('always') || api_map.workspaced?(source.filename)
|
10
|
+
# return [] unless args.include?('always') || api_map.workspaced?(source.filename)
|
11
11
|
severity = Diagnostics::Severities::ERROR
|
12
12
|
level = (args.reverse.find { |a| ['normal', 'typed', 'strict', 'strong'].include?(a) }) || :normal
|
13
13
|
checker = Solargraph::TypeChecker.new(source.filename, api_map: api_map, level: level.to_sym)
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'diff/lcs'
|
3
4
|
require 'observer'
|
4
|
-
require 'set'
|
5
5
|
require 'securerandom'
|
6
|
+
require 'set'
|
6
7
|
|
7
8
|
module Solargraph
|
8
9
|
module LanguageServer
|
@@ -30,7 +31,7 @@ module Solargraph
|
|
30
31
|
@cancel = []
|
31
32
|
@buffer = String.new
|
32
33
|
@stopped = true
|
33
|
-
@next_request_id =
|
34
|
+
@next_request_id = 1
|
34
35
|
@dynamic_capabilities = Set.new
|
35
36
|
@registered_capabilities = Set.new
|
36
37
|
end
|
@@ -107,9 +108,13 @@ module Solargraph
|
|
107
108
|
end
|
108
109
|
message
|
109
110
|
elsif request['id']
|
110
|
-
|
111
|
-
|
112
|
-
|
111
|
+
if requests[request['id']]
|
112
|
+
requests[request['id']].process(request['result'])
|
113
|
+
requests.delete request['id']
|
114
|
+
else
|
115
|
+
logger.warn "Discarding client response to unrecognized message #{request['id']}"
|
116
|
+
nil
|
117
|
+
end
|
113
118
|
else
|
114
119
|
logger.warn "Invalid message received."
|
115
120
|
logger.debug request
|
@@ -165,8 +170,6 @@ module Solargraph
|
|
165
170
|
# @return [void]
|
166
171
|
def open_from_disk uri
|
167
172
|
sources.open_from_disk(uri)
|
168
|
-
library = library_for(uri)
|
169
|
-
# library.open_from_disk uri_to_file(uri)
|
170
173
|
diagnoser.schedule uri
|
171
174
|
end
|
172
175
|
|
@@ -672,7 +675,8 @@ module Solargraph
|
|
672
675
|
# @return [Source::Updater]
|
673
676
|
def generate_updater params
|
674
677
|
changes = []
|
675
|
-
params['contentChanges'].each do |
|
678
|
+
params['contentChanges'].each do |recvd|
|
679
|
+
chng = check_diff(params['textDocument']['uri'], recvd)
|
676
680
|
changes.push Solargraph::Source::Change.new(
|
677
681
|
(chng['range'].nil? ?
|
678
682
|
nil :
|
@@ -688,6 +692,36 @@ module Solargraph
|
|
688
692
|
)
|
689
693
|
end
|
690
694
|
|
695
|
+
# @param uri [String]
|
696
|
+
# @param change [Hash]
|
697
|
+
# @return [Hash]
|
698
|
+
def check_diff uri, change
|
699
|
+
return change if change['range']
|
700
|
+
source = sources.find(uri)
|
701
|
+
return change if source.code.length + 1 != change['text'].length
|
702
|
+
diffs = Diff::LCS.diff(source.code, change['text'])
|
703
|
+
return change if diffs.length.zero? || diffs.length > 1 || diffs.first.length > 1
|
704
|
+
# @type [Diff::LCS::Change]
|
705
|
+
diff = diffs.first.first
|
706
|
+
return change unless diff.adding? && ['.', ':'].include?(diff.element)
|
707
|
+
position = Solargraph::Position.from_offset(source.code, diff.position)
|
708
|
+
{
|
709
|
+
'range' => {
|
710
|
+
'start' => {
|
711
|
+
'line' => position.line,
|
712
|
+
'character' => position.character
|
713
|
+
},
|
714
|
+
'end' => {
|
715
|
+
'line' => position.line,
|
716
|
+
'character' => position.character
|
717
|
+
}
|
718
|
+
},
|
719
|
+
'text' => diff.element
|
720
|
+
}
|
721
|
+
rescue Solargraph::FileNotFoundError
|
722
|
+
change
|
723
|
+
end
|
724
|
+
|
691
725
|
# @return [Hash]
|
692
726
|
def dynamic_capability_options
|
693
727
|
@dynamic_capability_options ||= {
|
@@ -787,7 +821,7 @@ module Solargraph
|
|
787
821
|
next unless uuid
|
788
822
|
cur = ((library.source_map_hash.keys.length.to_f / total.to_f) * 100).to_i
|
789
823
|
if cur > pct && cur % mod == 0
|
790
|
-
|
824
|
+
pct = cur
|
791
825
|
send_notification '$/progress', {
|
792
826
|
token: uuid,
|
793
827
|
value: {
|
@@ -62,7 +62,15 @@ module Solargraph
|
|
62
62
|
end
|
63
63
|
current = mutex.synchronize { queue.shift }
|
64
64
|
return if queue.include?(current)
|
65
|
-
|
65
|
+
begin
|
66
|
+
host.diagnose current
|
67
|
+
rescue InvalidOffsetError
|
68
|
+
# @todo This error can occur when the Source is out of sync with
|
69
|
+
# with the ApiMap. It's probably not the best way to handle it,
|
70
|
+
# but it's quick and easy.
|
71
|
+
Logging.logger.warn "Deferring diagnosis due to invalid offset: #{current}"
|
72
|
+
mutex.synchronize { queue.push current }
|
73
|
+
end
|
66
74
|
end
|
67
75
|
|
68
76
|
private
|
@@ -51,6 +51,7 @@ module Solargraph
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def static_completion
|
54
|
+
return {} unless host.options['completion']
|
54
55
|
{
|
55
56
|
completionProvider: {
|
56
57
|
resolveProvider: true,
|
@@ -84,18 +85,21 @@ module Solargraph
|
|
84
85
|
end
|
85
86
|
|
86
87
|
def static_hover
|
88
|
+
return {} unless host.options['hover']
|
87
89
|
{
|
88
90
|
hoverProvider: true
|
89
91
|
}
|
90
92
|
end
|
91
93
|
|
92
94
|
def static_document_formatting
|
95
|
+
return {} unless host.options['formatting']
|
93
96
|
{
|
94
97
|
documentFormattingProvider: true
|
95
98
|
}
|
96
99
|
end
|
97
100
|
|
98
101
|
def static_document_symbols
|
102
|
+
return {} unless host.options['symbols']
|
99
103
|
{
|
100
104
|
documentSymbolProvider: true
|
101
105
|
}
|
@@ -108,6 +112,7 @@ module Solargraph
|
|
108
112
|
end
|
109
113
|
|
110
114
|
def static_definitions
|
115
|
+
return {} unless host.options['definitions']
|
111
116
|
{
|
112
117
|
definitionProvider: true
|
113
118
|
}
|
@@ -120,12 +125,14 @@ module Solargraph
|
|
120
125
|
end
|
121
126
|
|
122
127
|
def static_references
|
128
|
+
return {} unless host.options['references']
|
123
129
|
{
|
124
130
|
referencesProvider: true
|
125
131
|
}
|
126
132
|
end
|
127
133
|
|
128
134
|
def static_folding_range
|
135
|
+
return {} unless host.options['folding']
|
129
136
|
{
|
130
137
|
foldingRangeProvider: true
|
131
138
|
}
|
@@ -17,7 +17,7 @@ module Solargraph
|
|
17
17
|
if !this_link.nil? && this_link != last_link
|
18
18
|
parts.push this_link
|
19
19
|
end
|
20
|
-
parts.push "
|
20
|
+
parts.push "`#{pin.detail}`" unless pin.is_a?(Pin::Namespace) || pin.detail.nil?
|
21
21
|
parts.push pin.documentation unless pin.documentation.nil? || pin.documentation.empty?
|
22
22
|
unless parts.empty?
|
23
23
|
data = parts.join("\n\n")
|
data/lib/solargraph/library.rb
CHANGED
@@ -46,8 +46,10 @@ module Solargraph
|
|
46
46
|
# @return [void]
|
47
47
|
def attach source
|
48
48
|
mutex.synchronize do
|
49
|
-
if @current && @current.filename != source.filename && source_map_hash.key?(@current.filename) && !workspace.has_file?(@current.filename)
|
49
|
+
if @current && (!source || @current.filename != source.filename) && source_map_hash.key?(@current.filename) && !workspace.has_file?(@current.filename)
|
50
50
|
source_map_hash.delete @current.filename
|
51
|
+
source_map_external_require_hash.delete @current.filename
|
52
|
+
@external_requires = nil
|
51
53
|
@synchronized = false
|
52
54
|
end
|
53
55
|
@current = source
|
@@ -252,7 +254,18 @@ module Solargraph
|
|
252
254
|
end
|
253
255
|
|
254
256
|
def locate_ref location
|
255
|
-
|
257
|
+
map = source_map_hash[location.filename]
|
258
|
+
return if map.nil?
|
259
|
+
pin = map.requires.select { |p| p.location.range.contain?(location.range.start) }.first
|
260
|
+
return nil if pin.nil?
|
261
|
+
workspace.require_paths.each do |path|
|
262
|
+
full = Pathname.new(path).join("#{pin.name}.rb").to_s
|
263
|
+
next unless source_map_hash.key?(full)
|
264
|
+
return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0))
|
265
|
+
end
|
266
|
+
api_map.yard_map.require_reference(pin.name)
|
267
|
+
rescue FileNotFoundError
|
268
|
+
nil
|
256
269
|
end
|
257
270
|
|
258
271
|
# Get an array of pins that match a path.
|
@@ -326,6 +339,7 @@ module Solargraph
|
|
326
339
|
return [] unless open?(filename)
|
327
340
|
result = []
|
328
341
|
source = read(filename)
|
342
|
+
catalog
|
329
343
|
repargs = {}
|
330
344
|
workspace.config.reporters.each do |line|
|
331
345
|
if line == 'all!'
|
@@ -361,12 +375,10 @@ module Solargraph
|
|
361
375
|
end
|
362
376
|
|
363
377
|
def bench
|
364
|
-
source_maps = @current ? [@current] : []
|
365
|
-
source_maps.concat source_map_hash.values
|
366
378
|
Bench.new(
|
367
|
-
source_maps:
|
368
|
-
|
369
|
-
|
379
|
+
source_maps: source_map_hash.values,
|
380
|
+
workspace: workspace,
|
381
|
+
external_requires: external_requires
|
370
382
|
)
|
371
383
|
end
|
372
384
|
|
@@ -422,6 +434,8 @@ module Solargraph
|
|
422
434
|
if src
|
423
435
|
Logging.logger.debug "Mapping #{src.filename}"
|
424
436
|
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
437
|
+
find_external_requires(source_map_hash[src.filename])
|
438
|
+
source_map_hash[src.filename]
|
425
439
|
else
|
426
440
|
false
|
427
441
|
end
|
@@ -431,6 +445,7 @@ module Solargraph
|
|
431
445
|
def map!
|
432
446
|
workspace.sources.each do |src|
|
433
447
|
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
448
|
+
find_external_requires(source_map_hash[src.filename])
|
434
449
|
end
|
435
450
|
self
|
436
451
|
end
|
@@ -439,8 +454,29 @@ module Solargraph
|
|
439
454
|
@pins ||= []
|
440
455
|
end
|
441
456
|
|
457
|
+
def external_requires
|
458
|
+
@external_requires ||= source_map_external_require_hash.values.flatten.to_set
|
459
|
+
end
|
460
|
+
|
442
461
|
private
|
443
462
|
|
463
|
+
def source_map_external_require_hash
|
464
|
+
@source_map_external_require_hash ||= {}
|
465
|
+
end
|
466
|
+
|
467
|
+
# @param source_map [SourceMap]
|
468
|
+
def find_external_requires source_map
|
469
|
+
new_set = source_map.requires.map(&:name).to_set
|
470
|
+
# return if new_set == source_map_external_require_hash[source_map.filename]
|
471
|
+
source_map_external_require_hash[source_map.filename] = new_set.reject do |path|
|
472
|
+
workspace.require_paths.any? do |base|
|
473
|
+
full = Pathname.new(base).join("#{path}.rb").to_s
|
474
|
+
workspace.filenames.include?(full)
|
475
|
+
end
|
476
|
+
end
|
477
|
+
@external_requires = nil
|
478
|
+
end
|
479
|
+
|
444
480
|
# @return [Mutex]
|
445
481
|
def mutex
|
446
482
|
@mutex ||= Mutex.new
|
@@ -475,6 +511,7 @@ module Solargraph
|
|
475
511
|
end
|
476
512
|
|
477
513
|
def maybe_map source
|
514
|
+
return unless source
|
478
515
|
if source_map_hash.key?(source.filename)
|
479
516
|
return if source_map_hash[source.filename].code == source.code &&
|
480
517
|
source_map_hash[source.filename].source.synchronized? &&
|
@@ -483,6 +520,7 @@ module Solargraph
|
|
483
520
|
new_map = Solargraph::SourceMap.map(source)
|
484
521
|
unless source_map_hash[source.filename].try_merge!(new_map)
|
485
522
|
source_map_hash[source.filename] = new_map
|
523
|
+
find_external_requires(source_map_hash[source.filename])
|
486
524
|
@synchronized = false
|
487
525
|
end
|
488
526
|
else
|
@@ -491,6 +529,7 @@ module Solargraph
|
|
491
529
|
end
|
492
530
|
else
|
493
531
|
source_map_hash[source.filename] = Solargraph::SourceMap.map(source)
|
532
|
+
find_external_requires(source_map_hash[source.filename])
|
494
533
|
@synchronized = false
|
495
534
|
end
|
496
535
|
end
|
@@ -3,7 +3,8 @@
|
|
3
3
|
module Solargraph
|
4
4
|
module Pin
|
5
5
|
class LocalVariable < BaseVariable
|
6
|
-
|
6
|
+
# @return [Range]
|
7
|
+
attr_reader :presence
|
7
8
|
|
8
9
|
def initialize assignment: nil, presence: nil, **splat
|
9
10
|
super(**splat)
|
@@ -16,6 +17,51 @@ module Solargraph
|
|
16
17
|
@presence = pin.presence
|
17
18
|
true
|
18
19
|
end
|
20
|
+
|
21
|
+
# @param other [Pin::Base] The caller's block
|
22
|
+
# @param position [Position, Array(Integer, Integer)] The caller's position
|
23
|
+
# @return [Boolean]
|
24
|
+
def visible_from?(other, position)
|
25
|
+
position = Position.normalize(position)
|
26
|
+
other.filename == filename &&
|
27
|
+
match_tags(other.full_context.tag, full_context.tag) &&
|
28
|
+
(other == closure ||
|
29
|
+
(closure.location.range.contain?(other.location.range.start) && closure.location.range.contain?(other.location.range.ending))
|
30
|
+
) &&
|
31
|
+
presence.contain?(position)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param other_loc [Location]
|
35
|
+
def visible_at?(other_closure, other_loc)
|
36
|
+
return true if location.filename == other_loc.filename &&
|
37
|
+
presence.include?(other_loc.range.start) &&
|
38
|
+
match_named_closure(other_closure, closure)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# @param tag1 [String]
|
44
|
+
# @param tag2 [String]
|
45
|
+
# @return [Boolean]
|
46
|
+
def match_tags tag1, tag2
|
47
|
+
# @todo This is an unfortunate hack made necessary by a discrepancy in
|
48
|
+
# how tags indicate the root namespace. The long-term solution is to
|
49
|
+
# standardize it, whether it's `Class<>`, an empty string, or
|
50
|
+
# something else.
|
51
|
+
tag1 == tag2 ||
|
52
|
+
(['', 'Class<>'].include?(tag1) && ['', 'Class<>'].include?(tag2))
|
53
|
+
end
|
54
|
+
|
55
|
+
def match_named_closure needle, haystack
|
56
|
+
return true if needle == haystack
|
57
|
+
cursor = haystack
|
58
|
+
until cursor.nil?
|
59
|
+
return true if needle.path == cursor.path
|
60
|
+
return false if cursor.path && !cursor.path.empty?
|
61
|
+
cursor = cursor.closure
|
62
|
+
end
|
63
|
+
false
|
64
|
+
end
|
19
65
|
end
|
20
66
|
end
|
21
67
|
end
|
data/lib/solargraph/shell.rb
CHANGED
@@ -74,10 +74,14 @@ module Solargraph
|
|
74
74
|
desc 'download-core [VERSION]', 'Download core documentation'
|
75
75
|
def download_core version = nil
|
76
76
|
ver = version || Solargraph::YardMap::CoreDocs.best_download
|
77
|
+
if RUBY_VERSION != ver
|
78
|
+
puts "Documentation for #{RUBY_VERSION} is not available. Reverting to closest match..."
|
79
|
+
end
|
77
80
|
puts "Downloading docs for #{ver}..."
|
78
81
|
Solargraph::YardMap::CoreDocs.download ver
|
79
82
|
# Clear cached documentation if it exists
|
80
83
|
FileUtils.rm_rf Dir.glob(File.join(Solargraph::YardMap::CoreDocs.cache_dir, ver, '*.ser'))
|
84
|
+
puts "Download complete."
|
81
85
|
rescue ArgumentError => e
|
82
86
|
STDERR.puts "ERROR: #{e.message}"
|
83
87
|
STDERR.puts "Run `solargraph available-cores` for a list."
|
@@ -77,6 +77,7 @@ module Solargraph
|
|
77
77
|
end
|
78
78
|
if match
|
79
79
|
type = extra_return_type(ol, context)
|
80
|
+
break if type
|
80
81
|
type = ComplexType.try_parse(*ol.tag(:return).types).self_to(context.to_s).qualify(api_map, context.namespace) if ol.has_tag?(:return) && ol.tag(:return).types && !ol.tag(:return).types.empty? && (type.nil? || type.undefined?)
|
81
82
|
type ||= ComplexType::UNDEFINED
|
82
83
|
end
|
@@ -170,8 +171,8 @@ module Solargraph
|
|
170
171
|
# @param context [ComplexType]
|
171
172
|
# @return [ComplexType]
|
172
173
|
def extra_return_type docstring, context
|
173
|
-
if docstring.has_tag?(:return_single_parameter)
|
174
|
-
return context.subtypes.first
|
174
|
+
if docstring.has_tag?(:return_single_parameter) #&& context.subtypes.one?
|
175
|
+
return context.subtypes.first || ComplexType::UNDEFINED
|
175
176
|
elsif docstring.has_tag?(:return_value_parameter) && context.value_types.one?
|
176
177
|
return context.value_types.first
|
177
178
|
end
|
@@ -131,7 +131,8 @@ module Solargraph
|
|
131
131
|
# @return [Array<Pin::LocalVariable>]
|
132
132
|
def locals_at(location)
|
133
133
|
return [] if location.filename != filename
|
134
|
-
|
134
|
+
closure = locate_named_path_pin(location.range.start.line, location.range.start.character)
|
135
|
+
locals.select { |pin| pin.visible_at?(closure, location) }
|
135
136
|
end
|
136
137
|
|
137
138
|
class << self
|
data/lib/solargraph/version.rb
CHANGED
data/lib/solargraph/workspace.rb
CHANGED
data/lib/solargraph/yard_map.rb
CHANGED
@@ -20,6 +20,8 @@ module Solargraph
|
|
20
20
|
autoload :Helpers, 'solargraph/yard_map/helpers'
|
21
21
|
autoload :ToMethod, 'solargraph/yard_map/to_method'
|
22
22
|
|
23
|
+
include ApiMap::BundlerMethods
|
24
|
+
|
23
25
|
CoreDocs.require_minimum
|
24
26
|
|
25
27
|
def stdlib_paths
|
@@ -37,33 +39,16 @@ module Solargraph
|
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
|
-
# @return [Array<String>]
|
41
|
-
attr_reader :required
|
42
|
-
|
43
42
|
# @return [Boolean]
|
44
43
|
attr_writer :with_dependencies
|
45
44
|
|
46
|
-
#
|
47
|
-
#
|
48
|
-
# @
|
49
|
-
attr_reader :gemset
|
50
|
-
|
51
|
-
# @param required [Array<String>]
|
52
|
-
# @param gemset [Hash{String => String}]
|
45
|
+
# @param required [Array<String>, Set<String>]
|
46
|
+
# @param directory [String]
|
47
|
+
# @param source_gems [Array<String>, Set<String>]
|
53
48
|
# @param with_dependencies [Boolean]
|
54
|
-
def initialize(required: [],
|
55
|
-
# HACK: YardMap needs its own copy of this array
|
56
|
-
@required = required.clone
|
57
|
-
# HACK: Hardcoded YAML handling
|
58
|
-
@required.push 'psych' if @required.include?('yaml')
|
49
|
+
def initialize(required: [], directory: '', source_gems: [], with_dependencies: true)
|
59
50
|
@with_dependencies = with_dependencies
|
60
|
-
|
61
|
-
@stdlib_namespaces = []
|
62
|
-
@gemset = gemset
|
63
|
-
@source_gems = []
|
64
|
-
process_requires
|
65
|
-
yardocs.uniq!
|
66
|
-
@pin_select_cache = {}
|
51
|
+
change required.to_set, directory, source_gems.to_set
|
67
52
|
end
|
68
53
|
|
69
54
|
# @return [Array<Solargraph::Pin::Base>]
|
@@ -76,25 +61,24 @@ module Solargraph
|
|
76
61
|
@with_dependencies
|
77
62
|
end
|
78
63
|
|
79
|
-
# @param new_requires [
|
80
|
-
# @param
|
64
|
+
# @param new_requires [Set<String>] Required paths to use for loading gems
|
65
|
+
# @param new_directory [String] The workspace directory
|
66
|
+
# @param new_source_gems [Set<String>] Gems under local development (i.e., part of the workspace)
|
81
67
|
# @return [Boolean]
|
82
|
-
def change new_requires,
|
68
|
+
def change new_requires, new_directory, new_source_gems
|
69
|
+
return false if new_requires == base_required && new_directory == @directory && new_source_gems == @source_gems
|
70
|
+
@gem_paths = {}
|
71
|
+
base_required.replace new_requires
|
72
|
+
required.replace new_requires
|
83
73
|
# HACK: Hardcoded YAML handling
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
process_requires
|
93
|
-
@rebindable_method_names = nil
|
94
|
-
@pin_class_hash = nil
|
95
|
-
@pin_select_cache = {}
|
96
|
-
true
|
97
|
-
end
|
74
|
+
required.add 'psych' if new_requires.include?('yaml')
|
75
|
+
@source_gems = new_source_gems
|
76
|
+
@directory = new_directory
|
77
|
+
process_requires
|
78
|
+
@rebindable_method_names = nil
|
79
|
+
@pin_class_hash = nil
|
80
|
+
@pin_select_cache = {}
|
81
|
+
true
|
98
82
|
end
|
99
83
|
|
100
84
|
# @return [Set<String>]
|
@@ -111,6 +95,11 @@ module Solargraph
|
|
111
95
|
@yardocs ||= []
|
112
96
|
end
|
113
97
|
|
98
|
+
# @return [Set<String>]
|
99
|
+
def required
|
100
|
+
@required ||= Set.new
|
101
|
+
end
|
102
|
+
|
114
103
|
# @return [Array<String>]
|
115
104
|
def unresolved_requires
|
116
105
|
@unresolved_requires ||= []
|
@@ -163,6 +152,14 @@ module Solargraph
|
|
163
152
|
@stdlib_pins ||= []
|
164
153
|
end
|
165
154
|
|
155
|
+
def base_required
|
156
|
+
@base_required ||= Set.new
|
157
|
+
end
|
158
|
+
|
159
|
+
def directory
|
160
|
+
@directory ||= ''
|
161
|
+
end
|
162
|
+
|
166
163
|
private
|
167
164
|
|
168
165
|
# @return [YardMap::Cache]
|
@@ -193,6 +190,8 @@ module Solargraph
|
|
193
190
|
|
194
191
|
# @return [void]
|
195
192
|
def process_requires
|
193
|
+
@gemset = process_gemsets
|
194
|
+
required.merge @gemset.keys if required.include?('bundler/require')
|
196
195
|
pins.replace core_pins
|
197
196
|
unresolved_requires.clear
|
198
197
|
stdlib_pins.clear
|
@@ -252,6 +251,11 @@ module Solargraph
|
|
252
251
|
pins.concat environ.pins
|
253
252
|
end
|
254
253
|
|
254
|
+
def process_gemsets
|
255
|
+
return {} if directory.empty? || !File.file?(File.join(directory, 'Gemfile'))
|
256
|
+
require_from_bundle(directory)
|
257
|
+
end
|
258
|
+
|
255
259
|
# @param spec [Gem::Specification]
|
256
260
|
# @return [void]
|
257
261
|
def add_gem_dependencies spec
|
@@ -82,6 +82,18 @@ module Solargraph
|
|
82
82
|
Override.method_return('Class#allocate', 'self'),
|
83
83
|
Override.method_return('Class.allocate', 'Class<Object>'),
|
84
84
|
|
85
|
+
Override.from_comment('Enumerable#detect', %(
|
86
|
+
@overload detect(&block)
|
87
|
+
@return_single_parameter
|
88
|
+
@overload detect()
|
89
|
+
@return [Enumerator]
|
90
|
+
)),
|
91
|
+
Override.from_comment('Enumerable#find', %(
|
92
|
+
@overload find(&block)
|
93
|
+
@return_single_parameter
|
94
|
+
@overload find()
|
95
|
+
@return [Enumerator]
|
96
|
+
)),
|
85
97
|
Override.method_return('Enumerable#select', 'self'),
|
86
98
|
|
87
99
|
Override.method_return('File.absolute_path', 'String'),
|
@@ -111,7 +123,12 @@ module Solargraph
|
|
111
123
|
@param y [Numeric]
|
112
124
|
@return [Numeric]
|
113
125
|
)),
|
114
|
-
Override.
|
126
|
+
Override.from_comment('Integer#times', %(
|
127
|
+
@overload times(&block)
|
128
|
+
@return [Integer]
|
129
|
+
@overload times()
|
130
|
+
@return [Enumerator]
|
131
|
+
)),
|
115
132
|
|
116
133
|
Override.method_return('Kernel#puts', 'nil'),
|
117
134
|
|
data/solargraph.gemspec
CHANGED
@@ -19,9 +19,10 @@ Gem::Specification.new do |s|
|
|
19
19
|
|
20
20
|
s.required_ruby_version = '>= 2.4'
|
21
21
|
|
22
|
-
s.add_runtime_dependency 'backport', '~> 1.
|
22
|
+
s.add_runtime_dependency 'backport', '~> 1.2'
|
23
23
|
s.add_runtime_dependency 'benchmark'
|
24
24
|
s.add_runtime_dependency 'bundler', '>= 1.17.2'
|
25
|
+
s.add_runtime_dependency 'diff-lcs', '~> 1.4'
|
25
26
|
s.add_runtime_dependency 'e2mmap'
|
26
27
|
s.add_runtime_dependency 'jaro_winkler', '~> 1.5'
|
27
28
|
s.add_runtime_dependency 'kramdown', '~> 2.3'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solargraph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.42.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backport
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: benchmark
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 1.17.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: diff-lcs
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.4'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.4'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: e2mmap
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -463,7 +477,6 @@ files:
|
|
463
477
|
- lib/solargraph/pin/keyword.rb
|
464
478
|
- lib/solargraph/pin/keyword_param.rb
|
465
479
|
- lib/solargraph/pin/local_variable.rb
|
466
|
-
- lib/solargraph/pin/localized.rb
|
467
480
|
- lib/solargraph/pin/method.rb
|
468
481
|
- lib/solargraph/pin/method_alias.rb
|
469
482
|
- lib/solargraph/pin/namespace.rb
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solargraph
|
4
|
-
module Pin
|
5
|
-
module Localized
|
6
|
-
# @return [Range]
|
7
|
-
attr_reader :presence
|
8
|
-
|
9
|
-
# @param other [Pin::Base] The caller's block
|
10
|
-
# @param position [Position, Array(Integer, Integer)] The caller's position
|
11
|
-
# @return [Boolean]
|
12
|
-
def visible_from?(other, position)
|
13
|
-
position = Position.normalize(position)
|
14
|
-
other.filename == filename &&
|
15
|
-
match_tags(other.full_context.tag, full_context.tag) &&
|
16
|
-
(other == closure ||
|
17
|
-
(closure.location.range.contain?(other.location.range.start) && closure.location.range.contain?(other.location.range.ending))
|
18
|
-
) &&
|
19
|
-
presence.contain?(position)
|
20
|
-
end
|
21
|
-
|
22
|
-
# @param other_loc [Location]
|
23
|
-
def visible_at?(other_loc)
|
24
|
-
return false if location.filename != other_loc.filename
|
25
|
-
presence.include?(other_loc.range.start)
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
# @param tag1 [String]
|
31
|
-
# @param tag2 [String]
|
32
|
-
# @return [Boolean]
|
33
|
-
def match_tags tag1, tag2
|
34
|
-
# @todo This is an unfortunate hack made necessary by a discrepancy in
|
35
|
-
# how tags indicate the root namespace. The long-term solution is to
|
36
|
-
# standardize it, whether it's `Class<>`, an empty string, or
|
37
|
-
# something else.
|
38
|
-
tag1 == tag2 ||
|
39
|
-
(['', 'Class<>'].include?(tag1) && ['', 'Class<>'].include?(tag2))
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|