moguro 0.0.1

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.
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ # MethodReference represents original method reference that was
5
+ # decorated by contracts.ruby. Used for instance methods.
6
+ # This class borrowed many source code from https://github.com/egonSchiele/contracts.ruby
7
+ # License:: https://github.com/egonSchiele/contracts.ruby/blob/master/LICENSE
8
+ class MethodReference
9
+ attr_reader :name
10
+
11
+ # name - name of the method
12
+ # method - method object
13
+ def initialize(method)
14
+ @name = method.name
15
+ @method = method
16
+ end
17
+
18
+ # Returns method_position, delegates to Support.method_position
19
+ def position
20
+ file, line = @method.source_location
21
+ if file.nil? || line.nil?
22
+ ''
23
+ else
24
+ "#{file}:#{line}"
25
+ end
26
+ end
27
+
28
+ def parameters
29
+ @method.parameters
30
+ end
31
+ end
32
+
33
+ # The same as MethodReference, but used for singleton methods.
34
+ class SingletonMethodReference < MethodReference
35
+ private
36
+
37
+ def private?(this)
38
+ this.private_methods.map(&:to_sym).include?(name)
39
+ end
40
+
41
+ def protected?(this)
42
+ this.protected_methods.map(&:to_sym).include?(name)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ module Processors
5
+ class ArgumentsProcessor < ::Parser::AST::Processor
6
+ attr_reader :rule
7
+
8
+ def initialize(klass, clause)
9
+ @klass = klass
10
+ @clause = clause
11
+ super()
12
+ end
13
+
14
+ def on_const(node)
15
+ symbol = node.children.last
16
+ validator = Moguro::Types.get_type_validator_from_const(get_const(symbol))
17
+ @array_processor = nil
18
+ @clause.add_type(validator)
19
+ super node
20
+ end
21
+
22
+ def on_nil(_node)
23
+ validator = Moguro::Types.get_type_validator_from_const(nil)
24
+ @clause.add_type(validator)
25
+ end
26
+
27
+ def on_send(node)
28
+ return unless node.children[1] == :[]
29
+ @clause.pop_type
30
+ @clause.add_type(
31
+ Moguro::Processors::EnumerableProcessor.generate_type_validator(node, @klass)
32
+ )
33
+ end
34
+
35
+ private
36
+
37
+ def get_const(symbol)
38
+ @klass.const_get(symbol)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ module Processors
5
+ class ContractParser
6
+ def initialize(str)
7
+ @str = str
8
+ end
9
+
10
+ def parse
11
+ ::Parser::CurrentRuby.parse(@str)
12
+ end
13
+ end
14
+
15
+ class ContractProcessor < ::Parser::AST::Processor
16
+ attr_reader :clauses
17
+ Rule = Struct.new(:key, :clauses)
18
+
19
+ def initialize(klass)
20
+ @current_arg = nil
21
+ @klass = klass
22
+ @clauses = Clauses.new
23
+ super()
24
+ end
25
+
26
+ def on_kwarg(node)
27
+ process_args(node)
28
+ super node
29
+ end
30
+
31
+ def on_kwoptarg(node)
32
+ process_args(node)
33
+ super node
34
+ end
35
+
36
+ class << self
37
+ def generate_type_validator(function, klass)
38
+ ast = ContractParser.new(
39
+ function.source
40
+ ).parse
41
+
42
+ processor = ContractProcessor.new(klass)
43
+ processor.process(ast)
44
+ processor.clauses
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def process_args(node)
51
+ argument_key, _other = *node
52
+ rotate_rule(argument_key)
53
+ processor = ArgumentsProcessor.new(@klass, current_clause)
54
+ processor.process(node)
55
+ end
56
+
57
+ def rotate_rule(argument_key)
58
+ @clauses.add_verified_argument(argument_key)
59
+ end
60
+
61
+ def current_clause
62
+ clauses.last
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ module Processors
5
+ class EnumerableProcessor < ::Parser::AST::Processor
6
+ attr_reader :enumerate_validator
7
+
8
+ def initialize(klass)
9
+ @current_arg = nil
10
+ @klass = klass
11
+ @enumerate_validator = nil
12
+ super()
13
+ end
14
+
15
+ def on_const(node)
16
+ symbol = node.children.last
17
+ type = @klass.const_get(symbol)
18
+ if @enumerate_validator.nil?
19
+ @enumerate_validator ||= Moguro::Types::Enumerable.new(type)
20
+ else
21
+ validator = Moguro::Types.get_type_validator_from_const(type)
22
+ @enumerate_validator.add_content_type(validator)
23
+ end
24
+ super node
25
+ end
26
+
27
+ def on_send(node)
28
+ @base_type = false if node.children[1] == :[]
29
+ super node
30
+ end
31
+
32
+ private
33
+
34
+ class << self
35
+ def generate_type_validator(ast, klass)
36
+ processor = EnumerableProcessor.new(klass)
37
+ processor.process(ast)
38
+ processor.enumerate_validator
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ module Processors
5
+ end
6
+ end
7
+
8
+ require_relative 'processors/contract_processor'
9
+ require_relative 'processors/arguments_processor'
10
+ require_relative 'processors/enumerable_processor'
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ class SandBox
5
+ include Test::Unit::Assertions
6
+
7
+ def initialize(klass)
8
+ @klass = klass
9
+ end
10
+
11
+ def method_missing(method_name, *args, &blk)
12
+ @klass.__send__(method_name, *args, &blk)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ module Types
5
+ Result = Struct.new(:emumerable_validator, :valid?)
6
+ class << self
7
+ def get_type_validator_from_const(type)
8
+ if type == Moguro::Types::Boolean
9
+ type.new
10
+ elsif type.nil?
11
+ Nil.new
12
+ elsif type == ::Array || type.include?(::Enumerable)
13
+ Enumerable.new(type)
14
+ else
15
+ Skin.new(type)
16
+ end
17
+ end
18
+ end
19
+
20
+ ###
21
+ # Type match class
22
+ # @private
23
+ # @since 0.0.1
24
+ # @abstract
25
+ class Base
26
+ def valid?(_p)
27
+ raise NotImplementedError
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ require_relative 'types/skin'
34
+ require_relative 'types/enumerable'
35
+ require_relative 'types/boolean'
36
+ require_relative 'types/nil'
37
+ require_relative 'types/any'
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ module Types
5
+ ###
6
+ #
7
+ # @since 0.0.1
8
+ class Any < Base
9
+ def valid?(_val)
10
+ true
11
+ end
12
+
13
+ ###
14
+ # Type name for error message
15
+ # @since 0.0.1
16
+ # @private
17
+ ###
18
+ def type
19
+ 'Any'
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ module Types
5
+ ###
6
+ # Fake Boolean class for type definition
7
+ # @since 0.0.1
8
+ ###
9
+ class Boolean < Base
10
+ ###
11
+ # validate value type
12
+ # TrueClass or FalseClass
13
+ # @since 0.0.1
14
+ ###
15
+ def valid?(val)
16
+ val.is_a?(TrueClass) || val.is_a?(FalseClass)
17
+ end
18
+
19
+ ###
20
+ # Type name for error message
21
+ # @since 0.0.1
22
+ # @private
23
+ ###
24
+ def type
25
+ 'TrueClass or FalseClass'
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ module Types
5
+ ###
6
+ # Array type validator
7
+ # @since 0.0.1
8
+ # @private
9
+ ###
10
+ class Enumerable < Base
11
+ def initialize(klass)
12
+ @content_type = []
13
+ @klass = klass
14
+ end
15
+
16
+ def add_content_type(type)
17
+ @content_type << type
18
+ end
19
+
20
+ def valid?(val)
21
+ eumerable?(val) && (val.empty? || content_type_valid?(val))
22
+ end
23
+
24
+ def type
25
+ if @content_type.empty?
26
+ @klass.to_s
27
+ else
28
+ "#{@klass}<#{@content_type.join('|')}>"
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def eumerable?(val)
35
+ val.is_a?(@klass)
36
+ end
37
+
38
+ def content_type_valid?(val)
39
+ return true if @content_type.empty?
40
+
41
+ val.all? do |v|
42
+ @content_type.any? { |type| type.valid?(v) }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ module Types
5
+ ###
6
+ # @since 0.0.1
7
+ # NilClass Wrapper
8
+ class Nil < Base
9
+ def valid?(p)
10
+ p.nil?
11
+ end
12
+
13
+ def type
14
+ 'nil'
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ module Types
5
+ ###
6
+ # The thin wrapper class for some instance object
7
+ # @since 0.0.1
8
+ ###
9
+ class Skin < SimpleDelegator
10
+ def initialize(klass)
11
+ @klass = klass
12
+ super(@klass)
13
+ end
14
+
15
+ def valid?(val)
16
+ val.is_a?(@klass)
17
+ end
18
+
19
+ ###
20
+ # Class name for error message
21
+ # @since 0.0.1
22
+ # @private
23
+ ###
24
+ def type
25
+ @klass
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moguro
4
+ ###
5
+ # Wrapper class for Arguments
6
+ # @since 0.0.1
7
+ # @private
8
+ ###
9
+ class Values < DelegateClass(Array)
10
+ def initialize
11
+ super([])
12
+ end
13
+
14
+ def to_h
15
+ each_with_object({}) do |value_class, hash|
16
+ hash[value_class.key] = value_class.value
17
+ end
18
+ end
19
+
20
+ def add_value(key, value, missing: false)
21
+ self << Value.new(key, value, missing: missing)
22
+ end
23
+
24
+ def inspect
25
+ map(&:inspect)
26
+ end
27
+ end
28
+
29
+ ###
30
+ # Wrapper class for Arguments value
31
+ # @since 0.0.1
32
+ # @private
33
+ ###
34
+ class Value < SimpleDelegator
35
+ attr_reader :key, :value
36
+
37
+ def initialize(key, value, missing: false)
38
+ @key = key
39
+ @value = value
40
+ @missing = missing
41
+ super(@value)
42
+ end
43
+
44
+ def missing?
45
+ @missing
46
+ end
47
+
48
+ def class
49
+ @value.class
50
+ end
51
+
52
+ def is_a?(val)
53
+ @value.is_a?(val)
54
+ end
55
+
56
+ def nil?
57
+ @value.nil?
58
+ end
59
+
60
+ def inspect
61
+ "#{key}: #{type_inspect}"
62
+ end
63
+
64
+ def type_inspect
65
+ if @value.class.include?(Enumerable) && !@value.empty?
66
+ "#{value}(#{value.class}<#{@value.map(&:class).uniq.join('|')}>)"
67
+ else
68
+ "#{value}(#{value.class})"
69
+ end
70
+ end
71
+ end
72
+ end