Skip to content

Commit 5bf2cf4

Browse files
authored
Fix type errors and warnings (#6)
* Save benchmark reports to files * Fix type errors and warnings
1 parent 09cbf39 commit 5bf2cf4

File tree

8 files changed

+53
-60
lines changed

8 files changed

+53
-60
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Next]
99

10-
**Changed**
10+
**Added**
1111
- `Forge#forge` (and all proxy methods) now accept an optional block, yielding the forged object to do user-defined post-processing.
1212

13+
**Changed**
14+
- [Breaking] `Forge#forge` no longer accepts array of traits and hash of overrides as positional arguments.
15+
1316
[Compare v0.1.0...main](https://github.com/trinistr/object_forge/compare/v0.1.0...main)
1417

1518
## [v0.1.0]

bin/benchmark

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require "bundler/setup"
66

77
# Load supporting libraries
88
require "fileutils"
9+
require "time"
910

1011
require "benchmark"
1112
require "benchmark/ips"
@@ -31,6 +32,9 @@ FORGE =
3132

3233
# Run benchmark
3334
FileUtils.mkdir_p("tmp")
35+
report_path = "tmp/benchmark #{Time.now.iso8601} " \
36+
"(#{`ruby -v`.chomp}) " \
37+
"(commit #{`git rev-parse HEAD`.chomp[0..7]}).json"
3438
StackProf.run(mode: :cpu, raw: true, out: "tmp/stackprof.dump") do
3539
Benchmark.ips do |ips|
3640
ips.report("yard.forge()") { FORGEYARD.forge(:foobar) }
@@ -44,9 +48,12 @@ StackProf.run(mode: :cpu, raw: true, out: "tmp/stackprof.dump") do
4448

4549
ips.report("yard.forge(foo: 1, bar: 2)") { FORGEYARD.forge(:foobar, foo: 1, bar: 2) }
4650
ips.report("forge.forge(foo: 1, bar: 2)") { FORGE.forge(foo: 1, bar: 2) }
51+
52+
ips.json!(report_path)
4753
end
4854
end
55+
puts "Report saved to #{report_path}"
4956

5057
# Generate flamegraph to actually understand StackProf's report
5158
`stackprof tmp/stackprof.dump --d3-flamegraph > tmp/flamegraph.html`
52-
puts "Flamegraph generated at tmp/flamegraph.html"
59+
puts "Flamegraph saved to tmp/flamegraph.html"

lib/object_forge/forge.rb

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,8 @@ def initialize(forged, parameters, name: nil)
7575
# @yieldreturn [void]
7676
# @return [Any] built instance
7777
def forge(*traits, **overrides)
78-
# @type var traits: Array[(Array[Symbol] | Hash[Symbol, untyped])]
79-
traits, overrides = check_traits_and_overrides(traits, overrides)
80-
attributes = @parameters.attributes.merge(*@parameters.traits.values_at(*traits), overrides)
81-
attributes = Crucible.new(attributes).resolve!
82-
83-
instance = forged.new(attributes)
78+
resolved_attributes = resolve_attributes(traits, overrides)
79+
instance = build_instance(resolved_attributes)
8480
yield instance if block_given?
8581
instance
8682
end
@@ -90,19 +86,13 @@ def forge(*traits, **overrides)
9086

9187
private
9288

93-
def check_traits_and_overrides(traits, overrides)
94-
unless traits.size == 2 && overrides.empty?
95-
# @type var traits: Array[Symbol]
96-
# @type var overrides: Hash[Symbol, untyped]
97-
return [traits, overrides]
98-
end
89+
def resolve_attributes(traits, overrides)
90+
attributes = @parameters.attributes.merge(*@parameters.traits.values_at(*traits), overrides)
91+
Crucible.new(attributes).resolve!
92+
end
9993

100-
case traits
101-
in [Array => real_traits, Hash => real_overrides]
102-
[real_traits, real_overrides]
103-
else
104-
[traits, overrides]
105-
end
94+
def build_instance(attributes)
95+
forged.new(attributes)
10696
end
10797
end
10898
end

lib/object_forge/forgeyard.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def register(name, forge)
5656
#
5757
# @raise [KeyError] if forge with the specified name is not registered
5858
def forge(name, *traits, **overrides, &)
59-
@forges.fetch(name)[traits, overrides, &]
59+
@forges.fetch(name)[*traits, **overrides, &]
6060
end
6161

6262
alias build forge

lib/object_forge/sequence.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def initialize(initial)
3232
end
3333

3434
@initial = initial
35-
@container = Concurrent::MVar.new(initial)
35+
@container = Concurrent::MVar.new(initial) # steep:ignore UnknownConstant
3636
end
3737

3838
# Get the next value in the sequence, starting with the initial value.

sig/object_forge.rbs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
module ObjectForge
2-
class Error < StandardError
3-
end
4-
class DSLError < Error
5-
end
2+
type sequenceable = ObjectForge::_RespondTo & ObjectForge::_Sequenceable
63

7-
interface _Sequenceable
8-
def succ: -> self
4+
interface _RespondTo
95
def respond_to?: (Symbol name, ?bool include_private) -> bool
106
def class: -> Class
117
end
8+
interface _Sequenceable
9+
def succ: -> self
10+
end
1211
interface _Forgable
1312
def new: (Hash[Symbol, untyped]) -> self
1413
end
@@ -17,11 +16,16 @@ module ObjectForge
1716
def traits: () -> Hash[Symbol, Hash[Symbol, untyped]]
1817
end
1918

19+
class Error < StandardError
20+
end
21+
class DSLError < Error
22+
end
23+
2024
VERSION: String
2125
DEFAULT_YARD: ObjectForge::Forgeyard
2226

2327
def self.sequence
24-
: (?(ObjectForge::_Sequenceable | ObjectForge::Sequence) initial) -> ObjectForge::Sequence
28+
: (?(ObjectForge::sequenceable | ObjectForge::Sequence) initial) -> ObjectForge::Sequence
2529

2630
def self.define
2731
: (Symbol name, ObjectForge::_Forgable forged) { (ObjectForge::ForgeDSL) -> void } -> ObjectForge::Forge
@@ -33,15 +37,15 @@ end
3337

3438
class ObjectForge::Sequence
3539
def self.new
36-
: (?(ObjectForge::_Sequenceable | ObjectForge::Sequence) initial) -> ObjectForge::Sequence
40+
: (?(ObjectForge::sequenceable | ObjectForge::Sequence) initial) -> ObjectForge::Sequence
3741

38-
attr_reader initial: ObjectForge::_Sequenceable
42+
attr_reader initial: ObjectForge::sequenceable
3943

40-
def initialize: (ObjectForge::_Sequenceable initial) -> void
44+
def initialize: (ObjectForge::sequenceable initial) -> void
4145

42-
def next: -> ObjectForge::_Sequenceable
46+
def next: -> ObjectForge::sequenceable
4347

44-
def reset: -> ObjectForge::_Sequenceable
48+
def reset: -> ObjectForge::sequenceable
4549
alias rewind reset
4650
end
4751

@@ -68,7 +72,7 @@ class ObjectForge::Forge
6872
class Parameters
6973
include ObjectForge::_ForgeParameters
7074

71-
def intitialize
75+
def initialize
7276
: (attributes: Hash[Symbol, untyped], traits: Hash[Symbol, Hash[Symbol, untyped]]) -> void
7377
end
7478

@@ -84,19 +88,21 @@ class ObjectForge::Forge
8488

8589
def forge
8690
: (*Symbol traits, **untyped overrides) ?{ (untyped) -> void } -> ObjectForge::_Forgable
87-
| (Array[Symbol] traits, Hash[Symbol, untyped] overrides) ?{ (untyped) -> void } -> ObjectForge::_Forgable
8891
alias build forge
8992
alias [] forge
9093

9194
private
9295

93-
def check_traits_and_overrides
94-
: (Array[Symbol] traits, Hash[Symbol, untyped] overrides) -> [Array[Symbol], Hash[Symbol, untyped]]
95-
| (Array[(Array[Symbol] | Hash[Symbol, untyped])], Hash[Symbol, untyped]) -> [Array[Symbol], Hash[Symbol, untyped]]
96+
def resolve_attributes
97+
: (Array[Symbol] traits, Hash[Symbol, untyped] overrides) -> Hash[Symbol, untyped]
98+
99+
def build_instance
100+
: (Hash[Symbol, untyped] attributes) -> ObjectForge::_Forgable
96101
end
97102

98103
class ObjectForge::ForgeDSL < ObjectForge::UnBasicObject
99104
include ObjectForge::_ForgeParameters
105+
100106
attr_reader sequences: Hash[Symbol, ObjectForge::Sequence]
101107

102108
@attributes: Hash[Symbol, Proc]
@@ -110,12 +116,11 @@ class ObjectForge::ForgeDSL < ObjectForge::UnBasicObject
110116
def freeze: -> self
111117

112118
def attribute
113-
: (Symbol name) { -> untyped } -> Symbol
114-
| (Symbol name) { (ObjectForge::_Sequenceable) -> untyped } -> Symbol
119+
: (Symbol name) { [self: ObjectForge::Crucible] -> untyped } -> Symbol
115120
alias [] attribute
116121

117122
def sequence
118-
: (Symbol name, ?(ObjectForge::_Sequenceable | ObjectForge::Sequence) initial) { (ObjectForge::_Sequenceable) -> untyped } -> Symbol
123+
: (Symbol name, ?(ObjectForge::sequenceable | ObjectForge::Sequence) initial) { (ObjectForge::sequenceable) [self: ObjectForge::Crucible] -> untyped } -> Symbol
119124

120125
def trait
121126
: (Symbol name) { (self) -> void } -> Symbol
@@ -125,7 +130,7 @@ class ObjectForge::ForgeDSL < ObjectForge::UnBasicObject
125130
private
126131

127132
def method_missing
128-
: (Symbol name) { -> untyped } -> Symbol
133+
: (Symbol name) { [self: ObjectForge::Crucible] -> untyped } -> Symbol
129134
# After freezing:
130135
| (Symbol name) { -> untyped } -> void
131136

@@ -182,5 +187,5 @@ class ObjectForge::UnBasicObject < BasicObject
182187

183188
def block_given?: -> bool
184189

185-
def raise: (_Exception exception, ?String message) -> void
190+
def raise: (_Exception exception, ?String message, ?Array[String] backtrace, ?cause: _Exception) -> void
186191
end

spec/object_forge/forge_spec.rb

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,6 @@ module ObjectForge
5050
it "builds an instance of the forged class, applying traits and overrides in order" do
5151
expect(forge.forge(:barfoo, :bazoo, foo: 3)).to eq forged_class.new(foo: 3, bar: 3)
5252
end
53-
54-
context "if traits and overrides are passed as two positional parameters" do
55-
it "works the same" do
56-
expect(forge.forge(%i[barfoo bazoo], { foo: 3 })).to eq forged_class.new(foo: 3, bar: 3)
57-
end
58-
end
59-
60-
context "if only two traits are passed" do
61-
it "does not try to parse them as traits and overrides" do
62-
expect(forge.forge(:barfoo, :bazoo)).to eq forged_class.new(foo: :baz, bar: :baz)
63-
end
64-
end
6553
end
6654

6755
context "with a block" do

spec/object_forge/forgeyard_spec.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ module ObjectForge
6969
context "with a single argument" do
7070
it "builds an instance through named forge with default parameters" do
7171
expect(forgeyard.forge(:test)).to be instance
72-
expect(forge).to have_received(:[]).with([], {})
72+
expect(forge).to have_received(:[]).with(no_args)
7373
end
7474
end
7575

7676
context "with multiple arguments" do
7777
it "builds an instance through named forge with specified parameters" do
7878
expect(forgeyard.forge(:test, :trait, attribute: 2)).to be instance
79-
expect(forge).to have_received(:[]).with([:trait], { attribute: 2 })
79+
expect(forge).to have_received(:[]).with(:trait, attribute: 2)
8080
end
8181
end
8282

@@ -88,13 +88,13 @@ module ObjectForge
8888

8989
it "allows tapping into the object" do
9090
expect(forgeyard[:test] { _1.foo = 33 }).to eq forged_class.new(foo: 33, bar: 2)
91-
expect(forge).to have_received(:[]).with([], {})
91+
expect(forge).to have_received(:[]).with(no_args)
9292
end
9393

9494
it "runs the block after forging the object with resolved attributes" do
9595
expect(forgeyard[:test, foo: :foo, bar: -> { foo }] { _1.foo = 33 })
9696
.to eq forged_class.new(foo: 33, bar: :foo)
97-
expect(forge).to have_received(:[]).with([], { foo: :foo, bar: Proc })
97+
expect(forge).to have_received(:[]).with(foo: :foo, bar: Proc)
9898
end
9999
end
100100

0 commit comments

Comments
 (0)