solargraph 0.40.1 → 0.41.1
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/CHANGELOG.md +32 -0
- data/README.md +15 -0
- data/SPONSORS.md +1 -0
- data/lib/.rubocop.yml +1 -1
- data/lib/solargraph.rb +8 -7
- data/lib/solargraph/api_map.rb +52 -75
- data/lib/solargraph/api_map/store.rb +5 -0
- data/lib/solargraph/bench.rb +19 -18
- data/lib/solargraph/compat.rb +15 -1
- data/lib/solargraph/diagnostics/rubocop.rb +10 -2
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +19 -20
- data/lib/solargraph/language_server/host.rb +74 -1
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +1 -0
- data/lib/solargraph/language_server/message/extended/environment.rb +3 -3
- data/lib/solargraph/language_server/message/initialize.rb +30 -35
- data/lib/solargraph/language_server/message/text_document/formatting.rb +68 -18
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
- data/lib/solargraph/library.rb +94 -21
- data/lib/solargraph/parser/legacy/node_methods.rb +4 -0
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -1
- data/lib/solargraph/parser/rubyvm/node_methods.rb +9 -2
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +11 -12
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +1 -6
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +1 -1
- data/lib/solargraph/source.rb +1 -1
- data/lib/solargraph/source/chain/head.rb +0 -16
- data/lib/solargraph/source/source_chainer.rb +1 -0
- data/lib/solargraph/source_map/mapper.rb +0 -5
- data/lib/solargraph/type_checker.rb +49 -39
- data/lib/solargraph/type_checker/checks.rb +9 -5
- data/lib/solargraph/type_checker/rules.rb +5 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +19 -3
- data/lib/solargraph/yard_map/core_fills.rb +1 -0
- data/solargraph.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 821bc3321cdaf8fd3a707fbf5c04545fadde37dbb4ce177c0f64cfc2330dd2f2
|
4
|
+
data.tar.gz: 29bfda592a11968558178117ac849e1dbc7bf02c5685740a79682e911cadadf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c1c06c2996704646df0c140b47e5109bfd6f70ba7504e7021fec26c1b6c8416cb099f4d23654b06959ccf268f2d213f65c2d586a2aae7b3ba6e6479d1f83bfb
|
7
|
+
data.tar.gz: '09f816e9bc2d8aed6e95f414e9859a32996f8b989d41e06519afdd2be72cffe6409c9502e9a57594c9d587fda187a2b218b0bdd46027a0d11e044d4320284842'
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,35 @@
|
|
1
|
+
## 0.41.1 - May 31, 2021
|
2
|
+
- ApiMap handles required bundles (#443)
|
3
|
+
|
4
|
+
## 0.41.0 - May 30, 2021
|
5
|
+
- Chain constant at last double colon with more than two nested namespaces
|
6
|
+
- Fill Integer#times return type (#440)
|
7
|
+
- Validate included modules in type checks (#424)
|
8
|
+
- Faster language server initialization
|
9
|
+
- Server response to initialize is near immediate
|
10
|
+
- Workspace is mapped in a background thread
|
11
|
+
- Supported clients report mapping progress
|
12
|
+
- Log RuboCop corrections at info level (#426)
|
13
|
+
- Allow configuring the version of RuboCop to require (#430)
|
14
|
+
- Fix source of diagnostic (#434)
|
15
|
+
- Fix file argument in RuboCop (#435)
|
16
|
+
- Config ignores directories with .rb extension (#423)
|
17
|
+
|
18
|
+
## 0.40.4 - March 3, 2021
|
19
|
+
- Fix optarg and blockarg ordering
|
20
|
+
- Override specialization for #initialize
|
21
|
+
- Find definitions with cursor after double colon
|
22
|
+
|
23
|
+
## 0.40.3 - February 7, 2021
|
24
|
+
- Simplify and allow to configure rubocop formatter (#403)
|
25
|
+
- Type checker shows tag in param type errors (#398)
|
26
|
+
- Handle bare private_constant (#408)
|
27
|
+
- Type checker handles splatted variables (#396)
|
28
|
+
|
29
|
+
## 0.40.2 - January 18, 2021
|
30
|
+
- Type checker ignores splatted calls in arity (#396)
|
31
|
+
- Allow Parser 3.0 (#400)
|
32
|
+
|
1
33
|
## 0.40.1 - December 28, 2020
|
2
34
|
- Use temp directory for RuboCop formatting (#397)
|
3
35
|
- NodeMethods reads splatted hashes (#396)
|
data/README.md
CHANGED
@@ -79,6 +79,21 @@ Run `bundle install` and use `bundle exec yard gems` to generate the documentati
|
|
79
79
|
|
80
80
|
In order to make sure you're using the correct dependencies, you can start the language server with Bundler. In VS Code, there's a `solargraph.useBundler` option. Other clients will vary, but the command you probably want to run is `bundle exec solargraph socket` or `bundle exec solargraph stdio`.
|
81
81
|
|
82
|
+
### Rubocop Version
|
83
|
+
|
84
|
+
If you have multiple versions of [`rubocop`](https://rubygems.org/gems/rubocop) installed and you would like to choose a version other than the latest to use, this specific version can be configured.
|
85
|
+
|
86
|
+
In `.solargraph.yml`:
|
87
|
+
|
88
|
+
```yaml
|
89
|
+
---
|
90
|
+
reporters:
|
91
|
+
- rubocop:version=0.61.0 # diagnostics
|
92
|
+
formatter:
|
93
|
+
rubocop:
|
94
|
+
version: 0.61.0 # formatting
|
95
|
+
```
|
96
|
+
|
82
97
|
### Integrating Other Editors
|
83
98
|
|
84
99
|
The [language server protocol](https://microsoft.github.io/language-server-protocol/specification) is the recommended way for integrating Solargraph into editors and IDEs. Clients can connect using either stdio or TCP. Language client developers should refer to [https://solargraph.org/guides/language-server](https://solargraph.org/guides/language-server).
|
data/SPONSORS.md
CHANGED
data/lib/.rubocop.yml
CHANGED
data/lib/solargraph.rb
CHANGED
@@ -9,13 +9,14 @@ require 'solargraph/version'
|
|
9
9
|
# static analysis, and language server libraries.
|
10
10
|
#
|
11
11
|
module Solargraph
|
12
|
-
class InvalidOffsetError
|
13
|
-
class DiagnosticsError
|
14
|
-
class FileNotFoundError
|
15
|
-
class SourceNotAvailableError
|
16
|
-
class ComplexTypeError
|
17
|
-
class WorkspaceTooLargeError
|
18
|
-
class BundleNotFoundError
|
12
|
+
class InvalidOffsetError < RangeError; end
|
13
|
+
class DiagnosticsError < RuntimeError; end
|
14
|
+
class FileNotFoundError < RuntimeError; end
|
15
|
+
class SourceNotAvailableError < StandardError; end
|
16
|
+
class ComplexTypeError < StandardError; end
|
17
|
+
class WorkspaceTooLargeError < RuntimeError; end
|
18
|
+
class BundleNotFoundError < StandardError; end
|
19
|
+
class InvalidRubocopVersionError < RuntimeError; end
|
19
20
|
|
20
21
|
autoload :Position, 'solargraph/position'
|
21
22
|
autoload :Range, 'solargraph/range'
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -33,7 +33,12 @@ module Solargraph
|
|
33
33
|
# @param pins [Array<Pin::Base>]
|
34
34
|
# @return [self]
|
35
35
|
def index pins
|
36
|
-
|
36
|
+
# @todo This implementation is incomplete. It should probably create a
|
37
|
+
# Bench.
|
38
|
+
@source_map_hash = {}
|
39
|
+
implicit.clear
|
40
|
+
cache.clear
|
41
|
+
@store = Store.new(yard_map.pins + pins)
|
37
42
|
self
|
38
43
|
end
|
39
44
|
|
@@ -42,97 +47,55 @@ module Solargraph
|
|
42
47
|
# @param source [Source]
|
43
48
|
# @return [self]
|
44
49
|
def map source
|
45
|
-
|
50
|
+
map = Solargraph::SourceMap.map(source)
|
51
|
+
catalog Bench.new(source_maps: [map])
|
46
52
|
self
|
47
53
|
end
|
48
54
|
|
49
|
-
# @param name [String]
|
50
|
-
# @return [YARD::Tags::MacroDirective, nil]
|
51
|
-
def named_macro name
|
52
|
-
store.named_macros[name]
|
53
|
-
end
|
54
|
-
|
55
55
|
# Catalog a bench.
|
56
56
|
#
|
57
57
|
# @param bench [Bench]
|
58
|
-
# @return [self]
|
59
58
|
def catalog bench
|
60
|
-
new_map_hash = {}
|
61
|
-
# Bench always needs to be merged if it adds or removes sources
|
62
|
-
merged = (bench.sources.length == source_map_hash.values.length)
|
63
|
-
bench.sources.each do |source|
|
64
|
-
if source_map_hash.key?(source.filename)
|
65
|
-
if source_map_hash[source.filename].code == source.code &&
|
66
|
-
source_map_hash[source.filename].source.synchronized? &&
|
67
|
-
source.synchronized?
|
68
|
-
new_map_hash[source.filename] = source_map_hash[source.filename]
|
69
|
-
elsif !source.synchronized?
|
70
|
-
new_map_hash[source.filename] = source_map_hash[source.filename]
|
71
|
-
# @todo Smelly instance variable access
|
72
|
-
new_map_hash[source.filename].instance_variable_set(:@source, source)
|
73
|
-
else
|
74
|
-
map = Solargraph::SourceMap.map(source)
|
75
|
-
if source_map_hash[source.filename].try_merge!(map)
|
76
|
-
new_map_hash[source.filename] = source_map_hash[source.filename]
|
77
|
-
else
|
78
|
-
new_map_hash[source.filename] = map
|
79
|
-
merged = false
|
80
|
-
end
|
81
|
-
end
|
82
|
-
else
|
83
|
-
map = Solargraph::SourceMap.map(source)
|
84
|
-
new_map_hash[source.filename] = map
|
85
|
-
merged = false
|
86
|
-
end
|
87
|
-
end
|
88
|
-
return self if bench.pins.empty? && @store && merged
|
89
59
|
implicit.clear
|
60
|
+
@cache.clear
|
61
|
+
@source_map_hash = bench.source_maps.map { |s| [s.filename, s] }.to_h
|
90
62
|
pins = []
|
91
|
-
|
92
|
-
|
93
|
-
|
63
|
+
@required = Set.new
|
64
|
+
local_path_hash.clear
|
65
|
+
source_map_hash.each_value do |map|
|
94
66
|
pins.concat map.pins
|
95
|
-
|
96
|
-
|
97
|
-
pins.concat bench.pins
|
98
|
-
reqs.merge bench.workspace.config.required
|
99
|
-
@required = reqs
|
100
|
-
bench.sources.each do |src|
|
101
|
-
implicit.merge new_map_hash[src.filename].environ
|
67
|
+
@required.merge map.requires.map(&:name)
|
68
|
+
implicit.merge map.environ
|
102
69
|
end
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
else
|
115
|
-
false
|
116
|
-
end
|
117
|
-
end
|
70
|
+
@required.merge implicit.requires
|
71
|
+
external_requires = []
|
72
|
+
@required.each do |req|
|
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
|
118
81
|
end
|
119
82
|
end
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
new_store = Store.new(yard_map.pins + implicit.pins + pins)
|
125
|
-
@cache.clear
|
126
|
-
@source_map_hash = new_map_hash
|
127
|
-
@store = new_store
|
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)
|
86
|
+
@store = Store.new(yard_map.pins + implicit.pins + pins)
|
128
87
|
@unresolved_requires = yard_map.unresolved_requires
|
129
|
-
workspace_filenames.clear
|
130
|
-
workspace_filenames.concat bench.workspace.filenames
|
131
88
|
@rebindable_method_names = nil
|
132
89
|
store.block_pins.each { |blk| blk.rebind(self) }
|
133
90
|
self
|
134
91
|
end
|
135
92
|
|
93
|
+
# @param name [String]
|
94
|
+
# @return [YARD::Tags::MacroDirective, nil]
|
95
|
+
def named_macro name
|
96
|
+
store.named_macros[name]
|
97
|
+
end
|
98
|
+
|
136
99
|
def required
|
137
100
|
@required ||= Set.new
|
138
101
|
end
|
@@ -173,7 +136,10 @@ module Solargraph
|
|
173
136
|
def self.load directory
|
174
137
|
api_map = new
|
175
138
|
workspace = Solargraph::Workspace.new(directory)
|
176
|
-
api_map.catalog Bench.new(workspace: workspace)
|
139
|
+
# api_map.catalog Bench.new(workspace: workspace)
|
140
|
+
library = Library.new(workspace)
|
141
|
+
library.map!
|
142
|
+
api_map.catalog library.bench
|
177
143
|
api_map
|
178
144
|
end
|
179
145
|
|
@@ -531,6 +497,15 @@ module Solargraph
|
|
531
497
|
@yard_map ||= YardMap.new
|
532
498
|
end
|
533
499
|
|
500
|
+
# Check if the host class includes the specified module.
|
501
|
+
#
|
502
|
+
# @param host [String] The class
|
503
|
+
# @param mod [String] The module
|
504
|
+
# @return [Boolean]
|
505
|
+
def type_include?(host, mod)
|
506
|
+
store.get_includes(host).include?(mod)
|
507
|
+
end
|
508
|
+
|
534
509
|
private
|
535
510
|
|
536
511
|
# @return [Array<String>]
|
@@ -544,7 +519,9 @@ module Solargraph
|
|
544
519
|
attr_reader :source_map_hash
|
545
520
|
|
546
521
|
# @return [ApiMap::Store]
|
547
|
-
|
522
|
+
def store
|
523
|
+
@store ||= Store.new
|
524
|
+
end
|
548
525
|
|
549
526
|
# @return [Solargraph::ApiMap::Cache]
|
550
527
|
attr_reader :cache
|
@@ -238,11 +238,16 @@ module Solargraph
|
|
238
238
|
pins_by_class(Pin::Reference::Override).each do |ovr|
|
239
239
|
pin = get_path_pins(ovr.name).first
|
240
240
|
next if pin.nil?
|
241
|
+
new_pin = if pin.path.end_with?('#initialize')
|
242
|
+
get_path_pins(pin.path.sub(/#initialize/, '.new')).first
|
243
|
+
end
|
241
244
|
(ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
|
242
245
|
pin.docstring.delete_tags tag.to_sym
|
246
|
+
new_pin.docstring.delete_tags tag.to_sym if new_pin
|
243
247
|
end
|
244
248
|
ovr.tags.each do |tag|
|
245
249
|
pin.docstring.add_tag(tag)
|
250
|
+
new_pin.docstring.add_tag(tag) if new_pin
|
246
251
|
end
|
247
252
|
end
|
248
253
|
end
|
data/lib/solargraph/bench.rb
CHANGED
@@ -1,30 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'set'
|
4
|
+
|
3
5
|
module Solargraph
|
4
|
-
#
|
5
|
-
# ApiMap.
|
6
|
+
# A container of source maps and gem specs to be cataloged in an ApiMap.
|
6
7
|
#
|
7
8
|
class Bench
|
8
|
-
# @return [
|
9
|
-
attr_reader :
|
9
|
+
# @return [Set<SourceMap>]
|
10
|
+
attr_reader :source_maps
|
10
11
|
|
11
|
-
# @return [
|
12
|
-
attr_reader :
|
12
|
+
# @return [Set<String>]
|
13
|
+
attr_reader :load_paths
|
13
14
|
|
14
|
-
# @return [
|
15
|
-
attr_reader :
|
15
|
+
# @return [Set<String>]
|
16
|
+
attr_reader :gemnames
|
16
17
|
|
17
|
-
# @
|
18
|
-
|
19
|
-
def initialize workspace: Workspace.new, opened: [], pins: []
|
20
|
-
@workspace = workspace
|
21
|
-
@opened = opened
|
22
|
-
@pins = pins
|
23
|
-
end
|
18
|
+
# @return [String]
|
19
|
+
attr_reader :directory
|
24
20
|
|
25
|
-
# @
|
26
|
-
|
27
|
-
|
21
|
+
# @param source_maps [Array<SourceMap>, Set<SourceMap>]
|
22
|
+
# @param load_paths [Array<String>, Set<String>]
|
23
|
+
# @param gemnames [Array<String>, Set<String>]
|
24
|
+
def initialize source_maps: [], load_paths: [], gemnames: [], directory: ''
|
25
|
+
@source_maps = source_maps.to_set
|
26
|
+
@load_paths = load_paths.to_set
|
27
|
+
@gemnames = gemnames.to_set
|
28
|
+
@directory = directory
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
data/lib/solargraph/compat.rb
CHANGED
@@ -1,9 +1,23 @@
|
|
1
|
+
unless Hash.method_defined?(:transform_keys)
|
2
|
+
class Hash
|
3
|
+
def transform_keys &block
|
4
|
+
result = {}
|
5
|
+
each_pair do |k, v|
|
6
|
+
result[block.call(k)] = v
|
7
|
+
end
|
8
|
+
result
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
1
13
|
unless Hash.method_defined?(:transform_values)
|
2
14
|
class Hash
|
3
15
|
def transform_values &block
|
16
|
+
result = {}
|
4
17
|
each_pair do |k, v|
|
5
|
-
|
18
|
+
result[k] = block.call(v)
|
6
19
|
end
|
20
|
+
result
|
7
21
|
end
|
8
22
|
end
|
9
23
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rubocop'
|
4
3
|
require 'stringio'
|
5
4
|
|
6
5
|
module Solargraph
|
@@ -23,6 +22,7 @@ module Solargraph
|
|
23
22
|
# @param _api_map [Solargraph::ApiMap]
|
24
23
|
# @return [Array<Hash>]
|
25
24
|
def diagnose source, _api_map
|
25
|
+
require_rubocop(rubocop_version)
|
26
26
|
options, paths = generate_options(source.filename, source.code)
|
27
27
|
store = RuboCop::ConfigStore.new
|
28
28
|
runner = RuboCop::Runner.new(options, store)
|
@@ -36,6 +36,13 @@ module Solargraph
|
|
36
36
|
|
37
37
|
private
|
38
38
|
|
39
|
+
# Extracts the rubocop version from _args_
|
40
|
+
#
|
41
|
+
# @return [String]
|
42
|
+
def rubocop_version
|
43
|
+
args.find { |a| a =~ /version=/ }.to_s.split('=').last
|
44
|
+
end
|
45
|
+
|
39
46
|
# @param resp [Hash]
|
40
47
|
# @return [Array<Hash>]
|
41
48
|
def make_array resp
|
@@ -57,7 +64,8 @@ module Solargraph
|
|
57
64
|
range: offense_range(off).to_hash,
|
58
65
|
# 1 = Error, 2 = Warning, 3 = Information, 4 = Hint
|
59
66
|
severity: SEVERITIES[off['severity']],
|
60
|
-
source:
|
67
|
+
source: 'rubocop',
|
68
|
+
code: off['cop_name'],
|
61
69
|
message: off['message'].gsub(/^#{off['cop_name']}\:/, '')
|
62
70
|
}
|
63
71
|
end
|
@@ -7,38 +7,37 @@ module Solargraph
|
|
7
7
|
module RubocopHelpers
|
8
8
|
module_function
|
9
9
|
|
10
|
+
# Requires a specific version of rubocop, or the latest installed version
|
11
|
+
# if _version_ is `nil`.
|
12
|
+
#
|
13
|
+
# @param version [String]
|
14
|
+
# @raise [InvalidRubocopVersionError] if _version_ is not installed
|
15
|
+
def require_rubocop(version = nil)
|
16
|
+
begin
|
17
|
+
gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path
|
18
|
+
gem_lib_path = File.join(gem_path, 'lib')
|
19
|
+
$LOAD_PATH.unshift(gem_lib_path) unless $LOAD_PATH.include?(gem_lib_path)
|
20
|
+
rescue Gem::MissingSpecVersionError => e
|
21
|
+
raise InvalidRubocopVersionError,
|
22
|
+
"could not find '#{e.name}' (#{e.requirement}) - "\
|
23
|
+
"did find: [#{e.specs.map { |s| s.version.version }.join(', ')}]"
|
24
|
+
end
|
25
|
+
require 'rubocop'
|
26
|
+
end
|
27
|
+
|
10
28
|
# Generate command-line options for the specified filename and code.
|
11
29
|
#
|
12
30
|
# @param filename [String]
|
13
31
|
# @param code [String]
|
14
32
|
# @return [Array(Array<String>, Array<String>)]
|
15
33
|
def generate_options filename, code
|
16
|
-
args = ['-f', 'j']
|
17
|
-
rubocop_file = find_rubocop_file(filename)
|
18
|
-
args.push('-c', fix_drive_letter(rubocop_file)) unless rubocop_file.nil?
|
19
|
-
args.push filename
|
34
|
+
args = ['-f', 'j', filename]
|
20
35
|
base_options = RuboCop::Options.new
|
21
36
|
options, paths = base_options.parse(args)
|
22
37
|
options[:stdin] = code
|
23
38
|
[options, paths]
|
24
39
|
end
|
25
40
|
|
26
|
-
# Find a RuboCop configuration file in a file's directory tree.
|
27
|
-
#
|
28
|
-
# @param filename [String]
|
29
|
-
# @return [String, nil]
|
30
|
-
def find_rubocop_file filename
|
31
|
-
return nil unless File.exist?(filename)
|
32
|
-
filename = File.realpath(filename)
|
33
|
-
dir = File.dirname(filename)
|
34
|
-
until File.dirname(dir) == dir
|
35
|
-
here = File.join(dir, '.rubocop.yml')
|
36
|
-
return here if File.exist?(here)
|
37
|
-
dir = File.dirname(dir)
|
38
|
-
end
|
39
|
-
nil
|
40
|
-
end
|
41
|
-
|
42
41
|
# RuboCop internally uses capitalized drive letters for Windows paths,
|
43
42
|
# so we need to convert the paths provided to the command.
|
44
43
|
#
|