u-struct 0.11.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +5 -5
  3. data/.rubocop.yml +129 -0
  4. data/.rubocop_todo.yml +10 -0
  5. data/.tool-versions +1 -0
  6. data/CHANGELOG.md +558 -13
  7. data/Gemfile +14 -3
  8. data/README.md +682 -16
  9. data/Rakefile +5 -5
  10. data/bin/console +3 -3
  11. data/bin/prepare_coverage +7 -9
  12. data/bin/run_ci +17 -0
  13. data/bin/tapioca +28 -0
  14. data/examples/rgb/number.rb +1 -1
  15. data/examples/rgb_1.rb +7 -6
  16. data/examples/rgb_2.rb +2 -2
  17. data/examples/rgb_3.rb +1 -1
  18. data/lib/micro/struct/factory/create_struct.rb +95 -69
  19. data/lib/micro/struct/factory/members.rb +1 -0
  20. data/lib/micro/struct/factory.rb +13 -4
  21. data/lib/micro/struct/features.rb +35 -16
  22. data/lib/micro/struct/normalize_names.rb +4 -3
  23. data/lib/micro/struct/version.rb +2 -1
  24. data/lib/micro/struct.rb +37 -5
  25. data/lib/u-struct.rb +2 -0
  26. data/rbi/micro/struct/factory/create_struct.rbi +60 -0
  27. data/rbi/micro/struct/factory/members.rbi +67 -0
  28. data/rbi/micro/struct/factory.rbi +41 -0
  29. data/rbi/micro/struct/features.rbi +41 -0
  30. data/rbi/micro/struct/normalize_names.rbi +20 -0
  31. data/rbi/micro/struct/version.rbi +3 -0
  32. data/rbi/micro/struct.rbi +68 -0
  33. data/sorbet/config +8 -0
  34. data/sorbet/rbi/gems/ast@2.4.2.rbi +54 -0
  35. data/sorbet/rbi/gems/coderay@1.1.3.rbi +8 -0
  36. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +11 -0
  37. data/sorbet/rbi/gems/docile@1.4.0.rbi +54 -0
  38. data/sorbet/rbi/gems/method_source@1.0.0.rbi +8 -0
  39. data/sorbet/rbi/gems/minitest@5.15.0.rbi +345 -0
  40. data/sorbet/rbi/gems/parser@3.1.0.0.rbi +1196 -0
  41. data/sorbet/rbi/gems/pry@0.14.1.rbi +8 -0
  42. data/sorbet/rbi/gems/rake@13.0.6.rbi +806 -0
  43. data/sorbet/rbi/gems/rbi@0.0.9.rbi +1602 -0
  44. data/sorbet/rbi/gems/simplecov-html@0.12.3.rbi +89 -0
  45. data/sorbet/rbi/gems/simplecov@0.21.2.rbi +577 -0
  46. data/sorbet/rbi/gems/simplecov_json_formatter@0.1.3.rbi +8 -0
  47. data/sorbet/rbi/gems/spoom@1.1.8.rbi +1252 -0
  48. data/sorbet/rbi/gems/tapioca@0.6.2.rbi +1232 -0
  49. data/sorbet/rbi/gems/thor@1.2.1.rbi +844 -0
  50. data/sorbet/rbi/gems/unparser@0.6.3.rbi +8 -0
  51. data/sorbet/rbi/gems/webrick@1.7.0.rbi +601 -0
  52. data/sorbet/rbi/gems/yard-sorbet@0.6.1.rbi +199 -0
  53. data/sorbet/rbi/gems/yard@0.9.27.rbi +4112 -0
  54. data/sorbet/tapioca/config.yml +13 -0
  55. data/sorbet/tapioca/require.rb +4 -0
  56. data/u-struct.gemspec +3 -3
  57. metadata +38 -4
  58. data/bin/test +0 -8
data/Rakefile CHANGED
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rake/testtask"
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
5
 
6
6
  Rake::TestTask.new(:test) do |t|
7
- t.libs << "test"
8
- t.libs << "lib"
9
- t.test_files = FileList["test/**/*_test.rb"]
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
10
10
  end
11
11
 
12
12
  task default: :test
data/bin/console CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
- require "micro/struct"
4
+ require 'bundler/setup'
5
+ require 'micro/struct'
6
6
 
7
7
  # You can add fixtures and/or initialization code here to make experimenting
8
8
  # with your gem easier. You can also use a different console, if you like.
@@ -11,5 +11,5 @@ require "micro/struct"
11
11
  # require "pry"
12
12
  # Pry.start
13
13
 
14
- require "irb"
14
+ require 'irb'
15
15
  IRB.start(__FILE__)
data/bin/prepare_coverage CHANGED
@@ -1,23 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
+
3
4
  # Borrowed from https://gist.github.com/qortex/7e7c49f3731391a91ee898336183acef
4
5
 
5
6
  # Temporary hack to get CodeClimate to work with SimpleCov 0.18 JSON format until issue is fixed
6
7
  # upstream: https://github.com/codeclimate/test-reporter/issues/413
7
8
 
8
- require "json"
9
+ require 'json'
9
10
 
10
- filename = "coverage/.resultset.json"
11
+ filename = 'coverage/.resultset.json'
11
12
  contents = JSON.parse(File.read(filename))
12
13
 
13
14
  def remove_lines_key(obj)
14
- case obj
15
- when Hash
16
- obj.transform_values do |val|
17
- val.is_a?(Hash) && val.key?("lines") ? val["lines"] : remove_lines_key(val)
18
- end
19
- else
20
- obj
15
+ return obj unless obj.is_a?(Hash)
16
+
17
+ obj.transform_values do |val|
18
+ val.is_a?(Hash) && val.key?('lines') ? val['lines'] : remove_lines_key(val)
21
19
  end
22
20
  end
23
21
 
data/bin/run_ci ADDED
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ RUBY_V=$(ruby -v)
6
+ RUBY_3_1="ruby 3.1."
7
+
8
+ rm Gemfile.lock
9
+
10
+ bundle install
11
+
12
+ if [[ $RUBY_V =~ $RUBY_3_1 ]]; then
13
+ bundle exec srb tc
14
+ bundle exec rubocop
15
+ fi
16
+
17
+ bundle exec rake test
data/bin/tapioca ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'tapioca' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require 'pathname'
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
13
+
14
+ bundle_binstub = File.expand_path('bundle', __dir__)
15
+
16
+ if File.file?(bundle_binstub)
17
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
18
+ load(bundle_binstub)
19
+ else
20
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
21
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
22
+ end
23
+ end
24
+
25
+ require 'rubygems'
26
+ require 'bundler/setup'
27
+
28
+ load Gem.bin_path('tapioca', 'tapioca')
@@ -11,7 +11,7 @@ module RGB
11
11
  end
12
12
 
13
13
  def to_s
14
- @to_s ||= '%02x' % value
14
+ @to_s ||= format('%02x', value)
15
15
  end
16
16
 
17
17
  def inspect
data/examples/rgb_1.rb CHANGED
@@ -6,12 +6,13 @@ gemfile do
6
6
  source 'https://rubygems.org'
7
7
 
8
8
  gem 'u-struct', path: '..'
9
- gem 'kind'
10
9
  end
11
10
 
12
11
  RGBColor = Micro::Struct.with(:readonly, :to_ary).new(:red, :green, :blue) do
13
- Number = Kind.object(name: 'Integer(>= 0 and <= 255)') do |value|
14
- value.is_a?(::Integer) && value >= 0 && value <= 255
12
+ Number = ->(value) do
13
+ return value if value.is_a?(::Integer) && value >= 0 && value <= 255
14
+
15
+ raise TypeError.new("#{value} must be an Integer(>= 0 and <= 255)")
15
16
  end
16
17
 
17
18
  def initialize(r, g, b)
@@ -19,7 +20,7 @@ RGBColor = Micro::Struct.with(:readonly, :to_ary).new(:red, :green, :blue) do
19
20
  end
20
21
 
21
22
  def to_hex
22
- '#%02x%02x%02x' % self
23
+ format('#%<r>02x%<g>02x%<b>02x', r: red, g: green, b: blue)
23
24
  end
24
25
  end
25
26
 
@@ -48,6 +49,6 @@ puts
48
49
 
49
50
  begin
50
51
  RGBColor.new(red: 1, green: -1, blue: 255)
51
- rescue => exception
52
- puts exception # Kind::Error (-1 expected to be a kind of Integer(>= 0 and <= 255))
52
+ rescue TypeError => exception
53
+ puts exception # TypeError (-1 must be an Integer(>= 0 and <= 255))
53
54
  end
data/examples/rgb_2.rb CHANGED
@@ -19,7 +19,7 @@ RGBNumber = Micro::Struct.with(:readonly).new(:value) do
19
19
  end
20
20
 
21
21
  def to_s
22
- '%02x' % value
22
+ format('%02x', value)
23
23
  end
24
24
 
25
25
  def inspect
@@ -70,6 +70,6 @@ puts
70
70
 
71
71
  begin
72
72
  RGBColor.new(r: 1, g: -1, b: 255)
73
- rescue => exception
73
+ rescue Kind::Error => exception
74
74
  puts exception # Kind::Error (-1 expected to be a kind of Integer(>= 0 and <= 255))
75
75
  end
data/examples/rgb_3.rb CHANGED
@@ -37,6 +37,6 @@ puts
37
37
 
38
38
  begin
39
39
  RGB::Color.new(red: 1, green: -1, blue: 255)
40
- rescue => exception
40
+ rescue Kind::Error => exception
41
41
  puts exception # Kind::Error (green: -1 expected to be a kind of Integer(>= 0 and <= 255))
42
42
  end
@@ -1,88 +1,114 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
- class Micro::Struct::Factory
4
- module CreateStruct
5
- extend self
4
+ module Micro::Struct
5
+ class Factory
6
+ module CreateStruct
7
+ extend self
6
8
 
7
- def with(members, block, features)
8
- struct = ::Struct.new(*members.required_and_optional)
9
+ def with(members, features, struct_block)
10
+ struct = create_struct(members)
9
11
 
10
- ClassScope.def_new(struct, members)
11
- ClassScope.def_to_proc(struct) if features[:to_proc]
12
- ClassScope.def_private_writers(struct) if features[:readonly]
12
+ ClassScope.def_new(struct, members)
13
13
 
14
- InstanceScope.def_with(struct) if features[:instance_copy]
15
- InstanceScope.def_to_ary(struct) if features[:to_ary]
16
- InstanceScope.def_to_hash(struct) if features[:to_hash]
14
+ ClassScope.def_features(struct, features) if features.is_a?(Features::Exposed)
15
+ ClassScope.def_to_proc(struct) if features.option?(:to_proc)
16
+ ClassScope.def_private_writers(struct) if features.option?(:readonly)
17
17
 
18
- ClassScope.evaluate(struct, block)
18
+ InstanceScope.def_with(struct) if features.option?(:instance_copy)
19
+ InstanceScope.def_to_ary(struct) if features.option?(:to_ary)
20
+ InstanceScope.def_to_hash(struct) if features.option?(:to_hash)
19
21
 
20
- struct
21
- end
22
+ ClassScope.evaluate(struct, struct_block)
22
23
 
23
- module ClassScope
24
- def self.def_new(struct, members)
25
- # The .new() method will require all required keyword arguments.
26
- # We are doing this because the Struct constructor keyword init option treats everything as optional.
27
- #
28
- struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
29
- class << self
30
- undef_method :new
31
-
32
- def new(#{members.to_eval.keyword_args}) # def new(a:, b:, c: nil) do
33
- instance = allocate # instance = allocate
34
- instance.send(:initialize, #{members.to_eval.positional_args}) # instance.send(:initialize, a, b, c)
35
- instance # instance
36
- end # end
37
-
38
- alias __new__ new
39
- end
40
- RUBY
24
+ struct
41
25
  end
42
26
 
43
- def self.def_to_proc(struct)
44
- struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
45
- def self.to_proc
46
- ->(hash) { new(**hash) }
47
- end
48
- RUBY
49
- end
27
+ private
50
28
 
51
- def self.def_private_writers(struct)
52
- struct.send(:private, *struct.members.map { |member| "#{member}=" })
29
+ def create_struct(members)
30
+ ::Struct.new(*members.required_and_optional)
53
31
  end
54
32
 
55
- def self.evaluate(struct, block)
56
- struct.class_eval(&block) if block
57
- end
58
- end
59
-
60
- module InstanceScope
61
- def self.def_to_ary(struct)
62
- struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
63
- def to_ary
64
- to_a
65
- end
66
- RUBY
33
+ module ClassScope
34
+ def self.def_new(struct, members)
35
+ # The .new() method will require all required keyword arguments.
36
+ # We are doing this because the Struct constructor keyword init option treats everything as optional.
37
+ #
38
+ struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
39
+ class << self
40
+ undef_method :new
41
+
42
+ def new(#{members.to_eval.keyword_args}) # def new(a:, b:, c: nil) do
43
+ instance = allocate # instance = allocate
44
+ instance.send(:initialize, #{members.to_eval.positional_args}) # instance.send(:initialize, a, b, c)
45
+ instance # instance
46
+ end # end
47
+
48
+ alias __new__ new
49
+ end
50
+ RUBY
51
+ end
52
+
53
+ def self.def_features(struct, features)
54
+ struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
55
+ class << self
56
+ attr_accessor :__features__
57
+
58
+ alias features __features__
59
+ end
60
+ RUBY
61
+
62
+ struct.__features__ = features
63
+
64
+ struct.send(:private_class_method, :__features__=)
65
+ end
66
+
67
+ def self.def_to_proc(struct)
68
+ struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
69
+ def self.to_proc
70
+ ->(hash) { new(**hash) }
71
+ end
72
+ RUBY
73
+ end
74
+
75
+ def self.def_private_writers(struct)
76
+ struct.send(:private, :[]=)
77
+ struct.members.each { |member| struct.send(:private, "#{member}=") }
78
+ end
79
+
80
+ def self.evaluate(struct, block)
81
+ struct.class_eval(&block) if block
82
+ end
67
83
  end
68
84
 
69
- def self.def_to_hash(struct)
70
- struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
71
- def to_hash
72
- to_h
73
- end
74
- RUBY
75
- end
76
-
77
- def self.def_with(struct)
78
- struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
79
- def with(**members)
80
- self.class.new(**to_h.merge(members))
81
- end
82
- RUBY
85
+ module InstanceScope
86
+ def self.def_to_ary(struct)
87
+ struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
88
+ def to_ary
89
+ to_a
90
+ end
91
+ RUBY
92
+ end
93
+
94
+ def self.def_to_hash(struct)
95
+ struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
96
+ def to_hash
97
+ to_h
98
+ end
99
+ RUBY
100
+ end
101
+
102
+ def self.def_with(struct)
103
+ struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
104
+ def with(**members)
105
+ self.class.new(**to_h.merge(members))
106
+ end
107
+ RUBY
108
+ end
83
109
  end
84
110
  end
85
- end
86
111
 
87
- private_constant :CreateStruct
112
+ private_constant :CreateStruct
113
+ end
88
114
  end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Micro::Struct
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Micro::Struct
@@ -5,14 +6,22 @@ module Micro::Struct
5
6
  require_relative 'factory/members'
6
7
  require_relative 'factory/create_struct'
7
8
 
8
- def initialize(features)
9
- @features = Features.require(features)
9
+ def initialize(feature_names)
10
+ @features = Features.config(feature_names)
10
11
  end
11
12
 
12
- def new(*required_members, required: nil, optional: nil, &struct_block)
13
+ def __create__(required_members, required, optional, struct_block) # :nodoc:
13
14
  members = Members.new(required_members, required, optional)
14
15
 
15
- CreateStruct.with(members, struct_block, @features)
16
+ CreateStruct.with(members, @features, struct_block)
17
+ end
18
+
19
+ def new(*required_members, required: nil, optional: nil, &struct_block)
20
+ __create__(required_members, required, optional, struct_block)
21
+ end
22
+
23
+ def instance(**members, &block)
24
+ __create__(members.keys, nil, nil, block).new(**members)
16
25
  end
17
26
  end
18
27
 
@@ -1,30 +1,49 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Micro::Struct
4
5
  module Features
5
- DISABLED =
6
- { to_ary: false,
7
- to_hash: false,
8
- to_proc: false,
9
- readonly: false,
10
- instance_copy: false }.freeze
11
-
12
- Check = ->(to_ary:, to_hash:, to_proc:, readonly:, instance_copy:) do
13
- { to_ary: to_ary,
14
- to_hash: to_hash,
15
- to_proc: to_proc,
16
- readonly: readonly,
17
- instance_copy: instance_copy }
6
+ module Options
7
+ def self.from(names:)
8
+ options = names.each_with_object({}) { |name, memo| memo[name] = true }
9
+
10
+ {
11
+ to_ary: options.fetch(:to_ary, false),
12
+ to_hash: options.fetch(:to_hash, false),
13
+ to_proc: options.fetch(:to_proc, false),
14
+ readonly: options.fetch(:readonly, false),
15
+ instance_copy: options.fetch(:instance_copy, false),
16
+ exposed_features: options.fetch(:exposed_features, false)
17
+ }
18
+ end
19
+ end
20
+
21
+ Config = ::Struct.new(:names, :options) do
22
+ def option?(name)
23
+ options.fetch(name)
24
+ end
25
+
26
+ def options?(*names)
27
+ names.all? { |name| option?(name) }
28
+ end
18
29
  end
19
30
 
31
+ Exposed = Class.new(Config)
32
+
20
33
  Names = ->(values) do
21
34
  NormalizeNames::AsSymbols.(values, context: 'feature')
22
35
  end
23
36
 
24
- def self.require(values)
25
- to_enable = Names[values].each_with_object({}) { |name, memo| memo[name] = true }
37
+ def self.config(values)
38
+ names = Names[values]
39
+ options = Options.from(names: names)
40
+
41
+ return Config.new(names, options) unless options[:exposed_features]
42
+
43
+ names.delete(:exposed_features)
44
+ options.delete(:exposed_features)
26
45
 
27
- Check.(**DISABLED.merge(to_enable))
46
+ Exposed.new(names.freeze, options.freeze).freeze
28
47
  end
29
48
  end
30
49
 
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Micro::Struct
@@ -5,10 +6,10 @@ module Micro::Struct
5
6
  module AsSymbols
6
7
  REGEXP = /\A[_A-Za-z]\w*\z/.freeze
7
8
  Invalid = ->(context, val) { raise NameError.new("invalid #{context} name: #{val}") }
8
- AsSymbol = ->(context, val) { REGEXP =~ val ? val.to_sym : Invalid[context, val] }.curry
9
+ AsSymbol = ->(context, val) { REGEXP =~ val ? val.to_sym : Invalid[context, val] }
9
10
 
10
- def self.call(values, context:)
11
- Array(values).map(&AsSymbol[context])
11
+ def self.call(arg, context:)
12
+ Array(arg).map { |values| AsSymbol[context, values] }
12
13
  end
13
14
  end
14
15
  end
@@ -1,7 +1,8 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Micro
4
5
  module Struct
5
- VERSION = '0.11.0'
6
+ VERSION = '1.1.0'
6
7
  end
7
8
  end
data/lib/micro/struct.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative 'struct/version'
@@ -31,13 +32,14 @@ module Micro
31
32
  # Micro::Struct.new(:name) {}
32
33
  #
33
34
  # Available features (use one, many, or all) to create Structs with a special behavior:
34
- # .with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy)
35
+ # .with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy, :exposed_features)
35
36
  #
36
37
  # Micro::Struct.with(:to_ary).new(:name)
37
38
  # Micro::Struct.with(:to_ary, :to_hash).new(:name)
38
39
  # Micro::Struct.with(:to_ary, :to_hash, :to_proc).new(:name)
39
40
  # Micro::Struct.with(:to_ary, :to_hash, :to_proc, :readonly).new(:name)
40
41
  # Micro::Struct.with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy).new(:name)
42
+ # Micro::Struct.with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy, :exposed_features).new(:name)
41
43
  #
42
44
  # All of the possible combinations to create a Ruby Struct. ;)
43
45
  #
@@ -57,12 +59,42 @@ module Micro
57
59
  #
58
60
  # Micro::Struct.with(*features).new(...) {}
59
61
  module Struct
60
- def self.new(*members, required: nil, optional: nil, &block)
61
- with.new(*members, required: required, optional: optional, &block)
62
+ extend self
63
+
64
+ def with(*feature_names)
65
+ factory(feature_names)
66
+ end
67
+
68
+ alias_method :[], :with
69
+
70
+ def new(*members, required: nil, optional: nil, &block)
71
+ with.__create__(members, required, optional, block)
72
+ end
73
+
74
+ def instance(**members, &block)
75
+ with.instance(**members, &block)
76
+ end
77
+
78
+ READONLY = [:readonly].freeze
79
+ IMMUTABLE = [:readonly, :instance_copy].freeze
80
+ EMPTY_ARRAY = [].freeze
81
+
82
+ def readonly(with: EMPTY_ARRAY)
83
+ factory(with, READONLY)
62
84
  end
63
85
 
64
- def self.with(*features)
65
- Factory.new(features)
86
+ def immutable(with: EMPTY_ARRAY)
87
+ factory(with, IMMUTABLE)
66
88
  end
89
+
90
+ private
91
+
92
+ def factory(names, defaults = EMPTY_ARRAY)
93
+ features = ::Kernel.Array(names)
94
+
95
+ Factory.new(defaults.empty? ? features : defaults + features)
96
+ end
97
+
98
+ private_constant :READONLY, :IMMUTABLE, :EMPTY_ARRAY
67
99
  end
68
100
  end
data/lib/u-struct.rb CHANGED
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'micro/struct'
@@ -0,0 +1,60 @@
1
+ # typed: true
2
+
3
+ module Micro::Struct::Factory::CreateStruct
4
+ extend self
5
+
6
+ STRUCT_BLOCK = T.type_alias { T.nilable(T.proc.params(arg0: T.untyped).returns(T.untyped)) }
7
+ STRUCT_MEMBERS = T.type_alias { Micro::Struct::Factory::Members }
8
+ FEATURES_EXPOSED = T.type_alias { Micro::Struct::Features::Exposed }
9
+ FEATURES_CONFIG = T.type_alias { T.any(Micro::Struct::Features::Config, FEATURES_EXPOSED) }
10
+
11
+ sig {
12
+ params(
13
+ members: STRUCT_MEMBERS,
14
+ features: FEATURES_CONFIG,
15
+ struct_block: STRUCT_BLOCK
16
+ ).returns(T.class_of(Struct))
17
+ }
18
+ def with(members, features, struct_block)
19
+ end
20
+
21
+ private
22
+
23
+ def create_struct(members); end
24
+
25
+ module ClassScope
26
+ sig { params(struct: T.class_of(Struct), members: STRUCT_MEMBERS).void }
27
+ def self.def_new(struct, members)
28
+ end
29
+
30
+ sig { params(struct: T.untyped, features: FEATURES_EXPOSED).void }
31
+ def self.def_features(struct, features)
32
+ end
33
+
34
+ sig { params(struct: T.class_of(Struct)).void }
35
+ def self.def_to_proc(struct)
36
+ end
37
+
38
+ sig { params(struct: T.class_of(Struct)).void }
39
+ def self.def_private_writers(struct)
40
+ end
41
+
42
+ sig { params(struct: T.class_of(Struct), block: STRUCT_BLOCK).void }
43
+ def self.evaluate(struct, block)
44
+ end
45
+ end
46
+
47
+ module InstanceScope
48
+ sig { params(struct: T.class_of(Struct)).void }
49
+ def self.def_to_ary(struct)
50
+ end
51
+
52
+ sig { params(struct: T.class_of(Struct)).void }
53
+ def self.def_to_hash(struct)
54
+ end
55
+
56
+ sig { params(struct: T.class_of(Struct)).void }
57
+ def self.def_with(struct)
58
+ end
59
+ end
60
+ end