steep 1.6.0 → 1.7.0.dev.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ruby-windows.yml +2 -1
- data/.github/workflows/ruby.yml +9 -10
- data/.gitignore +0 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +30 -28
- data/Rakefile +5 -0
- data/bin/output_test.rb +1 -0
- data/doc/narrowing.md +195 -0
- data/gemfile_steep/Gemfile +1 -1
- data/gemfile_steep/Gemfile.lock +31 -16
- data/guides/src/getting-started/getting-started.md +10 -11
- data/lib/steep/ast/ignore.rb +148 -0
- data/lib/steep/cli.rb +6 -1
- data/lib/steep/diagnostic/ruby.rb +16 -0
- data/lib/steep/drivers/utils/driver_helper.rb +22 -11
- data/lib/steep/node_helper.rb +12 -0
- data/lib/steep/project/dsl.rb +18 -21
- data/lib/steep/project/options.rb +39 -2
- data/lib/steep/project.rb +11 -7
- data/lib/steep/server/change_buffer.rb +2 -2
- data/lib/steep/server/interaction_worker.rb +61 -11
- data/lib/steep/server/worker_process.rb +3 -1
- data/lib/steep/services/completion_provider.rb +39 -8
- data/lib/steep/services/file_loader.rb +3 -2
- data/lib/steep/services/signature_help_provider.rb +20 -17
- data/lib/steep/services/type_check_service.rb +36 -8
- data/lib/steep/source/ignore_ranges.rb +69 -0
- data/lib/steep/source.rb +10 -4
- data/lib/steep/subtyping/check.rb +6 -0
- data/lib/steep/subtyping/result.rb +6 -0
- data/lib/steep/type_construction.rb +6 -151
- data/lib/steep/type_inference/case_when.rb +301 -0
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +14 -1
- data/rbs_collection.steep.lock.yaml +8 -6
- data/sig/shims/parser.rbs +10 -0
- data/sig/shims/yaml.rbs +4 -0
- data/sig/steep/ast/ignore.rbs +66 -0
- data/sig/steep/diagnostic/ruby.rbs +8 -0
- data/sig/steep/node_helper.rbs +2 -0
- data/sig/steep/project/dsl.rbs +8 -4
- data/sig/steep/project/options.rbs +21 -1
- data/sig/steep/project.rbs +3 -3
- data/sig/steep/server/change_buffer.rbs +6 -4
- data/sig/steep/server/interaction_worker.rbs +10 -0
- data/sig/steep/server/worker_process.rbs +4 -4
- data/sig/steep/services/completion_provider.rbs +14 -1
- data/sig/steep/services/type_check_service.rbs +6 -1
- data/sig/steep/source/ignore_ranges.rbs +38 -0
- data/sig/steep/source.rbs +5 -2
- data/sig/steep/subtyping/check.rbs +4 -2
- data/sig/steep/subtyping/result.rbs +5 -1
- data/sig/steep/type_construction.rbs +1 -26
- data/sig/steep/type_inference/case_when.rbs +130 -0
- data/sig/steep.rbs +9 -0
- data/steep.gemspec +1 -1
- metadata +11 -258
- data/smoke/alias/Steepfile +0 -6
- data/smoke/alias/a.rb +0 -16
- data/smoke/alias/a.rbs +0 -10
- data/smoke/alias/b.rb +0 -6
- data/smoke/alias/c.rb +0 -8
- data/smoke/alias/test_expectations.yml +0 -96
- data/smoke/and/Steepfile +0 -6
- data/smoke/and/a.rb +0 -8
- data/smoke/and/test_expectations.yml +0 -29
- data/smoke/array/Steepfile +0 -6
- data/smoke/array/a.rb +0 -18
- data/smoke/array/b.rb +0 -12
- data/smoke/array/c.rb +0 -6
- data/smoke/array/test_expectations.yml +0 -103
- data/smoke/block/Steepfile +0 -6
- data/smoke/block/a.rb +0 -10
- data/smoke/block/a.rbs +0 -6
- data/smoke/block/b.rb +0 -13
- data/smoke/block/c.rb +0 -9
- data/smoke/block/c.rbs +0 -3
- data/smoke/block/d.rb +0 -11
- data/smoke/block/e.rb +0 -12
- data/smoke/block/e.rbs +0 -4
- data/smoke/block/test_expectations.yml +0 -133
- data/smoke/case/Steepfile +0 -6
- data/smoke/case/a.rb +0 -18
- data/smoke/case/test_expectations.yml +0 -47
- data/smoke/class/Steepfile +0 -6
- data/smoke/class/a.rb +0 -25
- data/smoke/class/a.rbs +0 -23
- data/smoke/class/b.rb +0 -5
- data/smoke/class/c.rb +0 -9
- data/smoke/class/f.rb +0 -10
- data/smoke/class/g.rb +0 -6
- data/smoke/class/h.rb +0 -19
- data/smoke/class/h.rbs +0 -6
- data/smoke/class/i.rb +0 -14
- data/smoke/class/i.rbs +0 -9
- data/smoke/class/test_expectations.yml +0 -117
- data/smoke/compact/Steepfile +0 -6
- data/smoke/compact/a.rb +0 -2
- data/smoke/compact/a.rbs +0 -5
- data/smoke/compact/b.rb +0 -2
- data/smoke/compact/test_expectations.yml +0 -18
- data/smoke/const/Steepfile +0 -6
- data/smoke/const/a.rb +0 -27
- data/smoke/const/b.rb +0 -7
- data/smoke/const/b.rbs +0 -5
- data/smoke/const/test_expectations.yml +0 -134
- data/smoke/diagnostics/Steepfile +0 -6
- data/smoke/diagnostics/a.rbs +0 -22
- data/smoke/diagnostics/argument_type_mismatch.rb +0 -1
- data/smoke/diagnostics/block_body_type_mismatch.rb +0 -1
- data/smoke/diagnostics/block_type_mismatch.rb +0 -3
- data/smoke/diagnostics/break_type_mismatch.rb +0 -1
- data/smoke/diagnostics/different_method_parameter_kind.rb +0 -9
- data/smoke/diagnostics/else_on_exhaustive_case.rb +0 -12
- data/smoke/diagnostics/incompatible_annotation.rb +0 -6
- data/smoke/diagnostics/incompatible_argument.rb +0 -1
- data/smoke/diagnostics/incompatible_assignment.rb +0 -8
- data/smoke/diagnostics/method_arity_mismatch.rb +0 -11
- data/smoke/diagnostics/method_body_type_mismatch.rb +0 -6
- data/smoke/diagnostics/method_definition_missing.rb +0 -2
- data/smoke/diagnostics/method_parameter_mismatch.rb +0 -10
- data/smoke/diagnostics/method_return_type_annotation_mismatch.rb +0 -7
- data/smoke/diagnostics/missing_keyword.rb +0 -1
- data/smoke/diagnostics/no_method.rb +0 -1
- data/smoke/diagnostics/proc_type_expected.rb +0 -3
- data/smoke/diagnostics/required_block_missing.rb +0 -1
- data/smoke/diagnostics/return_type_mismatch.rb +0 -6
- data/smoke/diagnostics/test_expectations.yml +0 -591
- data/smoke/diagnostics/unexpected_block_given.rb +0 -1
- data/smoke/diagnostics/unexpected_dynamic_method.rb +0 -3
- data/smoke/diagnostics/unexpected_jump.rb +0 -4
- data/smoke/diagnostics/unexpected_jump_value.rb +0 -3
- data/smoke/diagnostics/unexpected_keyword.rb +0 -1
- data/smoke/diagnostics/unexpected_splat.rb +0 -1
- data/smoke/diagnostics/unexpected_yield.rb +0 -6
- data/smoke/diagnostics/unknown_constant_assigned.rb +0 -7
- data/smoke/diagnostics/unresolved_overloading.rb +0 -1
- data/smoke/diagnostics/unsupported_syntax.rb +0 -2
- data/smoke/diagnostics-rbs/Steepfile +0 -8
- data/smoke/diagnostics-rbs/duplicated-method-definition.rbs +0 -20
- data/smoke/diagnostics-rbs/generic-parameter-mismatch.rbs +0 -7
- data/smoke/diagnostics-rbs/inherit-module.rbs +0 -2
- data/smoke/diagnostics-rbs/invalid-method-overload.rbs +0 -3
- data/smoke/diagnostics-rbs/invalid-type-application.rbs +0 -7
- data/smoke/diagnostics-rbs/invalid_variance_annotation.rbs +0 -3
- data/smoke/diagnostics-rbs/mixin-class-error.rbs +0 -6
- data/smoke/diagnostics-rbs/nonregular-type-alias.rbs +0 -3
- data/smoke/diagnostics-rbs/recursive-alias.rbs +0 -5
- data/smoke/diagnostics-rbs/recursive-class.rbs +0 -8
- data/smoke/diagnostics-rbs/recursive-type-alias.rbs +0 -3
- data/smoke/diagnostics-rbs/superclass-mismatch.rbs +0 -7
- data/smoke/diagnostics-rbs/test_expectations.yml +0 -300
- data/smoke/diagnostics-rbs/unknown-method-alias.rbs +0 -3
- data/smoke/diagnostics-rbs/unknown-type-name-2.rbs +0 -5
- data/smoke/diagnostics-rbs/unknown-type-name.rbs +0 -13
- data/smoke/diagnostics-rbs-duplicated/Steepfile +0 -6
- data/smoke/diagnostics-rbs-duplicated/a.rbs +0 -5
- data/smoke/diagnostics-rbs-duplicated/test_expectations.yml +0 -13
- data/smoke/diagnostics-ruby-unsat/Steepfile +0 -6
- data/smoke/diagnostics-ruby-unsat/a.rbs +0 -3
- data/smoke/diagnostics-ruby-unsat/test_expectations.yml +0 -27
- data/smoke/diagnostics-ruby-unsat/unsatisfiable_constraint.rb +0 -6
- data/smoke/dstr/Steepfile +0 -6
- data/smoke/dstr/a.rb +0 -5
- data/smoke/dstr/test_expectations.yml +0 -13
- data/smoke/ensure/Steepfile +0 -6
- data/smoke/ensure/a.rb +0 -18
- data/smoke/ensure/test_expectations.yml +0 -62
- data/smoke/enumerator/Steepfile +0 -6
- data/smoke/enumerator/a.rb +0 -6
- data/smoke/enumerator/b.rb +0 -17
- data/smoke/enumerator/test_expectations.yml +0 -47
- data/smoke/extension/Steepfile +0 -6
- data/smoke/extension/a.rb +0 -10
- data/smoke/extension/a.rbs +0 -13
- data/smoke/extension/b.rb +0 -10
- data/smoke/extension/c.rb +0 -9
- data/smoke/extension/d.rb +0 -2
- data/smoke/extension/e.rb +0 -2
- data/smoke/extension/e.rbs +0 -7
- data/smoke/extension/f.rb +0 -2
- data/smoke/extension/f.rbs +0 -3
- data/smoke/extension/test_expectations.yml +0 -73
- data/smoke/hash/Steepfile +0 -6
- data/smoke/hash/a.rb +0 -17
- data/smoke/hash/a.rbs +0 -8
- data/smoke/hash/b.rb +0 -6
- data/smoke/hash/c.rb +0 -15
- data/smoke/hash/d.rb +0 -5
- data/smoke/hash/e.rb +0 -1
- data/smoke/hash/e.rbs +0 -3
- data/smoke/hash/f.rb +0 -11
- data/smoke/hash/test_expectations.yml +0 -81
- data/smoke/hello/Steepfile +0 -6
- data/smoke/hello/hello.rb +0 -11
- data/smoke/hello/hello.rbs +0 -7
- data/smoke/hello/test_expectations.yml +0 -25
- data/smoke/if/Steepfile +0 -6
- data/smoke/if/a.rb +0 -20
- data/smoke/if/test_expectations.yml +0 -34
- data/smoke/implements/Steepfile +0 -6
- data/smoke/implements/a.rb +0 -12
- data/smoke/implements/a.rbs +0 -6
- data/smoke/implements/b.rb +0 -13
- data/smoke/implements/b.rbs +0 -12
- data/smoke/implements/test_expectations.yml +0 -23
- data/smoke/initialize/Steepfile +0 -6
- data/smoke/initialize/a.rb +0 -12
- data/smoke/initialize/a.rbs +0 -3
- data/smoke/initialize/test_expectations.yml +0 -1
- data/smoke/integer/Steepfile +0 -6
- data/smoke/integer/a.rb +0 -26
- data/smoke/integer/test_expectations.yml +0 -110
- data/smoke/interface/Steepfile +0 -6
- data/smoke/interface/a.rb +0 -12
- data/smoke/interface/a.rbs +0 -12
- data/smoke/interface/test_expectations.yml +0 -23
- data/smoke/kwbegin/Steepfile +0 -6
- data/smoke/kwbegin/a.rb +0 -7
- data/smoke/kwbegin/test_expectations.yml +0 -17
- data/smoke/lambda/Steepfile +0 -6
- data/smoke/lambda/a.rb +0 -10
- data/smoke/lambda/test_expectations.yml +0 -17
- data/smoke/literal/Steepfile +0 -6
- data/smoke/literal/a.rb +0 -11
- data/smoke/literal/b.rb +0 -7
- data/smoke/literal/literal_methods.rbs +0 -4
- data/smoke/literal/test_expectations.yml +0 -106
- data/smoke/map/Steepfile +0 -6
- data/smoke/map/a.rb +0 -5
- data/smoke/map/test_expectations.yml +0 -1
- data/smoke/method/Steepfile +0 -6
- data/smoke/method/a.rb +0 -21
- data/smoke/method/a.rbs +0 -4
- data/smoke/method/b.rb +0 -25
- data/smoke/method/c.rb +0 -5
- data/smoke/method/d.rb +0 -1
- data/smoke/method/d.rbs +0 -3
- data/smoke/method/test_expectations.yml +0 -121
- data/smoke/module/Steepfile +0 -6
- data/smoke/module/a.rb +0 -19
- data/smoke/module/a.rbs +0 -16
- data/smoke/module/b.rb +0 -6
- data/smoke/module/c.rb +0 -22
- data/smoke/module/d.rb +0 -4
- data/smoke/module/e.rb +0 -13
- data/smoke/module/f.rb +0 -11
- data/smoke/module/test_expectations.yml +0 -75
- data/smoke/regexp/Steepfile +0 -6
- data/smoke/regexp/a.rb +0 -109
- data/smoke/regexp/b.rb +0 -79
- data/smoke/regexp/test_expectations.yml +0 -615
- data/smoke/regression/Steepfile +0 -6
- data/smoke/regression/array.rb +0 -7
- data/smoke/regression/block_param_split.rb +0 -7
- data/smoke/regression/block_param_split.rbs +0 -3
- data/smoke/regression/empty_yield.rb +0 -5
- data/smoke/regression/empty_yield.rbs +0 -3
- data/smoke/regression/enumerator_product.rb +0 -1
- data/smoke/regression/fun.rb +0 -8
- data/smoke/regression/fun.rbs +0 -4
- data/smoke/regression/hash.rb +0 -7
- data/smoke/regression/hello world.rb +0 -1
- data/smoke/regression/issue_328.rb +0 -1
- data/smoke/regression/issue_328.rbs +0 -0
- data/smoke/regression/issue_332.rb +0 -11
- data/smoke/regression/issue_332.rbs +0 -19
- data/smoke/regression/issue_372.rb +0 -8
- data/smoke/regression/issue_372.rbs +0 -4
- data/smoke/regression/lambda.rb +0 -3
- data/smoke/regression/masgn.rb +0 -4
- data/smoke/regression/poly_new.rb +0 -2
- data/smoke/regression/poly_new.rbs +0 -4
- data/smoke/regression/range.rb +0 -5
- data/smoke/regression/set_divide.rb +0 -12
- data/smoke/regression/test_expectations.yml +0 -120
- data/smoke/regression/thread.rb +0 -7
- data/smoke/rescue/Steepfile +0 -6
- data/smoke/rescue/a.rb +0 -48
- data/smoke/rescue/test_expectations.yml +0 -79
- data/smoke/self/Steepfile +0 -6
- data/smoke/self/a.rb +0 -21
- data/smoke/self/a.rbs +0 -4
- data/smoke/self/test_expectations.yml +0 -23
- data/smoke/skip/Steepfile +0 -6
- data/smoke/skip/skip.rb +0 -13
- data/smoke/skip/test_expectations.yml +0 -23
- data/smoke/stdout/Steepfile +0 -6
- data/smoke/stdout/a.rb +0 -8
- data/smoke/stdout/a.rbs +0 -7
- data/smoke/stdout/test_expectations.yml +0 -1
- data/smoke/super/Steepfile +0 -6
- data/smoke/super/a.rb +0 -30
- data/smoke/super/a.rbs +0 -10
- data/smoke/super/test_expectations.yml +0 -69
- data/smoke/toplevel/Steepfile +0 -6
- data/smoke/toplevel/a.rb +0 -3
- data/smoke/toplevel/a.rbs +0 -3
- data/smoke/toplevel/test_expectations.yml +0 -15
- data/smoke/tsort/Steepfile +0 -7
- data/smoke/tsort/a.rb +0 -12
- data/smoke/tsort/test_expectations.yml +0 -1
- data/smoke/type_case/Steepfile +0 -6
- data/smoke/type_case/a.rb +0 -24
- data/smoke/type_case/test_expectations.yml +0 -58
- data/smoke/unexpected/Steepfile +0 -6
- data/smoke/unexpected/test_expectations.yml +0 -13
- data/smoke/unexpected/unexpected.rbs +0 -3
- data/smoke/yield/Steepfile +0 -6
- data/smoke/yield/a.rb +0 -15
- data/smoke/yield/b.rb +0 -6
- data/smoke/yield/test_expectations.yml +0 -88
@@ -0,0 +1,148 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Ignore
|
4
|
+
class BufferScanner
|
5
|
+
attr_reader :scanner, :location
|
6
|
+
|
7
|
+
def initialize(location)
|
8
|
+
@location = location
|
9
|
+
|
10
|
+
@scanner = StringScanner.new(location.source)
|
11
|
+
end
|
12
|
+
|
13
|
+
def offset
|
14
|
+
@location.start_pos
|
15
|
+
end
|
16
|
+
|
17
|
+
def charpos
|
18
|
+
scanner.charpos + offset
|
19
|
+
end
|
20
|
+
|
21
|
+
def scan(regexp)
|
22
|
+
if matched = scanner.scan(regexp)
|
23
|
+
end_pos = charpos()
|
24
|
+
begin_pos = end_pos - matched.size
|
25
|
+
RBS::Location.new(location.buffer, begin_pos, end_pos)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def skip(regexp)
|
30
|
+
scanner.skip(regexp)
|
31
|
+
end
|
32
|
+
|
33
|
+
def eos?
|
34
|
+
scanner.eos?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class IgnoreStart
|
39
|
+
attr_reader :comment, :location
|
40
|
+
|
41
|
+
def initialize(comment, location)
|
42
|
+
@comment = comment
|
43
|
+
@location = location
|
44
|
+
end
|
45
|
+
|
46
|
+
def line
|
47
|
+
location.start_line
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class IgnoreEnd
|
52
|
+
attr_reader :comment, :location
|
53
|
+
|
54
|
+
def initialize(comment, location)
|
55
|
+
@comment = comment
|
56
|
+
@location = location
|
57
|
+
end
|
58
|
+
|
59
|
+
def line
|
60
|
+
location.start_line
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class IgnoreLine
|
65
|
+
attr_reader :comment, :location, :raw_diagnostics
|
66
|
+
|
67
|
+
def initialize(comment, diagnostics, location)
|
68
|
+
@comment = comment
|
69
|
+
@raw_diagnostics = diagnostics
|
70
|
+
@location = location
|
71
|
+
end
|
72
|
+
|
73
|
+
def line
|
74
|
+
location.start_line
|
75
|
+
end
|
76
|
+
|
77
|
+
def ignored_diagnostics
|
78
|
+
if raw_diagnostics.empty?
|
79
|
+
return :all
|
80
|
+
end
|
81
|
+
|
82
|
+
if raw_diagnostics.size == 1 && raw_diagnostics[0].source == "all"
|
83
|
+
return :all
|
84
|
+
end
|
85
|
+
|
86
|
+
raw_diagnostics.map do |diagnostic|
|
87
|
+
name = diagnostic[:name].source
|
88
|
+
name.gsub(/\ARuby::/, "")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.parse(comment, buffer)
|
94
|
+
return unless comment.inline?
|
95
|
+
|
96
|
+
comment_location = RBS::Location.new(buffer, comment.loc.expression.begin_pos, comment.loc.expression.end_pos)
|
97
|
+
scanner = BufferScanner.new(comment_location)
|
98
|
+
|
99
|
+
scanner.scan(/#/)
|
100
|
+
scanner.skip(/\s*/)
|
101
|
+
|
102
|
+
begin_pos = comment.location.expression.begin_pos
|
103
|
+
end_pos = comment.location.expression.end_pos
|
104
|
+
|
105
|
+
case
|
106
|
+
when loc = scanner.scan(/steep:ignore:start\b/)
|
107
|
+
scanner.skip(/\s*/)
|
108
|
+
return unless scanner.eos?
|
109
|
+
|
110
|
+
IgnoreStart.new(comment, loc)
|
111
|
+
when loc = scanner.scan(/steep:ignore:end\b/)
|
112
|
+
scanner.skip(/\s*/)
|
113
|
+
return unless scanner.eos?
|
114
|
+
|
115
|
+
IgnoreEnd.new(comment, loc)
|
116
|
+
when keyword_loc = scanner.scan(/steep:ignore\b/)
|
117
|
+
# @type var diagnostics: IgnoreLine::diagnostics
|
118
|
+
diagnostics = []
|
119
|
+
|
120
|
+
scanner.skip(/\s*/)
|
121
|
+
|
122
|
+
while true
|
123
|
+
name = scanner.scan(/[A-Z]\w*/) or break
|
124
|
+
scanner.skip(/\s*/)
|
125
|
+
comma = scanner.scan(/,/)
|
126
|
+
scanner.skip(/\s*/)
|
127
|
+
|
128
|
+
diagnostic = RBS::Location.new(buffer, name.start_pos, comma&.end_pos || name.end_pos) #: IgnoreLine::diagnostic
|
129
|
+
diagnostic.add_required_child(:name, name.range)
|
130
|
+
diagnostic.add_optional_child(:following_comma, comma&.range)
|
131
|
+
diagnostics << diagnostic
|
132
|
+
|
133
|
+
break unless comma
|
134
|
+
end
|
135
|
+
|
136
|
+
return unless scanner.eos?
|
137
|
+
|
138
|
+
loc = RBS::Location.new(
|
139
|
+
buffer,
|
140
|
+
keyword_loc.start_pos,
|
141
|
+
diagnostics.last&.end_pos || keyword_loc.end_pos
|
142
|
+
)
|
143
|
+
IgnoreLine.new(comment, diagnostics, loc)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
data/lib/steep/cli.rb
CHANGED
@@ -63,6 +63,7 @@ module Steep
|
|
63
63
|
def handle_logging_options(opts)
|
64
64
|
opts.on("--log-level=LEVEL", "Specify log level: debug, info, warn, error, fatal") do |level|
|
65
65
|
Steep.logger.level = level
|
66
|
+
Steep.ui_logger.level = level
|
66
67
|
end
|
67
68
|
|
68
69
|
opts.on("--log-output=PATH", "Print logs to given path") do |file|
|
@@ -71,6 +72,7 @@ module Steep
|
|
71
72
|
|
72
73
|
opts.on("--verbose", "Set log level to debug") do
|
73
74
|
Steep.logger.level = Logger::DEBUG
|
75
|
+
Steep.ui_logger.level = Logger::DEBUG
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
@@ -129,7 +131,7 @@ module Steep
|
|
129
131
|
end.parse!(argv)
|
130
132
|
|
131
133
|
setup_jobs_for_ci(command.jobs_option)
|
132
|
-
|
134
|
+
|
133
135
|
command.command_line_patterns.push *argv
|
134
136
|
end.run
|
135
137
|
end
|
@@ -349,6 +351,9 @@ TEMPLATE
|
|
349
351
|
opts.on("--index=INDEX") {|index| command.index = Integer(index) }
|
350
352
|
end.parse!(argv)
|
351
353
|
|
354
|
+
# Disable any `ui_logger` output in workers
|
355
|
+
Steep.ui_logger.level = :fatal
|
356
|
+
|
352
357
|
command.commandline_args.push(*argv)
|
353
358
|
end.run
|
354
359
|
end
|
@@ -997,6 +997,19 @@ module Steep
|
|
997
997
|
end
|
998
998
|
end
|
999
999
|
|
1000
|
+
class InvalidIgnoreComment < Base
|
1001
|
+
attr_reader :comment
|
1002
|
+
|
1003
|
+
def initialize(comment:)
|
1004
|
+
@comment = comment
|
1005
|
+
super(node: nil, location: comment.location.expression)
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
def header_line
|
1009
|
+
"Invalid ignore comment"
|
1010
|
+
end
|
1011
|
+
end
|
1012
|
+
|
1000
1013
|
ALL = ObjectSpace.each_object(Class).with_object([]) do |klass, array|
|
1001
1014
|
if klass < Base
|
1002
1015
|
array << klass
|
@@ -1028,6 +1041,7 @@ module Steep
|
|
1028
1041
|
InsufficientKeywordArguments => :error,
|
1029
1042
|
InsufficientPositionalArguments => :error,
|
1030
1043
|
InsufficientTypeArgument => :hint,
|
1044
|
+
InvalidIgnoreComment => :warning,
|
1031
1045
|
MethodArityMismatch => :error,
|
1032
1046
|
MethodBodyTypeMismatch => :error,
|
1033
1047
|
MethodDefinitionMissing => nil,
|
@@ -1086,6 +1100,7 @@ module Steep
|
|
1086
1100
|
InsufficientKeywordArguments => :error,
|
1087
1101
|
InsufficientPositionalArguments => :error,
|
1088
1102
|
InsufficientTypeArgument => :error,
|
1103
|
+
InvalidIgnoreComment => :warning,
|
1089
1104
|
MethodArityMismatch => :error,
|
1090
1105
|
MethodBodyTypeMismatch => :error,
|
1091
1106
|
MethodDefinitionMissing => :hint,
|
@@ -1144,6 +1159,7 @@ module Steep
|
|
1144
1159
|
InsufficientKeywordArguments => :information,
|
1145
1160
|
InsufficientPositionalArguments => :information,
|
1146
1161
|
InsufficientTypeArgument => nil,
|
1162
|
+
InvalidIgnoreComment => :warning,
|
1147
1163
|
MethodArityMismatch => :information,
|
1148
1164
|
MethodBodyTypeMismatch => :warning,
|
1149
1165
|
MethodDefinitionMissing => nil,
|
@@ -5,18 +5,29 @@ module Steep
|
|
5
5
|
attr_accessor :steepfile
|
6
6
|
|
7
7
|
def load_config(path: steepfile || Pathname("Steepfile"))
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
if path.file?
|
9
|
+
steep_file_path = path.absolute? ? path : Pathname.pwd + path
|
10
|
+
Project.new(steepfile_path: steep_file_path).tap do |project|
|
11
|
+
Project::DSL.parse(project, path.read, filename: path.to_s)
|
12
|
+
end
|
13
|
+
else
|
14
|
+
Steep.ui_logger.error { "Cannot find a configuration at #{path}: `steep init` to scaffold. Using current directory..." }
|
15
|
+
Project.new(steepfile_path: nil, base_dir: Pathname.pwd).tap do |project|
|
16
|
+
Project::DSL.new(project: project).target :'.' do
|
17
|
+
check '.'
|
18
|
+
signature '.'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end.tap do |project|
|
14
22
|
project.targets.each do |target|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
case result = target.options.load_collection_lock
|
24
|
+
when nil, RBS::Collection::Config::Lockfile
|
25
|
+
# ok
|
26
|
+
else
|
27
|
+
if result == target.options.collection_config_path
|
28
|
+
Steep.ui_logger.error { "rbs-collection setup is broken: `#{result}` is missing" }
|
29
|
+
else
|
30
|
+
Steep.ui_logger.error { "Run `rbs collection install` to install type definitions" }
|
20
31
|
end
|
21
32
|
end
|
22
33
|
end
|
data/lib/steep/node_helper.rb
CHANGED
@@ -240,5 +240,17 @@ module Steep
|
|
240
240
|
end
|
241
241
|
end
|
242
242
|
end
|
243
|
+
|
244
|
+
def clone_node(node)
|
245
|
+
children = node.children.map do |child|
|
246
|
+
if child.is_a?(Parser::AST::Node)
|
247
|
+
clone_node(child)
|
248
|
+
else
|
249
|
+
child.dup
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
node.updated(nil, children)
|
254
|
+
end
|
243
255
|
end
|
244
256
|
end
|
data/lib/steep/project/dsl.rb
CHANGED
@@ -14,9 +14,7 @@ module Steep
|
|
14
14
|
attr_reader :project
|
15
15
|
attr_reader :collection_config_path
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
def initialize(name, sources: [], libraries: [], signatures: [], ignored_sources: [], repo_paths: [], code_diagnostics_config: {}, project: nil, collection_config_path: NONE)
|
17
|
+
def initialize(name, sources: [], libraries: [], signatures: [], ignored_sources: [], repo_paths: [], code_diagnostics_config: {}, project: nil, collection_config_path: nil)
|
20
18
|
@name = name
|
21
19
|
@sources = sources
|
22
20
|
@libraries = libraries
|
@@ -27,14 +25,7 @@ module Steep
|
|
27
25
|
@repo_paths = []
|
28
26
|
@code_diagnostics_config = code_diagnostics_config
|
29
27
|
@project = project
|
30
|
-
@collection_config_path =
|
31
|
-
case collection_config_path
|
32
|
-
when NONE
|
33
|
-
path = project&.absolute_path(RBS::Collection::Config::PATH)
|
34
|
-
path&.exist? ? path : nil
|
35
|
-
else
|
36
|
-
collection_config_path
|
37
|
-
end
|
28
|
+
@collection_config_path = collection_config_path
|
38
29
|
end
|
39
30
|
|
40
31
|
def initialize_copy(other)
|
@@ -135,8 +126,8 @@ module Steep
|
|
135
126
|
end
|
136
127
|
|
137
128
|
def stdlib_path(core_root:, stdlib_root:)
|
138
|
-
@core_root =
|
139
|
-
@stdlib_root =
|
129
|
+
@core_root = Pathname(core_root)
|
130
|
+
@stdlib_root = Pathname(stdlib_root)
|
140
131
|
end
|
141
132
|
|
142
133
|
def repo_path(*paths)
|
@@ -160,7 +151,7 @@ module Steep
|
|
160
151
|
end
|
161
152
|
|
162
153
|
def disable_collection
|
163
|
-
@collection_config_path =
|
154
|
+
@collection_config_path = false
|
164
155
|
end
|
165
156
|
end
|
166
157
|
|
@@ -206,12 +197,18 @@ module Steep
|
|
206
197
|
source_pattern = Pattern.new(patterns: target.sources, ignores: target.ignored_sources, ext: ".rb")
|
207
198
|
signature_pattern = Pattern.new(patterns: target.signatures, ext: ".rbs")
|
208
199
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
200
|
+
config_path =
|
201
|
+
case target.collection_config_path
|
202
|
+
when Pathname
|
203
|
+
target.collection_config_path
|
204
|
+
when nil
|
205
|
+
default = project.absolute_path(RBS::Collection::Config::PATH)
|
206
|
+
if default.file?
|
207
|
+
default
|
208
|
+
end
|
209
|
+
when false
|
210
|
+
nil
|
211
|
+
end
|
215
212
|
|
216
213
|
Project::Target.new(
|
217
214
|
name: target.name,
|
@@ -224,7 +221,7 @@ module Steep
|
|
224
221
|
stdlib_root: target.stdlib_root,
|
225
222
|
repo_paths: target.repo_paths
|
226
223
|
)
|
227
|
-
options.
|
224
|
+
options.collection_config_path = config_path
|
228
225
|
end,
|
229
226
|
code_diagnostics_config: target.code_diagnostics_config
|
230
227
|
).tap do |target|
|
@@ -3,7 +3,7 @@ module Steep
|
|
3
3
|
class Options
|
4
4
|
PathOptions = _ = Struct.new(:core_root, :stdlib_root, :repo_paths, keyword_init: true) do
|
5
5
|
# @implements PathOptions
|
6
|
-
|
6
|
+
|
7
7
|
def customized_stdlib?
|
8
8
|
stdlib_root != nil
|
9
9
|
end
|
@@ -15,12 +15,49 @@ module Steep
|
|
15
15
|
|
16
16
|
attr_reader :libraries
|
17
17
|
attr_accessor :paths
|
18
|
-
attr_accessor :
|
18
|
+
attr_accessor :collection_config_path
|
19
19
|
|
20
20
|
def initialize
|
21
21
|
@paths = PathOptions.new(repo_paths: [])
|
22
22
|
@libraries = []
|
23
23
|
end
|
24
|
+
|
25
|
+
def collection_lock_path
|
26
|
+
if collection_config_path
|
27
|
+
RBS::Collection::Config.to_lockfile_path(collection_config_path)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_collection_lock(force: false)
|
32
|
+
@collection_lock = nil if force
|
33
|
+
@collection_lock ||=
|
34
|
+
if collection_config_path && collection_lock_path
|
35
|
+
case
|
36
|
+
when !collection_config_path.file?
|
37
|
+
collection_config_path
|
38
|
+
when !collection_lock_path.file?
|
39
|
+
collection_lock_path
|
40
|
+
else
|
41
|
+
begin
|
42
|
+
content = YAML.load_file(collection_lock_path)
|
43
|
+
lock_file = RBS::Collection::Config::Lockfile.from_lockfile(lockfile_path: collection_lock_path, data: content)
|
44
|
+
lock_file.check_rbs_availability!
|
45
|
+
lock_file
|
46
|
+
rescue YAML::SyntaxError, RBS::Collection::Config::CollectionNotAvailable => exn
|
47
|
+
exn
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def collection_lock
|
54
|
+
case config = load_collection_lock()
|
55
|
+
when RBS::Collection::Config::Lockfile
|
56
|
+
config
|
57
|
+
else
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
24
61
|
end
|
25
62
|
end
|
26
63
|
end
|
data/lib/steep/project.rb
CHANGED
@@ -2,18 +2,22 @@ module Steep
|
|
2
2
|
class Project
|
3
3
|
attr_reader :targets
|
4
4
|
attr_reader :steepfile_path
|
5
|
+
attr_reader :base_dir
|
5
6
|
|
6
|
-
def initialize(steepfile_path:)
|
7
|
+
def initialize(steepfile_path:, base_dir: nil)
|
7
8
|
@targets = []
|
8
9
|
@steepfile_path = steepfile_path
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
@base_dir = if base_dir
|
11
|
+
base_dir
|
12
|
+
elsif steepfile_path
|
13
|
+
steepfile_path.parent
|
14
|
+
else
|
15
|
+
raise ArgumentError, "Project#initialize(base_dir:): neither base_dir nor steepfile_path given"
|
12
16
|
end
|
13
|
-
end
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
if steepfile_path and !steepfile_path.absolute?
|
19
|
+
raise ArgumentError, "Project#initialize(steepfile_path:): steepfile_path should be absolute path"
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
23
|
def relative_path(path)
|
@@ -5,13 +5,13 @@ module Steep
|
|
5
5
|
attr_reader :buffered_changes
|
6
6
|
|
7
7
|
def push_buffer
|
8
|
-
|
8
|
+
mutex.synchronize do
|
9
9
|
yield buffered_changes
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
def pop_buffer
|
14
|
-
changes =
|
14
|
+
changes = mutex.synchronize do
|
15
15
|
copy = buffered_changes.dup
|
16
16
|
buffered_changes.clear
|
17
17
|
copy
|
@@ -10,14 +10,15 @@ module Steep
|
|
10
10
|
|
11
11
|
LSP = LanguageServer::Protocol
|
12
12
|
|
13
|
-
attr_reader :service
|
13
|
+
attr_reader :service, :mutex
|
14
14
|
|
15
15
|
def initialize(project:, reader:, writer:, queue: Queue.new)
|
16
16
|
super(project: project, reader: reader, writer: writer)
|
17
17
|
@queue = queue
|
18
|
-
@service = Services::TypeCheckService.new(project: project)
|
19
18
|
@mutex = Mutex.new
|
19
|
+
@service = Services::TypeCheckService.new(project: project)
|
20
20
|
@buffered_changes = {}
|
21
|
+
@last_job_mutex = Mutex.new
|
21
22
|
end
|
22
23
|
|
23
24
|
def handle_job(job)
|
@@ -33,25 +34,61 @@ module Steep
|
|
33
34
|
when ApplyChangeJob
|
34
35
|
# nop
|
35
36
|
when HoverJob
|
36
|
-
writer.write(
|
37
|
+
writer.write(
|
38
|
+
{
|
39
|
+
id: job.id,
|
40
|
+
result: process_latest_job(job) { process_hover(job) }
|
41
|
+
}
|
42
|
+
)
|
37
43
|
when CompletionJob
|
38
|
-
writer.write(
|
44
|
+
writer.write(
|
45
|
+
{
|
46
|
+
id: job.id,
|
47
|
+
result: process_latest_job(job) { process_completion(job) }
|
48
|
+
}
|
49
|
+
)
|
39
50
|
when SignatureHelpJob
|
40
|
-
writer.write(
|
51
|
+
writer.write(
|
52
|
+
{
|
53
|
+
id: job.id,
|
54
|
+
result: process_latest_job(job) { process_signature_help(job) }
|
55
|
+
}
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def process_latest_job(job)
|
62
|
+
@last_job_mutex.synchronize do
|
63
|
+
unless job.equal?(@last_job)
|
64
|
+
Steep.logger.debug { "Skipping interaction job: latest_job=#{@last_job.class}, skipped_job#{job.class}" }
|
65
|
+
return
|
66
|
+
end
|
67
|
+
@last_job = nil
|
68
|
+
end
|
69
|
+
|
70
|
+
yield
|
71
|
+
end
|
72
|
+
|
73
|
+
def queue_job(job)
|
74
|
+
@last_job_mutex.synchronize do
|
75
|
+
unless job.is_a?(ApplyChangeJob)
|
76
|
+
@last_job = job
|
41
77
|
end
|
42
78
|
end
|
79
|
+
queue << job
|
43
80
|
end
|
44
81
|
|
45
82
|
def handle_request(request)
|
46
83
|
case request[:method]
|
47
84
|
when "initialize"
|
48
85
|
load_files(project: project, commandline_args: [])
|
49
|
-
|
86
|
+
queue_job ApplyChangeJob.new
|
50
87
|
writer.write({ id: request[:id], result: nil })
|
51
88
|
|
52
89
|
when "textDocument/didChange"
|
53
90
|
collect_changes(request)
|
54
|
-
|
91
|
+
queue_job ApplyChangeJob.new
|
55
92
|
|
56
93
|
when "textDocument/hover"
|
57
94
|
id = request[:id]
|
@@ -60,7 +97,7 @@ module Steep
|
|
60
97
|
line = request[:params][:position][:line]+1
|
61
98
|
column = request[:params][:position][:character]
|
62
99
|
|
63
|
-
|
100
|
+
queue_job HoverJob.new(id: id, path: path, line: line, column: column)
|
64
101
|
|
65
102
|
when "textDocument/completion"
|
66
103
|
id = request[:id]
|
@@ -71,14 +108,14 @@ module Steep
|
|
71
108
|
line, column = params[:position].yield_self {|hash| [hash[:line]+1, hash[:character]] }
|
72
109
|
trigger = params.dig(:context, :triggerCharacter)
|
73
110
|
|
74
|
-
|
111
|
+
queue_job CompletionJob.new(id: id, path: path, line: line, column: column, trigger: trigger)
|
75
112
|
when "textDocument/signatureHelp"
|
76
113
|
id = request[:id]
|
77
114
|
params = request[:params]
|
78
115
|
path = project.relative_path(PathHelper.to_pathname!(params[:textDocument][:uri]))
|
79
116
|
line, column = params[:position].yield_self {|hash| [hash[:line]+1, hash[:character]] }
|
80
117
|
|
81
|
-
|
118
|
+
queue_job SignatureHelpJob.new(id: id, path: path, line: line, column: column)
|
82
119
|
end
|
83
120
|
end
|
84
121
|
|
@@ -394,6 +431,17 @@ module Steep
|
|
394
431
|
new_text: item.relative_type_name.to_s
|
395
432
|
)
|
396
433
|
)
|
434
|
+
when Services::CompletionProvider::TextItem
|
435
|
+
LSP::Interface::CompletionItem.new(
|
436
|
+
label: item.label,
|
437
|
+
label_details: item.help_text && LSP::Interface::CompletionItemLabelDetails.new(description: item.help_text),
|
438
|
+
kind: LSP::Constant::CompletionItemKind::SNIPPET,
|
439
|
+
insert_text_format: LSP::Constant::InsertTextFormat::SNIPPET,
|
440
|
+
text_edit: LSP::Interface::TextEdit.new(
|
441
|
+
range: range,
|
442
|
+
new_text: item.text
|
443
|
+
)
|
444
|
+
)
|
397
445
|
end
|
398
446
|
end
|
399
447
|
|
@@ -402,7 +450,9 @@ module Steep
|
|
402
450
|
if target = project.target_for_source_path(job.path)
|
403
451
|
file = service.source_files[job.path] or return
|
404
452
|
subtyping = service.signature_services[target.name].current_subtyping or return
|
405
|
-
source =
|
453
|
+
source =
|
454
|
+
Source.parse(file.content, path: file.path, factory: subtyping.factory)
|
455
|
+
.without_unrelated_defs(line: job.line, column: job.column)
|
406
456
|
|
407
457
|
provider = Services::SignatureHelpProvider.new(source: source, subtyping: subtyping)
|
408
458
|
|
@@ -64,6 +64,7 @@ module Steep
|
|
64
64
|
|
65
65
|
pid = fork do
|
66
66
|
Process.setpgid(0, 0)
|
67
|
+
Steep.ui_logger.level = :fatal
|
67
68
|
stdin_out.close
|
68
69
|
stdout_in.close
|
69
70
|
worker.run()
|
@@ -92,7 +93,8 @@ module Steep
|
|
92
93
|
end
|
93
94
|
|
94
95
|
def self.spawn_worker(type, name:, steepfile:, steep_command:, index:, delay_shutdown:, patterns:)
|
95
|
-
args = ["--name=#{name}"
|
96
|
+
args = ["--name=#{name}"]
|
97
|
+
args << "--steepfile=#{steepfile}" if steepfile
|
96
98
|
args << (%w(debug info warn error fatal unknown)[Steep.logger.level].yield_self {|log_level| "--log-level=#{log_level}" })
|
97
99
|
|
98
100
|
if Steep.log_output.is_a?(String)
|