typerb 0.1.6 → 0.1.7

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: 1ce9f42a58f215a179f850016e0f647a4e16b4f23b3021d7cd17a43960857439
4
- data.tar.gz: 9bb4dc2cb1f2396c7ccfd773d27a2d85e0d11f3a66ef54537e9c809594795d5a
3
+ metadata.gz: f7cef67daf67692e132e69a417bc8d7ea8162c56e87f7c058b5d095aed720506
4
+ data.tar.gz: 8493a01a0310fe1accb703ee82515b8f59163dc4069117774df00fafd0228113
5
5
  SHA512:
6
- metadata.gz: a35899b9f7f7cc045725241d6eef0d312470016e2945edea86c67696c67f3ba69bbc52743fd51cb0253b6b7bc4f3be30ac9567784269a6f382d46484b9bc2476
7
- data.tar.gz: 58c8a8839809ff2c87801388cca35dca300a565616645a01d9bd59fdea6e6986c74763250093400aaca8d2b91a47cfad8b24b0060b24ae0215a3bdb846617568
6
+ metadata.gz: e69f6c28e078a84bded21be966969c7979ab71f26dff4379b7952026c3ea180422ac68ae82b4e2ef003cd34cb47fd0902f474024758ff756984aaa0f937a7eae
7
+ data.tar.gz: f5ea90611dbd4429a48b11b59ce69d2e6f4e267e7d451916171bb06f680e64f6bec033f1f31dd7c6c6096f510123d1dc2b0aa50932630c0ec6406022bb81e2e9
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /vendor/
9
10
  *.gem
10
11
 
11
12
  # rspec failure tracking
data/.rubocop.yml CHANGED
@@ -2,6 +2,7 @@ AllCops:
2
2
  TargetRubyVersion: 2.4
3
3
  Exclude:
4
4
  - 'bin/**/*'
5
+ - 'Guardfile'
5
6
 
6
7
  inherit_mode:
7
8
  merge:
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- typerb (0.1.6)
4
+ typerb (0.1.7)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -10,8 +10,33 @@ GEM
10
10
  awesome_print (1.8.0)
11
11
  coderay (1.1.2)
12
12
  diff-lcs (1.3)
13
+ ffi (1.9.25)
14
+ formatador (0.2.5)
15
+ guard (2.14.2)
16
+ formatador (>= 0.2.4)
17
+ listen (>= 2.7, < 4.0)
18
+ lumberjack (>= 1.0.12, < 2.0)
19
+ nenv (~> 0.1)
20
+ notiffany (~> 0.0)
21
+ pry (>= 0.9.12)
22
+ shellany (~> 0.0)
23
+ thor (>= 0.18.1)
24
+ guard-compat (1.2.1)
25
+ guard-rspec (4.7.3)
26
+ guard (~> 2.1)
27
+ guard-compat (~> 1.1)
28
+ rspec (>= 2.99.0, < 4.0)
13
29
  jaro_winkler (1.5.1)
30
+ listen (3.1.5)
31
+ rb-fsevent (~> 0.9, >= 0.9.4)
32
+ rb-inotify (~> 0.9, >= 0.9.7)
33
+ ruby_dep (~> 1.2)
34
+ lumberjack (1.0.13)
14
35
  method_source (0.9.1)
36
+ nenv (0.3.0)
37
+ notiffany (0.1.1)
38
+ nenv (~> 0.1)
39
+ shellany (~> 0.0)
15
40
  parallel (1.12.1)
16
41
  parser (2.5.3.0)
17
42
  ast (~> 2.4.0)
@@ -21,6 +46,9 @@ GEM
21
46
  method_source (~> 0.9.0)
22
47
  rainbow (3.0.0)
23
48
  rake (10.5.0)
49
+ rb-fsevent (0.10.3)
50
+ rb-inotify (0.9.10)
51
+ ffi (>= 0.5.0, < 2)
24
52
  rspec (3.8.0)
25
53
  rspec-core (~> 3.8.0)
26
54
  rspec-expectations (~> 3.8.0)
@@ -43,8 +71,11 @@ GEM
43
71
  ruby-progressbar (~> 1.7)
44
72
  unicode-display_width (~> 1.4.0)
45
73
  ruby-progressbar (1.10.0)
74
+ ruby_dep (1.5.0)
75
+ shellany (0.0.1)
46
76
  super_awesome_print (0.2.5)
47
77
  awesome_print
78
+ thor (0.20.0)
48
79
  unicode-display_width (1.4.0)
49
80
 
50
81
  PLATFORMS
@@ -52,6 +83,8 @@ PLATFORMS
52
83
 
53
84
  DEPENDENCIES
54
85
  bundler (>= 1.17)
86
+ guard
87
+ guard-rspec
55
88
  pry
56
89
  rake (>= 10.0)
57
90
  rspec (>= 3.0)
data/Guardfile ADDED
@@ -0,0 +1,36 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+ guard :rspec, cmd: "bundle exec rspec" do
18
+ require "guard/rspec/dsl"
19
+ dsl = Guard::RSpec::Dsl.new(self)
20
+
21
+ # Feel free to open issues for suggestions and improvements
22
+
23
+ # RSpec files
24
+ rspec = dsl.rspec
25
+ watch(rspec.spec_helper) { rspec.spec_dir }
26
+ watch(rspec.spec_support) { rspec.spec_dir }
27
+ watch(rspec.spec_files)
28
+
29
+ # Ruby files
30
+ ruby = dsl.ruby
31
+ dsl.watch_spec_files_for(ruby.lib_files)
32
+
33
+
34
+ # watch(rails.routes) { "#{rspec.spec_dir}/routing" }
35
+ # watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
36
+ end
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # Typerb
5
5
 
6
- Proof of concept type-checking library for Ruby 2.6.
6
+ Proof of concept type-checking library for Ruby 2.6. Works with previous versions too with some limitation (see below).
7
7
 
8
8
  ```ruby
9
9
  class A
@@ -12,9 +12,15 @@ class A
12
12
  def call(some_arg)
13
13
  some_arg.type!(String, Symbol)
14
14
  end
15
+
16
+ def call_with_respond_checks(some_arg)
17
+ some_arg.respond_to!(:strip)
18
+ end
19
+
15
20
  end
16
21
 
17
22
  A.new.call(1) #=> TypeError: `some_arg` should be String or Symbol, not Integer
23
+ A.new.call_with_respond_checks(1) #=> TypeError: 'Integer should respond to all methods: strip'
18
24
  ```
19
25
 
20
26
  This is equivalent to:
@@ -23,6 +29,10 @@ class A
23
29
  def call(some_arg)
24
30
  raise TypeError, "`some_arg` should be String or Symbol, not #{some_arg.class}" unless [String, Symbol].include?(some_arg.class)
25
31
  end
32
+
33
+ def call_with_respond_checks(some_arg)
34
+ raise TypeError, "#{some_arg.class} should respond to all methods: strip" unless [:strip].all{|meth| some_arg.respond_to?(meth)}
35
+ end
26
36
  end
27
37
  ```
28
38
 
@@ -90,13 +100,13 @@ end
90
100
 
91
101
  If you're unfamiliar with `using` keyword - this is refinement - a relatively new feature in Ruby (since 2.0). It's kind of monkey-patch, but with strict scope. Learn more about [refinements](https://ruby-doc.org/core-2.5.3/doc/syntax/refinements_rdoc.html).
92
102
 
93
- This refinement adds `type!()` method to `Object` class so you can call it on almost much any object (except those inherited from `BasicObject`, but these are rare).
103
+ This refinement adds `type!()` and `not_nil!` methods to `Object` class so you can call it on almost much any object (except those inherited from `BasicObject`, but these are rare).
94
104
 
95
105
  The method will raise an exception if `self` is not an instance of one of the classes passed as arguments. The tricky part, however, is to get the variable name on which it's called. You need this to get a nice error message telling you exactly which variable has wrong type, not just an abstract `TypeError`. That's why we need Ruby 2.6 with its new `RubyVM::AST` (https://ruby-doc.org/core-2.6.0.preview3/RubyVM/AST.html).
96
106
 
97
107
  ## Limitations
98
108
 
99
- It requires Ruby 2.6.0-preview3. Relies on `RubyVM::AST` which may change in release version. So, expect breaking changes in Ruby.
109
+ Full functionality Ruby 2.6.0-preview3. Relies on `RubyVM::AST` which may change in release version. So, expect breaking changes in Ruby. Previous versions also supported, but without variable name in exception message.
100
110
 
101
111
  Known limitations:
102
112
 
@@ -107,8 +117,9 @@ class A
107
117
 
108
118
  def call(some_arg)
109
119
  some_arg.
110
- type!(String) # this won't work. type!() call must be on the same line with the variable it's called on - raise error message without variable name
111
- # some_arg. type!(String) is ok though
120
+ type!(String)
121
+ # this won't work. type!() call must be on the same line with the variable it's called on - raise error message without variable name
122
+ # some_arg. type!(String) is ok though
112
123
  end
113
124
  end
114
125
  ```
@@ -119,10 +130,11 @@ end
119
130
  [1] pry(main)* using Typerb
120
131
  [1] pry(main)* def call(a)
121
132
  [1] pry(main)* a.type!(Hash)
122
- [1] pry(main)* end
123
- [1] pry(main)* end
133
+ [1] pry(main)* end
134
+ [1] pry(main)* end
124
135
  [2] pry(main)> A.new.call(1)
125
- TypeError: expected Hash, got Integer # here we cannot get the source code for a line containing "a.type!(Hash)", so cannot see the variable name
136
+ TypeError: expected Hash, got Integer
137
+ # here we cannot get the source code for a line containing "a.type!(Hash)", so cannot see the variable name
126
138
  ```
127
139
 
128
140
  3. Multiple arguments on the same line:
@@ -131,7 +143,9 @@ class A
131
143
  using Typerb
132
144
 
133
145
  def initialize(arg1, arg2)
134
- arg1.type!(Integer); arg2.type!(String) # no way to tell the variable - raise error message without variable name
146
+ arg1.type!(Integer); arg2.type!(String)
147
+ # no way to tell the variable - raise error message without variable name
148
+ # same error will be raised on Ruby < 2.6.0 because there is no RubyVM::AST
135
149
  end
136
150
  end
137
151
  ```
@@ -6,6 +6,10 @@ module Typerb
6
6
  def klasses_text(klasses)
7
7
  klasses.size > 1 ? klasses.map(&:name).join(' or ') : klasses.first.name
8
8
  end
9
+
10
+ def methods_text(methods)
11
+ methods.join(', ')
12
+ end
9
13
  end
10
14
 
11
15
  def raise_with(backtrace, exception_text)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Typerb
4
- VERSION = '0.1.6'
4
+ VERSION = '0.1.7'
5
5
  end
data/lib/typerb.rb CHANGED
@@ -31,5 +31,19 @@ module Typerb
31
31
 
32
32
  Typerb::Exceptional.new.raise_with(caller, exception_text)
33
33
  end
34
+
35
+ def respond_to!(*methods)
36
+ raise ArgumentError, 'provide at least one method' if methods.empty?
37
+ return self if methods.all? { |meth| respond_to?(meth) }
38
+
39
+ methods_text = Typerb::Exceptional.methods_text(methods)
40
+ exception_text = if (var_name = Typerb::VariableName.new(caller_locations(1, 1)).get)
41
+ "#{self.class} (`#{var_name}`) should respond to all methods: #{methods_text}"
42
+ else
43
+ "#{self.class} should respond to all methods: #{methods_text}"
44
+ end
45
+
46
+ Typerb::Exceptional.new.raise_with(caller, exception_text)
47
+ end
34
48
  end
35
49
  end
data/typerb.gemspec CHANGED
@@ -25,6 +25,8 @@ Gem::Specification.new do |spec|
25
25
  spec.require_paths = ['lib']
26
26
 
27
27
  spec.add_development_dependency 'bundler', '>= 1.17'
28
+ spec.add_development_dependency 'guard'
29
+ spec.add_development_dependency 'guard-rspec'
28
30
  spec.add_development_dependency 'pry'
29
31
  spec.add_development_dependency 'rake', '>= 10.0'
30
32
  spec.add_development_dependency 'rspec', '>= 3.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typerb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleg Antonyan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-13 00:00:00.000000000 Z
11
+ date: 2018-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: guard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: pry
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -109,6 +137,7 @@ files:
109
137
  - CODE_OF_CONDUCT.md
110
138
  - Gemfile
111
139
  - Gemfile.lock
140
+ - Guardfile
112
141
  - LICENSE.txt
113
142
  - README.md
114
143
  - Rakefile