u-struct 0.11.0 → 1.1.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.
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