lowtype 1.3.2 → 1.5.0
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/cli/cli.rb +36 -0
- data/lib/cli/rbs/class_sig.rb +57 -0
- data/lib/cli/rbs/exporter.rb +67 -0
- data/lib/cli/rbs/expression_mapper.rb +34 -0
- data/lib/cli/rbs/method_sig.rb +52 -0
- data/lib/cli/rbs/type_mapper.rb +65 -0
- data/lib/cli/type_stripper.rb +9 -0
- data/lib/definitions/redefiner.rb +30 -15
- data/lib/expressions/type_expression.rb +8 -5
- data/lib/lowtype.rb +7 -3
- data/lib/proxies/param_proxy.rb +5 -1
- data/lib/types/error_types.rb +1 -1
- data/lib/version.rb +1 -1
- metadata +37 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8fa1f2cac7f1067dd6d9c7c8f9a2c9d206cc22638c0223259a39909b65b8169f
|
|
4
|
+
data.tar.gz: bd3eaa654437ebabeecad44fccd7aa01cff8fb92d489318181c7d0fc0f757ebe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ece1f0a96afaebdb246a4448875873fddd1eb8b2785a83f20c41f8960d46f6d37bab589743bec4fc945c237c8fef6cca5ce1a973133e81dcb08fddfdb39273a4
|
|
7
|
+
data.tar.gz: 5e5d946234acf6666fc3671d7027368fce3f0bcfcdf665083d45b15a6ea8bd56111c9c61f5ad3bbfeb09995ebce1563160c0a3c3eebb46d0902638077637e3be
|
data/lib/cli/cli.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'trees'
|
|
4
|
+
|
|
5
|
+
require_relative 'rbs/exporter'
|
|
6
|
+
require_relative 'type_stripper'
|
|
7
|
+
|
|
8
|
+
module LowType
|
|
9
|
+
module CLI
|
|
10
|
+
extend Trees
|
|
11
|
+
|
|
12
|
+
line('rbs :src') do |src|
|
|
13
|
+
s { 'Exports files from the source to type signatures in the sig directory' }
|
|
14
|
+
e { 'lowtype rbs app' }
|
|
15
|
+
x { RBS::Exporter.export(path: src) }
|
|
16
|
+
|
|
17
|
+
line('--boot', '-b') do |src, boot|
|
|
18
|
+
s { 'Runs a file before export and could be used to load constants outside your source directory' }
|
|
19
|
+
e { 'lowtype rbs app --boot config/boot.rb' }
|
|
20
|
+
x { RBS::Exporter.export(path: src, boot:) }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
line('strip!') do
|
|
25
|
+
s { 'Strips files from the current directory of their types' }
|
|
26
|
+
e { 'lowtype strip' }
|
|
27
|
+
x { TypeStripper.export(src: '.', dest: '.') }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
line('strip :src :dest') do |src, dest|
|
|
31
|
+
s { 'Exports files from the source directory to a destination directory with types stripped' }
|
|
32
|
+
e { 'lowtype strip src/app dest/app' }
|
|
33
|
+
x { TypeStripper.export(src:, dest:) }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lowkey'
|
|
4
|
+
|
|
5
|
+
require_relative 'method_sig'
|
|
6
|
+
|
|
7
|
+
module LowType
|
|
8
|
+
module CLI
|
|
9
|
+
module RBS
|
|
10
|
+
module ClassSig
|
|
11
|
+
class << self
|
|
12
|
+
def build(class_proxy:, file_proxy:)
|
|
13
|
+
body = method_lines(class_proxy)
|
|
14
|
+
wrap_namespace(namespace: class_proxy.namespace, name: class_proxy.name, body:, file_proxy:).join("\n")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def method_lines(class_proxy)
|
|
20
|
+
instance_lines = class_proxy.instance_methods.each_value.map do |method_proxy|
|
|
21
|
+
MethodSig.build(method_proxy:)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class_lines = class_proxy.class_methods.each_value.map do |method_proxy|
|
|
25
|
+
MethodSig.build(method_proxy:, class_method: true)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
instance_lines + class_lines
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def wrap_namespace(namespace:, name:, body:, file_proxy:)
|
|
32
|
+
lines = wrap("class #{name}", body)
|
|
33
|
+
|
|
34
|
+
segments(namespace).reverse_each do |segment|
|
|
35
|
+
lines = wrap("#{namespace_type(segment:, file_proxy:)} #{segment}", lines)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
lines
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def wrap(header, body_lines)
|
|
42
|
+
[header, *body_lines.map { |line| " #{line}" }, 'end']
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Lowkey's "namespace" includes the class's own name.
|
|
46
|
+
def segments(namespace)
|
|
47
|
+
namespace.split('::')[0..-2]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def namespace_type(segment:, file_proxy:)
|
|
51
|
+
file_proxy.definitions[segment].is_a?(::Lowkey::ClassProxy) ? 'class' : 'module'
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'lowkey'
|
|
5
|
+
require 'dirload'
|
|
6
|
+
|
|
7
|
+
require_relative 'class_sig'
|
|
8
|
+
|
|
9
|
+
module LowType
|
|
10
|
+
module CLI
|
|
11
|
+
module RBS
|
|
12
|
+
class MissingPathError < StandardError; end
|
|
13
|
+
|
|
14
|
+
# Exports .rbs files for every class in `path` (a file or directory) that includes LowType.
|
|
15
|
+
# Uses dirload() to autoload missing constants from files within the same directory.
|
|
16
|
+
module Exporter
|
|
17
|
+
class << self
|
|
18
|
+
def export(path:, boot: nil)
|
|
19
|
+
dirload(path).loaded_paths.each do |file_path, _adapter|
|
|
20
|
+
next unless file_path.end_with?('.rb') || file_path.end_with?('.rbx')
|
|
21
|
+
|
|
22
|
+
export_file(file_path:)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def export_file(file_path:)
|
|
29
|
+
return unless file_proxy = ::Lowkey[file_path]
|
|
30
|
+
|
|
31
|
+
class_proxies = typed_class_proxies(file_proxy)
|
|
32
|
+
return if class_proxies.empty?
|
|
33
|
+
|
|
34
|
+
content = class_proxies.map do |class_proxy|
|
|
35
|
+
ClassSig.build(class_proxy:, file_proxy:)
|
|
36
|
+
end.join("\n\n")
|
|
37
|
+
|
|
38
|
+
save_file(file_path:, content:)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def typed_class_proxies(file_proxy)
|
|
42
|
+
file_proxy.definitions.values.filter do |proxy|
|
|
43
|
+
includes_lowtype = proxy.lines[proxy.start_line..proxy.end_line].find do |line|
|
|
44
|
+
line.include?('include LowType')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
proxy.is_a?(::Lowkey::ClassProxy) && includes_lowtype
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def save_file(file_path:, content:)
|
|
52
|
+
sig_path = sig_path(file_path:)
|
|
53
|
+
FileUtils.mkdir_p(File.dirname(sig_path))
|
|
54
|
+
File.write(sig_path, "#{content}\n")
|
|
55
|
+
|
|
56
|
+
puts "Exported #{sig_path}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def sig_path(file_path:)
|
|
60
|
+
relative = file_path.delete_prefix("#{Dir.pwd}/").delete_prefix('lib/')
|
|
61
|
+
File.join('sig', relative.sub(/\.rb\z/, '.rbs'))
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'type_mapper'
|
|
4
|
+
|
|
5
|
+
module LowType
|
|
6
|
+
module CLI
|
|
7
|
+
module RBS
|
|
8
|
+
# Maps a TypeExpression to an RBS type.
|
|
9
|
+
module ExpressionMapper
|
|
10
|
+
class << self
|
|
11
|
+
def match(expression)
|
|
12
|
+
return 'untyped' if expression.nil?
|
|
13
|
+
|
|
14
|
+
types = expression.types.map { |type| TypeMapper.map(type) }.uniq
|
|
15
|
+
types = ['untyped'] if types.empty?
|
|
16
|
+
|
|
17
|
+
union = types.join(' | ')
|
|
18
|
+
nilable?(expression) ? nilable(union:, multiple: types.length > 1) : union
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def nilable?(expression)
|
|
24
|
+
expression.default_value.nil?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def nilable(union:, multiple:)
|
|
28
|
+
multiple ? "(#{union})?" : "#{union}?"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'expression_mapper'
|
|
4
|
+
|
|
5
|
+
module LowType
|
|
6
|
+
module CLI
|
|
7
|
+
module RBS
|
|
8
|
+
# Builds an RBS method signature line from a Lowkey::MethodProxy.
|
|
9
|
+
# TODO: Support positional args, keyword args and blocks.
|
|
10
|
+
module MethodSig
|
|
11
|
+
POSITIONAL_TYPES = %i[pos_req pos_opt].freeze
|
|
12
|
+
KEYWORD_TYPES = %i[key_req key_opt].freeze
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def build(method_proxy:, class_method: false)
|
|
16
|
+
scope = class_method ? 'self.' : ''
|
|
17
|
+
"def #{scope}#{method_proxy.name}: (#{params(method_proxy)}) -> #{return_type(method_proxy)}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def params(method_proxy)
|
|
23
|
+
positional = method_proxy.params.select { |param| POSITIONAL_TYPES.include?(param.type) }
|
|
24
|
+
keyword = method_proxy.params.select { |param| KEYWORD_TYPES.include?(param.type) }
|
|
25
|
+
|
|
26
|
+
(positional.map { |param| positional_fragment(param) } + keyword.map { |param| keyword_fragment(param) }).join(', ')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def positional_fragment(param_proxy)
|
|
30
|
+
type = ExpressionMapper.match(param_proxy.expression)
|
|
31
|
+
optional?(param_proxy) ? "?#{type} #{param_proxy.name}" : "#{type} #{param_proxy.name}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def keyword_fragment(param_proxy)
|
|
35
|
+
type = ExpressionMapper.match(param_proxy.expression)
|
|
36
|
+
optional?(param_proxy) ? "?#{param_proxy.name}: #{type}" : "#{param_proxy.name}: #{type}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def optional?(param_proxy)
|
|
40
|
+
return !param_proxy.expression.required? if param_proxy.expression
|
|
41
|
+
|
|
42
|
+
%i[pos_opt key_opt].include?(param_proxy.type)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def return_type(method_proxy)
|
|
46
|
+
ExpressionMapper.match(method_proxy.return_proxy&.expression)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../types/complex_types'
|
|
4
|
+
|
|
5
|
+
module LowType
|
|
6
|
+
module CLI
|
|
7
|
+
module RBS
|
|
8
|
+
module TypeMapper
|
|
9
|
+
COMPLEX_TYPE_MAP = {
|
|
10
|
+
Low::Types::Boolean => 'bool',
|
|
11
|
+
Low::Types::HTML => 'String',
|
|
12
|
+
Low::Types::JSON => 'String',
|
|
13
|
+
Low::Types::XML => 'String',
|
|
14
|
+
Low::Types::Status => 'Integer',
|
|
15
|
+
Low::Types::Headers => 'Hash[String, untyped]',
|
|
16
|
+
Low::Types::Tuple => 'Array[untyped]'
|
|
17
|
+
}.freeze
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
def map(type)
|
|
21
|
+
return 'nil' if type == NilClass
|
|
22
|
+
return 'bool' if [TrueClass, FalseClass].include?(type)
|
|
23
|
+
return COMPLEX_TYPE_MAP[type] if COMPLEX_TYPE_MAP.key?(type)
|
|
24
|
+
|
|
25
|
+
case type
|
|
26
|
+
when ::Low::TypeExpression then map_expression(type)
|
|
27
|
+
when Array then map_array(type)
|
|
28
|
+
when Hash then map_hash(type)
|
|
29
|
+
when Class then map_class(type)
|
|
30
|
+
else 'untyped'
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
# A nested type expressio like "String | Integer" inside "Array[String | Integer]".
|
|
37
|
+
def map_expression(expression)
|
|
38
|
+
require_relative 'expression_mapper'
|
|
39
|
+
ExpressionMapper.match(expression)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# When [T] then every element is type T. When [X, Y, Z] then each element is that type at that position.
|
|
43
|
+
def map_array(type)
|
|
44
|
+
return 'Array[untyped]' if type.empty?
|
|
45
|
+
return "[#{type.map { |subtype| map(subtype) }.join(', ')}]" if type.length > 1
|
|
46
|
+
|
|
47
|
+
"Array[#{map(type.first)}]"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def map_hash(type)
|
|
51
|
+
return 'Hash[untyped, untyped]' if type.empty?
|
|
52
|
+
|
|
53
|
+
"Hash[#{map(type.keys.first)}, #{map(type.values.first)}]"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def map_class(type)
|
|
57
|
+
return 'untyped' if type.name.nil?
|
|
58
|
+
|
|
59
|
+
"::#{type.name}"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -26,25 +26,28 @@ module Low
|
|
|
26
26
|
# │ │ │ │ │
|
|
27
27
|
class Redefiner
|
|
28
28
|
class << self
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
def redefine(method_proxies:, class_proxy:, klass: nil)
|
|
30
|
+
return typed_methods(method_proxies:, class_proxy:) if LowType.config.type_checking
|
|
31
|
+
|
|
32
|
+
case LowType.config.disable_mode
|
|
33
|
+
when :shim
|
|
34
|
+
shimmed_methods(method_proxies:, class_proxy:)
|
|
35
|
+
when :strip
|
|
36
|
+
strip_types(method_proxies:, class_proxy:, klass:)
|
|
35
37
|
end
|
|
36
38
|
end
|
|
37
39
|
|
|
38
|
-
def
|
|
40
|
+
def untyped_shimmed_args(args:, kwargs:, method_proxy:) # rubocop:disable Metrics/AbcSize
|
|
39
41
|
method_proxy.params_with_expressions.each do |param_proxy|
|
|
40
|
-
|
|
42
|
+
positional = %i[pos_req pos_opt].include?(param_proxy.type)
|
|
43
|
+
value = positional ? args[param_proxy.position] : kwargs[param_proxy.name]
|
|
41
44
|
|
|
42
45
|
next unless value.nil?
|
|
43
46
|
raise param_proxy.error_type, param_proxy.error_message(value:) if param_proxy.expression.required?
|
|
44
47
|
|
|
45
48
|
value = param_proxy.expression.default_value # Default value can still be `nil`.
|
|
46
49
|
value = value.value if value.is_a?(ValueExpression)
|
|
47
|
-
|
|
50
|
+
positional ? args[param_proxy.position] = value : kwargs[param_proxy.name] = value
|
|
48
51
|
end
|
|
49
52
|
|
|
50
53
|
[args, kwargs]
|
|
@@ -82,15 +85,13 @@ module Low
|
|
|
82
85
|
end
|
|
83
86
|
end
|
|
84
87
|
|
|
85
|
-
def
|
|
88
|
+
def shimmed_methods(method_proxies:, class_proxy:)
|
|
86
89
|
Module.new do
|
|
87
90
|
method_proxies.values.filter(&:expressions?).each do |method_proxy|
|
|
88
|
-
# You are now in the binding of the includer class.
|
|
91
|
+
# You are now in the binding of both LowType and the includer class.
|
|
89
92
|
define_method(method_proxy.name) do |*args, **kwargs|
|
|
90
|
-
# NOTE: Type checking is currently disabled. See 'config.type_checking'.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
args, kwargs = Low::Redefiner.untyped_args(args:, kwargs:, method_proxy:)
|
|
93
|
+
# NOTE: Type checking is currently disabled via shim. See 'config.type_checking'.
|
|
94
|
+
args, kwargs = Low::Redefiner.untyped_shimmed_args(args:, kwargs:, method_proxy:)
|
|
94
95
|
super(*args, **kwargs)
|
|
95
96
|
end
|
|
96
97
|
|
|
@@ -98,6 +99,20 @@ module Low
|
|
|
98
99
|
end
|
|
99
100
|
end
|
|
100
101
|
end
|
|
102
|
+
|
|
103
|
+
def strip_types(method_proxies:, class_proxy:, klass:)
|
|
104
|
+
method_proxies.values.filter(&:expressions?).each do |method_proxy|
|
|
105
|
+
method_proxy.rewrite_signature
|
|
106
|
+
|
|
107
|
+
klass.class_eval(method_proxy.export, method_proxy.file_path, method_proxy.start_line)
|
|
108
|
+
|
|
109
|
+
if class_proxy.private_start_line && method_proxy.start_line > class_proxy.private_start_line
|
|
110
|
+
klass.send(:private, method_proxy.name)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
nil
|
|
115
|
+
end
|
|
101
116
|
end
|
|
102
117
|
end
|
|
103
118
|
end
|
|
@@ -7,9 +7,11 @@ require_relative '../proxies/param_proxy'
|
|
|
7
7
|
require_relative '../queries/type_query'
|
|
8
8
|
|
|
9
9
|
module Low
|
|
10
|
-
|
|
11
|
-
adapter_paths = Dir.
|
|
12
|
-
module_paths = %w[expressions/
|
|
10
|
+
lib_path = File.expand_path('..', __dir__)
|
|
11
|
+
adapter_paths = Dir.glob('adapters/*', base: lib_path).map { |path| File.join(lib_path, path) }
|
|
12
|
+
module_paths = %w[expressions/expression_helpers definitions/type_accessors definitions/redefiner].map do |path|
|
|
13
|
+
File.join(lib_path, "#{path}.rb")
|
|
14
|
+
end
|
|
13
15
|
|
|
14
16
|
HIDDEN_PATHS = [File.expand_path(__FILE__), *adapter_paths, *module_paths].freeze
|
|
15
17
|
|
|
@@ -18,7 +20,7 @@ module Low
|
|
|
18
20
|
attr_reader :types, :default_value
|
|
19
21
|
|
|
20
22
|
# @param type - A literal type or an instance representation of a typed structure.
|
|
21
|
-
def initialize(type: nil, default_value: :
|
|
23
|
+
def initialize(type: nil, default_value: :LOWTYPE_UNDEFINED)
|
|
22
24
|
@types = []
|
|
23
25
|
@types << type unless type.nil?
|
|
24
26
|
@default_value = default_value
|
|
@@ -27,9 +29,10 @@ module Low
|
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
def required?
|
|
30
|
-
@default_value == :
|
|
32
|
+
@default_value == :LOWTYPE_UNDEFINED
|
|
31
33
|
end
|
|
32
34
|
|
|
35
|
+
# TODO: Might need to accept error class here so that type accessors can be disabled and supply ArgumentError.
|
|
33
36
|
def validate!(value:, proxy:) # rubocop:disable Metrics
|
|
34
37
|
if value.nil?
|
|
35
38
|
return true if @default_value.nil?
|
data/lib/lowtype.rb
CHANGED
|
@@ -52,8 +52,11 @@ module LowType
|
|
|
52
52
|
|
|
53
53
|
Low::Evaluator.evaluate(method_proxies: class_proxy.keyed_methods, class_binding: class_proxy.class_binding)
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
klass.
|
|
55
|
+
result = Low::Redefiner.redefine(method_proxies: class_proxy.instance_methods, class_proxy:, klass:)
|
|
56
|
+
klass.prepend result if result.is_a?(Module)
|
|
57
|
+
|
|
58
|
+
singleton_result = Low::Redefiner.redefine(method_proxies: class_proxy.class_methods, class_proxy:, klass: klass.singleton_class)
|
|
59
|
+
klass.singleton_class.prepend singleton_result if singleton_result.is_a?(Module)
|
|
57
60
|
|
|
58
61
|
Low::Adapter::Loader.load(klass:, class_proxy:)
|
|
59
62
|
|
|
@@ -65,6 +68,7 @@ module LowType
|
|
|
65
68
|
|
|
66
69
|
Config = Struct.new(
|
|
67
70
|
:type_checking,
|
|
71
|
+
:disable_mode,
|
|
68
72
|
:error_mode,
|
|
69
73
|
:output_mode,
|
|
70
74
|
:output_size,
|
|
@@ -74,7 +78,7 @@ module LowType
|
|
|
74
78
|
|
|
75
79
|
class << self
|
|
76
80
|
def config
|
|
77
|
-
@config ||= Config.new(true, :error, :type, 100, true, true)
|
|
81
|
+
@config ||= Config.new(true, :shim, :error, :type, 100, true, true)
|
|
78
82
|
end
|
|
79
83
|
|
|
80
84
|
def configure
|
data/lib/proxies/param_proxy.rb
CHANGED
|
@@ -9,10 +9,14 @@ module ::Lowkey
|
|
|
9
9
|
class ParamProxy
|
|
10
10
|
include ::Low::ErrorHandling
|
|
11
11
|
|
|
12
|
+
# Error type should be an ArgumentError when type checking disabled via shim methods.
|
|
12
13
|
def error_type
|
|
13
|
-
::Low::ArgumentTypeError
|
|
14
|
+
return ::Low::ArgumentTypeError if LowType.config.type_checking
|
|
15
|
+
|
|
16
|
+
ArgumentError
|
|
14
17
|
end
|
|
15
18
|
|
|
19
|
+
# When shimmed the error message will be from LowType, when stripped standard Ruby.
|
|
16
20
|
def error_message(value:)
|
|
17
21
|
"Invalid argument type '#{output(value:)}' for parameter '#{@name}'. Valid types: '#{@expression.valid_types}'"
|
|
18
22
|
end
|
data/lib/types/error_types.rb
CHANGED
data/lib/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lowtype
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- maedi
|
|
8
|
-
bindir:
|
|
8
|
+
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: dirload
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: expressions
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -37,6 +51,20 @@ dependencies:
|
|
|
37
51
|
- - "~>"
|
|
38
52
|
- !ruby/object:Gem::Version
|
|
39
53
|
version: '0.4'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: trees
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
40
68
|
description: "LowType introduces the concept of \"type expressions\" in method arguments.
|
|
41
69
|
\nWhen an argument's default value resolves to a type instead of a value then it's
|
|
42
70
|
treated as a type expression. \nNow you can have types in Ruby in the simplest syntax
|
|
@@ -49,6 +77,13 @@ extra_rdoc_files: []
|
|
|
49
77
|
files:
|
|
50
78
|
- lib/adapters/adapter_loader.rb
|
|
51
79
|
- lib/adapters/sinatra_adapter.rb
|
|
80
|
+
- lib/cli/cli.rb
|
|
81
|
+
- lib/cli/rbs/class_sig.rb
|
|
82
|
+
- lib/cli/rbs/exporter.rb
|
|
83
|
+
- lib/cli/rbs/expression_mapper.rb
|
|
84
|
+
- lib/cli/rbs/method_sig.rb
|
|
85
|
+
- lib/cli/rbs/type_mapper.rb
|
|
86
|
+
- lib/cli/type_stripper.rb
|
|
52
87
|
- lib/definitions/evaluator.rb
|
|
53
88
|
- lib/definitions/redefiner.rb
|
|
54
89
|
- lib/definitions/type_accessors.rb
|