low_type 0.3.0 → 0.4.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.
- checksums.yaml +4 -4
- data/lib/low_type.rb +11 -3
- data/lib/method_proxy.rb +11 -0
- data/lib/parser.rb +9 -0
- data/lib/redefiner.rb +35 -13
- data/lib/type_expression.rb +11 -10
- data/lib/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4ec90c752620d94c2f38e287ce6927684bb77b17caf65c9551765a37b031d2ab
|
|
4
|
+
data.tar.gz: 6d6106390f7286f5d1812c4de79fe1a72f021db0d0b0f62c1dce5bf5a4cfc02c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 791da36eca530ac38f459cbdb25253089be16e1d2c544f478c3c0fc80a7249f5c942706ec93cc4ef5340779d746f5c3be559d435f8bbdb25f2d092c6d9128681
|
|
7
|
+
data.tar.gz: a92a680924fd3219cc5b88e6097aaadb12fb0f0f26d175591bbcd27c5d045286dd5c392d3218f5ed1600b639a79be5be643d6c0784212a7c72e6dde945946625
|
data/lib/low_type.rb
CHANGED
|
@@ -16,12 +16,20 @@ module LowType
|
|
|
16
16
|
# Hash[] class method returns a type expression only for the duration of this "included" hook.
|
|
17
17
|
hash_class_method = Hash.method('[]').unbind
|
|
18
18
|
Hash.define_singleton_method('[]') do |expression|
|
|
19
|
+
# Support Pry which uses Hash[].
|
|
20
|
+
unless LowType.type?(expression)
|
|
21
|
+
Hash.define_singleton_method('[]', hash_class_method)
|
|
22
|
+
result = Hash[expression]
|
|
23
|
+
Hash.method('[]').unbind
|
|
24
|
+
return result
|
|
25
|
+
end
|
|
26
|
+
|
|
19
27
|
TypeExpression.new(type: expression)
|
|
20
28
|
end
|
|
21
29
|
|
|
22
30
|
class << klass
|
|
23
|
-
def
|
|
24
|
-
@
|
|
31
|
+
def low_methods
|
|
32
|
+
@low_methods ||= {}
|
|
25
33
|
end
|
|
26
34
|
|
|
27
35
|
def type(expression)
|
|
@@ -51,7 +59,7 @@ module LowType
|
|
|
51
59
|
end
|
|
52
60
|
|
|
53
61
|
def type?(expression)
|
|
54
|
-
expression.respond_to?(:new) || expression == Integer
|
|
62
|
+
expression.respond_to?(:new) || expression == Integer || (expression.is_a?(Hash) && expression.keys.first.respond_to?(:new) && expression.values.first.respond_to?(:new))
|
|
55
63
|
end
|
|
56
64
|
|
|
57
65
|
def value?(expression)
|
data/lib/method_proxy.rb
ADDED
data/lib/parser.rb
CHANGED
|
@@ -18,6 +18,15 @@ module LowType
|
|
|
18
18
|
@class_methods = method_visitor.class_methods
|
|
19
19
|
@private_start_line = method_visitor.private_start_line
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
def self.return_node(method_node:)
|
|
23
|
+
# Only a lambda defined immediately after a method's parameters is considered a return type expression.
|
|
24
|
+
node = method_node.compact_child_nodes.find { |node| node.is_a?(Prism::StatementsNode) }.body.first
|
|
25
|
+
|
|
26
|
+
return node if node.is_a?(Prism::LambdaNode)
|
|
27
|
+
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
21
30
|
end
|
|
22
31
|
|
|
23
32
|
class MethodVisitor < Prism::Visitor
|
data/lib/redefiner.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require_relative 'method_proxy'
|
|
1
2
|
require_relative 'param_proxy'
|
|
2
3
|
require_relative 'parser'
|
|
3
4
|
require_relative 'type_expression'
|
|
@@ -8,31 +9,52 @@ module LowType
|
|
|
8
9
|
def redefine_methods(method_nodes:, private_start_line:, klass:)
|
|
9
10
|
Module.new do
|
|
10
11
|
method_nodes.each do |method_node|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
param_proxy.position ? args[param_proxy.position]
|
|
12
|
+
name = method_node.name
|
|
13
|
+
params = Redefiner.params_with_type_expressions(method_node:)
|
|
14
|
+
return_expression = Redefiner.return_type_expression(method_node:)
|
|
15
|
+
|
|
16
|
+
klass.low_methods[name] = MethodProxy.new(name:, params:, return_expression:)
|
|
17
|
+
|
|
18
|
+
define_method(name) do |*args, **kwargs|
|
|
19
|
+
klass.low_methods[name].params.each do |param_proxy|
|
|
20
|
+
value = param_proxy.position ? args[param_proxy.position] : kwargs[param_proxy.name]
|
|
21
|
+
value = param_proxy.type_expression.default_value if value.nil? && param_proxy.type_expression.default_value != :LOW_TYPE_UNDEFINED
|
|
22
|
+
param_proxy.type_expression.validate!(value:, name: param_proxy.name)
|
|
23
|
+
param_proxy.position ? args[param_proxy.position] = value : kwargs[param_proxy.name] = value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if return_expression
|
|
27
|
+
return_value = super(*args, **kwargs)
|
|
28
|
+
return_expression.validate!(value: return_value, name:)
|
|
29
|
+
return return_value
|
|
20
30
|
end
|
|
21
31
|
|
|
22
32
|
super(*args, **kwargs)
|
|
23
33
|
end
|
|
24
34
|
|
|
25
35
|
if private_start_line && method_node.start_line > private_start_line
|
|
26
|
-
private
|
|
36
|
+
private name
|
|
27
37
|
end
|
|
28
38
|
end
|
|
29
39
|
end
|
|
30
40
|
end
|
|
31
41
|
|
|
32
|
-
def
|
|
42
|
+
def return_type_expression(method_node:)
|
|
43
|
+
return_node = Parser.return_node(method_node:)
|
|
44
|
+
return nil if return_node.nil?
|
|
45
|
+
|
|
46
|
+
expression = eval(return_node.slice).call
|
|
47
|
+
|
|
48
|
+
return expression if expression.class == TypeExpression
|
|
49
|
+
TypeExpression.new(type: expression)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def params_with_type_expressions(method_node:)
|
|
53
|
+
return [] if method_node.parameters.nil?
|
|
54
|
+
|
|
33
55
|
params = method_node.parameters.slice
|
|
34
56
|
proxy_method = eval("-> (#{params}) {}")
|
|
35
|
-
required_args, required_kwargs = Redefiner.required_args(proxy_method)
|
|
57
|
+
required_args, required_kwargs = Redefiner.required_args(proxy_method:)
|
|
36
58
|
|
|
37
59
|
typed_method = eval(
|
|
38
60
|
<<~RUBY
|
|
@@ -65,7 +87,7 @@ module LowType
|
|
|
65
87
|
raise ArgumentError, "Incorrect param syntax"
|
|
66
88
|
end
|
|
67
89
|
|
|
68
|
-
def required_args(proxy_method)
|
|
90
|
+
def required_args(proxy_method:)
|
|
69
91
|
required_args = []
|
|
70
92
|
required_kwargs = {}
|
|
71
93
|
|
data/lib/type_expression.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module LowType
|
|
2
2
|
class TypeExpression
|
|
3
|
-
attr_reader :
|
|
3
|
+
attr_reader :types, :default_value
|
|
4
4
|
|
|
5
|
-
def initialize(type:)
|
|
5
|
+
def initialize(type:, default_value: :LOW_TYPE_UNDEFINED)
|
|
6
6
|
@types = [type]
|
|
7
|
-
@default_value =
|
|
7
|
+
@default_value = default_value
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def |(expression)
|
|
@@ -24,21 +24,22 @@ module LowType
|
|
|
24
24
|
@default_value == :LOW_TYPE_UNDEFINED
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
def validate!(
|
|
28
|
-
if
|
|
29
|
-
|
|
27
|
+
def validate!(value:, name:)
|
|
28
|
+
if value.nil?
|
|
29
|
+
return true if @default_value.nil?
|
|
30
|
+
raise ArgumentError, "Missing required argument of type '#{@types.join(', ')}' for '#{name}'" if required?
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
@types.each do |type|
|
|
33
|
-
return true if LowType.type?(type) && type ==
|
|
34
|
+
return true if LowType.type?(type) && type == value.class
|
|
34
35
|
# TODO: Shallow validation of enumerables could be made deeper with user config.
|
|
35
|
-
return true if type.class == Array &&
|
|
36
|
-
if type.class == Hash &&
|
|
36
|
+
return true if type.class == Array && value.class == Array && type.first == value.first.class
|
|
37
|
+
if type.class == Hash && value.class == Hash && type.keys[0] == value.keys[0].class && type.values[0] == value.values[0].class
|
|
37
38
|
return true
|
|
38
39
|
end
|
|
39
40
|
end
|
|
40
41
|
|
|
41
|
-
raise TypeError, "Invalid type '#{
|
|
42
|
+
raise TypeError, "Invalid type '#{value.class}' for '#{name}'"
|
|
42
43
|
end
|
|
43
44
|
end
|
|
44
45
|
end
|
data/lib/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: low_type
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- maedi
|
|
@@ -18,6 +18,7 @@ extensions: []
|
|
|
18
18
|
extra_rdoc_files: []
|
|
19
19
|
files:
|
|
20
20
|
- lib/low_type.rb
|
|
21
|
+
- lib/method_proxy.rb
|
|
21
22
|
- lib/param_proxy.rb
|
|
22
23
|
- lib/parser.rb
|
|
23
24
|
- lib/redefiner.rb
|