steep-relaxed 1.9.3.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 +7 -0
- data/.gitignore +13 -0
- data/.gitmodules +0 -0
- data/CHANGELOG.md +1032 -0
- data/LICENSE +21 -0
- data/README.md +260 -0
- data/Rakefile +227 -0
- data/STDGEM_DEPENDENCIES.txt +59 -0
- data/Steepfile +68 -0
- data/bin/console +14 -0
- data/bin/generate-diagnostics-docs.rb +112 -0
- data/bin/mem_graph.rb +67 -0
- data/bin/mem_prof.rb +102 -0
- data/bin/output_rebaseline.rb +34 -0
- data/bin/output_test.rb +60 -0
- data/bin/rbs +20 -0
- data/bin/rbs-inline +19 -0
- data/bin/setup +9 -0
- data/bin/stackprof_test.rb +19 -0
- data/bin/steep +19 -0
- data/bin/steep-check.rb +251 -0
- data/bin/steep-prof +16 -0
- data/doc/narrowing.md +195 -0
- data/doc/shape.md +194 -0
- data/exe/steep +18 -0
- data/guides/README.md +5 -0
- data/guides/src/gem-rbs-collection/gem-rbs-collection.md +126 -0
- data/guides/src/getting-started/getting-started.md +163 -0
- data/guides/src/nil-optional/nil-optional.md +195 -0
- data/lib/steep/annotation_parser.rb +199 -0
- data/lib/steep/ast/annotation/collection.rb +172 -0
- data/lib/steep/ast/annotation.rb +137 -0
- data/lib/steep/ast/builtin.rb +104 -0
- data/lib/steep/ast/ignore.rb +148 -0
- data/lib/steep/ast/node/type_application.rb +88 -0
- data/lib/steep/ast/node/type_assertion.rb +81 -0
- data/lib/steep/ast/types/any.rb +35 -0
- data/lib/steep/ast/types/boolean.rb +45 -0
- data/lib/steep/ast/types/bot.rb +35 -0
- data/lib/steep/ast/types/class.rb +43 -0
- data/lib/steep/ast/types/factory.rb +557 -0
- data/lib/steep/ast/types/helper.rb +40 -0
- data/lib/steep/ast/types/instance.rb +42 -0
- data/lib/steep/ast/types/intersection.rb +93 -0
- data/lib/steep/ast/types/literal.rb +59 -0
- data/lib/steep/ast/types/logic.rb +84 -0
- data/lib/steep/ast/types/name.rb +128 -0
- data/lib/steep/ast/types/nil.rb +41 -0
- data/lib/steep/ast/types/proc.rb +117 -0
- data/lib/steep/ast/types/record.rb +79 -0
- data/lib/steep/ast/types/self.rb +43 -0
- data/lib/steep/ast/types/shared_instance.rb +11 -0
- data/lib/steep/ast/types/top.rb +35 -0
- data/lib/steep/ast/types/tuple.rb +60 -0
- data/lib/steep/ast/types/union.rb +97 -0
- data/lib/steep/ast/types/var.rb +65 -0
- data/lib/steep/ast/types/void.rb +35 -0
- data/lib/steep/cli.rb +401 -0
- data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
- data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
- data/lib/steep/diagnostic/helper.rb +18 -0
- data/lib/steep/diagnostic/lsp_formatter.rb +78 -0
- data/lib/steep/diagnostic/result_printer2.rb +48 -0
- data/lib/steep/diagnostic/ruby.rb +1221 -0
- data/lib/steep/diagnostic/signature.rb +570 -0
- data/lib/steep/drivers/annotations.rb +52 -0
- data/lib/steep/drivers/check.rb +339 -0
- data/lib/steep/drivers/checkfile.rb +210 -0
- data/lib/steep/drivers/diagnostic_printer.rb +105 -0
- data/lib/steep/drivers/init.rb +66 -0
- data/lib/steep/drivers/langserver.rb +56 -0
- data/lib/steep/drivers/print_project.rb +113 -0
- data/lib/steep/drivers/stats.rb +203 -0
- data/lib/steep/drivers/utils/driver_helper.rb +143 -0
- data/lib/steep/drivers/utils/jobs_option.rb +26 -0
- data/lib/steep/drivers/vendor.rb +27 -0
- data/lib/steep/drivers/watch.rb +194 -0
- data/lib/steep/drivers/worker.rb +58 -0
- data/lib/steep/equatable.rb +23 -0
- data/lib/steep/expectations.rb +228 -0
- data/lib/steep/index/rbs_index.rb +350 -0
- data/lib/steep/index/signature_symbol_provider.rb +185 -0
- data/lib/steep/index/source_index.rb +167 -0
- data/lib/steep/interface/block.rb +103 -0
- data/lib/steep/interface/builder.rb +843 -0
- data/lib/steep/interface/function.rb +1090 -0
- data/lib/steep/interface/method_type.rb +330 -0
- data/lib/steep/interface/shape.rb +239 -0
- data/lib/steep/interface/substitution.rb +159 -0
- data/lib/steep/interface/type_param.rb +115 -0
- data/lib/steep/located_value.rb +20 -0
- data/lib/steep/method_name.rb +42 -0
- data/lib/steep/module_helper.rb +24 -0
- data/lib/steep/node_helper.rb +273 -0
- data/lib/steep/path_helper.rb +30 -0
- data/lib/steep/project/dsl.rb +268 -0
- data/lib/steep/project/group.rb +31 -0
- data/lib/steep/project/options.rb +63 -0
- data/lib/steep/project/pattern.rb +59 -0
- data/lib/steep/project/target.rb +92 -0
- data/lib/steep/project.rb +78 -0
- data/lib/steep/rake_task.rb +132 -0
- data/lib/steep/range_extension.rb +29 -0
- data/lib/steep/server/base_worker.rb +97 -0
- data/lib/steep/server/change_buffer.rb +73 -0
- data/lib/steep/server/custom_methods.rb +77 -0
- data/lib/steep/server/delay_queue.rb +45 -0
- data/lib/steep/server/interaction_worker.rb +492 -0
- data/lib/steep/server/lsp_formatter.rb +455 -0
- data/lib/steep/server/master.rb +922 -0
- data/lib/steep/server/target_group_files.rb +205 -0
- data/lib/steep/server/type_check_controller.rb +366 -0
- data/lib/steep/server/type_check_worker.rb +303 -0
- data/lib/steep/server/work_done_progress.rb +64 -0
- data/lib/steep/server/worker_process.rb +176 -0
- data/lib/steep/services/completion_provider.rb +802 -0
- data/lib/steep/services/content_change.rb +61 -0
- data/lib/steep/services/file_loader.rb +74 -0
- data/lib/steep/services/goto_service.rb +441 -0
- data/lib/steep/services/hover_provider/rbs.rb +88 -0
- data/lib/steep/services/hover_provider/ruby.rb +221 -0
- data/lib/steep/services/hover_provider/singleton_methods.rb +20 -0
- data/lib/steep/services/path_assignment.rb +46 -0
- data/lib/steep/services/signature_help_provider.rb +202 -0
- data/lib/steep/services/signature_service.rb +428 -0
- data/lib/steep/services/stats_calculator.rb +68 -0
- data/lib/steep/services/type_check_service.rb +394 -0
- data/lib/steep/services/type_name_completion.rb +236 -0
- data/lib/steep/signature/validator.rb +651 -0
- data/lib/steep/source/ignore_ranges.rb +69 -0
- data/lib/steep/source.rb +691 -0
- data/lib/steep/subtyping/cache.rb +30 -0
- data/lib/steep/subtyping/check.rb +1113 -0
- data/lib/steep/subtyping/constraints.rb +341 -0
- data/lib/steep/subtyping/relation.rb +101 -0
- data/lib/steep/subtyping/result.rb +324 -0
- data/lib/steep/subtyping/variable_variance.rb +89 -0
- data/lib/steep/test.rb +9 -0
- data/lib/steep/thread_waiter.rb +43 -0
- data/lib/steep/type_construction.rb +5183 -0
- data/lib/steep/type_inference/block_params.rb +416 -0
- data/lib/steep/type_inference/case_when.rb +303 -0
- data/lib/steep/type_inference/constant_env.rb +56 -0
- data/lib/steep/type_inference/context.rb +195 -0
- data/lib/steep/type_inference/logic_type_interpreter.rb +613 -0
- data/lib/steep/type_inference/method_call.rb +193 -0
- data/lib/steep/type_inference/method_params.rb +531 -0
- data/lib/steep/type_inference/multiple_assignment.rb +194 -0
- data/lib/steep/type_inference/send_args.rb +712 -0
- data/lib/steep/type_inference/type_env.rb +341 -0
- data/lib/steep/type_inference/type_env_builder.rb +138 -0
- data/lib/steep/typing.rb +321 -0
- data/lib/steep/version.rb +3 -0
- data/lib/steep.rb +369 -0
- data/manual/annotations.md +181 -0
- data/manual/ignore.md +20 -0
- data/manual/ruby-diagnostics.md +1879 -0
- data/sample/Steepfile +22 -0
- data/sample/lib/conference.rb +49 -0
- data/sample/lib/length.rb +35 -0
- data/sample/sig/conference.rbs +42 -0
- data/sample/sig/generics.rbs +15 -0
- data/sample/sig/length.rbs +34 -0
- data/steep-relaxed.gemspec +56 -0
- metadata +340 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Tuple
|
5
|
+
attr_reader :types
|
6
|
+
|
7
|
+
def initialize(types:)
|
8
|
+
@types = types
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
other.is_a?(Tuple) &&
|
13
|
+
other.types == types
|
14
|
+
end
|
15
|
+
|
16
|
+
def hash
|
17
|
+
self.class.hash ^ types.hash
|
18
|
+
end
|
19
|
+
|
20
|
+
alias eql? ==
|
21
|
+
|
22
|
+
def subst(s)
|
23
|
+
self.class.new(types: types.map {|ty| ty.subst(s) })
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
"[#{types.join(", ")}]"
|
28
|
+
end
|
29
|
+
|
30
|
+
def free_variables()
|
31
|
+
@fvs ||= each_child.with_object(Set[]) do |type, set| #$ Set[variable]
|
32
|
+
set.merge(type.free_variables)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
include Helper::ChildrenLevel
|
37
|
+
|
38
|
+
def each_child(&block)
|
39
|
+
if block
|
40
|
+
types.each(&block)
|
41
|
+
else
|
42
|
+
types.each
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def map_type(&block)
|
47
|
+
Tuple.new(types: types.map(&block))
|
48
|
+
end
|
49
|
+
|
50
|
+
def level
|
51
|
+
[0] + level_of_children(types)
|
52
|
+
end
|
53
|
+
|
54
|
+
def with_location(new_location)
|
55
|
+
self.class.new(types: types)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Union
|
5
|
+
attr_reader :types
|
6
|
+
|
7
|
+
def initialize(types:)
|
8
|
+
@types = types
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.build(types:)
|
12
|
+
return AST::Types::Bot.instance if types.empty?
|
13
|
+
if types.size == 1
|
14
|
+
return types.first || raise
|
15
|
+
end
|
16
|
+
|
17
|
+
types.flat_map do |type|
|
18
|
+
if type.is_a?(Union)
|
19
|
+
type.types
|
20
|
+
else
|
21
|
+
[type]
|
22
|
+
end
|
23
|
+
end.map do |type|
|
24
|
+
case type
|
25
|
+
when AST::Types::Any
|
26
|
+
return AST::Types::Any.instance()
|
27
|
+
when AST::Types::Top
|
28
|
+
return AST::Types::Top.instance
|
29
|
+
when AST::Types::Bot
|
30
|
+
nil
|
31
|
+
else
|
32
|
+
type
|
33
|
+
end
|
34
|
+
end.compact.uniq.yield_self do |tys|
|
35
|
+
case tys.size
|
36
|
+
when 0
|
37
|
+
AST::Types::Bot.instance
|
38
|
+
when 1
|
39
|
+
tys.first || raise
|
40
|
+
else
|
41
|
+
new(types: tys)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def ==(other)
|
47
|
+
other.is_a?(Union) &&
|
48
|
+
Set.new(other.types) == Set.new(types)
|
49
|
+
end
|
50
|
+
|
51
|
+
def hash
|
52
|
+
@hash ||= types.inject(self.class.hash) {|c, type| type.hash ^ c } #$ Integer
|
53
|
+
end
|
54
|
+
|
55
|
+
alias eql? ==
|
56
|
+
|
57
|
+
def subst(s)
|
58
|
+
self.class.build(types: types.map {|ty| ty.subst(s) })
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
"(#{types.map(&:to_s).join(" | ")})"
|
63
|
+
end
|
64
|
+
|
65
|
+
def free_variables
|
66
|
+
@fvs ||= Set.new.tap do |set|
|
67
|
+
types.each do |type|
|
68
|
+
set.merge(type.free_variables)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def each_child(&block)
|
74
|
+
if block
|
75
|
+
types.each(&block)
|
76
|
+
else
|
77
|
+
types.each
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def map_type(&block)
|
82
|
+
Union.build(types: types.map(&block))
|
83
|
+
end
|
84
|
+
|
85
|
+
include Helper::ChildrenLevel
|
86
|
+
|
87
|
+
def level
|
88
|
+
[0] + level_of_children(types)
|
89
|
+
end
|
90
|
+
|
91
|
+
def with_location(new_location)
|
92
|
+
self.class.new(types: types)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Var
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(name:)
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
other.is_a?(Var) &&
|
13
|
+
other.name == name
|
14
|
+
end
|
15
|
+
|
16
|
+
def hash
|
17
|
+
self.class.hash ^ name.hash
|
18
|
+
end
|
19
|
+
|
20
|
+
alias eql? ==
|
21
|
+
|
22
|
+
def self.fresh_name(name)
|
23
|
+
@mutex ||= Thread::Mutex.new
|
24
|
+
|
25
|
+
@mutex.synchronize do
|
26
|
+
@max ||= 0
|
27
|
+
@max += 1
|
28
|
+
|
29
|
+
:"#{name}(#{@max})"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.fresh(name, location: nil)
|
34
|
+
new(name: fresh_name(name))
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
name.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
def subst(s)
|
42
|
+
if s.key?(name)
|
43
|
+
s[name]
|
44
|
+
else
|
45
|
+
self
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def free_variables()
|
50
|
+
@fvs ||= Set.new([name])
|
51
|
+
end
|
52
|
+
|
53
|
+
include Helper::NoChild
|
54
|
+
|
55
|
+
def level
|
56
|
+
[0]
|
57
|
+
end
|
58
|
+
|
59
|
+
def update(name: self.name)
|
60
|
+
self.class.new(name: name)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Void
|
5
|
+
extend SharedInstance
|
6
|
+
|
7
|
+
def ==(other)
|
8
|
+
other.is_a?(Void)
|
9
|
+
end
|
10
|
+
|
11
|
+
def hash
|
12
|
+
self.class.hash
|
13
|
+
end
|
14
|
+
|
15
|
+
alias eql? ==
|
16
|
+
|
17
|
+
def subst(s)
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"void"
|
23
|
+
end
|
24
|
+
|
25
|
+
include Helper::NoFreeVariables
|
26
|
+
|
27
|
+
include Helper::NoChild
|
28
|
+
|
29
|
+
def level
|
30
|
+
[0]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/steep/cli.rb
ADDED
@@ -0,0 +1,401 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Steep
|
4
|
+
class CLI
|
5
|
+
attr_reader :argv
|
6
|
+
attr_reader :stdout
|
7
|
+
attr_reader :stdin
|
8
|
+
attr_reader :stderr
|
9
|
+
attr_reader :command
|
10
|
+
|
11
|
+
def initialize(stdout:, stdin:, stderr:, argv:)
|
12
|
+
@stdout = stdout
|
13
|
+
@stdin = stdin
|
14
|
+
@stderr = stderr
|
15
|
+
@argv = argv
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.available_commands
|
19
|
+
[:init, :check, :validate, :annotations, :version, :project, :watch, :langserver, :stats, :binstub, :checkfile]
|
20
|
+
end
|
21
|
+
|
22
|
+
def process_global_options
|
23
|
+
OptionParser.new do |opts|
|
24
|
+
opts.banner = <<~USAGE
|
25
|
+
Usage: steep [options]
|
26
|
+
|
27
|
+
available commands: #{CLI.available_commands.join(', ')}
|
28
|
+
|
29
|
+
Options:
|
30
|
+
USAGE
|
31
|
+
|
32
|
+
opts.on("--version") do
|
33
|
+
process_version
|
34
|
+
exit 0
|
35
|
+
end
|
36
|
+
|
37
|
+
handle_logging_options(opts)
|
38
|
+
end.order!(argv)
|
39
|
+
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def setup_command
|
44
|
+
return false unless command = argv.shift&.to_sym
|
45
|
+
@command = command
|
46
|
+
|
47
|
+
if CLI.available_commands.include?(@command) || @command == :worker || @command == :vendor
|
48
|
+
true
|
49
|
+
else
|
50
|
+
stderr.puts "Unknown command: #{command}"
|
51
|
+
stderr.puts " available commands: #{CLI.available_commands.join(', ')}"
|
52
|
+
false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def run
|
57
|
+
process_global_options or return 1
|
58
|
+
setup_command or return 1
|
59
|
+
|
60
|
+
__send__(:"process_#{command}")
|
61
|
+
end
|
62
|
+
|
63
|
+
def handle_logging_options(opts)
|
64
|
+
opts.on("--log-level=LEVEL", "Specify log level: debug, info, warn, error, fatal") do |level|
|
65
|
+
Steep.logger.level = level
|
66
|
+
Steep.ui_logger.level = level
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("--log-output=PATH", "Print logs to given path") do |file|
|
70
|
+
Steep.log_output = file
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on("--verbose", "Set log level to debug") do
|
74
|
+
Steep.logger.level = Logger::DEBUG
|
75
|
+
Steep.ui_logger.level = Logger::DEBUG
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def handle_jobs_option(option, opts)
|
80
|
+
opts.on("-j N", "--jobs=N", "Specify the number of type check workers (defaults: #{option.default_jobs_count})") do |count|
|
81
|
+
option.jobs_count = Integer(count) if Integer(count) > 0
|
82
|
+
end
|
83
|
+
|
84
|
+
opts.on("--steep-command=COMMAND", "Specify command to exec Steep CLI for worker (defaults: steep)") do |cmd|
|
85
|
+
option.steep_command = cmd
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def setup_jobs_for_ci(jobs_option)
|
90
|
+
if ENV["CI"]
|
91
|
+
unless jobs_option.jobs_count
|
92
|
+
stderr.puts Rainbow("CI environment is detected but no `--jobs` option is given.").yellow
|
93
|
+
stderr.puts " Using `[2, #{jobs_option.default_jobs_count} (# or processors)].min` to avoid hitting memory limit."
|
94
|
+
stderr.puts " Specify `--jobs` option to increase the number of jobs."
|
95
|
+
|
96
|
+
jobs_option.jobs_count = [2, jobs_option.default_jobs_count].min
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def process_init
|
102
|
+
Drivers::Init.new(stdout: stdout, stderr: stderr).tap do |command|
|
103
|
+
OptionParser.new do |opts|
|
104
|
+
opts.banner = "Usage: steep init [options]"
|
105
|
+
|
106
|
+
opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
|
107
|
+
opts.on("--force") { command.force_write = true }
|
108
|
+
|
109
|
+
handle_logging_options opts
|
110
|
+
end.parse!(argv)
|
111
|
+
end.run()
|
112
|
+
end
|
113
|
+
|
114
|
+
def process_check
|
115
|
+
Drivers::Check.new(stdout: stdout, stderr: stderr).tap do |command|
|
116
|
+
OptionParser.new do |opts|
|
117
|
+
opts.banner = "Usage: steep check [options] [sources]"
|
118
|
+
|
119
|
+
opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
|
120
|
+
opts.on("--with-expectations[=PATH]", "Type check with expectations saved in PATH (or steep_expectations.yml)") do |path|
|
121
|
+
command.with_expectations_path = Pathname(path || "steep_expectations.yml")
|
122
|
+
end
|
123
|
+
opts.on("--save-expectations[=PATH]", "Save expectations with current type check result to PATH (or steep_expectations.yml)") do |path|
|
124
|
+
command.save_expectations_path = Pathname(path || "steep_expectations.yml")
|
125
|
+
end
|
126
|
+
opts.on("--severity-level=LEVEL", /^error|warning|information|hint$/, "Specify the minimum diagnostic severity to be recognized as an error (defaults: warning): error, warning, information, or hint") do |level|
|
127
|
+
command.severity_level = level.to_sym
|
128
|
+
end
|
129
|
+
|
130
|
+
opts.on("--group=GROUP", "Specify target/group name to type check") do |arg|
|
131
|
+
# @type var arg: String
|
132
|
+
target, group = arg.split(".")
|
133
|
+
target or raise
|
134
|
+
case group
|
135
|
+
when "*"
|
136
|
+
command.active_group_names << [target.to_sym, true]
|
137
|
+
when nil
|
138
|
+
command.active_group_names << [target.to_sym, nil]
|
139
|
+
else
|
140
|
+
command.active_group_names << [target.to_sym, group.to_sym]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
opts.on("--[no-]type-check", "Type check Ruby code") do |v|
|
145
|
+
command.type_check_code = v ? true : false
|
146
|
+
end
|
147
|
+
|
148
|
+
opts.on("--validate=OPTION", ["skip", "group", "project", "library"], "Validation levels of signatures (default: group, options: skip,group,project,library)") do |level|
|
149
|
+
case level
|
150
|
+
when "skip"
|
151
|
+
command.validate_group_signatures = false
|
152
|
+
command.validate_project_signatures = false
|
153
|
+
command.validate_library_signatures = false
|
154
|
+
when "group"
|
155
|
+
command.validate_group_signatures = true
|
156
|
+
command.validate_project_signatures = false
|
157
|
+
command.validate_library_signatures = false
|
158
|
+
when "project"
|
159
|
+
command.validate_group_signatures = true
|
160
|
+
command.validate_project_signatures = true
|
161
|
+
command.validate_library_signatures = false
|
162
|
+
when "library"
|
163
|
+
command.validate_group_signatures = true
|
164
|
+
command.validate_project_signatures = true
|
165
|
+
command.validate_library_signatures = true
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
handle_jobs_option command.jobs_option, opts
|
170
|
+
handle_logging_options opts
|
171
|
+
end.parse!(argv)
|
172
|
+
|
173
|
+
setup_jobs_for_ci(command.jobs_option)
|
174
|
+
|
175
|
+
command.command_line_patterns.push *argv
|
176
|
+
end.run
|
177
|
+
end
|
178
|
+
|
179
|
+
def process_checkfile
|
180
|
+
Drivers::Checkfile.new(stdout: stdout, stderr: stderr).tap do |command|
|
181
|
+
OptionParser.new do |opts|
|
182
|
+
opts.banner = "Usage: steep checkfile [options] [files]"
|
183
|
+
|
184
|
+
opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
|
185
|
+
opts.on("--all-rbs", "Type check all RBS files") { command.all_rbs = true }
|
186
|
+
opts.on("--all-ruby", "Type check all Ruby files") { command.all_ruby = true }
|
187
|
+
opts.on("--stdin", "Read files to type check from stdin") do
|
188
|
+
while line = stdin.gets()
|
189
|
+
object = JSON.parse(line, symbolize_names: true)
|
190
|
+
Steep.logger.info { "Loading content of `#{object[:path]}` from stdin: #{object[:content].lines[0].chomp}" }
|
191
|
+
command.stdin_input[Pathname(object[:path])] = object[:content]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
handle_jobs_option command.jobs_option, opts
|
195
|
+
handle_logging_options opts
|
196
|
+
end.parse!(argv)
|
197
|
+
|
198
|
+
setup_jobs_for_ci(command.jobs_option)
|
199
|
+
|
200
|
+
command.command_line_args.push *argv
|
201
|
+
end.run
|
202
|
+
end
|
203
|
+
|
204
|
+
def process_stats
|
205
|
+
Drivers::Stats.new(stdout: stdout, stderr: stderr).tap do |command|
|
206
|
+
OptionParser.new do |opts|
|
207
|
+
opts.banner = "Usage: steep stats [options] [sources]"
|
208
|
+
|
209
|
+
opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
|
210
|
+
opts.on("--format=FORMAT", "Specify output format: csv, table") {|format| command.format = format }
|
211
|
+
handle_jobs_option command.jobs_option, opts
|
212
|
+
handle_logging_options opts
|
213
|
+
end.parse!(argv)
|
214
|
+
|
215
|
+
setup_jobs_for_ci(command.jobs_option)
|
216
|
+
|
217
|
+
command.command_line_patterns.push *argv
|
218
|
+
end.run
|
219
|
+
end
|
220
|
+
|
221
|
+
def process_validate
|
222
|
+
stderr.puts "`steep validate` is deprecated. Use `steep check` with `--validate` option instead."
|
223
|
+
1
|
224
|
+
end
|
225
|
+
|
226
|
+
def process_annotations
|
227
|
+
Drivers::Annotations.new(stdout: stdout, stderr: stderr).tap do |command|
|
228
|
+
OptionParser.new do |opts|
|
229
|
+
opts.banner = "Usage: steep annotations [options] [sources]"
|
230
|
+
handle_logging_options opts
|
231
|
+
end.parse!(argv)
|
232
|
+
|
233
|
+
command.command_line_patterns.push *argv
|
234
|
+
end.run
|
235
|
+
end
|
236
|
+
|
237
|
+
def process_project
|
238
|
+
Drivers::PrintProject.new(stdout: stdout, stderr: stderr).tap do |command|
|
239
|
+
OptionParser.new do |opts|
|
240
|
+
opts.banner = "Usage: steep project [options]"
|
241
|
+
opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
|
242
|
+
opts.on("--[no-]print-files", "Print files") {|v|
|
243
|
+
command.print_files = v ? true : false
|
244
|
+
}
|
245
|
+
handle_logging_options opts
|
246
|
+
end.parse!(argv)
|
247
|
+
end.run
|
248
|
+
end
|
249
|
+
|
250
|
+
def process_watch
|
251
|
+
Drivers::Watch.new(stdout: stdout, stderr: stderr).tap do |command|
|
252
|
+
OptionParser.new do |opts|
|
253
|
+
opts.banner = "Usage: steep watch [options] [dirs]"
|
254
|
+
opts.on("--severity-level=LEVEL", /^error|warning|information|hint$/, "Specify the minimum diagnostic severity to be recognized as an error (defaults: warning): error, warning, information, or hint") do |level|
|
255
|
+
# @type var level: String
|
256
|
+
command.severity_level = _ = level.to_sym
|
257
|
+
end
|
258
|
+
handle_jobs_option command.jobs_option, opts
|
259
|
+
handle_logging_options opts
|
260
|
+
end.parse!(argv)
|
261
|
+
|
262
|
+
setup_jobs_for_ci(command.jobs_option)
|
263
|
+
|
264
|
+
dirs = argv.map {|dir| Pathname(dir) }
|
265
|
+
command.dirs.push(*dirs)
|
266
|
+
end.run
|
267
|
+
end
|
268
|
+
|
269
|
+
def process_langserver
|
270
|
+
Drivers::Langserver.new(stdout: stdout, stderr: stderr, stdin: stdin).tap do |command|
|
271
|
+
OptionParser.new do |opts|
|
272
|
+
opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
|
273
|
+
handle_jobs_option command.jobs_option, opts
|
274
|
+
handle_logging_options opts
|
275
|
+
end.parse!(argv)
|
276
|
+
end.run
|
277
|
+
end
|
278
|
+
|
279
|
+
def process_vendor
|
280
|
+
Drivers::Vendor.new(stdout: stdout, stderr: stderr, stdin: stdin).tap do |command|
|
281
|
+
OptionParser.new do |opts|
|
282
|
+
opts.banner = "Usage: steep vendor [options] [dir]"
|
283
|
+
handle_logging_options opts
|
284
|
+
|
285
|
+
opts.on("--[no-]clean") do |v|
|
286
|
+
command.clean_before = v
|
287
|
+
end
|
288
|
+
end.parse!(argv)
|
289
|
+
|
290
|
+
command.vendor_dir = Pathname(argv[0] || "vendor/sigs")
|
291
|
+
end.run
|
292
|
+
end
|
293
|
+
|
294
|
+
def process_binstub
|
295
|
+
path = Pathname("bin/steep")
|
296
|
+
root_path = Pathname.pwd
|
297
|
+
force = false
|
298
|
+
|
299
|
+
OptionParser.new do |opts|
|
300
|
+
opts.banner = <<BANNER
|
301
|
+
Usage: steep binstub [options]
|
302
|
+
|
303
|
+
Generate a binstub to execute Steep with setting up Bundler and rbenv/rvm.
|
304
|
+
Use the executable for LSP integration setup.
|
305
|
+
|
306
|
+
Options:
|
307
|
+
BANNER
|
308
|
+
handle_logging_options opts
|
309
|
+
|
310
|
+
opts.on("-o PATH", "--output=PATH", "The path of the executable file (defaults to `bin/steep`)") do |v|
|
311
|
+
path = Pathname(v)
|
312
|
+
end
|
313
|
+
|
314
|
+
opts.on("--root=PATH", "The repository root path (defaults to `.`)") do |v|
|
315
|
+
root_path = (Pathname.pwd + v).cleanpath
|
316
|
+
end
|
317
|
+
|
318
|
+
opts.on("--[no-]force", "Overwrite file (defaults to false)") do
|
319
|
+
force = true
|
320
|
+
end
|
321
|
+
end.parse!(argv)
|
322
|
+
|
323
|
+
binstub_path = (Pathname.pwd + path).cleanpath
|
324
|
+
bindir_path = binstub_path.parent
|
325
|
+
|
326
|
+
bindir_path.mkpath
|
327
|
+
|
328
|
+
gemfile_path =
|
329
|
+
if defined?(Bundler)
|
330
|
+
Bundler.default_gemfile.relative_path_from(bindir_path)
|
331
|
+
else
|
332
|
+
Pathname("../Gemfile")
|
333
|
+
end
|
334
|
+
|
335
|
+
if binstub_path.file?
|
336
|
+
if force
|
337
|
+
stdout.puts Rainbow("#{path} already exists. Overwriting...").yellow
|
338
|
+
else
|
339
|
+
stdout.puts Rainbow(''"⚠️ #{path} already exists. Bye! 👋").red
|
340
|
+
return 0
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
template = <<TEMPLATE
|
345
|
+
#!/usr/bin/env bash
|
346
|
+
|
347
|
+
BINSTUB_DIR=$(cd $(dirname $0); pwd)
|
348
|
+
GEMFILE=$(readlink -f ${BINSTUB_DIR}/#{gemfile_path})
|
349
|
+
ROOT_DIR=$(readlink -f ${BINSTUB_DIR}/#{root_path.relative_path_from(bindir_path)})
|
350
|
+
|
351
|
+
STEEP="bundle exec --gemfile=${GEMFILE} steep"
|
352
|
+
|
353
|
+
if type "rbenv" > /dev/null 2>&1; then
|
354
|
+
STEEP="rbenv exec ${STEEP}"
|
355
|
+
else
|
356
|
+
if type "rvm" > /dev/null 2>&1; then
|
357
|
+
if [ -e ${ROOT_DIR}/.ruby-version ]; then
|
358
|
+
STEEP="rvm ${ROOT_DIR} do ${STEEP}"
|
359
|
+
fi
|
360
|
+
fi
|
361
|
+
fi
|
362
|
+
|
363
|
+
exec $STEEP $@
|
364
|
+
TEMPLATE
|
365
|
+
|
366
|
+
binstub_path.write(template)
|
367
|
+
binstub_path.chmod(0755)
|
368
|
+
|
369
|
+
stdout.puts Rainbow("Successfully generated executable #{path} 🎉").blue
|
370
|
+
|
371
|
+
0
|
372
|
+
end
|
373
|
+
|
374
|
+
def process_version
|
375
|
+
stdout.puts Steep::VERSION
|
376
|
+
0
|
377
|
+
end
|
378
|
+
|
379
|
+
def process_worker
|
380
|
+
Drivers::Worker.new(stdout: stdout, stderr: stderr, stdin: stdin).tap do |command|
|
381
|
+
OptionParser.new do |opts|
|
382
|
+
opts.banner = "Usage: steep worker [options] [dir]"
|
383
|
+
handle_logging_options opts
|
384
|
+
|
385
|
+
opts.on("--interaction") { command.worker_type = :interaction }
|
386
|
+
opts.on("--typecheck") { command.worker_type = :typecheck }
|
387
|
+
opts.on("--steepfile=PATH") {|path| command.steepfile = Pathname(path) }
|
388
|
+
opts.on("--name=NAME") {|name| command.worker_name = name }
|
389
|
+
opts.on("--delay-shutdown") { command.delay_shutdown = true }
|
390
|
+
opts.on("--max-index=COUNT") {|count| command.max_index = Integer(count) }
|
391
|
+
opts.on("--index=INDEX") {|index| command.index = Integer(index) }
|
392
|
+
end.parse!(argv)
|
393
|
+
|
394
|
+
# Disable any `ui_logger` output in workers
|
395
|
+
Steep.ui_logger.level = :fatal
|
396
|
+
|
397
|
+
command.commandline_args.push(*argv)
|
398
|
+
end.run
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Steep.logger.error "Diagnostic `Ruby::ElseOnExhaustiveCase` is deprecated. Use `Ruby::UnreachableBranch` instead."
|
2
|
+
|
3
|
+
module Steep
|
4
|
+
module Diagnostic
|
5
|
+
module Ruby
|
6
|
+
class ElseOnExhaustiveCase < Base
|
7
|
+
attr_reader :type
|
8
|
+
|
9
|
+
def initialize(node:, type:)
|
10
|
+
super(node: node)
|
11
|
+
@type = type
|
12
|
+
end
|
13
|
+
|
14
|
+
def header_line
|
15
|
+
"The branch is unreachable because the condition is exhaustive"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Steep.logger.error "Diagnostic `Ruby::UnknownConstantAssigned` is deprecated. Use `Ruby::UnknownConstant` instead."
|
2
|
+
|
3
|
+
module Steep
|
4
|
+
module Diagnostic
|
5
|
+
module Ruby
|
6
|
+
class UnknownConstantAssigned < Base
|
7
|
+
attr_reader :context
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
def initialize(node:, context:, name:)
|
11
|
+
const = node.children[0]
|
12
|
+
loc = if const
|
13
|
+
const.loc.expression.join(node.loc.name)
|
14
|
+
else
|
15
|
+
node.loc.name
|
16
|
+
end
|
17
|
+
super(node: node, location: loc)
|
18
|
+
@context = context
|
19
|
+
@name = name
|
20
|
+
end
|
21
|
+
|
22
|
+
def header_line
|
23
|
+
"Cannot find the declaration of constant `#{name}`"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|