solargraph 0.41.1 → 0.42.3
Sign up to get free protection for your applications and to get access to all the features.
- 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 -13
- 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 +48 -8
- 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 +22 -9
- 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: f99f80989cced14064f1739f7a193f207fe92c8f696374de2f4798e3662196f0
|
4
|
+
data.tar.gz: efb7011bebf1eaab6b374c093fe25abe67a7b5da469024d78702feae1e4449a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3975f82cf5ac9c25e6d49dfe5cee21fc780d98f38dfca83371750c8a7913d53684d142f21047fcf132cdb7e02efb878b8956aab94b982ae764a3dcae9bf62cc
|
7
|
+
data.tar.gz: 6917cfd70a9d436792456857154b6de5c10ded3d08f3ae9caf029307581577fcd1d1934fe3959c5c84750006d9e3d6a55c4a344746dee72eb8fa9dcf3a25e078
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
## 0.42.3 - June 14, 2021
|
2
|
+
- Require 'pathname' for Library
|
3
|
+
|
4
|
+
## 0.42.2 - June 14, 2021
|
5
|
+
- Improve download-core command output
|
6
|
+
- Ignore missing requests to client responses
|
7
|
+
- Add automatically required gems to YardMap
|
8
|
+
- Use closures to identify local variables
|
9
|
+
|
10
|
+
## 0.42.1 - June 11, 2021
|
11
|
+
- YardMap#change sets new directory (#445)
|
12
|
+
|
13
|
+
## 0.42.0 - June 11, 2021
|
14
|
+
- Improve YardMap efficiency
|
15
|
+
- Bench includes Workspace for cataloging
|
16
|
+
- Initialize confirms static features from options (#436)
|
17
|
+
- Enable simple repairs without incremental sync (#416)
|
18
|
+
- Discard unrecognized client responses
|
19
|
+
- Notify on use of closest match for core (#390)
|
20
|
+
|
21
|
+
## 0.41.2 - June 9, 2021
|
22
|
+
- Rescue InvalidOffset in async diagnosis
|
23
|
+
- Remove erroneous escaping from Hover
|
24
|
+
|
1
25
|
## 0.41.1 - May 31, 2021
|
2
26
|
- ApiMap handles required bundles (#443)
|
3
27
|
|
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') ? require_from_bundle(bench.directory) : {}
|
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,29 +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 :
|
17
|
-
|
18
|
-
# @return [String]
|
19
|
-
attr_reader :directory
|
16
|
+
attr_reader :external_requires
|
20
17
|
|
21
18
|
# @param source_maps [Array<SourceMap>, Set<SourceMap>]
|
22
|
-
# @param
|
23
|
-
# @param
|
24
|
-
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: []
|
25
22
|
@source_maps = source_maps.to_set
|
26
|
-
@
|
27
|
-
@
|
28
|
-
@directory = directory
|
23
|
+
@workspace = workspace
|
24
|
+
@external_requires = external_requires.to_set
|
29
25
|
end
|
30
26
|
end
|
31
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
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'pathname'
|
4
|
+
|
3
5
|
module Solargraph
|
4
6
|
# A Library handles coordination between a Workspace and an ApiMap.
|
5
7
|
#
|
@@ -46,8 +48,10 @@ module Solargraph
|
|
46
48
|
# @return [void]
|
47
49
|
def attach source
|
48
50
|
mutex.synchronize do
|
49
|
-
if @current && @current.filename != source.filename && source_map_hash.key?(@current.filename) && !workspace.has_file?(@current.filename)
|
51
|
+
if @current && (!source || @current.filename != source.filename) && source_map_hash.key?(@current.filename) && !workspace.has_file?(@current.filename)
|
50
52
|
source_map_hash.delete @current.filename
|
53
|
+
source_map_external_require_hash.delete @current.filename
|
54
|
+
@external_requires = nil
|
51
55
|
@synchronized = false
|
52
56
|
end
|
53
57
|
@current = source
|
@@ -252,7 +256,18 @@ module Solargraph
|
|
252
256
|
end
|
253
257
|
|
254
258
|
def locate_ref location
|
255
|
-
|
259
|
+
map = source_map_hash[location.filename]
|
260
|
+
return if map.nil?
|
261
|
+
pin = map.requires.select { |p| p.location.range.contain?(location.range.start) }.first
|
262
|
+
return nil if pin.nil?
|
263
|
+
workspace.require_paths.each do |path|
|
264
|
+
full = Pathname.new(path).join("#{pin.name}.rb").to_s
|
265
|
+
next unless source_map_hash.key?(full)
|
266
|
+
return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0))
|
267
|
+
end
|
268
|
+
api_map.yard_map.require_reference(pin.name)
|
269
|
+
rescue FileNotFoundError
|
270
|
+
nil
|
256
271
|
end
|
257
272
|
|
258
273
|
# Get an array of pins that match a path.
|
@@ -326,6 +341,7 @@ module Solargraph
|
|
326
341
|
return [] unless open?(filename)
|
327
342
|
result = []
|
328
343
|
source = read(filename)
|
344
|
+
catalog
|
329
345
|
repargs = {}
|
330
346
|
workspace.config.reporters.each do |line|
|
331
347
|
if line == 'all!'
|
@@ -361,13 +377,10 @@ module Solargraph
|
|
361
377
|
end
|
362
378
|
|
363
379
|
def bench
|
364
|
-
source_maps = @current ? [@current] : []
|
365
|
-
source_maps.concat source_map_hash.values
|
366
380
|
Bench.new(
|
367
|
-
source_maps:
|
368
|
-
|
369
|
-
|
370
|
-
directory: workspace.directory
|
381
|
+
source_maps: source_map_hash.values,
|
382
|
+
workspace: workspace,
|
383
|
+
external_requires: external_requires
|
371
384
|
)
|
372
385
|
end
|
373
386
|
|
@@ -423,6 +436,8 @@ module Solargraph
|
|
423
436
|
if src
|
424
437
|
Logging.logger.debug "Mapping #{src.filename}"
|
425
438
|
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
439
|
+
find_external_requires(source_map_hash[src.filename])
|
440
|
+
source_map_hash[src.filename]
|
426
441
|
else
|
427
442
|
false
|
428
443
|
end
|
@@ -432,6 +447,7 @@ module Solargraph
|
|
432
447
|
def map!
|
433
448
|
workspace.sources.each do |src|
|
434
449
|
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
450
|
+
find_external_requires(source_map_hash[src.filename])
|
435
451
|
end
|
436
452
|
self
|
437
453
|
end
|
@@ -440,8 +456,29 @@ module Solargraph
|
|
440
456
|
@pins ||= []
|
441
457
|
end
|
442
458
|
|
459
|
+
def external_requires
|
460
|
+
@external_requires ||= source_map_external_require_hash.values.flatten.to_set
|
461
|
+
end
|
462
|
+
|
443
463
|
private
|
444
464
|
|
465
|
+
def source_map_external_require_hash
|
466
|
+
@source_map_external_require_hash ||= {}
|
467
|
+
end
|
468
|
+
|
469
|
+
# @param source_map [SourceMap]
|
470
|
+
def find_external_requires source_map
|
471
|
+
new_set = source_map.requires.map(&:name).to_set
|
472
|
+
# return if new_set == source_map_external_require_hash[source_map.filename]
|
473
|
+
source_map_external_require_hash[source_map.filename] = new_set.reject do |path|
|
474
|
+
workspace.require_paths.any? do |base|
|
475
|
+
full = Pathname.new(base).join("#{path}.rb").to_s
|
476
|
+
workspace.filenames.include?(full)
|
477
|
+
end
|
478
|
+
end
|
479
|
+
@external_requires = nil
|
480
|
+
end
|
481
|
+
|
445
482
|
# @return [Mutex]
|
446
483
|
def mutex
|
447
484
|
@mutex ||= Mutex.new
|
@@ -476,6 +513,7 @@ module Solargraph
|
|
476
513
|
end
|
477
514
|
|
478
515
|
def maybe_map source
|
516
|
+
return unless source
|
479
517
|
if source_map_hash.key?(source.filename)
|
480
518
|
return if source_map_hash[source.filename].code == source.code &&
|
481
519
|
source_map_hash[source.filename].source.synchronized? &&
|
@@ -484,6 +522,7 @@ module Solargraph
|
|
484
522
|
new_map = Solargraph::SourceMap.map(source)
|
485
523
|
unless source_map_hash[source.filename].try_merge!(new_map)
|
486
524
|
source_map_hash[source.filename] = new_map
|
525
|
+
find_external_requires(source_map_hash[source.filename])
|
487
526
|
@synchronized = false
|
488
527
|
end
|
489
528
|
else
|
@@ -492,6 +531,7 @@ module Solargraph
|
|
492
531
|
end
|
493
532
|
else
|
494
533
|
source_map_hash[source.filename] = Solargraph::SourceMap.map(source)
|
534
|
+
find_external_requires(source_map_hash[source.filename])
|
495
535
|
@synchronized = false
|
496
536
|
end
|
497
537
|
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
|
-
autorequire:
|
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
|
@@ -540,7 +553,7 @@ homepage: http://solargraph.org
|
|
540
553
|
licenses:
|
541
554
|
- MIT
|
542
555
|
metadata: {}
|
543
|
-
post_install_message:
|
556
|
+
post_install_message:
|
544
557
|
rdoc_options: []
|
545
558
|
require_paths:
|
546
559
|
- lib
|
@@ -555,8 +568,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
555
568
|
- !ruby/object:Gem::Version
|
556
569
|
version: '0'
|
557
570
|
requirements: []
|
558
|
-
rubygems_version: 3.1.
|
559
|
-
signing_key:
|
571
|
+
rubygems_version: 3.1.6
|
572
|
+
signing_key:
|
560
573
|
specification_version: 4
|
561
574
|
summary: A Ruby language server
|
562
575
|
test_files: []
|
@@ -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
|