From e8a1d1c8e8b87f84b8ed70f7eafe9f464ef31bfa Mon Sep 17 00:00:00 2001 From: yanis_biziuk Date: Thu, 17 Jun 2021 16:21:19 +0300 Subject: [PATCH] fixed dependency cycle checker --- .../src/main/java/toothpick/ScopeImpl.java | 4 +- .../configuration/Configuration.java | 8 ++-- .../RuntimeCheckConfiguration.java | 4 +- .../RuntimeCheckOffConfiguration.java | 4 +- .../RuntimeCheckOnConfiguration.java | 42 ++++++++++--------- 5 files changed, 32 insertions(+), 30 deletions(-) diff --git a/toothpick-runtime/src/main/java/toothpick/ScopeImpl.java b/toothpick-runtime/src/main/java/toothpick/ScopeImpl.java index 15fa20b2..b31791de 100644 --- a/toothpick-runtime/src/main/java/toothpick/ScopeImpl.java +++ b/toothpick-runtime/src/main/java/toothpick/ScopeImpl.java @@ -87,12 +87,12 @@ public T getInstance(Class clazz) { @Override public T getInstance(Class clazz, String name) { crashIfClosed(); - ConfigurationHolder.configuration.checkCyclesStart(clazz, name); + ConfigurationHolder.configuration.checkCyclesStart(this, clazz, name); T t; try { t = lookupProvider(clazz, name).get(this); } finally { - ConfigurationHolder.configuration.checkCyclesEnd(clazz, name); + ConfigurationHolder.configuration.checkCyclesEnd(this, clazz, name); } return t; } diff --git a/toothpick-runtime/src/main/java/toothpick/configuration/Configuration.java b/toothpick-runtime/src/main/java/toothpick/configuration/Configuration.java index 4fe563b6..a9203333 100644 --- a/toothpick-runtime/src/main/java/toothpick/configuration/Configuration.java +++ b/toothpick-runtime/src/main/java/toothpick/configuration/Configuration.java @@ -88,13 +88,13 @@ public void checkIllegalBinding(Binding binding, Scope scope) { } @Override - public void checkCyclesStart(Class clazz, String name) { - runtimeCheckConfiguration.checkCyclesStart(clazz, name); + public void checkCyclesStart(Scope scope, Class clazz, String name) { + runtimeCheckConfiguration.checkCyclesStart(scope, clazz, name); } @Override - public void checkCyclesEnd(Class clazz, String name) { - runtimeCheckConfiguration.checkCyclesEnd(clazz, name); + public void checkCyclesEnd(Scope scope, Class clazz, String name) { + runtimeCheckConfiguration.checkCyclesEnd(scope, clazz, name); } @Override diff --git a/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckConfiguration.java b/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckConfiguration.java index 9c95460b..f9eb6ed9 100644 --- a/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckConfiguration.java +++ b/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckConfiguration.java @@ -37,7 +37,7 @@ interface RuntimeCheckConfiguration { * @param clazz the class to be injected. * @param name the name of the required injection. */ - void checkCyclesStart(Class clazz, String name); + void checkCyclesStart(Scope scope, Class clazz, String name); /** * Called when the class {@code class} ends being injected using the qualifier {@code name}. Will @@ -47,5 +47,5 @@ interface RuntimeCheckConfiguration { * @param clazz the class to be injected. * @param name the name of the required injection. */ - void checkCyclesEnd(Class clazz, String name); + void checkCyclesEnd(Scope scope, Class clazz, String name); } diff --git a/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckOffConfiguration.java b/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckOffConfiguration.java index 97f26e4d..7c7d9601 100644 --- a/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckOffConfiguration.java +++ b/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckOffConfiguration.java @@ -24,8 +24,8 @@ class RuntimeCheckOffConfiguration implements RuntimeCheckConfiguration { public void checkIllegalBinding(Binding binding, Scope scope) {} @Override - public void checkCyclesStart(Class clazz, String name) {} + public void checkCyclesStart(Scope scope, Class clazz, String name) {} @Override - public void checkCyclesEnd(Class clazz, String name) {} + public void checkCyclesEnd(Scope scope, Class clazz, String name) {} } diff --git a/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckOnConfiguration.java b/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckOnConfiguration.java index 8e60c298..e6b5b4a5 100644 --- a/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckOnConfiguration.java +++ b/toothpick-runtime/src/main/java/toothpick/configuration/RuntimeCheckOnConfiguration.java @@ -29,10 +29,10 @@ class RuntimeCheckOnConfiguration implements RuntimeCheckConfiguration { // We need a LIFO structure here, but stack is thread safe and we use thread local, // so this property is overkill and LinkedHashSet is faster on retrieval. - private ThreadLocal> cycleDetectionStack = - new ThreadLocal>() { + private ThreadLocal> cycleDetectionStack = + new ThreadLocal>() { @Override - protected LinkedHashSet initialValue() { + protected LinkedHashSet initialValue() { return new LinkedHashSet<>(); } }; @@ -76,52 +76,54 @@ public void checkIllegalBinding(Binding binding, Scope scope) { } @Override - public void checkCyclesStart(Class clazz, String name) { - final Pair pair = new Pair(clazz, name); - final LinkedHashSet linkedHashSet = cycleDetectionStack.get(); - if (linkedHashSet.contains(pair)) { - throw new CyclicDependencyException(Pair.getClassList(linkedHashSet), clazz); + public void checkCyclesStart(Scope scope, Class clazz, String name) { + final Entry entry = new Entry(scope, clazz, name); + final LinkedHashSet linkedHashSet = cycleDetectionStack.get(); + if (linkedHashSet.contains(entry)) { + throw new CyclicDependencyException(Entry.getClassList(linkedHashSet), clazz); } - linkedHashSet.add(pair); + linkedHashSet.add(entry); } @Override - public void checkCyclesEnd(Class clazz, String name) { - cycleDetectionStack.get().remove(new Pair(clazz, name)); + public void checkCyclesEnd(Scope scope, Class clazz, String name) { + cycleDetectionStack.get().remove(new Entry(scope, clazz, name)); } - private static class Pair { + private static class Entry { + public final Scope scope; public final Class clazz; public final String name; - Pair(Class clazz, String name) { + Entry(Scope scope, Class clazz, String name) { + this.scope = scope; this.clazz = clazz; this.name = name; } @Override public boolean equals(Object o) { - if (!(o instanceof Pair)) { + if (!(o instanceof Entry)) { return false; } - Pair p = (Pair) o; - return equal(p.clazz, clazz) && equal(p.name, name); + Entry p = (Entry) o; + return equal(p.scope, scope) && equal(p.clazz, clazz) && equal(p.name, name); } @Override public int hashCode() { - return (clazz == null ? 0 : clazz.hashCode()) ^ (name == null ? 0 : name.hashCode()); + return (scope == null ? 0 : scope.hashCode()) ^ (clazz == null ? 0 : clazz.hashCode()) ^ (name == null ? 0 : name.hashCode()); } private boolean equal(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); } - private static List> getClassList(Collection pairCollection) { + private static List> getClassList(Collection entryCollection) { List> classList = new ArrayList<>(); - for (Pair pair : pairCollection) { - classList.add(pair.clazz); + for (Entry entry : entryCollection) { + classList.add(entry.clazz); } return classList; }