steep 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|