solargraph 0.40.2 → 0.41.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +15 -0
- data/SPONSORS.md +1 -0
- data/lib/.rubocop.yml +2 -2
- 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/host/diagnoser.rb +9 -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/rubyvm/node_chainer.rb +0 -1
- 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 +25 -22
- 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
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4533d6cac061c01e292b70313f68a9de816c8af4ca6d34ddf7bde467d0428b0
|
4
|
+
data.tar.gz: 1fd4959f4e1652c8725fcc79f5da92df9f91a90eb5462879f87c30c0c8f2ada2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48b7f57a7b84140cb4ff9b1f2428fb1dfe2c814ef9fca26585bec17ea61a122a8755ab60e8da52969942c5ab674501332f6fc0655fcceb77606f1ab353899a4b
|
7
|
+
data.tar.gz: cd817d200a9579e66f612a100b17096fb56eb468c356de4c75d7c5d0f5621f6e734596f9babe809398f26bd2bcc2226bf424215393fe03626adf03f856eb24b9
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,35 @@
|
|
1
|
+
## 0.41.2 - June 9, 2021
|
2
|
+
- Rescue InvalidOffset in async diagnosis
|
3
|
+
- Remove erroneous escaping from Hover
|
4
|
+
|
5
|
+
## 0.41.1 - May 31, 2021
|
6
|
+
- ApiMap handles required bundles (#443)
|
7
|
+
|
8
|
+
## 0.41.0 - May 30, 2021
|
9
|
+
- Chain constant at last double colon with more than two nested namespaces
|
10
|
+
- Fill Integer#times return type (#440)
|
11
|
+
- Validate included modules in type checks (#424)
|
12
|
+
- Faster language server initialization
|
13
|
+
- Server response to initialize is near immediate
|
14
|
+
- Workspace is mapped in a background thread
|
15
|
+
- Supported clients report mapping progress
|
16
|
+
- Log RuboCop corrections at info level (#426)
|
17
|
+
- Allow configuring the version of RuboCop to require (#430)
|
18
|
+
- Fix source of diagnostic (#434)
|
19
|
+
- Fix file argument in RuboCop (#435)
|
20
|
+
- Config ignores directories with .rb extension (#423)
|
21
|
+
|
22
|
+
## 0.40.4 - March 3, 2021
|
23
|
+
- Fix optarg and blockarg ordering
|
24
|
+
- Override specialization for #initialize
|
25
|
+
- Find definitions with cursor after double colon
|
26
|
+
|
27
|
+
## 0.40.3 - February 7, 2021
|
28
|
+
- Simplify and allow to configure rubocop formatter (#403)
|
29
|
+
- Type checker shows tag in param type errors (#398)
|
30
|
+
- Handle bare private_constant (#408)
|
31
|
+
- Type checker handles splatted variables (#396)
|
32
|
+
|
1
33
|
## 0.40.2 - January 18, 2021
|
2
34
|
- Type checker ignores splatted calls in arity (#396)
|
3
35
|
- Allow Parser 3.0 (#400)
|
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
|
#
|