steep 1.5.2 → 1.6.0.pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby-windows.yml +1 -2
- data/.github/workflows/ruby.yml +1 -2
- data/CHANGELOG.md +41 -0
- data/Gemfile +2 -4
- data/Gemfile.lock +37 -19
- data/gemfile_steep/Gemfile.lock +4 -4
- data/lib/steep/ast/types/logic.rb +6 -0
- data/lib/steep/cli.rb +39 -19
- data/lib/steep/interface/builder.rb +9 -0
- data/lib/steep/path_helper.rb +2 -0
- data/lib/steep/server/change_buffer.rb +9 -0
- data/lib/steep/server/delay_queue.rb +41 -0
- data/lib/steep/server/interaction_worker.rb +4 -2
- data/lib/steep/server/master.rb +106 -10
- data/lib/steep/server/type_check_worker.rb +10 -3
- data/lib/steep/services/completion_provider.rb +1 -1
- data/lib/steep/services/stats_calculator.rb +2 -2
- data/lib/steep/services/type_name_completion.rb +86 -15
- data/lib/steep/signature/validator.rb +9 -2
- data/lib/steep/subtyping/check.rb +24 -18
- data/lib/steep/type_construction.rb +60 -18
- data/lib/steep/type_inference/logic_type_interpreter.rb +26 -0
- data/lib/steep/type_inference/method_params.rb +1 -1
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +1 -3
- data/sig/shims/language-server_protocol.rbs +12 -0
- data/sig/steep/ast/types/logic.rbs +5 -0
- data/sig/steep/ast/types.rbs +1 -1
- data/sig/steep/cli.rbs +2 -0
- data/sig/steep/diagnostic/ruby.rbs +7 -7
- data/sig/steep/server/change_buffer.rbs +4 -0
- data/sig/steep/server/delay_queue.rbs +37 -0
- data/sig/steep/server/master.rbs +4 -0
- data/sig/steep/services/stats_calculator.rbs +30 -6
- data/sig/steep/services/type_name_completion.rbs +13 -0
- data/sig/steep/signature/validator.rbs +5 -0
- data/sig/steep/subtyping/check.rbs +1 -1
- data/sig/steep/subtyping/relation.rbs +11 -1
- data/sig/steep/subtyping/result.rbs +1 -1
- data/sig/steep/type_construction.rbs +1 -1
- data/smoke/block/test_expectations.yml +10 -14
- data/smoke/enumerator/test_expectations.yml +10 -10
- data/smoke/integer/test_expectations.yml +5 -16
- data/smoke/regression/hello world.rb +1 -0
- data/smoke/regression/test_expectations.yml +12 -0
- data/steep.gemspec +1 -1
- metadata +8 -7
- data/lib/steep/shims/filter_map.rb +0 -30
- data/lib/steep/shims/symbol_start_with.rb +0 -18
@@ -98,19 +98,19 @@ module Steep
|
|
98
98
|
end
|
99
99
|
|
100
100
|
class UnresolvedOverloading < Base
|
101
|
-
attr_reader node:
|
101
|
+
attr_reader node (): Parser::AST::Node
|
102
102
|
|
103
|
-
attr_reader receiver_type:
|
103
|
+
attr_reader receiver_type: AST::Types::t
|
104
104
|
|
105
|
-
attr_reader method_name:
|
105
|
+
attr_reader method_name: Symbol
|
106
106
|
|
107
|
-
attr_reader method_types:
|
107
|
+
attr_reader method_types: Array[Interface::MethodType]
|
108
108
|
|
109
|
-
def initialize: (node:
|
109
|
+
def initialize: (node: Parser::AST::Node, receiver_type: AST::Types::t, method_name: Symbol, method_types: Array[Interface::MethodType]) -> void
|
110
110
|
|
111
|
-
def header_line: () ->
|
111
|
+
def header_line: () -> String
|
112
112
|
|
113
|
-
def detail_lines: () ->
|
113
|
+
def detail_lines: () -> String
|
114
114
|
end
|
115
115
|
|
116
116
|
class ArgumentTypeMismatch < Base
|
@@ -27,6 +27,10 @@ module Steep
|
|
27
27
|
# Load changes from a request with `DidChangeTextDocumentParams` into `buffered_changes`
|
28
28
|
#
|
29
29
|
def collect_changes: (untyped request) -> void
|
30
|
+
|
31
|
+
# Reset the content of `uri` to `text`
|
32
|
+
#
|
33
|
+
def reset_change: (uri: String, text: String) -> void
|
30
34
|
end
|
31
35
|
end
|
32
36
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Steep
|
2
|
+
module Server
|
3
|
+
# DelayQueue provides a queue that delays running given job
|
4
|
+
#
|
5
|
+
# 1. The `delay` is specific to a DelayQueue instance, not job specific
|
6
|
+
# 2. It executes only the last job
|
7
|
+
#
|
8
|
+
# ```ruby
|
9
|
+
# queue = DelayQueue.new(delay: 0.5)
|
10
|
+
# queue.execute { pp 1 }
|
11
|
+
# queue.execute { pp 2 }
|
12
|
+
# queue.execute { pp 3 }
|
13
|
+
#
|
14
|
+
# # => Will print only `3`, and the jobs printing `1` and `2` will be discarded
|
15
|
+
# ```
|
16
|
+
#
|
17
|
+
# The job will run on `#thread`.
|
18
|
+
#
|
19
|
+
class DelayQueue
|
20
|
+
attr_reader delay: Float
|
21
|
+
|
22
|
+
attr_reader thread: Thread
|
23
|
+
|
24
|
+
attr_reader queue: Thread::Queue
|
25
|
+
|
26
|
+
attr_reader last_task: Proc
|
27
|
+
|
28
|
+
def initialize: (delay: Float) -> void
|
29
|
+
|
30
|
+
# The `#execute` method is not thread safe
|
31
|
+
#
|
32
|
+
# You should synchronize yourself if you want to call the method from multiple threads.
|
33
|
+
#
|
34
|
+
def execute: () { () -> void } -> void
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/sig/steep/server/master.rbs
CHANGED
@@ -225,6 +225,8 @@ module Steep
|
|
225
225
|
|
226
226
|
attr_accessor typecheck_automatically: bool
|
227
227
|
|
228
|
+
attr_reader start_type_checking_queue: DelayQueue
|
229
|
+
|
228
230
|
def initialize: (project: Project, reader: untyped, writer: untyped, interaction_worker: WorkerProcess?, typecheck_workers: Array[WorkerProcess], ?queue: Thread::Queue) -> void
|
229
231
|
|
230
232
|
# Start the Steep language server
|
@@ -252,6 +254,8 @@ module Steep
|
|
252
254
|
|
253
255
|
def work_done_progress_supported?: () -> bool
|
254
256
|
|
257
|
+
def file_system_watcher_supported?: () -> bool
|
258
|
+
|
255
259
|
def process_message_from_client: (untyped message) -> void
|
256
260
|
|
257
261
|
def process_message_from_worker: (untyped message, worker: WorkerProcess) -> void
|
@@ -1,17 +1,41 @@
|
|
1
1
|
module Steep
|
2
2
|
module Services
|
3
3
|
class StatsCalculator
|
4
|
-
SuccessStats
|
4
|
+
class SuccessStats
|
5
|
+
attr_reader target: Project::Target
|
5
6
|
|
6
|
-
|
7
|
+
attr_reader path: Pathname
|
7
8
|
|
8
|
-
|
9
|
+
attr_reader typed_calls_count: Integer
|
9
10
|
|
10
|
-
|
11
|
+
attr_reader untyped_calls_count: Integer
|
11
12
|
|
12
|
-
|
13
|
+
attr_reader error_calls_count: Integer
|
13
14
|
|
14
|
-
|
15
|
+
def initialize: (target: Project::Target, path: Pathname, typed_calls_count: Integer, untyped_calls_count: Integer, error_calls_count: Integer) -> void
|
16
|
+
|
17
|
+
def as_json: () -> Hash[Symbol, untyped]
|
18
|
+
end
|
19
|
+
|
20
|
+
class ErrorStats
|
21
|
+
attr_reader target: Project::Target
|
22
|
+
|
23
|
+
attr_reader path: Pathname
|
24
|
+
|
25
|
+
def initialize: (target: Project::Target, path: Pathname) -> void
|
26
|
+
|
27
|
+
def as_json: () -> Hash[Symbol, untyped]
|
28
|
+
end
|
29
|
+
|
30
|
+
type stats = SuccessStats | ErrorStats
|
31
|
+
|
32
|
+
attr_reader service: TypeCheckService
|
33
|
+
|
34
|
+
def initialize: (service: TypeCheckService) -> void
|
35
|
+
|
36
|
+
def project: () -> Project
|
37
|
+
|
38
|
+
def calc_stats: (Project::Target target, file: TypeCheckService::SourceFile) -> stats
|
15
39
|
end
|
16
40
|
end
|
17
41
|
end
|
@@ -112,9 +112,22 @@ module Steep
|
|
112
112
|
|
113
113
|
def format_constant_name: (TypeName) -> String
|
114
114
|
|
115
|
+
def resolve_used_name: (TypeName) -> TypeName?
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
# Yield type names defined in the environment
|
120
|
+
#
|
121
|
+
# * Yields an absolute type name if it is defined in the environment
|
122
|
+
# * Yields an relative type name if it is imported with `use` declerative
|
123
|
+
#
|
124
|
+
# Alias classes/modules and types under them are yielded.
|
125
|
+
#
|
115
126
|
def each_type_name: () { (TypeName) -> void } -> void
|
116
127
|
| () -> Enumerator[TypeName, void]
|
117
128
|
|
129
|
+
def each_type_name_under: (TypeName module_name, TypeName normalized_name, table: Hash[Namespace, Array[TypeName]]) { (TypeName) -> void } -> void
|
130
|
+
|
118
131
|
def each_outer_module: (?Resolver::context) { (Namespace) -> void } -> Namespace
|
119
132
|
| () -> Enumerator[Namespace, void]
|
120
133
|
end
|
@@ -66,6 +66,11 @@ module Steep
|
|
66
66
|
|
67
67
|
def validate_one_global: (Symbol name, RBS::Environment::GlobalEntry) -> void
|
68
68
|
|
69
|
+
# Validate type alias
|
70
|
+
#
|
71
|
+
# 1. Make sure the outer namespace of given `name` exists
|
72
|
+
# 2. Make sure the type alias is valid with respect to `RBS::Validator`
|
73
|
+
#
|
69
74
|
def validate_one_alias: (RBS::TypeName name, ?RBS::Environment::TypeAliasEntry entry) -> void
|
70
75
|
|
71
76
|
def validate_one_class_decl: (RBS::TypeName) -> void
|
@@ -123,7 +123,7 @@ module Steep
|
|
123
123
|
# Returns nil if there is no path.
|
124
124
|
def hole_path: (AST::Types::t `type`, ?Array[AST::Types::t] path) -> Array[AST::Types::t]?
|
125
125
|
|
126
|
-
def Relation: [T <
|
126
|
+
def Relation: [T < Relation::_Subject] (T sub, T sup) -> Relation[T]
|
127
127
|
end
|
128
128
|
end
|
129
129
|
end
|
@@ -1,6 +1,16 @@
|
|
1
1
|
module Steep
|
2
2
|
module Subtyping
|
3
|
-
class Relation[out Subject <
|
3
|
+
class Relation[out Subject < _Subject]
|
4
|
+
interface _Subject
|
5
|
+
def hash: () -> Integer
|
6
|
+
|
7
|
+
def is_a?: (Module) -> bool
|
8
|
+
|
9
|
+
def class: () -> Class
|
10
|
+
|
11
|
+
def !: () -> bool
|
12
|
+
end
|
13
|
+
|
4
14
|
attr_reader sub_type: Subject
|
5
15
|
|
6
16
|
attr_reader super_type: Subject
|
@@ -45,7 +45,7 @@ module Steep
|
|
45
45
|
@failure: bool
|
46
46
|
|
47
47
|
# Returns `false` if no future `#add` changes the result.
|
48
|
-
def add: [T <
|
48
|
+
def add: [T < Relation::_Subject] (*Relation[T] relations) { (Relation[T]) -> t? } -> bool
|
49
49
|
|
50
50
|
# Returns `false` if no future `#add` changes the result.
|
51
51
|
def add_result: (t?) -> bool
|
@@ -271,7 +271,7 @@ module Steep
|
|
271
271
|
def calculate_interface: (AST::Types::t `type`, private: bool) -> Interface::Shape?
|
272
272
|
| (AST::Types::t `type`, Symbol method_name, private: bool) -> Interface::Shape::Entry?
|
273
273
|
|
274
|
-
def expand_self: (
|
274
|
+
def expand_self: (AST::Types::t `type`) -> AST::Types::t
|
275
275
|
|
276
276
|
SPECIAL_METHOD_NAMES: Hash[Symbol, Set[method_name]]
|
277
277
|
|
@@ -98,31 +98,27 @@
|
|
98
98
|
- range:
|
99
99
|
start:
|
100
100
|
line: 10
|
101
|
-
character:
|
101
|
+
character: 12
|
102
102
|
end:
|
103
103
|
line: 10
|
104
|
-
character:
|
104
|
+
character: 28
|
105
105
|
severity: ERROR
|
106
106
|
message: |-
|
107
|
-
Cannot
|
108
|
-
|
109
|
-
|
110
|
-
| () -> ::Enumerator[::Integer, ::Array[untyped]]
|
111
|
-
code: Ruby::UnresolvedOverloading
|
107
|
+
Cannot pass a value of type `::Proc` as a block-pass-argument of type `^(::Integer) -> U(3)`
|
108
|
+
::Proc <: ^(::Integer) -> U(3)
|
109
|
+
code: Ruby::BlockTypeMismatch
|
112
110
|
- range:
|
113
111
|
start:
|
114
112
|
line: 11
|
115
|
-
character:
|
113
|
+
character: 12
|
116
114
|
end:
|
117
115
|
line: 11
|
118
|
-
character:
|
116
|
+
character: 20
|
119
117
|
severity: ERROR
|
120
118
|
message: |-
|
121
|
-
Cannot
|
122
|
-
|
123
|
-
|
124
|
-
| () -> ::Enumerator[::Integer, ::Array[untyped]]
|
125
|
-
code: Ruby::UnresolvedOverloading
|
119
|
+
Cannot pass a value of type `::Proc` as a block-pass-argument of type `^(::Integer) -> U(4)`
|
120
|
+
::Proc <: ^(::Integer) -> U(4)
|
121
|
+
code: Ruby::BlockTypeMismatch
|
126
122
|
- file: e.rb
|
127
123
|
diagnostics:
|
128
124
|
- range:
|
@@ -10,11 +10,11 @@
|
|
10
10
|
character: 3
|
11
11
|
severity: ERROR
|
12
12
|
message: |-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
code: Ruby::
|
13
|
+
Unsatisfiable constraint `::String <: U(1) <: ::Hash[::Symbol, ::String]` is generated through (U(1)) { (::Integer, U(1)) -> untyped } -> U(1)
|
14
|
+
::String <: ::Hash[::Symbol, ::String]
|
15
|
+
::Object <: ::Hash[::Symbol, ::String]
|
16
|
+
::BasicObject <: ::Hash[::Symbol, ::String]
|
17
|
+
code: Ruby::UnsatisfiableConstraint
|
18
18
|
- file: b.rb
|
19
19
|
diagnostics:
|
20
20
|
- range:
|
@@ -40,8 +40,8 @@
|
|
40
40
|
character: 3
|
41
41
|
severity: ERROR
|
42
42
|
message: |-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
code: Ruby::
|
43
|
+
Unsatisfiable constraint `::Array[untyped] <: U(3) <: ::String` is generated through (U(3)) { (::Integer, U(3)) -> untyped } -> U(3)
|
44
|
+
::Array[untyped] <: ::String
|
45
|
+
::Object <: ::String
|
46
|
+
::BasicObject <: ::String
|
47
|
+
code: Ruby::UnsatisfiableConstraint
|
@@ -102,20 +102,9 @@
|
|
102
102
|
message: |-
|
103
103
|
Cannot find compatible overloading of method `Integer` of type `::Object`
|
104
104
|
Method types:
|
105
|
-
def Integer: ((::
|
106
|
-
| (::
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
line: 26
|
111
|
-
character: 0
|
112
|
-
end:
|
113
|
-
line: 26
|
114
|
-
character: 12
|
115
|
-
severity: ERROR
|
116
|
-
message: |-
|
117
|
-
Cannot find compatible overloading of method `Integer` of type `::Object`
|
118
|
-
Method types:
|
119
|
-
def Integer: ((::Numeric | ::String), ?exception: bool) -> ::Integer
|
120
|
-
| (::String, ?::Integer, ?exception: bool) -> ::Integer
|
105
|
+
def Integer: ((::_ToInt | ::_ToI), ?exception: true) -> ::Integer
|
106
|
+
| ((::_ToInt | ::_ToI), exception: bool) -> (::Integer | nil)
|
107
|
+
| (::string, ?::int, ?exception: true) -> ::Integer
|
108
|
+
| (::string, ?::int, exception: bool) -> (::Integer | nil)
|
109
|
+
| (untyped, ?untyped, exception: false) -> nil
|
121
110
|
code: Ruby::UnresolvedOverloading
|
@@ -0,0 +1 @@
|
|
1
|
+
1.foo()
|
@@ -35,6 +35,18 @@
|
|
35
35
|
severity: ERROR
|
36
36
|
message: 'Cannot find the declaration of class: `Foo`'
|
37
37
|
code: Ruby::UnknownConstant
|
38
|
+
- file: hello world.rb
|
39
|
+
diagnostics:
|
40
|
+
- range:
|
41
|
+
start:
|
42
|
+
line: 1
|
43
|
+
character: 2
|
44
|
+
end:
|
45
|
+
line: 1
|
46
|
+
character: 5
|
47
|
+
severity: ERROR
|
48
|
+
message: Type `::Integer` does not have method `foo`
|
49
|
+
code: Ruby::NoMethod
|
38
50
|
- file: issue_332.rb
|
39
51
|
diagnostics:
|
40
52
|
- range:
|
data/steep.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
27
|
spec.require_paths = ["lib"]
|
28
28
|
|
29
|
-
spec.required_ruby_version = '>=
|
29
|
+
spec.required_ruby_version = '>= 3.0.0'
|
30
30
|
|
31
31
|
spec.add_runtime_dependency "parser", ">= 3.1"
|
32
32
|
spec.add_runtime_dependency "activesupport", ">= 5.1"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0.pre.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soutaro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -332,6 +332,7 @@ files:
|
|
332
332
|
- lib/steep/range_extension.rb
|
333
333
|
- lib/steep/server/base_worker.rb
|
334
334
|
- lib/steep/server/change_buffer.rb
|
335
|
+
- lib/steep/server/delay_queue.rb
|
335
336
|
- lib/steep/server/interaction_worker.rb
|
336
337
|
- lib/steep/server/lsp_formatter.rb
|
337
338
|
- lib/steep/server/master.rb
|
@@ -350,8 +351,6 @@ files:
|
|
350
351
|
- lib/steep/services/stats_calculator.rb
|
351
352
|
- lib/steep/services/type_check_service.rb
|
352
353
|
- lib/steep/services/type_name_completion.rb
|
353
|
-
- lib/steep/shims/filter_map.rb
|
354
|
-
- lib/steep/shims/symbol_start_with.rb
|
355
354
|
- lib/steep/signature/validator.rb
|
356
355
|
- lib/steep/source.rb
|
357
356
|
- lib/steep/subtyping/cache.rb
|
@@ -467,6 +466,7 @@ files:
|
|
467
466
|
- sig/steep/range_extension.rbs
|
468
467
|
- sig/steep/server/base_worker.rbs
|
469
468
|
- sig/steep/server/change_buffer.rbs
|
469
|
+
- sig/steep/server/delay_queue.rbs
|
470
470
|
- sig/steep/server/interaction_worker.rbs
|
471
471
|
- sig/steep/server/lsp_formatter.rbs
|
472
472
|
- sig/steep/server/master.rbs
|
@@ -712,6 +712,7 @@ files:
|
|
712
712
|
- smoke/regression/fun.rb
|
713
713
|
- smoke/regression/fun.rbs
|
714
714
|
- smoke/regression/hash.rb
|
715
|
+
- smoke/regression/hello world.rb
|
715
716
|
- smoke/regression/issue_328.rb
|
716
717
|
- smoke/regression/issue_328.rbs
|
717
718
|
- smoke/regression/issue_332.rb
|
@@ -777,12 +778,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
777
778
|
requirements:
|
778
779
|
- - ">="
|
779
780
|
- !ruby/object:Gem::Version
|
780
|
-
version:
|
781
|
+
version: 3.0.0
|
781
782
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
782
783
|
requirements:
|
783
|
-
- - "
|
784
|
+
- - ">"
|
784
785
|
- !ruby/object:Gem::Version
|
785
|
-
version:
|
786
|
+
version: 1.3.1
|
786
787
|
requirements: []
|
787
788
|
rubygems_version: 3.4.10
|
788
789
|
signing_key:
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# Steep runs on Ruby 2.6 and it needs a shim of `filter_map`
|
2
|
-
|
3
|
-
module Shims
|
4
|
-
module EnumerableFilterMap
|
5
|
-
def filter_map(&block)
|
6
|
-
if block
|
7
|
-
result = []
|
8
|
-
|
9
|
-
each do |element|
|
10
|
-
if value = yield(element)
|
11
|
-
result << value
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
result
|
16
|
-
else
|
17
|
-
enum_for :filter_map
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
unless Enumerable.method_defined?(:filter_map)
|
23
|
-
Enumerable.include EnumerableFilterMap
|
24
|
-
|
25
|
-
module ::Enumerable
|
26
|
-
alias filter_map filter_map
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# Steep runs on Ruby 2.6 and it needs a shim of `Symbol#start_with?`
|
2
|
-
|
3
|
-
module Shims
|
4
|
-
module SymbolStartWith
|
5
|
-
def start_with?(*args)
|
6
|
-
to_s.start_with?(*args)
|
7
|
-
end
|
8
|
-
|
9
|
-
def end_with?(*args)
|
10
|
-
to_s.end_with?(*args)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
unless Symbol.method_defined?(:start_with?)
|
15
|
-
Symbol.include(SymbolStartWith)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|