steep 0.2.0 → 0.3.0
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 +10 -0
- data/lib/steep.rb +1 -0
- data/lib/steep/cli.rb +26 -2
- data/lib/steep/drivers/print_interface.rb +60 -0
- data/lib/steep/drivers/scaffold.rb +15 -1
- data/lib/steep/parser.y +7 -0
- data/lib/steep/type_construction.rb +14 -0
- data/lib/steep/version.rb +1 -1
- data/smoke/stdout/a.rb +8 -0
- data/smoke/stdout/a.rbi +7 -0
- data/stdlib/builtin.rbi +13 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 123376eb779b7118cfc9fb097cbd2bd028c4ce154526d5c79339902b170ad2c3
|
4
|
+
data.tar.gz: b6b4c6e49b3f998103582a7c416a5f3603cb9204ab672b2c4b4f911eebc8adcb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f5df26d1601a390adba84efabadd1a6947c601df83ab48fb538dea000b1cc05bb26dffd894f2c7c8c198c2c63e54972e695390de21b9580249b283e6a54d3d4
|
7
|
+
data.tar.gz: c8e99c6e9247fbec030279f02891ba2aa6d2b217b7c8a61f9decc0afa308841245088785e21590858cc5e73f79827cf1515f4e9fa399ffcab18637e6851ac292
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.3.0 (2018-05-31)
|
6
|
+
|
7
|
+
* Add `interface` command to print interface built for given type
|
8
|
+
* Add `--strict` option for `check` command
|
9
|
+
* Fix `scaffold` command for empty class/modules
|
10
|
+
* Type check method definition with empty body
|
11
|
+
* Add `STDOUT` and `StringIO` minimal definition
|
12
|
+
* Fix validate command to load stdlib
|
13
|
+
* Fix parsing keyword argument type
|
14
|
+
|
5
15
|
## 0.2.0 (2018-05-30)
|
6
16
|
|
7
17
|
* Add `attr_reader` and `attr_accessor` syntax to signature (#33)
|
data/lib/steep.rb
CHANGED
data/lib/steep/cli.rb
CHANGED
@@ -16,7 +16,7 @@ module Steep
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.available_commands
|
19
|
-
[:check, :validate, :annotations, :scaffold]
|
19
|
+
[:check, :validate, :annotations, :scaffold, :interface]
|
20
20
|
end
|
21
21
|
|
22
22
|
def setup_global_options
|
@@ -47,12 +47,14 @@ module Steep
|
|
47
47
|
no_builtin = false
|
48
48
|
dump_all_types = false
|
49
49
|
fallback_any_is_error = false
|
50
|
+
strict = false
|
50
51
|
|
51
52
|
OptionParser.new do |opts|
|
52
53
|
opts.on("-I [PATH]") {|path| signature_dirs << Pathname(path) }
|
53
54
|
opts.on("--no-builtin") { no_builtin = true }
|
54
55
|
opts.on("--verbose") { verbose = true }
|
55
56
|
opts.on("--dump-all-types") { dump_all_types = true }
|
57
|
+
opts.on("--strict") { strict = true }
|
56
58
|
opts.on("--fallback-any-is-error") { fallback_any_is_error = true }
|
57
59
|
end.parse!(argv)
|
58
60
|
|
@@ -72,15 +74,17 @@ module Steep
|
|
72
74
|
Drivers::Check.new(source_paths: source_paths, signature_dirs: signature_dirs, stdout: stdout, stderr: stderr).tap do |check|
|
73
75
|
check.verbose = verbose
|
74
76
|
check.dump_all_types = dump_all_types
|
75
|
-
check.fallback_any_is_error = fallback_any_is_error
|
77
|
+
check.fallback_any_is_error = fallback_any_is_error || strict
|
76
78
|
end.run
|
77
79
|
end
|
78
80
|
|
79
81
|
def process_validate
|
80
82
|
verbose = false
|
83
|
+
no_builtin = false
|
81
84
|
|
82
85
|
OptionParser.new do |opts|
|
83
86
|
opts.on("--verbose") { verbose = true }
|
87
|
+
opts.on("--no-builtin") { no_builtin = true }
|
84
88
|
end.parse!(argv)
|
85
89
|
|
86
90
|
signature_dirs = argv.map {|path| Pathname(path) }
|
@@ -88,6 +92,10 @@ module Steep
|
|
88
92
|
signature_dirs << Pathname(".")
|
89
93
|
end
|
90
94
|
|
95
|
+
unless no_builtin
|
96
|
+
signature_dirs.unshift Pathname(__dir__).join("../../stdlib").realpath
|
97
|
+
end
|
98
|
+
|
91
99
|
Drivers::Validate.new(signature_dirs: signature_dirs, stdout: stdout, stderr: stderr).tap do |validate|
|
92
100
|
validate.verbose = verbose
|
93
101
|
end.run
|
@@ -102,5 +110,21 @@ module Steep
|
|
102
110
|
source_paths = argv.map {|file| Pathname(file) }
|
103
111
|
Drivers::Scaffold.new(source_paths: source_paths, stdout: stdout, stderr: stderr).run
|
104
112
|
end
|
113
|
+
|
114
|
+
def process_interface
|
115
|
+
signature_dirs = []
|
116
|
+
no_builtin = false
|
117
|
+
|
118
|
+
OptionParser.new do |opts|
|
119
|
+
opts.on("-I [PATH]") {|path| signature_dirs << Pathname(path) }
|
120
|
+
opts.on("--no-builtin") { no_builtin = true }
|
121
|
+
end
|
122
|
+
|
123
|
+
unless no_builtin
|
124
|
+
signature_dirs.unshift Pathname(__dir__).join("../../stdlib").realpath
|
125
|
+
end
|
126
|
+
|
127
|
+
Drivers::PrintInterface.new(type_name: argv.first, signature_dirs: signature_dirs, stdout: stdout, stderr: stderr).run
|
128
|
+
end
|
105
129
|
end
|
106
130
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Steep
|
2
|
+
module Drivers
|
3
|
+
class PrintInterface
|
4
|
+
attr_reader :type_name
|
5
|
+
attr_reader :signature_dirs
|
6
|
+
attr_reader :stdout
|
7
|
+
attr_reader :stderr
|
8
|
+
|
9
|
+
include Utils::EachSignature
|
10
|
+
|
11
|
+
def initialize(type_name:, signature_dirs:, stdout:, stderr:)
|
12
|
+
@type_name = type_name
|
13
|
+
@signature_dirs = signature_dirs
|
14
|
+
@stdout = stdout
|
15
|
+
@stderr = stderr
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
if type_name
|
20
|
+
type = Parser.parse_type(type_name)
|
21
|
+
|
22
|
+
env = AST::Signature::Env.new
|
23
|
+
|
24
|
+
each_signature(signature_dirs, false) do |signature|
|
25
|
+
env.add signature
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
builder = Interface::Builder.new(signatures: env)
|
30
|
+
check = Subtyping::Check.new(builder: builder)
|
31
|
+
|
32
|
+
interface = check.resolve(type, with_initialize: true)
|
33
|
+
|
34
|
+
stdout.puts "#{type}"
|
35
|
+
stdout.puts "- Instance variables:"
|
36
|
+
interface.ivars.each do |name, type|
|
37
|
+
puts " - #{name}: #{type}"
|
38
|
+
end
|
39
|
+
stdout.puts "- Methods:"
|
40
|
+
interface.methods.each do |name, method|
|
41
|
+
puts " - #{Rainbow(name).blue}:"
|
42
|
+
method.types.each do |method_type|
|
43
|
+
loc = if method_type.location
|
44
|
+
"#{method_type.location.buffer.name}:#{method_type.location.to_s}"
|
45
|
+
else
|
46
|
+
"no location"
|
47
|
+
end
|
48
|
+
puts " - #{Rainbow(method_type.to_s).red} (#{loc})"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
rescue Steep::Subtyping::Check::CannotResolveError
|
52
|
+
stderr.puts "🤔 #{Rainbow(type.to_s).red} cannot be resolved to interface"
|
53
|
+
end
|
54
|
+
else
|
55
|
+
stderr.puts "Pass a type name to command line"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -45,6 +45,12 @@ module Steep
|
|
45
45
|
def module?
|
46
46
|
kind == :module
|
47
47
|
end
|
48
|
+
|
49
|
+
attr_accessor :has_subclass
|
50
|
+
|
51
|
+
def namespace_class?
|
52
|
+
has_subclass && methods.empty? && singleton_methods.empty?
|
53
|
+
end
|
48
54
|
end
|
49
55
|
|
50
56
|
attr_reader :source
|
@@ -63,7 +69,7 @@ module Steep
|
|
63
69
|
generate(source.node, current_path: [])
|
64
70
|
|
65
71
|
modules.each do |mod|
|
66
|
-
unless mod.
|
72
|
+
unless mod.namespace_class?
|
67
73
|
io.puts "#{mod.kind} #{mod.name}"
|
68
74
|
|
69
75
|
mod.ivars.each do |name, type|
|
@@ -119,6 +125,10 @@ module Steep
|
|
119
125
|
current_module: mod)
|
120
126
|
end
|
121
127
|
|
128
|
+
if current_module
|
129
|
+
current_module.has_subclass = true
|
130
|
+
end
|
131
|
+
|
122
132
|
when :class
|
123
133
|
name = module_name(node.children[0])
|
124
134
|
klass = Module.new(name: full_name(current_path, name), kind: :class)
|
@@ -130,6 +140,10 @@ module Steep
|
|
130
140
|
current_module: klass)
|
131
141
|
end
|
132
142
|
|
143
|
+
if current_module
|
144
|
+
current_module.has_subclass = true
|
145
|
+
end
|
146
|
+
|
133
147
|
when :def
|
134
148
|
name, args, body = node.children
|
135
149
|
|
data/lib/steep/parser.y
CHANGED
@@ -7,6 +7,7 @@ rule
|
|
7
7
|
target: type_METHOD method_type { result = val[1] }
|
8
8
|
| type_SIGNATURE signatures { result = val[1] }
|
9
9
|
| type_ANNOTATION annotation { result = val[1] }
|
10
|
+
| type_TYPE type { result = val[1] }
|
10
11
|
|
11
12
|
method_type:
|
12
13
|
type_params params block_opt ARROW return_type {
|
@@ -202,6 +203,8 @@ keyword: IDENT
|
|
202
203
|
| INSTANCE
|
203
204
|
| BLOCK
|
204
205
|
| INCLUDE
|
206
|
+
| IVAR
|
207
|
+
| SELF
|
205
208
|
|
206
209
|
signatures: { result = [] }
|
207
210
|
| interface signatures { result = [val[0]] + val[1] }
|
@@ -545,6 +548,10 @@ rescue => exn
|
|
545
548
|
nil
|
546
549
|
end
|
547
550
|
|
551
|
+
def self.parse_type(input, name: nil)
|
552
|
+
new(:TYPE, buffer: AST::Buffer.new(name: name, content: input), offset: 0).do_parse
|
553
|
+
end
|
554
|
+
|
548
555
|
class LocatedValue
|
549
556
|
attr_reader :location
|
550
557
|
attr_reader :value
|
@@ -647,6 +647,20 @@ module Steep
|
|
647
647
|
else
|
648
648
|
new.synthesize(node.children[2])
|
649
649
|
end
|
650
|
+
else
|
651
|
+
return_type = new.method_context&.return_type
|
652
|
+
if return_type && !return_type.is_a?(AST::Types::Void)
|
653
|
+
result = checker.check(
|
654
|
+
Subtyping::Relation.new(sub_type: Types.nil_instance, super_type: return_type),
|
655
|
+
constraints: Subtyping::Constraints.empty
|
656
|
+
)
|
657
|
+
if result.failure?
|
658
|
+
typing.add_error(Errors::MethodBodyTypeMismatch.new(node: node,
|
659
|
+
expected: return_type,
|
660
|
+
actual: Types.nil_instance,
|
661
|
+
result: result))
|
662
|
+
end
|
663
|
+
end
|
650
664
|
end
|
651
665
|
|
652
666
|
if module_context
|
data/lib/steep/version.rb
CHANGED
data/smoke/stdout/a.rb
ADDED
data/smoke/stdout/a.rbi
ADDED
data/stdlib/builtin.rbi
CHANGED
@@ -532,7 +532,12 @@ end
|
|
532
532
|
class Regexp
|
533
533
|
end
|
534
534
|
|
535
|
-
class
|
535
|
+
class IO
|
536
|
+
def gets: -> (String | nil)
|
537
|
+
def puts: (*any) -> void
|
538
|
+
end
|
539
|
+
|
540
|
+
class File <: IO
|
536
541
|
def self.binread: (String) -> String
|
537
542
|
def self.extname: (String) -> String
|
538
543
|
def self.basename: (String) -> String
|
@@ -541,3 +546,10 @@ class File
|
|
541
546
|
def self.read: (String) -> String
|
542
547
|
| (String, Integer | nil) -> (String | nil)
|
543
548
|
end
|
549
|
+
|
550
|
+
STDOUT: IO
|
551
|
+
|
552
|
+
class StringIO
|
553
|
+
def initialize: (?String, ?String) -> any
|
554
|
+
def puts: (*any) -> void
|
555
|
+
end
|
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: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soutaro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -170,6 +170,7 @@ files:
|
|
170
170
|
- lib/steep/cli.rb
|
171
171
|
- lib/steep/drivers/annotations.rb
|
172
172
|
- lib/steep/drivers/check.rb
|
173
|
+
- lib/steep/drivers/print_interface.rb
|
173
174
|
- lib/steep/drivers/scaffold.rb
|
174
175
|
- lib/steep/drivers/utils/each_signature.rb
|
175
176
|
- lib/steep/drivers/utils/validator.rb
|
@@ -253,6 +254,8 @@ files:
|
|
253
254
|
- smoke/rescue/a.rb
|
254
255
|
- smoke/self/a.rb
|
255
256
|
- smoke/self/a.rbi
|
257
|
+
- smoke/stdout/a.rb
|
258
|
+
- smoke/stdout/a.rbi
|
256
259
|
- smoke/super/a.rb
|
257
260
|
- smoke/super/a.rbi
|
258
261
|
- smoke/type_case/a.rb
|