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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5bc8e25ce0d9d4c9946d0100d3a011ca486086997b4ba86644939cfed1a9b08
4
- data.tar.gz: 7d4c26a383e9387a9f4c15c09f488eb24dc5d7ede91b9acc8da1d033f32389ff
3
+ metadata.gz: 123376eb779b7118cfc9fb097cbd2bd028c4ce154526d5c79339902b170ad2c3
4
+ data.tar.gz: b6b4c6e49b3f998103582a7c416a5f3603cb9204ab672b2c4b4f911eebc8adcb
5
5
  SHA512:
6
- metadata.gz: d491cda774d07a99a41be32e9bf7559104d84a68bb36ba590e70d1592a1a4cda40a1bba416c50969279b7e6c1cfd3f4b80274d32e7ef29fa8b71851de4d214f7
7
- data.tar.gz: 5140446569e665f76971fbf4dec158a664f8e2e4ae32339480069288c1e3fdbbc50237db5999c3f9d124190859a334696dcb579f09009762c25aa5bdd3361edc
6
+ metadata.gz: 0f5df26d1601a390adba84efabadd1a6947c601df83ab48fb538dea000b1cc05bb26dffd894f2c7c8c198c2c63e54972e695390de21b9580249b283e6a54d3d4
7
+ data.tar.gz: c8e99c6e9247fbec030279f02891ba2aa6d2b217b7c8a61f9decc0afa308841245088785e21590858cc5e73f79827cf1515f4e9fa399ffcab18637e6851ac292
@@ -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)
@@ -70,6 +70,7 @@ require "steep/drivers/check"
70
70
  require "steep/drivers/validate"
71
71
  require "steep/drivers/annotations"
72
72
  require "steep/drivers/scaffold"
73
+ require "steep/drivers/print_interface"
73
74
 
74
75
  if ENV["NO_COLOR"]
75
76
  Rainbow.enabled = false
@@ -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.methods.empty? && mod.singleton_methods.empty?
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
 
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -0,0 +1,8 @@
1
+ class A
2
+ def write_to(io:)
3
+ io.puts "Hello World"
4
+ end
5
+ end
6
+
7
+ A.new(STDOUT)
8
+ A.new(StringIO.new)
@@ -0,0 +1,7 @@
1
+ interface _Puts
2
+ def puts: (*any) -> void
3
+ end
4
+
5
+ class A
6
+ def write_to: (io: _Puts) -> void
7
+ end
@@ -532,7 +532,12 @@ end
532
532
  class Regexp
533
533
  end
534
534
 
535
- class File
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.2.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-30 00:00:00.000000000 Z
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