From 55172af7ba1e902080dbcd0cb469ae3c58bd8f22 Mon Sep 17 00:00:00 2001 From: Galen Suen Date: Wed, 1 Nov 2023 00:49:02 +0000 Subject: [PATCH] Returns an existing Scope with the same name --- scope.go | 15 ++++++++++++++- scope_test.go | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/scope.go b/scope.go index dc0c7ac5..53c3dccb 100644 --- a/scope.go +++ b/scope.go @@ -107,12 +107,25 @@ func newScope() *Scope { return s } -// Scope creates a new Scope with the given name and options from current Scope. +// Scope creates a new Scope with the given name and options from current Scope, +// or returns an existing Scope with the same name. // Any constructors that the current Scope knows about, as well as any modifications // made to it in the future will be propagated to the child scope. // However, no modifications made to the child scope being created will be propagated // to the parent Scope. func (s *Scope) Scope(name string, opts ...ScopeOption) *Scope { + // Check if a child scope with the same name already exists. + for _, s := range s.childScopes { + if s.name == name { + // in future, we may want to allow users to override options + for _, opt := range opts { + opt.noScopeOption() + } + return s + } + } + + // otherwise, create a new child scope. child := newScope() child.name = name child.parentScope = s diff --git a/scope_test.go b/scope_test.go index ff5db69d..40a22ae1 100644 --- a/scope_test.go +++ b/scope_test.go @@ -172,6 +172,21 @@ func TestScopedOperations(t *testing.T) { child.RequireInvoke(func(T2) {}) }) + + t.Run("return existing scope if it already exists", func(t *testing.T) { + type A struct{} + type B struct{} + + c := digtest.New(t) + s := c.Scope("child") + s.RequireProvide(func() *A { return &A{} }) + s.RequireProvide(func() *B { return &B{} }) + + // Reuse the existing child scope. + s2 := c.Scope("child") + s2.RequireInvoke(func(*A) {}) + s2.RequireInvoke(func(*B) {}) + }) } func TestScopeFailures(t *testing.T) {