low_type 1.0.6 → 1.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a59004f5c707ad93a543ad18cfe56525d8dfc878ea76f83f8b5bddee0190ded8
4
- data.tar.gz: 8dd19cda1ae90570b2b0005d862f9d59a9387d7f50f2d10ebcbdda7132133eda
3
+ metadata.gz: 6e3e1dca0d960082a4de505f3422e00c648f660306c22d24db65590db0543f5e
4
+ data.tar.gz: a87156e750aee311a9afb2a95166a9d00f99a744c05fc1dac0d9ab7120882760
5
5
  SHA512:
6
- metadata.gz: 8ae9ca6844f6701f0f8ff7e666d9ebb6a8fd652a58bcffd8e72d38e862637c0f98d037c864f0082bcd351dda83dd0487215f2ee7d722bbd49f2b27551ca1064b
7
- data.tar.gz: c305a84e9b71612b8ec803ab1bce909e83721127fd2bce3caddea3daa7a5a2bb964c7821e8098def80b9323a50d2a72f9e80cc8ace0a9975bc9c18bdea58b315
6
+ metadata.gz: f8e3054ab427c0635aa27f78ae966e3a90c9f78ec660651d6025956ddc83582a1b46f66268e7a335d8ff72ed87bf92a09672a38509067d42d3b79253a97e8d49
7
+ data.tar.gz: 4698ae94c57a2de408ba085029f18b1bc100375972f3f253294dfcef71741d959da1db6773544f4bf55133d5a95d3e2eee44f274f167c503e7f462489e247153
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../type_expression'
4
+ require_relative '../value_expression'
5
+
6
+ module LowType
7
+ class ExpressionFactory
8
+ class << self
9
+ def type_expression_with_value(type:)
10
+ TypeExpression.new(default_value: ValueExpression.new(value: type))
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../proxies/return_proxy'
4
- require_relative '../file_parser'
4
+ require_relative '../queries/file_parser'
5
5
  require_relative '../type_expression'
6
6
 
7
7
  module LowType
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'proxies/return_proxy'
4
+ require_relative 'queries/type_query'
4
5
  require_relative 'type_expression'
5
6
 
6
7
  module LowType
@@ -50,7 +51,7 @@ module LowType
50
51
  def type_expression(expression)
51
52
  if expression.instance_of?(TypeExpression)
52
53
  expression
53
- elsif ::LowType.type?(expression)
54
+ elsif ::LowType::TypeQuery.type?(expression)
54
55
  TypeExpression.new(type: expression)
55
56
  end
56
57
  end
@@ -4,6 +4,23 @@ module LowType
4
4
  class ErrorInterface
5
5
  attr_reader :file
6
6
 
7
+ def initialize
8
+ @file = nil
9
+ @output_mode = LowType.config.output_mode
10
+ @output_size = LowType.config.output_size
11
+ end
12
+
13
+ def output(value:)
14
+ case @output_mode
15
+ when :type
16
+ value.class
17
+ when :value
18
+ value.inspect[0...@output_size]
19
+ else
20
+ 'REDACTED'
21
+ end
22
+ end
23
+
7
24
  def error_type
8
25
  raise NotImplementedError
9
26
  end
data/lib/local_types.rb CHANGED
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'factories/expression_factory'
3
4
  require_relative 'proxies/file_proxy'
4
5
  require_relative 'proxies/local_proxy'
5
6
  require_relative 'types/error_types'
6
- require_relative 'type_expression'
7
- require_relative 'value_expression'
8
7
 
9
8
  module LowType
10
9
  module LocalTypes
@@ -26,7 +25,7 @@ module LowType
26
25
  alias low_type type
27
26
 
28
27
  def value(type)
29
- LowType.value(type:)
28
+ ExpressionFactory.type_expression_with_value(type:)
30
29
  end
31
30
  alias low_value value
32
31
  end
data/lib/low_type.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'adapters/adapter_loader'
4
+ require_relative 'syntax/syntax'
4
5
  require_relative 'types/complex_types'
6
+ require_relative 'queries/file_parser'
7
+ require_relative 'queries/file_query'
5
8
  require_relative 'instance_types'
6
9
  require_relative 'local_types'
7
10
  require_relative 'redefiner'
8
- require_relative 'syntax/syntax'
9
- require_relative 'type_expression'
10
- require_relative 'value_expression'
11
11
 
12
12
  module LowType
13
13
  # We do as much as possible on class load rather than on instantiation to be thread-safe and efficient.
@@ -20,14 +20,14 @@ module LowType
20
20
  end
21
21
  end
22
22
 
23
- file_path = LowType.file_path
23
+ file_path = FileQuery.file_path(klass:)
24
24
  parser = FileParser.new(klass:, file_path:)
25
25
  line_numbers = parser.line_numbers
26
26
 
27
27
  klass.extend InstanceTypes
28
28
  klass.include LocalTypes
29
- klass.prepend LowType::Redefiner.redefine(method_nodes: parser.instance_methods, klass:, line_numbers:, file_path:)
30
- klass.singleton_class.prepend LowType::Redefiner.redefine(method_nodes: parser.class_methods, klass:, line_numbers:, file_path:)
29
+ klass.prepend Redefiner.redefine(method_nodes: parser.instance_methods, klass:, line_numbers:, file_path:)
30
+ klass.singleton_class.prepend Redefiner.redefine(method_nodes: parser.class_methods, klass:, line_numbers:, file_path:)
31
31
 
32
32
  if (adapter = Adapter::Loader.load(klass:, parser:, file_path:))
33
33
  adapter.process
@@ -36,47 +36,13 @@ module LowType
36
36
  end
37
37
 
38
38
  class << self
39
- # Public API.
40
-
41
39
  def config
42
- config = Struct.new(:deep_type_check, :severity_level, :union_type_expressions)
43
- @config ||= config.new(false, :error, true)
40
+ config = Struct.new(:error_mode, :output_mode, :output_size, :deep_type_check, :union_type_expressions)
41
+ @config ||= config.new(:error, :type, 100, false, true)
44
42
  end
45
43
 
46
44
  def configure
47
45
  yield(config)
48
46
  end
49
-
50
- # Internal API.
51
-
52
- def file_path
53
- includer_file = caller.find { |callee| callee.end_with?("include'") }
54
- includer_file.split(':').first
55
- end
56
-
57
- # TODO: Unit test.
58
- def type?(type)
59
- LowType.basic_type?(type:) || LowType.complex_type?(type:)
60
- end
61
-
62
- def basic_type?(type:)
63
- type.class == Class
64
- end
65
-
66
- def complex_type?(type:)
67
- !basic_type?(type:) && LowType.typed_hash?(type:)
68
- end
69
-
70
- def typed_hash?(type:)
71
- type.is_a?(::Hash) && LowType.basic_type?(type: type.keys.first) && LowType.basic_type?(type: type.values.first)
72
- end
73
-
74
- def value?(expression)
75
- !expression.respond_to?(:new) && expression != Integer
76
- end
77
-
78
- def value(type:)
79
- TypeExpression.new(default_value: ValueExpression.new(value: type))
80
- end
81
47
  end
82
48
  end
@@ -8,6 +8,8 @@ module LowType
8
8
  attr_reader :type_expression, :name
9
9
 
10
10
  def initialize(type_expression:, name:, file:)
11
+ super()
12
+
11
13
  @type_expression = type_expression
12
14
  @name = name
13
15
  @file = file
@@ -18,7 +20,7 @@ module LowType
18
20
  end
19
21
 
20
22
  def error_message(value:)
21
- "Invalid variable type #{value.class} in '#{@name.class}' on line #{@file.line}. Valid types: '#{@type_expression.valid_types}'"
23
+ "Invalid variable type #{output(value:)} in '#{@name.class}' on line #{@file.line}. Valid types: '#{@type_expression.valid_types}'"
22
24
  end
23
25
  end
24
26
  end
@@ -8,6 +8,8 @@ module LowType
8
8
  attr_reader :type_expression, :name, :type, :position
9
9
 
10
10
  def initialize(type_expression:, name:, type:, file:, position: nil)
11
+ super()
12
+
11
13
  @type_expression = type_expression
12
14
  @name = name
13
15
  @type = type
@@ -20,7 +22,7 @@ module LowType
20
22
  end
21
23
 
22
24
  def error_message(value:)
23
- "Invalid argument type '#{value.class}' for parameter '#{@name}'. Valid types: '#{@type_expression.valid_types}'"
25
+ "Invalid argument type '#{output(value:)}' for parameter '#{@name}'. Valid types: '#{@type_expression.valid_types}'"
24
26
  end
25
27
  end
26
28
  end
@@ -8,6 +8,8 @@ module LowType
8
8
  attr_reader :type_expression, :name
9
9
 
10
10
  def initialize(type_expression:, name:, file:)
11
+ super()
12
+
11
13
  @type_expression = type_expression
12
14
  @name = name
13
15
  @file = file
@@ -18,7 +20,7 @@ module LowType
18
20
  end
19
21
 
20
22
  def error_message(value:)
21
- "Invalid return type '#{value.class}' for method '#{@name}'. Valid types: '#{@type_expression.valid_types}'"
23
+ "Invalid return type '#{output(value:)}' for method '#{@name}'. Valid types: '#{@type_expression.valid_types}'"
22
24
  end
23
25
  end
24
26
  end
@@ -62,7 +62,7 @@ module LowType
62
62
 
63
63
  @instance_methods = []
64
64
  @class_methods = []
65
- @line_numbers = { class_start: 0, class_end: root_node.respond_to?(:end_line) ? root_node.end_line : nil}
65
+ @line_numbers = { class_start: 0, class_end: root_node.respond_to?(:end_line) ? root_node.end_line : nil }
66
66
  end
67
67
 
68
68
  def visit_def_node(node)
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LowType
4
+ class FileQuery
5
+ class << self
6
+ def file_path(klass:)
7
+ includer_line = line_from_class(klass:) || line_from_include || ''
8
+ includer_line.split(':').first || ''
9
+ end
10
+
11
+ private
12
+
13
+ def line_from_class(klass:)
14
+ class_name = klass.to_s.split(':').last # Also remove the module namespaces from the class.
15
+ caller.find { |callee| callee.end_with?("<class:#{class_name}>'") }
16
+ end
17
+
18
+ def line_from_include
19
+ caller.find { |callee| callee.end_with?("include'") }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LowType
4
+ # TODO: Unit test.
5
+ class TypeQuery
6
+ class << self
7
+ def type?(type)
8
+ basic_type?(type:) || complex_type?(type:)
9
+ end
10
+
11
+ def basic_type?(type:)
12
+ type.instance_of?(Class)
13
+ end
14
+
15
+ def complex_type?(type:)
16
+ !basic_type?(type:) && typed_hash?(type:)
17
+ end
18
+
19
+ def typed_hash?(type:)
20
+ type.is_a?(::Hash) && basic_type?(type: type.keys.first) && basic_type?(type: type.values.first)
21
+ end
22
+
23
+ def value?(expression)
24
+ !expression.respond_to?(:new) && expression != Integer
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/redefiner.rb CHANGED
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'factories/expression_factory'
3
4
  require_relative 'factories/proxy_factory'
4
5
  require_relative 'proxies/file_proxy'
5
6
  require_relative 'proxies/method_proxy'
6
7
  require_relative 'proxies/param_proxy'
8
+ require_relative 'queries/type_query'
7
9
  require_relative 'syntax/syntax'
8
10
  require_relative 'type_expression'
11
+ require_relative 'value_expression'
9
12
 
10
13
  module LowType
11
14
  # Redefine methods to have their arguments and return values type checked.
@@ -42,9 +45,7 @@ module LowType
42
45
  method_start = method_node.respond_to?(:start_line) ? method_node.start_line : nil
43
46
  method_end = method_node.respond_to?(:end_line) ? method_node.end_line : nil
44
47
 
45
- if method_start && method_end && class_end
46
- next unless method_start > class_start && method_end <= class_end
47
- end
48
+ next if method_start && method_end && class_end && !(method_start > class_start && method_end <= class_end)
48
49
 
49
50
  name = method_node.name
50
51
 
@@ -96,7 +97,7 @@ module LowType
96
97
 
97
98
  if expression.is_a?(TypeExpression)
98
99
  param_proxies << ParamProxy.new(type_expression: expression, name:, type:, position:, file:)
99
- elsif ::LowType.type?(expression)
100
+ elsif ::LowType::TypeQuery.type?(expression)
100
101
  param_proxies << ParamProxy.new(type_expression: TypeExpression.new(type: expression), name:, type:, position:, file:)
101
102
  end
102
103
  end
@@ -139,7 +140,7 @@ module LowType
139
140
 
140
141
  # Value expressions are eval()'d in the context of this module class (the instance doesn't exist yet) so alias API.
141
142
  def value(type)
142
- LowType.value(type:)
143
+ ExpressionFactory.type_expression_with_value(type:)
143
144
  end
144
145
  end
145
146
  end
data/lib/syntax/syntax.rb CHANGED
@@ -1,17 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../queries/type_query'
4
+
3
5
  module LowType
4
6
  module Syntax
5
7
  refine Array.singleton_class do
6
8
  def [](*types)
7
- return LowType::TypeExpression.new(type: [*types]) if types.all? { |type| LowType.type?(type) }
9
+ return TypeExpression.new(type: [*types]) if types.all? { |type| TypeQuery.type?(type) }
10
+
8
11
  super
9
12
  end
10
13
  end
11
14
 
12
15
  refine Hash.singleton_class do
13
16
  def [](type)
14
- return LowType::TypeExpression.new(type:) if LowType.type?(type)
17
+ return TypeExpression.new(type:) if TypeQuery.type?(type)
18
+
15
19
  super
16
20
  end
17
21
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ###
2
4
  # Type expressions from union types.
3
5
  #
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'proxies/param_proxy'
4
+ require_relative 'queries/type_query'
4
5
 
5
6
  module LowType
6
7
  root_path = File.expand_path(__dir__)
@@ -24,7 +25,7 @@ module LowType
24
25
  if expression.instance_of?(::LowType::TypeExpression)
25
26
  @types += expression.types
26
27
  @default_value = expression.default_value
27
- elsif ::LowType.value?(expression)
28
+ elsif ::LowType::TypeQuery.value?(expression)
28
29
  @default_value = expression
29
30
  else
30
31
  @types << expression
@@ -45,7 +46,7 @@ module LowType
45
46
 
46
47
  @types.each do |type|
47
48
  # Example: HTML is a subclass of String and should pass as a String.
48
- return true if LowType.basic_type?(type:) && type <= value.class
49
+ return true if LowType::TypeQuery.basic_type?(type:) && type <= value.class
49
50
  return true if type.is_a?(::Array) && value.is_a?(::Array) && array_types_match_values?(types: type, values: value)
50
51
  return true if type.is_a?(::Hash) && value.is_a?(::Hash) && hash_types_match_values?(type:, value:)
51
52
  end
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LowType
4
- VERSION = '1.0.6'
4
+ VERSION = '1.0.8'
5
5
  end
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: 1.0.6
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - maedi
@@ -19,8 +19,8 @@ extra_rdoc_files: []
19
19
  files:
20
20
  - lib/adapters/adapter_loader.rb
21
21
  - lib/adapters/sinatra_adapter.rb
22
+ - lib/factories/expression_factory.rb
22
23
  - lib/factories/proxy_factory.rb
23
- - lib/file_parser.rb
24
24
  - lib/instance_types.rb
25
25
  - lib/interfaces/adapter_interface.rb
26
26
  - lib/interfaces/error_interface.rb
@@ -31,6 +31,9 @@ files:
31
31
  - lib/proxies/method_proxy.rb
32
32
  - lib/proxies/param_proxy.rb
33
33
  - lib/proxies/return_proxy.rb
34
+ - lib/queries/file_parser.rb
35
+ - lib/queries/file_query.rb
36
+ - lib/queries/type_query.rb
34
37
  - lib/redefiner.rb
35
38
  - lib/syntax/syntax.rb
36
39
  - lib/syntax/union_types.rb