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 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