solargraph 0.40.2 → 0.40.3
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 +6 -0
- data/lib/.rubocop.yml +2 -2
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -20
- data/lib/solargraph/language_server/host.rb +5 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +46 -17
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +1 -1
- data/lib/solargraph/type_checker.rb +23 -20
- data/lib/solargraph/type_checker/checks.rb +5 -1
- data/lib/solargraph/type_checker/rules.rb +5 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +15 -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: 8eaae0cf888e025f51bdbeea3c414f98e7014d416f58e23d29770b4969f1eb5a
|
4
|
+
data.tar.gz: 4d0b4b1d24e81953aa819b83f318767e79ce7d6ed3cfb5f6e4b1fcf6a3b5ffc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 668db64477f7249ad2d9381292e19f4007a28d607eedfb96848bbb9efd55645ec78c705976e31f765d706c47f08243a322594ccf177f54c950432f565f286789
|
7
|
+
data.tar.gz: e0986273bb88005f0471c5837f979507fd8f2d13b9d45c1717e6bd77c3ebfd42c746e87aaf41fdf0271007c31849f8622fe9e5a4974e8a35bd0d9f6a4b8e9e3c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 0.40.3 - February 7, 2021
|
2
|
+
- Simplify and allow to configure rubocop formatter (#403)
|
3
|
+
- Type checker shows tag in param type errors (#398)
|
4
|
+
- Handle bare private_constant (#408)
|
5
|
+
- Type checker handles splatted variables (#396)
|
6
|
+
|
1
7
|
## 0.40.2 - January 18, 2021
|
2
8
|
- Type checker ignores splatted calls in arity (#396)
|
3
9
|
- Allow Parser 3.0 (#400)
|
data/lib/.rubocop.yml
CHANGED
@@ -13,32 +13,13 @@ module Solargraph
|
|
13
13
|
# @param code [String]
|
14
14
|
# @return [Array(Array<String>, Array<String>)]
|
15
15
|
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
|
16
|
+
args = ['-f', 'j', filename]
|
20
17
|
base_options = RuboCop::Options.new
|
21
18
|
options, paths = base_options.parse(args)
|
22
19
|
options[:stdin] = code
|
23
20
|
[options, paths]
|
24
21
|
end
|
25
22
|
|
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
23
|
# RuboCop internally uses capitalized drive letters for Windows paths,
|
43
24
|
# so we need to convert the paths provided to the command.
|
44
25
|
#
|
@@ -494,6 +494,11 @@ module Solargraph
|
|
494
494
|
library.read_text(filename)
|
495
495
|
end
|
496
496
|
|
497
|
+
def formatter_config uri
|
498
|
+
library = library_for(uri)
|
499
|
+
library.workspace.config.formatter
|
500
|
+
end
|
501
|
+
|
497
502
|
# @param uri [String]
|
498
503
|
# @param line [Integer]
|
499
504
|
# @param column [Integer]
|
@@ -11,29 +11,58 @@ module Solargraph
|
|
11
11
|
class Formatting < Base
|
12
12
|
include Solargraph::Diagnostics::RubocopHelpers
|
13
13
|
|
14
|
+
class BlankRubocopFormatter < ::RuboCop::Formatter::BaseFormatter; end
|
15
|
+
|
14
16
|
def process
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
options, paths = RuboCop::Options.new.parse(args)
|
25
|
-
store = RuboCop::ConfigStore.new
|
26
|
-
redirect_stdout { RuboCop::Runner.new(options, store).run(paths) }
|
27
|
-
result = File.read(tempfile)
|
28
|
-
format original, result
|
29
|
-
rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
|
30
|
-
set_error(Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}")
|
31
|
-
end
|
17
|
+
file_uri = params['textDocument']['uri']
|
18
|
+
config = config_for(file_uri)
|
19
|
+
original = host.read_text(file_uri)
|
20
|
+
args = cli_args(file_uri, config)
|
21
|
+
|
22
|
+
options, paths = RuboCop::Options.new.parse(args)
|
23
|
+
options[:stdin] = original
|
24
|
+
redirect_stdout do
|
25
|
+
RuboCop::Runner.new(options, RuboCop::ConfigStore.new).run(paths)
|
32
26
|
end
|
27
|
+
result = options[:stdin]
|
28
|
+
|
29
|
+
format original, result
|
30
|
+
rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
|
31
|
+
set_error(Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}")
|
33
32
|
end
|
34
33
|
|
35
34
|
private
|
36
35
|
|
36
|
+
def config_for(file_uri)
|
37
|
+
conf = host.formatter_config(file_uri)
|
38
|
+
return {} unless conf.is_a?(Hash)
|
39
|
+
|
40
|
+
conf['rubocop'] || {}
|
41
|
+
end
|
42
|
+
|
43
|
+
def cli_args file, config
|
44
|
+
args = [
|
45
|
+
config['cops'] == 'all' ? '--auto-correct-all' : '--auto-correct',
|
46
|
+
'--cache', 'false',
|
47
|
+
'--format', 'Solargraph::LanguageServer::Message::' \
|
48
|
+
'TextDocument::Formatting::BlankRubocopFormatter',
|
49
|
+
]
|
50
|
+
|
51
|
+
['except', 'only'].each do |arg|
|
52
|
+
cops = cop_list(config[arg])
|
53
|
+
args += ["--#{arg}", cops] if cops
|
54
|
+
end
|
55
|
+
|
56
|
+
args += config['extra_args'] if config['extra_args']
|
57
|
+
args + [file]
|
58
|
+
end
|
59
|
+
|
60
|
+
def cop_list(value)
|
61
|
+
value = value.join(',') if value.respond_to?(:join)
|
62
|
+
return nil if value == '' || !value.is_a?(String)
|
63
|
+
value
|
64
|
+
end
|
65
|
+
|
37
66
|
# @param original [String]
|
38
67
|
# @param result [String]
|
39
68
|
# @return [void]
|
@@ -226,7 +226,7 @@ module Solargraph
|
|
226
226
|
|
227
227
|
# @return [void]
|
228
228
|
def process_private_constant
|
229
|
-
|
229
|
+
return unless Parser.is_ast_node?(node.children.last)
|
230
230
|
node.children.last.children[0..-2].each do |child|
|
231
231
|
if [:LIT, :STR].include?(child.type)
|
232
232
|
cn = child.children[0].to_s
|
@@ -129,10 +129,10 @@ module Solargraph
|
|
129
129
|
end
|
130
130
|
end
|
131
131
|
end
|
132
|
-
params.each_pair do |name,
|
133
|
-
type =
|
132
|
+
params.each_pair do |name, data|
|
133
|
+
type = data[:qualified]
|
134
134
|
if type.undefined?
|
135
|
-
result.push Problem.new(pin.location, "Unresolved type #{
|
135
|
+
result.push Problem.new(pin.location, "Unresolved type #{data[:tagged]} for #{name} param on #{pin.path}", pin: pin)
|
136
136
|
end
|
137
137
|
end
|
138
138
|
result
|
@@ -266,12 +266,12 @@ module Solargraph
|
|
266
266
|
result.concat kwarg_problems_for argchain, api_map, block_pin, locals, location, pin, params, idx
|
267
267
|
break
|
268
268
|
else
|
269
|
-
ptype = params[par.name]
|
269
|
+
ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
|
270
270
|
if ptype.nil?
|
271
271
|
# @todo Some level (strong, I guess) should require the param here
|
272
272
|
else
|
273
273
|
argtype = argchain.infer(api_map, block_pin, locals)
|
274
|
-
if argtype.defined? && ptype && !any_types_match?(api_map, ptype, argtype)
|
274
|
+
if argtype.defined? && ptype.defined? && !any_types_match?(api_map, ptype, argtype)
|
275
275
|
result.push Problem.new(location, "Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
276
276
|
end
|
277
277
|
end
|
@@ -299,19 +299,19 @@ module Solargraph
|
|
299
299
|
result.concat kwrestarg_problems_for(api_map, block_pin, locals, location, pin, params, kwargs)
|
300
300
|
else
|
301
301
|
if argchain
|
302
|
-
|
303
|
-
if
|
302
|
+
data = params[par.name]
|
303
|
+
if data.nil?
|
304
304
|
# @todo Some level (strong, I guess) should require the param here
|
305
305
|
else
|
306
|
+
ptype = data[:qualified]
|
307
|
+
next if ptype.undefined?
|
306
308
|
argtype = argchain.infer(api_map, block_pin, locals)
|
307
309
|
if argtype.defined? && ptype && !any_types_match?(api_map, ptype, argtype)
|
308
310
|
result.push Problem.new(location, "Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
309
311
|
end
|
310
312
|
end
|
311
|
-
|
312
|
-
|
313
|
-
result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
314
|
-
end
|
313
|
+
elsif par.decl == :kwarg
|
314
|
+
result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
315
315
|
end
|
316
316
|
end
|
317
317
|
end
|
@@ -321,14 +321,11 @@ module Solargraph
|
|
321
321
|
def kwrestarg_problems_for(api_map, block_pin, locals, location, pin, params, kwargs)
|
322
322
|
result = []
|
323
323
|
kwargs.each_pair do |pname, argchain|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
if argtype.defined? && ptype && !any_types_match?(api_map, ptype, argtype)
|
330
|
-
result.push Problem.new(location, "Wrong argument type for #{pin.path}: #{pname} expected #{ptype}, received #{argtype}")
|
331
|
-
end
|
324
|
+
next unless params.key?(pname.to_s)
|
325
|
+
ptype = params[pname.to_s][:qualified]
|
326
|
+
argtype = argchain.infer(api_map, block_pin, locals)
|
327
|
+
if argtype.defined? && ptype && !any_types_match?(api_map, ptype, argtype)
|
328
|
+
result.push Problem.new(location, "Wrong argument type for #{pin.path}: #{pname} expected #{ptype}, received #{argtype}")
|
332
329
|
end
|
333
330
|
end
|
334
331
|
result
|
@@ -342,7 +339,10 @@ module Solargraph
|
|
342
339
|
result = {}
|
343
340
|
tags.each do |tag|
|
344
341
|
next if tag.types.nil? || tag.types.empty?
|
345
|
-
result[tag.name.to_s] =
|
342
|
+
result[tag.name.to_s] = {
|
343
|
+
tagged: tag.types.join(', '),
|
344
|
+
qualified: Solargraph::ComplexType.try_parse(*tag.types).qualify(api_map, pin.full_context.namespace)
|
345
|
+
}
|
346
346
|
end
|
347
347
|
result
|
348
348
|
end
|
@@ -450,6 +450,9 @@ module Solargraph
|
|
450
450
|
if unchecked.length == req + opt + 1 && unchecked.last.links.last.is_a?(Source::Chain::BlockVariable)
|
451
451
|
return []
|
452
452
|
end
|
453
|
+
if req + add_params + 1 == unchecked.length && splatted_call?(unchecked.last.node) && (pin.parameters.map(&:decl) & [:kwarg, :kwoptarg, :kwrestarg]).any?
|
454
|
+
return []
|
455
|
+
end
|
453
456
|
return [Problem.new(location, "Too many arguments to #{pin.path}")]
|
454
457
|
elsif unchecked.length < req - settled_kwargs && (arguments.empty? || !arguments.last.splat?)
|
455
458
|
return [Problem.new(location, "Not enough arguments to #{pin.path}")]
|
@@ -1,5 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Solargraph
|
2
4
|
class TypeChecker
|
5
|
+
# Helper methods for performing type checks
|
6
|
+
#
|
3
7
|
module Checks
|
4
8
|
module_function
|
5
9
|
|
@@ -62,7 +66,7 @@ module Solargraph
|
|
62
66
|
# @param inferred [ComplexType]
|
63
67
|
# @return [Boolean]
|
64
68
|
def duck_types_match? api_map, expected, inferred
|
65
|
-
raise ArgumentError,
|
69
|
+
raise ArgumentError, 'Expected type must be duck type' unless expected.duck_type?
|
66
70
|
expected.each do |exp|
|
67
71
|
next unless exp.duck_type?
|
68
72
|
quack = exp.to_s[1..-1]
|
@@ -1,12 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Solargraph
|
2
4
|
class TypeChecker
|
5
|
+
# Definitions of type checking rules to be performed at various levels
|
6
|
+
#
|
3
7
|
class Rules
|
4
8
|
LEVELS = {
|
5
9
|
normal: 0,
|
6
10
|
typed: 1,
|
7
11
|
strict: 2,
|
8
12
|
strong: 3
|
9
|
-
}
|
13
|
+
}.freeze
|
10
14
|
|
11
15
|
# @return [Symbol]
|
12
16
|
attr_reader :level
|
data/lib/solargraph/version.rb
CHANGED
@@ -85,6 +85,13 @@ module Solargraph
|
|
85
85
|
raw_data['reporters']
|
86
86
|
end
|
87
87
|
|
88
|
+
# A hash of options supported by the formatter
|
89
|
+
#
|
90
|
+
# @return [Hash]
|
91
|
+
def formatter
|
92
|
+
raw_data['formatter']
|
93
|
+
end
|
94
|
+
|
88
95
|
# An array of plugins to require.
|
89
96
|
#
|
90
97
|
# @return [Array<String>]
|
@@ -144,6 +151,14 @@ module Solargraph
|
|
144
151
|
'require' => [],
|
145
152
|
'domains' => [],
|
146
153
|
'reporters' => %w[rubocop require_not_found],
|
154
|
+
'formatter' => {
|
155
|
+
'rubocop' => {
|
156
|
+
'cops' => 'safe',
|
157
|
+
'except' => [],
|
158
|
+
'only' => [],
|
159
|
+
'extra_args' =>[]
|
160
|
+
}
|
161
|
+
},
|
147
162
|
'require_paths' => [],
|
148
163
|
'plugins' => [],
|
149
164
|
'max_files' => MAX_FILES
|
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.40.
|
4
|
+
version: 0.40.3
|
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-02-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backport
|