Skip to content

Commit

Permalink
Revamp aliases implementation (#389)
Browse files Browse the repository at this point in the history
  • Loading branch information
Blacksmoke16 authored Apr 7, 2024
1 parent c67f573 commit 48ee843
Show file tree
Hide file tree
Showing 17 changed files with 534 additions and 356 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
require "../spec_helper"

private def assert_success(code : String, *, line : Int32 = __LINE__) : Nil
ASPEC::Methods.assert_success <<-CR, codegen: true, line: line
require "../spec_helper.cr"
#{code}
ADI::ServiceContainer.new
CR
end

private def assert_error(message : String, code : String, *, line : Int32 = __LINE__) : Nil
ASPEC::Methods.assert_error message, <<-CR, line: line
require "../spec_helper.cr"
#{code}
CR
end

private def assert_success(code : String, *, line : Int32 = __LINE__) : Nil
ASPEC::Methods.assert_success <<-CR, codegen: true, line: line
require "../spec_helper.cr"
#{code}
ADI::ServiceContainer.new
CR
end

describe ADI::ServiceContainer::DefineGetters, tags: "compiled" do
describe "compiler errors" do
describe "aliases" do
it "does not expose named getter for non-public string aliases" do
assert_error "undefined method 'bar' for Athena::DependencyInjection::ServiceContainer", <<-CR
module SomeInterface; end
@[ADI::Register]
@[ADI::AsAlias("bar")]
class Foo
include SomeInterface
end
ADI.container.bar
CR
end

it "does not expose typed getter for non-public typed aliases" do
assert_error "undefined method 'get' for Athena::DependencyInjection::ServiceContainer", <<-CR
module SomeInterface; end
@[ADI::Register]
@[ADI::AsAlias]
class Foo
include SomeInterface
end
ADI.container.get SomeInterface
CR
end
end
end

describe "aliases" do
it "exposes named getter for public string alias" do
assert_success <<-CR
module SomeInterface; end
@[ADI::Register]
@[ADI::AsAlias("bar", public: true)]
class Foo
include SomeInterface
end
ADI.container.bar.should be_a Foo
CR
end

it "exposes typed getter for public typed alias" do
assert_success <<-CR
module SomeInterface; end
@[ADI::Register]
@[ADI::AsAlias(public: true)]
class Foo
include SomeInterface
end
ADI.container.get(SomeInterface).should be_a Foo
CR
end
end
end

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
require "../spec_helper"

private def assert_success(code : String, *, line : Int32 = __LINE__) : Nil
ASPEC::Methods.assert_success <<-CR, codegen: true, line: line
require "../spec_helper.cr"
#{code}
ADI::ServiceContainer.new
CR
end

private def assert_error(message : String, code : String, *, line : Int32 = __LINE__) : Nil
ASPEC::Methods.assert_error message, <<-CR, line: line
require "../spec_helper.cr"
#{code}
ADI::ServiceContainer.new
CR
end

describe ADI::ServiceContainer::ProcessAliases, tags: "compiled" do
it "errors if unable to determine the alias name" do
assert_error "Alias cannot be automatically determined for 'foo' (Foo). If the type includes multiple interfaces, provide the interface to alias as the first positional argument to `@[ADI::AsAlias]`.", <<-CR
module SomeInterface; end
module OtherInterface; end
@[ADI::Register]
@[ADI::AsAlias]
class Foo
include SomeInterface
include OtherInterface
end
macro finished
macro finished
it { \\{{ADI::ServiceContainer::ALIASES.keys}}.should eq [SomeInterface] }
it { \\{{ADI::ServiceContainer::ALIASES[SomeInterface]["id"].stringify}}.should eq %("foo") }
it { \\{{ADI::ServiceContainer::ALIASES[SomeInterface]["public"]}}.should be_false }
end
end
CR
end

it "allows explicit string alias name" do
assert_success <<-CR
@[ADI::Register]
@[ADI::AsAlias("bar")]
class Foo; end
macro finished
macro finished
it { \\{{ADI::ServiceContainer::ALIASES.keys}}.should eq ["bar"] }
it { \\{{ADI::ServiceContainer::ALIASES["bar"]["id"].stringify}}.should eq %("foo") }
it { \\{{ADI::ServiceContainer::ALIASES["bar"]["public"]}}.should be_false }
end
end
CR
end

it "allows explicit const alias name" do
assert_success <<-CR
BAR = "bar"
@[ADI::Register]
@[ADI::AsAlias(BAR)]
class Foo; end
macro finished
macro finished
it { \\{{ADI::ServiceContainer::ALIASES.keys}}.should eq ["bar"] }
it { \\{{ADI::ServiceContainer::ALIASES["bar"]["id"].stringify}}.should eq %("foo") }
it { \\{{ADI::ServiceContainer::ALIASES["bar"]["public"]}}.should be_false }
end
end
CR
end

it "allows explicit TypeNode alias name" do
assert_success <<-CR
module SomeInterface; end
@[ADI::Register]
@[ADI::AsAlias(SomeInterface, public: true)]
class Foo
include SomeInterface
end
macro finished
macro finished
it { \\{{ADI::ServiceContainer::ALIASES.keys}}.should eq [SomeInterface] }
it { \\{{ADI::ServiceContainer::ALIASES[SomeInterface]["id"].stringify}}.should eq %("foo") }
it { \\{{ADI::ServiceContainer::ALIASES[SomeInterface]["public"]}}.should be_true }
end
end
CR
end

it "uses included interface type as alias name if there is only 1" do
assert_success <<-CR
module SomeInterface; end
@[ADI::Register]
@[ADI::AsAlias]
class Foo
include SomeInterface
end
macro finished
macro finished
it { \\{{ADI::ServiceContainer::ALIASES.keys}}.should eq [SomeInterface] }
it { \\{{ADI::ServiceContainer::ALIASES[SomeInterface]["id"].stringify}}.should eq %("foo") }
it { \\{{ADI::ServiceContainer::ALIASES[SomeInterface]["public"]}}.should be_false }
end
end
CR
end

it "allows aliasing more than one interface" do
assert_success <<-CR
module SomeInterface; end
module OtherInterface; end
@[ADI::Register]
@[ADI::AsAlias(SomeInterface)]
@[ADI::AsAlias(OtherInterface)]
class Foo
include SomeInterface
include OtherInterface
end
macro finished
macro finished
it { \\{{ADI::ServiceContainer::ALIASES.keys}}.should eq [SomeInterface, OtherInterface] }
end
end
CR
end
end
Loading

0 comments on commit 48ee843

Please sign in to comment.