moguro 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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