rubysierung 0.0.2 → 0.0.3
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 +13 -5
- data/.hound.yml +3 -0
- data/.rubocop.yml +0 -0
- data/.travis.yml +10 -1
- data/CHANGELOG.md +8 -0
- data/README.md +30 -16
- data/Rakefile +6 -4
- data/lib/ast/ast.rb +32 -0
- data/lib/rubysierung/ast.rb +31 -0
- data/lib/rubysierung/core.rb +85 -0
- data/lib/rubysierung/error.rb +54 -3
- data/lib/rubysierung/types.rb +8 -8
- data/lib/rubysierung/version.rb +1 -1
- data/lib/rubysierung.rb +74 -75
- data/rubysierung.gemspec +14 -11
- data/test/test_ast.rb +39 -0
- data/test/test_core.rb +31 -0
- data/test/test_error.rb +45 -0
- data/test/test_rubysierung.rb +21 -69
- data/test/test_rubysierung_ast.rb +25 -0
- data/test/test_types.rb +51 -0
- metadata +52 -23
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OTFkNDk1ZTEyYmJiZDZiMmFjNTFlMWY0OTE0MmFlY2RlOTA5YjY2YQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
N2ZhODk2ZjA5MjM4NDVhMTJiNGZhODAxZDlhZjFmNGNiNTVlMjc0ZQ==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjcyMTMwODA2MmRmNzU0NzBlNzdlZjhmMTVkMDFiMTU2ZDYzOTc1NWFmZjIw
|
10
|
+
ZGNiNmMwNGNmNDhmODM5OTQ3ZmQ3ZTAwMWIzMmVmNDFjNDM0MGVlNDE2N2Yx
|
11
|
+
MDg3NzgxNzFkODljMmNhNzc2NzQ3NTYyMGEzZjI3NTA1MjRiOTA=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZjcxYmMwMzJkMWZmZTdhMTdkMWU5YjM4NjAwYTM0OTkyNTkxYTAyMzU4NmI2
|
14
|
+
NzNhOTU1NGVhNTE1ZWJiYzAwZWU2ZTkxNGVmODFlNzBmMTYwODY3YTlkYTcz
|
15
|
+
YzFkNTIwOWQyMjVhZjNkMzA3MjEyODAzYWQxM2RhMzhkZjEwZGE=
|
data/.hound.yml
ADDED
data/.rubocop.yml
ADDED
File without changes
|
data/.travis.yml
CHANGED
@@ -1,3 +1,12 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
|
3
|
+
- 2.1.0
|
4
|
+
deploy:
|
5
|
+
provider: rubygems
|
6
|
+
api_key:
|
7
|
+
secure: QA2OqytUOFV+W0dcIhULAS6bEZTMRfwrWHFmi1T4Ce3MtZ2o4f2kYsE+9wbFmfKqI35NljsUZYzunbAADGAXuGiir0pzFh5XzCJX/SPCUeNj79UwadByMmfI+dHzRTQdnPeGDsxBSg+N35yPCNenJlAgfX7Ed5YXJ4bAbWjPsds=
|
8
|
+
gem: rubysierung
|
9
|
+
on:
|
10
|
+
tags: true
|
11
|
+
all_branches: true
|
12
|
+
repo: doodzik/rubysierung
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# 0.0.3
|
2
|
+
|
3
|
+
- ADD: support of default values
|
4
|
+
- ADD: CallBaecker doesn't have to be included manually
|
5
|
+
- ADD: @__add_type 3rd argument is now optional and is set to the 2nd type
|
6
|
+
- FIX: strict custom_type
|
7
|
+
- REFACTOR: Tests seperated into different files
|
8
|
+
- REFACTOR: Source splitted into multiple types
|
data/README.md
CHANGED
@@ -2,17 +2,19 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/doodzik/rubysierung)
|
4
4
|
|
5
|
-
|
5
|
+
[](https://www.omniref.com/github/doodzik/rubysierung/HEAD)
|
6
|
+
|
7
|
+
Rubysierung is an implementation of Soft Typing in Ruby
|
8
|
+
|
6
9
|
|
7
10
|
## Installation
|
8
11
|
|
9
12
|
Add this line to your application's Gemfile:
|
10
13
|
|
11
14
|
```ruby
|
12
|
-
# ruby 2.1.0
|
13
|
-
|
15
|
+
# ruby >= 2.1.0
|
16
|
+
# You can only use Rubysierung in a file context, see issue #5 and #7.
|
14
17
|
gem 'rubysierung'
|
15
|
-
gem 'CallBaecker', '~> 0.0.3'
|
16
18
|
```
|
17
19
|
|
18
20
|
And then execute:
|
@@ -25,25 +27,28 @@ Or install it yourself as:
|
|
25
27
|
|
26
28
|
## Usage
|
27
29
|
|
28
|
-
## Have a look at all available
|
30
|
+
## Have a look at all available [Types] (https://github.com/doodzik/rubysierung/blob/master/lib/rubysierung/types.rb#L3-L19)
|
29
31
|
|
30
32
|
```ruby
|
31
|
-
require 'CallBaecker'
|
32
33
|
require 'rubysierung'
|
33
34
|
|
34
|
-
# define a custom
|
35
|
-
class
|
36
|
-
end
|
35
|
+
# define a custom types
|
36
|
+
class Strict::CustomTyp;end
|
37
|
+
class CustomTyp;end
|
38
|
+
|
39
|
+
class Strict::CustomTypX;end
|
40
|
+
class CustomTypX;end
|
37
41
|
|
38
42
|
class Example
|
39
43
|
extend Rubysierung
|
40
|
-
include CallBaecker # include Callbaecker after Rubysierung
|
41
44
|
|
42
45
|
# if the type doesnt match Rubisierung will raise an Error messages
|
43
46
|
|
44
47
|
# add custom Types
|
45
|
-
#
|
46
|
-
|
48
|
+
# if you don't specify a Strict Type the standard type is being set for it
|
49
|
+
# [TypeClass, StandardConversionMethodAsSymbol, StrictConversionMethodSymbol]
|
50
|
+
@__add_type[CustomType, :to_s, :to_str]
|
51
|
+
@__add_type[CustomTypeX, :to_s]
|
47
52
|
|
48
53
|
# define foo to respond to :to_s and bar to :to_i
|
49
54
|
def one(foo: String, bar: Integer)
|
@@ -51,23 +56,28 @@ class Example
|
|
51
56
|
end
|
52
57
|
|
53
58
|
# you can still define empty/default parameters
|
54
|
-
def self.
|
59
|
+
def self.two(foo:, bar: 'hallo World')
|
55
60
|
[foo, bar]
|
56
61
|
end
|
57
62
|
|
58
63
|
# use a custom type
|
59
|
-
def self.
|
64
|
+
def self.three(foo:, bar: CustomType)
|
60
65
|
[foo, bar]
|
61
66
|
end
|
62
67
|
|
63
68
|
# define foo to respond to :to_str (strict type)
|
64
|
-
def self.
|
69
|
+
def self.four(foo: Strict::String, bar: Integer)
|
70
|
+
[foo, bar]
|
71
|
+
end
|
72
|
+
|
73
|
+
# with default parameters
|
74
|
+
def self.five(foo: String||'I am a default :)', bar: Integer||42)
|
65
75
|
[foo, bar]
|
66
76
|
end
|
67
77
|
end
|
68
78
|
```
|
69
79
|
|
70
|
-
## what would
|
80
|
+
## what it would look like normally
|
71
81
|
```ruby
|
72
82
|
def one(foo:, bar:)
|
73
83
|
sFoo = foo.to_s
|
@@ -76,6 +86,10 @@ def one(foo:, bar:)
|
|
76
86
|
end
|
77
87
|
```
|
78
88
|
|
89
|
+
## Other Typing implementations
|
90
|
+
(contracts.ruby)[https://github.com/egonSchiele/contracts.ruby]
|
91
|
+
(typo)[https://github.com/hannestyden/typo/blob/master/typo.rb]
|
92
|
+
|
79
93
|
## Contributing
|
80
94
|
|
81
95
|
1. Fork it ( https://github.com/doodzik/rubysierung/fork )
|
data/Rakefile
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
2
|
require 'rake/testtask'
|
3
|
+
require 'rubocop/rake_task'
|
3
4
|
|
4
5
|
Rake::TestTask.new do |t|
|
5
|
-
|
6
|
+
t.libs << 'test'
|
6
7
|
end
|
7
8
|
|
8
|
-
|
9
|
-
task :default => :test
|
9
|
+
RuboCop::RakeTask.new
|
10
10
|
|
11
|
+
desc 'Run tests and rubocop'
|
12
|
+
task default: [:test]
|
data/lib/ast/ast.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
class AST < Struct.new(:to_parse)
|
2
|
+
# @return [Hash<String, String>] parameter of a method
|
3
|
+
def params
|
4
|
+
get_param_hash to_parse
|
5
|
+
end
|
6
|
+
|
7
|
+
# just so it makes sense in contest of the ast
|
8
|
+
# @return [self] make it chainable
|
9
|
+
def method
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# @param declaration_string [String] the string which is being evaluated
|
16
|
+
# @return [Hash<String, String>] parameter of a method
|
17
|
+
def get_param_hash(declaration_string)
|
18
|
+
Hash[
|
19
|
+
*declaration_string.scan(regex_keyword_param).flatten
|
20
|
+
].reject { |_, v| v =~ regex_isnt_constant }
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Regex] which returns keywords and value from ruby string
|
24
|
+
def regex_keyword_param
|
25
|
+
/([a-z][a-zA-Z]+):\s*([^,\n)]+)/
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Regex] which checks if the String isn't a Constant
|
29
|
+
def regex_isnt_constant
|
30
|
+
/^[^A-Z]/
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'ast/ast'
|
2
|
+
|
3
|
+
module Rubysierung
|
4
|
+
class AST < AST
|
5
|
+
# Calls super and uses it result as a arg for default_param
|
6
|
+
# @return [Array<Hash<>, Hash<Symbol, String>>] returns the same as default_param
|
7
|
+
def params
|
8
|
+
default_param super
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# @return [Regex] splits default param and type
|
14
|
+
def regex_default_arg
|
15
|
+
/([A-Z]\w*?)\s*\|\|\s*(.+)/
|
16
|
+
end
|
17
|
+
|
18
|
+
# seperates a param from default argument and stores the defaults inside a hash
|
19
|
+
# @param hash [Hash<String, String>] {"foo"=>"String||'bar'", "bar"=>"String||'foo'"}
|
20
|
+
# @return [Array<Hash<String, String>, Hash<Symbol, String>>] params, defaults for params
|
21
|
+
def default_param(hash)
|
22
|
+
defaults = {}
|
23
|
+
hash.map do |k, v|
|
24
|
+
const, default = v.scan(regex_default_arg).flatten
|
25
|
+
next unless const && default
|
26
|
+
hash[k], defaults[k.to_sym] = [const, default]
|
27
|
+
end
|
28
|
+
[hash, defaults]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rubysierung/error'
|
2
|
+
|
3
|
+
module Rubysierung
|
4
|
+
module Core
|
5
|
+
# sets defaults as @__defaults
|
6
|
+
# @param ast [AST] an instance of modefied ruby ast class
|
7
|
+
# @todo refactor into adapter
|
8
|
+
# @return [Hash<Symbol, Constant>]
|
9
|
+
def default_hash(ast)
|
10
|
+
param_hash, defaults = ast.method.params
|
11
|
+
@__defaults = @__defaults.merge(defaults)
|
12
|
+
convert_value_to_constant param_hash
|
13
|
+
end
|
14
|
+
|
15
|
+
# applies conversion methods on args and returns args(for CallBaecker)
|
16
|
+
# @param klass_hash [Hash<Symbol, Constant>] holds types for Arguments
|
17
|
+
# @param value_hash [Hash<Symbol, Constant>] holds values for Arguments
|
18
|
+
# @return [Hash<Symbol, Constant>] same as value_hash only that on its
|
19
|
+
# values the type was applied and merged with the other values
|
20
|
+
def call(klass_hash:, value_hash:)
|
21
|
+
return value_hash if klass_hash.empty?
|
22
|
+
return_hash = each_param(klass_hash, value_hash) do |key|
|
23
|
+
@__error_data[:var_sym] = key
|
24
|
+
end
|
25
|
+
value_hash.merge return_hash
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# @param klass_hash [Hash<Symbol, Constant>] holds types for Arguments
|
31
|
+
# @param value_hash [Hash<Symbol, Constant>] holds values for Arguments
|
32
|
+
# @yield [Symbol] param name
|
33
|
+
# @todo don't use eval -> String.new('default') something like this
|
34
|
+
# @todo refactor: i can't point my finger on it, but it feels bad
|
35
|
+
# @return [Hash] same as value_hash only that on its
|
36
|
+
# values the type was applied
|
37
|
+
def each_param(klass_hash, value_hash)
|
38
|
+
return_hash = {}
|
39
|
+
klass_hash.keys.map do |key|
|
40
|
+
yield(key) if block_given?
|
41
|
+
value = value_hash[key] ? value_hash[key] : eval(@__defaults[key])
|
42
|
+
return_hash[key] = convert(klass: klass_hash[key], value: value)
|
43
|
+
end
|
44
|
+
return_hash
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param klass [Hash<>]
|
48
|
+
# @option value [Hash<>]
|
49
|
+
# @raise [Rubysierung::Error:Standard|Rubysierung::Error::Strict]
|
50
|
+
# @return [self]
|
51
|
+
def convert(klass:, value: nil)
|
52
|
+
strict, klass = get_kind(klass: klass)
|
53
|
+
type = @__types.reject { |t| klass != t[0] }.flatten
|
54
|
+
klass == type[0] ? value.send(type[1 + strict]) : value
|
55
|
+
rescue NoMethodError
|
56
|
+
err = @__error_data.merge(klass: klass, type: type[1 + strict],
|
57
|
+
value: value, value_class: value.class)
|
58
|
+
raise Rubysierung::Error.new(err).raise_child strict
|
59
|
+
end
|
60
|
+
|
61
|
+
# @param klass [String] takes the type of a klass
|
62
|
+
# @return [Array<Int, Constant>] if klass is Strict it returns 1 else 0 as
|
63
|
+
# the int. So that we can look up the conversion method in @__types
|
64
|
+
# and a klass without strict prefix
|
65
|
+
def get_kind(klass:)
|
66
|
+
if klass.respond_to? :name
|
67
|
+
splitted, splitted1 = klass.name.split('::')
|
68
|
+
splitted == 'Strict' ? [1, Kernel.const_get(splitted1)] : [0, klass]
|
69
|
+
else
|
70
|
+
[0, klass]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @note this could be the point where we could use Symbols instead
|
75
|
+
# of Constants.
|
76
|
+
# @param hash [Hash<String, String>] takes a string string hash
|
77
|
+
# @todo refactor into adapter
|
78
|
+
# @return [Hash<Symbol, Constant>] returns a symbol Constant hash
|
79
|
+
def convert_value_to_constant(hash)
|
80
|
+
Hash[hash.map do |k, v|
|
81
|
+
[k.to_sym, Kernel.const_get(v)]
|
82
|
+
end]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/rubysierung/error.rb
CHANGED
@@ -1,4 +1,55 @@
|
|
1
|
-
module Rubysierung
|
2
|
-
class
|
3
|
-
|
1
|
+
module Rubysierung
|
2
|
+
class Error < StandardError
|
3
|
+
# @param error_data [Hash<..>] look at message what is needed
|
4
|
+
# @return [void]
|
5
|
+
def initialize(error_data)
|
6
|
+
@error_data = error_data
|
7
|
+
end
|
8
|
+
|
9
|
+
# @param strict [Int] 0 or 1, 1 if it strict
|
10
|
+
# @return [Rubysierung::Error::Standard|Rubysierung::Error::Strict] instance of one of the two classes
|
11
|
+
def raise_child(strict)
|
12
|
+
if strict == 0
|
13
|
+
Rubysierung::Error::Standard.new(@error_data)
|
14
|
+
else
|
15
|
+
Rubysierung::Error::Strict.new(@error_data)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @todo refactor into idependend methods and assemble them inside message
|
20
|
+
# @return [String] error message
|
21
|
+
def message
|
22
|
+
"Class:#{@error_data[:klass]}, Conversion Method:#{@error_data[:type]}, Method:#{@error_data[:method_object]}:#{@error_data[:method_file]} #{@error_data[:method_name]}:#{@error_data[:method_line]} -- called on #{@error_data[:caller]} with #{@error_data[:var_sym]}:#{@error_data[:value]} of #{@error_data[:value_class]} doesn't respond to #{@error_data[:type]}"
|
23
|
+
end
|
24
|
+
|
25
|
+
# sets @__error_data on provided obj pointer
|
26
|
+
# @param _self [self]
|
27
|
+
# @param name [Symbol]
|
28
|
+
# @param method_object [?]
|
29
|
+
# @param file [String]
|
30
|
+
# @param line [Int]
|
31
|
+
# @return [void]
|
32
|
+
def self.set_data(_self:, name:, method_object:, file:, line:)
|
33
|
+
err_data = _self.instance_variable_get :@__error_data
|
34
|
+
err_data[:method_object] = method_object
|
35
|
+
err_data[:method_file] = file
|
36
|
+
err_data[:method_name] = name
|
37
|
+
err_data[:method_line] = line
|
38
|
+
_self.instance_variable_set :@__error_data, err_data
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Error::Standard < Error
|
43
|
+
# @return [String] Rubysierung::Error prefixed with self namespace
|
44
|
+
def message
|
45
|
+
"#{to_s}: #{super}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Error::Strict < Error
|
50
|
+
# @return [String] Rubysierung::Error prefixed with self namespace
|
51
|
+
def message
|
52
|
+
"#{to_s}: #{super}"
|
53
|
+
end
|
54
|
+
end
|
4
55
|
end
|
data/lib/rubysierung/types.rb
CHANGED
@@ -9,11 +9,11 @@ module Rubysierung::Types
|
|
9
9
|
[Float, :to_f, :to_f],
|
10
10
|
[Hash, :to_h, :to_hash],
|
11
11
|
[Rational, :to_r, :to_r],
|
12
|
-
#[Enum, :to_enum, :to_enum],
|
12
|
+
# [Enum, :to_enum, :to_enum],
|
13
13
|
[IO, :to_io, :to_io],
|
14
14
|
[Proc, :to_proc, :to_proc],
|
15
|
-
#[Path, :to_path, :to_path],
|
16
|
-
#[JSON, :to_json, :to_json],
|
15
|
+
# [Path, :to_path, :to_path],
|
16
|
+
# [JSON, :to_json, :to_json],
|
17
17
|
[Symbol, :to_sym, :to_sym],
|
18
18
|
[Thread, :join, :join]
|
19
19
|
]
|
@@ -23,13 +23,13 @@ module Rubysierung::Types
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
# Make Strict types accessible in Global namespace
|
26
|
+
# Make Strict types accessible in Global namespace
|
27
27
|
module Strict
|
28
28
|
end
|
29
29
|
|
30
|
-
|
30
|
+
strict_eval = ''
|
31
31
|
|
32
|
-
Rubysierung::Types.types.map { |
|
33
|
-
Strict.module_eval
|
32
|
+
Rubysierung::Types.types.map { |typ| strict_eval += "class #{typ[0]} ;end;" }
|
33
|
+
Strict.module_eval strict_eval
|
34
34
|
|
35
|
-
|
35
|
+
strict_eval = nil
|
data/lib/rubysierung/version.rb
CHANGED
data/lib/rubysierung.rb
CHANGED
@@ -1,92 +1,91 @@
|
|
1
|
-
require
|
1
|
+
require 'rubysierung/version'
|
2
2
|
require 'rubysierung/types'
|
3
|
-
require 'rubysierung/
|
3
|
+
require 'rubysierung/core'
|
4
|
+
require 'rubysierung/ast'
|
5
|
+
require 'CallBaecker'
|
4
6
|
|
7
|
+
# This is currently works as an Adapter for Rubysierung
|
8
|
+
# @todo refactor into its own adapter module
|
5
9
|
module Rubysierung
|
6
|
-
|
7
|
-
|
8
|
-
puts @__types
|
9
|
-
end
|
10
|
-
|
11
|
-
base.instance_variable_set :@__add_type, -> (klass, standard, strict) do
|
12
|
-
@__types << [klass, standard, strict]
|
13
|
-
end
|
14
|
-
|
15
|
-
base.instance_variable_set :@__before_hook, -> (i,ii, callee) do
|
16
|
-
@__error_data[:caller] = callee
|
17
|
-
Rubysierung.convert_multiple(klass_hash: i, value_hash: ii)
|
18
|
-
end
|
19
|
-
|
20
|
-
base.instance_variable_set :@__setup_instance_method, -> (_self, name) do
|
21
|
-
file, line = _self.instance_method(name.to_sym).source_location
|
22
|
-
set_error_data(_self: self, name: name, method_object: _self.name, file: file, line: line - 1)
|
23
|
-
get_default_hash_from_fileline(file: file, line: line-1)
|
24
|
-
end
|
25
|
-
|
26
|
-
base.instance_variable_set :@__setup_class_method, -> (_self, name) do
|
27
|
-
file, line = _self.method(name.to_sym).source_location
|
28
|
-
set_error_data(_self: self, name: name, method_object: _self.name, file: file, line: line - 1)
|
29
|
-
get_default_hash_from_fileline(file: file, line: line-1)
|
30
|
-
end
|
10
|
+
class << self
|
11
|
+
include Rubysierung::Core
|
31
12
|
end
|
32
13
|
|
33
14
|
@__types = Rubysierung::Types.types
|
15
|
+
# error data of the current method
|
34
16
|
@__error_data = {}
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
17
|
+
# default parameters of the current method
|
18
|
+
@__defaults = {}
|
19
|
+
@__method_data = {}
|
20
|
+
|
21
|
+
# @todo access __type through method and make it return the types not print
|
22
|
+
# @return [void] puts all current types
|
23
|
+
@__types_show = -> () do
|
24
|
+
puts @__types
|
25
|
+
end
|
43
26
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
27
|
+
# @param base [self] pointer to the class on which it is extended
|
28
|
+
# @todo get rid of this method in order to understand the source better
|
29
|
+
# @todo refactor into adapter
|
30
|
+
# @return [void]
|
31
|
+
def self.extended(base)
|
32
|
+
# @__before_hook is called by CallBaecker inside the defined method
|
33
|
+
# then Rubysierung is called with the klass_hash and value_hash
|
34
|
+
# @note This lambda is called before anything happens in a method
|
35
|
+
# @note This is the starting point of Rubysierung.
|
36
|
+
# @param klass_hash [Hash<Symbol, Constant>] holds types for Arguments
|
37
|
+
# @param value_hash [Hash<Symbol, Constant>] holds values for Arguments
|
38
|
+
# @param callee [String] first element of the current execution stack
|
39
|
+
# @param _self [self]
|
40
|
+
# @param name [String] name of method
|
41
|
+
# @see CallBaecker
|
42
|
+
# @return [self]
|
43
|
+
base.instance_variable_set :@__before_hook, -> (klass_hash, value_hash, callee, _self, name) do
|
44
|
+
@__error_data[:caller] = callee
|
45
|
+
Error.set_data @__method_data[name]
|
46
|
+
Rubysierung.call(klass_hash: klass_hash, value_hash: value_hash)
|
52
47
|
end
|
53
48
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
rescue NoMethodError
|
63
|
-
# return argument, param, duck_type, calle/receiver -> file, line
|
64
|
-
if strict == 0
|
65
|
-
raise Rubysierung::Error::Standart, "Rubysierung::Error::Standart: Class:#{klass}, DuckType:#{type[2]}, Method:#{@__error_data[:method_object]}:#{@__error_data[:method_file]}#{@__error_data[:method_name]}:#{@__error_data[:method_line]} -- called on #{@__error_data[:caller]} with #{@__error_data[:var_sym]}:#{value} of #{value.class} doesn't respond to #{type[2]}"
|
66
|
-
else
|
67
|
-
raise Rubysierung::Error::Strict, "Rubysierung::Error::Strict: Class:#{klass}, DuckType:#{type[2]}, Method:#{@__error_data[:method_object]}:#{@__error_data[:method_file]}#{@__error_data[:method_name]}:#{@__error_data[:method_line]} -- called on #{@__error_data[:caller]} with #{@__error_data[:var_sym]}:#{value} of #{value.class} doesn't respond to #{type[2]}"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
value
|
49
|
+
# pushes an custom type onto @__types
|
50
|
+
# @param klass [Constant] the CustomType
|
51
|
+
# @param standard [Symbol] the standard conversion method
|
52
|
+
# @param strict [Symbol] the strict conversion method
|
53
|
+
# @todo access __type through method
|
54
|
+
# @return [self]
|
55
|
+
base.instance_variable_set :@__add_type, -> (klass, standard, strict = standard) do
|
56
|
+
@__types << [klass, standard, strict]
|
72
57
|
end
|
73
58
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
59
|
+
# @note This lambda is called before a method is defined inside method added
|
60
|
+
# @param _self [self] pointer to the implementation object
|
61
|
+
# @param name [Symbol] name of the method
|
62
|
+
# @see CallBaecker
|
63
|
+
# @todo get rid of :@__setup_instance_method/:@__setup_class_method
|
64
|
+
# and make it one
|
65
|
+
# @return [self]
|
66
|
+
base.instance_variable_set :@__setup_instance_method, -> (_self, name) do
|
67
|
+
file, line = _self.instance_method(name).source_location
|
68
|
+
ruby_str = IO.readlines(file)[line-1]
|
69
|
+
ast = Rubysierung::AST.new(ruby_str)
|
70
|
+
@__method_data[name] = {_self: self, name: name, method_object: _self.name, file: file, line: line}
|
71
|
+
default_hash(ast)
|
81
72
|
end
|
82
73
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
74
|
+
# @note This lambda is called before a method is defined inside method added
|
75
|
+
# @param _self [self] pointer to the implementation object
|
76
|
+
# @param name [Symbol] name of the method
|
77
|
+
# @todo get rid of :@__setup_instance_method/:@__setup_class_method
|
78
|
+
# and make it one
|
79
|
+
# @see CallBaecker
|
80
|
+
# @return [self]
|
81
|
+
base.instance_variable_set :@__setup_class_method, -> (_self, name) do
|
82
|
+
file, line = _self.method(name).source_location
|
83
|
+
ruby_str = IO.readlines(file)[line-1]
|
84
|
+
ast = Rubysierung::AST.new(ruby_str)
|
85
|
+
@__method_data[name] = {_self: self, name: name, method_object: _self.name, file: file, line: line}
|
86
|
+
default_hash(ast)
|
90
87
|
end
|
88
|
+
|
89
|
+
base.include CallBaecker
|
91
90
|
end
|
92
91
|
end
|
data/rubysierung.gemspec
CHANGED
@@ -4,21 +4,24 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'rubysierung/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'rubysierung'
|
8
8
|
spec.version = Rubysierung::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary = %q
|
12
|
-
spec.homepage =
|
13
|
-
spec.license =
|
9
|
+
spec.authors = ['doodzik']
|
10
|
+
spec.email = ['4004blog@gmail.com']
|
11
|
+
spec.summary = %q(Rubysierung is the type system Ruby deserves)
|
12
|
+
spec.homepage = 'https://github.com/doodzik/rubysierung'
|
13
|
+
spec.license = 'MIT'
|
14
14
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0")
|
16
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
-
spec.require_paths = [
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
spec.required_ruby_version = '~> 2.1'
|
19
20
|
|
20
|
-
spec.add_development_dependency
|
21
|
-
spec.add_development_dependency
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
23
|
+
spec.add_development_dependency 'minitest'
|
24
|
+
spec.add_development_dependency 'rubocop'
|
25
|
+
|
26
|
+
spec.add_dependency 'CallBaecker', '0.0.4'
|
24
27
|
end
|
data/test/test_ast.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'ast/ast'
|
3
|
+
|
4
|
+
class AstTest < Minitest::Test
|
5
|
+
def test_params
|
6
|
+
ast = AST.new "def self.example2(foo: Strict::String, bar: Integer, buz: String||'fu')"
|
7
|
+
result = ast.send :params
|
8
|
+
assert_equal({"foo"=>"Strict::String", "bar"=>"Integer", "buz"=>"String||'fu'"}, result)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_method
|
12
|
+
ast = AST.new ''
|
13
|
+
assert_equal ast, ast.method
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_regex_isnt_constant
|
17
|
+
ast = AST.new ''
|
18
|
+
regex = ast.send :regex_isnt_constant#/^[^A-Z]/
|
19
|
+
assert_equal(nil, regex =~ 'Foo')
|
20
|
+
assert_equal(0, regex =~ 'foo')
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_regex_keyword_param
|
24
|
+
ast = AST.new ''
|
25
|
+
regex = ast.send :regex_keyword_param#/([a-z][a-zA-Z]+):\s*([^,\n)]+)/
|
26
|
+
str = "def self.example2(foo: Strict::String, bar: Integer, buz: String||'fu')"
|
27
|
+
assert_equal(str.scan(regex).flatten,
|
28
|
+
['foo', 'Strict::String', 'bar', 'Integer', 'buz', "String||'fu'"])
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_get_param_hash
|
32
|
+
# @param declaration_string [String] the string which is being evaluated
|
33
|
+
# @return [Hash<String, String>] parameter of a method
|
34
|
+
ast = AST.new ''
|
35
|
+
str = "def self.example2(foo: Strict::String, bar: Integer, buz: String||'fu')"
|
36
|
+
result = ast.send :get_param_hash, str
|
37
|
+
assert_equal({"foo"=>"Strict::String", "bar"=>"Integer", "buz"=>"String||'fu'"}, result)
|
38
|
+
end
|
39
|
+
end
|
data/test/test_core.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'rubysierung'
|
3
|
+
|
4
|
+
class RubysierungCoreTest < Minitest::Test
|
5
|
+
def test_rubisierung_converte_Int_to_string
|
6
|
+
assert_equal('23', Rubysierung.send(:convert, { klass: String, value: 23 }))
|
7
|
+
end
|
8
|
+
def test_rubisierung_converte_string_to_Int
|
9
|
+
assert_equal(23, Rubysierung.send(:convert, { klass: Integer, value: '23' }))
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_rubisierung_converte_pass_nonexisting_klass_then_return_value
|
13
|
+
assert_equal('23', Rubysierung.send(:convert, { klass: 'huhu', value: '23' }))
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_run_type_hash_agains_value_hash
|
17
|
+
assert_equal({ foo: 23, bar: '23' },
|
18
|
+
Rubysierung.call(value_hash: { foo: '23', bar: 23 },
|
19
|
+
klass_hash: { foo: Integer, bar: String }))
|
20
|
+
end
|
21
|
+
def test_run_type_hash_agains_value_hash_without_a_class_on_klass_hash
|
22
|
+
assert_equal({ foo: '23', bar: '23' },
|
23
|
+
Rubysierung.call(value_hash: { foo: '23', bar: 23 },
|
24
|
+
klass_hash: { foo: 14, bar: String }))
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_is_strict
|
28
|
+
assert_equal([0, String], Rubysierung.send(:get_kind, { klass: String }))
|
29
|
+
assert_equal([1, String], Rubysierung.send(:get_kind, { klass: Strict::String }))
|
30
|
+
end
|
31
|
+
end
|
data/test/test_error.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'rubysierung'
|
3
|
+
|
4
|
+
class SetupError
|
5
|
+
attr_reader :__error_data
|
6
|
+
def initialize
|
7
|
+
@__error_data = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def example
|
11
|
+
Rubysierung::Error.set_data(_self: self, name: 42, method_object: 42, file: 42, line: 42)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class RubysierungErrorTest < Minitest::Test
|
16
|
+
def test_Error
|
17
|
+
data = {}
|
18
|
+
[:klass, :type, :method_object, :method_file, :method_name, :method_line, :caller, :var_sym, :value, :value_class, :type].map { |sym| data[sym] = '42' }
|
19
|
+
raise Rubysierung::Error.new(data)
|
20
|
+
rescue Rubysierung::Error => e
|
21
|
+
assert_equal("Class:42, Conversion Method:42, Method:42:42 42:42 -- called on 42 with 42:42 of 42 doesn't respond to 42", e.message)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_Error_Standard
|
25
|
+
data = {}
|
26
|
+
[:klass, :type, :method_object, :method_file, :method_name, :method_line, :caller, :var_sym, :value, :value_class, :type].map { |sym| data[sym] = '42' }
|
27
|
+
raise Rubysierung::Error::Standard.new(data)
|
28
|
+
rescue Rubysierung::Error::Standard => e
|
29
|
+
assert_equal("Rubysierung::Error::Standard: Class:42, Conversion Method:42, Method:42:42 42:42 -- called on 42 with 42:42 of 42 doesn't respond to 42", e.message)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_Error_Strict
|
33
|
+
data = {}
|
34
|
+
[:klass, :type, :method_object, :method_file, :method_name, :method_line, :caller, :var_sym, :value, :value_class, :type].map { |sym| data[sym] = '42' }
|
35
|
+
fail Rubysierung::Error::Strict.new(data)
|
36
|
+
rescue Rubysierung::Error::Strict => e
|
37
|
+
assert_equal("Rubysierung::Error::Strict: Class:42, Conversion Method:42, Method:42:42 42:42 -- called on 42 with 42:42 of 42 doesn't respond to 42", e.message)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_set_data
|
41
|
+
s_e = SetupError.new
|
42
|
+
s_e.example
|
43
|
+
assert_equal({ method_object: 42, method_file: 42, method_name: 42, method_line: 42 }, s_e.__error_data)
|
44
|
+
end
|
45
|
+
end
|
data/test/test_rubysierung.rb
CHANGED
@@ -1,15 +1,8 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
|
-
require 'CallBaecker'
|
3
2
|
require 'rubysierung'
|
4
3
|
|
5
|
-
class
|
6
|
-
end
|
7
|
-
|
8
|
-
class Setup
|
4
|
+
class SetupRubysierung
|
9
5
|
extend Rubysierung
|
10
|
-
include CallBaecker
|
11
|
-
|
12
|
-
@__add_type[CustomTyp, :to_s, :to_str]
|
13
6
|
|
14
7
|
def example1(foo: String, bar: Integer)
|
15
8
|
[foo, bar]
|
@@ -19,93 +12,52 @@ class Setup
|
|
19
12
|
[foo, bar]
|
20
13
|
end
|
21
14
|
|
22
|
-
def self.example3(foo
|
23
|
-
[foo, bar]
|
24
|
-
end
|
25
|
-
|
26
|
-
# custom Class
|
27
|
-
def self.example4(foo: ,bar: CustomTyp)
|
15
|
+
def self.example3(foo:, bar: 'hallo World')
|
28
16
|
[foo, bar]
|
29
17
|
end
|
30
18
|
|
31
|
-
#
|
32
|
-
def self.
|
19
|
+
# Default
|
20
|
+
def self.example4(foo: String||'bar', bar: String||'foo')
|
33
21
|
[foo, bar]
|
34
22
|
end
|
35
23
|
|
36
24
|
# Default
|
37
|
-
|
38
|
-
|
39
|
-
|
25
|
+
def self.example_err(foo: Strict::String, bar: String||'foo')
|
26
|
+
[foo, bar, (__LINE__ - 1), caller]
|
27
|
+
end
|
40
28
|
end
|
41
29
|
|
42
30
|
class RubysierungTest < Minitest::Test
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
def test_rubisierung_converte_pass_nonexisting_klass_then_return_value
|
51
|
-
assert_equal('23', Rubysierung.convert(klass: 'huhu', value: '23'))
|
52
|
-
end
|
53
|
-
|
54
|
-
def test_run_type_hash_agains_value_hash
|
55
|
-
assert_equal({foo: 23, bar:'23'},
|
56
|
-
Rubysierung.convert_multiple(value_hash: {foo: '23', bar: 23},
|
57
|
-
klass_hash: {foo: Integer, bar: String}))
|
58
|
-
end
|
59
|
-
def test_run_type_hash_agains_value_hash_without_a_class_on_klass_hash
|
60
|
-
assert_equal({foo: '23', bar:'23'},
|
61
|
-
Rubysierung.convert_multiple(value_hash: {foo: '23', bar: 23},
|
62
|
-
klass_hash: {foo: 14, bar: String}))
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_is_strict
|
66
|
-
assert_equal([0, String], Rubysierung.get_kind(klass: String))
|
67
|
-
assert_equal([1, String], Rubysierung.get_kind(klass: Strict::String))
|
31
|
+
def test_error_implementation
|
32
|
+
SetupRubysierung.example_err(foo: 4, bar: '3')
|
33
|
+
rescue Rubysierung::Error::Strict => e
|
34
|
+
foo, bar, line, callee = SetupRubysierung.example_err(foo: '4', bar: '3')
|
35
|
+
data = {klass: 'String', type: 'to_str', method_object: 'SetupRubysierung', method_file: __FILE__, method_name: 'example_err', method_line: line, caller: callee[4] , var_sym: 'foo', value: '4', value_class: 'Fixnum'}
|
36
|
+
str = Rubysierung::Error::Strict.new(data).message
|
37
|
+
assert_equal(str, e.message)
|
68
38
|
end
|
69
39
|
|
70
40
|
def test_example_2_standart
|
71
|
-
foo, bar=
|
41
|
+
foo, bar = SetupRubysierung.example2(foo: 4, bar: '3')
|
72
42
|
assert_equal(3, bar)
|
73
43
|
assert_equal('4', foo)
|
74
44
|
end
|
75
45
|
|
76
46
|
def test_example_1_instance_method
|
77
|
-
foo, bar=
|
47
|
+
foo, bar = SetupRubysierung.new.example1(foo: 4, bar: '3')
|
78
48
|
assert_equal(3, bar)
|
79
49
|
assert_equal('4', foo)
|
80
50
|
end
|
81
51
|
|
82
52
|
def test_example_3_default_works
|
83
|
-
foo, bar=
|
53
|
+
foo, bar = SetupRubysierung.example3(foo: 4)
|
84
54
|
assert_equal('hallo World', bar)
|
85
55
|
assert_equal(4, foo)
|
86
56
|
end
|
87
57
|
|
88
|
-
def
|
89
|
-
foo, bar =
|
90
|
-
assert_equal('
|
91
|
-
assert_equal(
|
58
|
+
def test_example_4_default_value
|
59
|
+
foo, bar = SetupRubysierung.example4(bar: 'buz')
|
60
|
+
assert_equal('buz', bar)
|
61
|
+
assert_equal('bar', foo)
|
92
62
|
end
|
93
|
-
|
94
|
-
def test_example_5_strict_type
|
95
|
-
foo, bar = Setup.example5(foo: '4', bar: 2)
|
96
|
-
assert_equal(2, bar)
|
97
|
-
assert_equal('4', foo)
|
98
|
-
begin
|
99
|
-
Setup.example5(foo: 4, bar: 2)
|
100
|
-
assert_equal(false, true)
|
101
|
-
rescue StandardError => e
|
102
|
-
assert_equal(true, true)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# def test_example_6_default_value
|
107
|
-
# foo, bar = Setup.example5(bar: 'bar')
|
108
|
-
# assert_equal('bar', bar)
|
109
|
-
# assert_equal('bar', foo)
|
110
|
-
# end
|
111
63
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'rubysierung/ast'
|
3
|
+
|
4
|
+
class RubysierungAstTest < Minitest::Test
|
5
|
+
def test_params
|
6
|
+
ast = Rubysierung::AST.new "def self.example2(foo: Strict::String, bar: Integer, buz: String||'fu')"
|
7
|
+
param, default = ast.params
|
8
|
+
assert_equal({"foo"=>"Strict::String", "bar"=>"Integer", "buz"=>"String"}, param)
|
9
|
+
assert_equal({:buz=>"'fu'"}, default)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_regex_default_arg
|
13
|
+
ast = Rubysierung::AST.new ''
|
14
|
+
regex = ast.send :regex_default_arg
|
15
|
+
str = "String||'fu'"
|
16
|
+
assert_equal(str.scan(regex).flatten, ['String', "'fu'"])
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_default_param
|
20
|
+
ast = Rubysierung::AST.new ''
|
21
|
+
param, default = ast.send :default_param, {"foo"=>"String||'bar'", "bar"=>"String||'foo'"}
|
22
|
+
assert_equal({'foo' => 'String', 'bar' => 'String'}, param)
|
23
|
+
assert_equal({foo: "'bar'", bar: "'foo'"}, default)
|
24
|
+
end
|
25
|
+
end
|
data/test/test_types.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'rubysierung'
|
3
|
+
|
4
|
+
class Strict::CustomTyp;end
|
5
|
+
class CustomTyp;end
|
6
|
+
|
7
|
+
|
8
|
+
class SetupRubysierungTypes
|
9
|
+
extend Rubysierung
|
10
|
+
|
11
|
+
@__add_type[CustomTyp, :to_s, :to_str]
|
12
|
+
|
13
|
+
# custom Class
|
14
|
+
def self.example1(foo:, bar: CustomTyp)
|
15
|
+
[foo, bar]
|
16
|
+
end
|
17
|
+
|
18
|
+
# strict
|
19
|
+
def self.example2(foo: Strict::String, bar: Integer)
|
20
|
+
[foo, bar]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Custom strict
|
24
|
+
def self.example3(foo: Strict::String, bar: Strict::CustomTyp)
|
25
|
+
[foo, bar]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class RubysierungTypesTest < Minitest::Test
|
30
|
+
def test_example_1_custum_type
|
31
|
+
foo, bar = SetupRubysierungTypes.example1(foo: 4, bar: 3)
|
32
|
+
assert_equal('3', bar)
|
33
|
+
assert_equal(4, foo)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_example_2_strict_type
|
37
|
+
foo, bar = SetupRubysierungTypes.example2(foo: '4', bar: 2)
|
38
|
+
assert_equal(2, bar)
|
39
|
+
assert_equal('4', foo)
|
40
|
+
SetupRubysierungTypes.example2(foo: 4, bar: 2)
|
41
|
+
assert_equal(false, true)
|
42
|
+
rescue StandardError
|
43
|
+
assert_equal(true, true)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_example_3_custum_type_strict
|
47
|
+
foo, bar = SetupRubysierungTypes.example3(foo: '4', bar: 'hi')
|
48
|
+
assert_equal('hi', bar)
|
49
|
+
assert_equal('4', foo)
|
50
|
+
end
|
51
|
+
end
|
metadata
CHANGED
@@ -1,71 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubysierung
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- doodzik
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.6'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '10.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ! '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ! '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rubocop
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ! '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: CallBaecker
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.0.4
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.0.4
|
69
83
|
description:
|
70
84
|
email:
|
71
85
|
- 4004blog@gmail.com
|
@@ -73,18 +87,29 @@ executables: []
|
|
73
87
|
extensions: []
|
74
88
|
extra_rdoc_files: []
|
75
89
|
files:
|
76
|
-
-
|
77
|
-
-
|
90
|
+
- .gitignore
|
91
|
+
- .hound.yml
|
92
|
+
- .rubocop.yml
|
93
|
+
- .travis.yml
|
94
|
+
- CHANGELOG.md
|
78
95
|
- Gemfile
|
79
96
|
- LICENSE.txt
|
80
97
|
- README.md
|
81
98
|
- Rakefile
|
99
|
+
- lib/ast/ast.rb
|
82
100
|
- lib/rubysierung.rb
|
101
|
+
- lib/rubysierung/ast.rb
|
102
|
+
- lib/rubysierung/core.rb
|
83
103
|
- lib/rubysierung/error.rb
|
84
104
|
- lib/rubysierung/types.rb
|
85
105
|
- lib/rubysierung/version.rb
|
86
106
|
- rubysierung.gemspec
|
107
|
+
- test/test_ast.rb
|
108
|
+
- test/test_core.rb
|
109
|
+
- test/test_error.rb
|
87
110
|
- test/test_rubysierung.rb
|
111
|
+
- test/test_rubysierung_ast.rb
|
112
|
+
- test/test_types.rb
|
88
113
|
homepage: https://github.com/doodzik/rubysierung
|
89
114
|
licenses:
|
90
115
|
- MIT
|
@@ -95,20 +120,24 @@ require_paths:
|
|
95
120
|
- lib
|
96
121
|
required_ruby_version: !ruby/object:Gem::Requirement
|
97
122
|
requirements:
|
98
|
-
- -
|
123
|
+
- - ~>
|
99
124
|
- !ruby/object:Gem::Version
|
100
|
-
version: '
|
125
|
+
version: '2.1'
|
101
126
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
127
|
requirements:
|
103
|
-
- -
|
128
|
+
- - ! '>='
|
104
129
|
- !ruby/object:Gem::Version
|
105
130
|
version: '0'
|
106
131
|
requirements: []
|
107
132
|
rubyforge_project:
|
108
|
-
rubygems_version: 2.
|
133
|
+
rubygems_version: 2.4.2
|
109
134
|
signing_key:
|
110
135
|
specification_version: 4
|
111
136
|
summary: Rubysierung is the type system Ruby deserves
|
112
137
|
test_files:
|
138
|
+
- test/test_ast.rb
|
139
|
+
- test/test_core.rb
|
140
|
+
- test/test_error.rb
|
113
141
|
- test/test_rubysierung.rb
|
114
|
-
|
142
|
+
- test/test_rubysierung_ast.rb
|
143
|
+
- test/test_types.rb
|