typerb 0.1.3 → 0.1.4

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: b684a861507b2c491d213388d490af7b7543146dc3938f6817a8c1c909a359b5
4
- data.tar.gz: 53160641ff2410235cc25b73c37a57d81d14b4b322a6e7fabe68f424e076907c
3
+ metadata.gz: 19f90a93082e4acdb25f5750c9de2880bf0c613cb414800a7ce8beb275d2ee54
4
+ data.tar.gz: 10e47702b997c0f4b54b416c7f77c800ee50343b391a0f41b33ff6bd4b379dc2
5
5
  SHA512:
6
- metadata.gz: b2bde15804ce81dd7ddf94eefba526ca8ae24bb2880a628163d11068ea6c2fa8527dd4e6ef9be1ccba9689ed4b7a7cb6874be4dd7a9c7bd8eaebfc6f1457311b
7
- data.tar.gz: 563e93c1cd6b3787d8876da94ac612af27be1accb3300012f5eb7bac9fdbb3ebdc7f68e6efe5b2d15126ca14cec5d55d1769990fe7e387d793e91321a12df9d7
6
+ metadata.gz: 4c3a3d1dbc81a742d08c3e68413a70a7aa8858e473bf46a78dcdec452e862421bf85b02354ad70d203600ea1031ac85dbfc08758ea1bc79145ce03542bc92b6c
7
+ data.tar.gz: 55ffd3b8d1ed4fc33141a9345baaf3f7380336bfa7a4135630e24009607d7d3554b8d5892a887676a24a38a70ca7acfa351293b31f8d3f77e13ba31558cdcf5a
data/.rubocop.yml ADDED
@@ -0,0 +1,15 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'bin/**/*'
4
+
5
+ Style/CommentedKeyword:
6
+ Enabled: false
7
+
8
+ Style/Documentation:
9
+ Enabled: false
10
+
11
+ Style/Semicolon:
12
+ Enabled: false
13
+
14
+ Metrics/LineLength:
15
+ Max: 170
data/.travis.yml CHANGED
@@ -2,6 +2,8 @@
2
2
  sudo: false
3
3
  language: ruby
4
4
  cache: bundler
5
- rvm:
6
- - 2.6.0
7
- before_install: gem install bundler -v 1.17.1
5
+ before_install: gem install bundler
6
+
7
+ script:
8
+ - bundle exec rubocop -DP
9
+ - bundle exec rspec
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
- git_source(:github) { |repo_name| 'https://github.com/#{repo_name}' }
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
6
 
5
7
  # Specify your gem's dependencies in typerb.gemspec
6
8
  gemspec
data/Gemfile.lock CHANGED
@@ -1,18 +1,25 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- typerb (0.1.2)
4
+ typerb (0.1.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ ast (2.4.0)
9
10
  awesome_print (1.8.0)
10
11
  coderay (1.1.2)
11
12
  diff-lcs (1.3)
13
+ jaro_winkler (1.5.1)
12
14
  method_source (0.9.1)
15
+ parallel (1.12.1)
16
+ parser (2.5.3.0)
17
+ ast (~> 2.4.0)
18
+ powerpack (0.1.2)
13
19
  pry (0.12.0)
14
20
  coderay (~> 1.1.0)
15
21
  method_source (~> 0.9.0)
22
+ rainbow (3.0.0)
16
23
  rake (10.5.0)
17
24
  rspec (3.8.0)
18
25
  rspec-core (~> 3.8.0)
@@ -27,8 +34,18 @@ GEM
27
34
  diff-lcs (>= 1.2.0, < 2.0)
28
35
  rspec-support (~> 3.8.0)
29
36
  rspec-support (3.8.0)
37
+ rubocop (0.60.0)
38
+ jaro_winkler (~> 1.5.1)
39
+ parallel (~> 1.10)
40
+ parser (>= 2.5, != 2.5.1.1)
41
+ powerpack (~> 0.1)
42
+ rainbow (>= 2.2.2, < 4.0)
43
+ ruby-progressbar (~> 1.7)
44
+ unicode-display_width (~> 1.4.0)
45
+ ruby-progressbar (1.10.0)
30
46
  super_awesome_print (0.2.5)
31
47
  awesome_print
48
+ unicode-display_width (1.4.0)
32
49
 
33
50
  PLATFORMS
34
51
  ruby
@@ -38,6 +55,7 @@ DEPENDENCIES
38
55
  pry
39
56
  rake (>= 10.0)
40
57
  rspec (>= 3.0)
58
+ rubocop
41
59
  super_awesome_print
42
60
  typerb!
43
61
 
data/README.md CHANGED
@@ -1,3 +1,6 @@
1
+ [![Gem Version](https://badge.fury.io/rb/typerb.svg)](https://badge.fury.io/rb/typerb)
2
+ [![Build Status](https://travis-ci.org/olegantonyan/typerb.svg?branch=master)](https://travis-ci.org/olegantonyan/typerb)
3
+
1
4
  # Typerb
2
5
 
3
6
  Proof of concept type-checking library for Ruby 2.6.
@@ -11,7 +14,7 @@ class A
11
14
  end
12
15
  end
13
16
 
14
- A.new.call(1) #=> TypeError: '`some_arg` should be String or Symbol, not Integer'
17
+ A.new.call(1) #=> TypeError: `some_arg` should be String or Symbol, not Integer
15
18
  ```
16
19
 
17
20
  This is equivalent to:
@@ -25,6 +28,20 @@ end
25
28
 
26
29
  But without boilerplate.
27
30
 
31
+ It also has `not_nil!` method, similar to Crystal language.
32
+
33
+ ```ruby
34
+ class A
35
+ using Typerb
36
+
37
+ def call(some_arg)
38
+ some_arg.not_nil!
39
+ end
40
+ end
41
+
42
+ A.new.call(nil) #=> TypeError: expected not nil, but got nil
43
+ ```
44
+
28
45
  ## Installation
29
46
 
30
47
  Add this line to your application's Gemfile:
@@ -58,6 +75,19 @@ gem 'typerb', github: 'olegantonyan/typerb'
58
75
  2. Call `.type!()` on any object to assert its type.
59
76
  3. PROFIT! No more "NoMethodError for nil" 10 methods up the stack. You'll know exactly where this nil came from.
60
77
 
78
+ ```ruby
79
+ class A
80
+ using Typerb
81
+
82
+ attr_reader :param, :another_param
83
+
84
+ def initialize(param, another_param)
85
+ @param = param.type!(String)
86
+ @another_param = another_param.not_nil!
87
+ end
88
+ end
89
+ ```
90
+
61
91
  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).
62
92
 
63
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).
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Typerb
4
- VERSION = '0.1.3'
4
+ VERSION = '0.1.4'
5
5
  end
data/lib/typerb.rb CHANGED
@@ -6,27 +6,52 @@ module Typerb
6
6
  refine Object do
7
7
  def type!(*klasses)
8
8
  raise ArgumentError, 'provide at least one class' if klasses.empty?
9
- return if klasses.any? { |kls| is_a?(kls) }
9
+ return self if klasses.any? { |kls| is_a?(kls) }
10
10
 
11
- kls_text = klasses.size > 1 ? klasses.map(&:name).join(' or ') : klasses.first.name
11
+ exception_text = if (var_name = VariableNameUtil.get(caller_locations(1, 1)))
12
+ "`#{var_name}` should be #{VariableNameUtil.klasses_text(klasses)}, not #{self.class} (#{self})"
13
+ else
14
+ "expected #{VariableNameUtil.klasses_text(klasses)}, got #{self.class} (#{self})"
15
+ end
12
16
 
13
- # error message when multiple calls on the same line, or in a console - can't extract variable name
14
- exception_text = "expected #{kls_text}, got #{self.class} (#{to_s})"
17
+ exception = TypeError.new(exception_text)
18
+ exception.set_backtrace(caller)
19
+ raise exception
20
+ end
21
+
22
+ def not_nil!
23
+ return self unless self.nil? # rubocop: disable Style/RedundantSelf
24
+
25
+ exception_text = if (var_name = VariableNameUtil.get(caller_locations(1, 1)))
26
+ "`#{var_name}` should not be nil"
27
+ else
28
+ 'expected not nil, but got nil'
29
+ end
15
30
 
16
- where = caller_locations(1, 1)[0]
17
- file = where.path
18
- line = where.lineno
19
- if File.exist?(file)
20
- code = File.read(file).lines[line - 1].strip
21
- node = RubyVM::AST.parse(code)
22
- if node.children.last.children.size == 3 && node.children.last.children[1] == :type!
23
- var_name = node.children.last.children.first.children.first
24
- exception_text = "`#{var_name}` should be #{kls_text}, not #{self.class} (#{to_s})"
25
- end
26
- end
27
31
  exception = TypeError.new(exception_text)
28
32
  exception.set_backtrace(caller)
29
33
  raise exception
30
34
  end
31
35
  end
36
+
37
+ module VariableNameUtil
38
+ module_function
39
+
40
+ def get(c_loc) # rubocop: disable Metrics/AbcSize screw this
41
+ where = c_loc[0]
42
+ file = where.path
43
+ line = where.lineno
44
+ return unless File.exist?(file)
45
+
46
+ code = File.read(file).lines[line - 1].strip
47
+ node = RubyVM::AST.parse(code)
48
+ if node.children.last.children.size == 3 && %i[type! not_nil!].include?(node.children.last.children[1]) # rubocop: disable Style/IfUnlessModifier, Style/GuardClause
49
+ node.children.last.children.first.children.first
50
+ end
51
+ end
52
+
53
+ def klasses_text(klasses)
54
+ klasses.size > 1 ? klasses.map(&:name).join(' or ') : klasses.first.name
55
+ end
56
+ end
32
57
  end
data/typerb.gemspec CHANGED
@@ -1,4 +1,6 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require 'typerb/version'
4
6
 
@@ -8,8 +10,8 @@ Gem::Specification.new do |spec|
8
10
  spec.authors = ['Oleg Antonyan']
9
11
  spec.email = ['oleg.b.antonyan@gmail.com']
10
12
 
11
- spec.summary = %q(Typecheck sugar for Ruby.)
12
- spec.description = %q(Typecheck sugar for Ruby.)
13
+ spec.summary = 'Typecheck sugar for Ruby.'
14
+ spec.description = 'Typecheck sugar for Ruby.'
13
15
  spec.homepage = 'https://github.com/olegantonyan/typerb'
14
16
  spec.license = 'MIT'
15
17
 
@@ -23,10 +25,11 @@ Gem::Specification.new do |spec|
23
25
  spec.require_paths = ['lib']
24
26
 
25
27
  spec.add_development_dependency 'bundler', '>= 1.17'
28
+ spec.add_development_dependency 'pry'
26
29
  spec.add_development_dependency 'rake', '>= 10.0'
27
30
  spec.add_development_dependency 'rspec', '>= 3.0'
31
+ spec.add_development_dependency 'rubocop'
28
32
  spec.add_development_dependency 'super_awesome_print'
29
- spec.add_development_dependency 'pry'
30
33
 
31
34
  spec.required_ruby_version = '>= 2.6.0-preview3'
32
35
  end
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.3
4
+ version: 0.1.4
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-09 00:00:00.000000000 Z
11
+ date: 2018-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
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'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,7 +67,7 @@ dependencies:
53
67
  - !ruby/object:Gem::Version
54
68
  version: '3.0'
55
69
  - !ruby/object:Gem::Dependency
56
- name: super_awesome_print
70
+ name: rubocop
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
@@ -67,7 +81,7 @@ dependencies:
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
- name: pry
84
+ name: super_awesome_print
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - ">="
@@ -89,6 +103,7 @@ extra_rdoc_files: []
89
103
  files:
90
104
  - ".gitignore"
91
105
  - ".rspec"
106
+ - ".rubocop.yml"
92
107
  - ".ruby-version"
93
108
  - ".travis.yml"
94
109
  - CODE_OF_CONDUCT.md