Skip to content

Commit

Permalink
Resolve an old TODO in ExposedKeyFactory by supplying a source about …
Browse files Browse the repository at this point in the history
…the exposed binding to thrown exceptions

PiperOrigin-RevId: 716798470
  • Loading branch information
lukesandberg authored and Guice Team committed Jan 17, 2025
1 parent 325ac9c commit b673643
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 12 deletions.
10 changes: 3 additions & 7 deletions core/src/com/google/inject/internal/BindingProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,10 @@ public Boolean visit(PrivateElements privateElements) {
}

private <T> void bindExposed(PrivateElements privateElements, Key<T> key) {
ExposedKeyFactory<T> exposedKeyFactory = new ExposedKeyFactory<>(key, privateElements);
Object source = privateElements.getExposedSource(key);
ExposedKeyFactory<T> exposedKeyFactory = new ExposedKeyFactory<>(key, source, privateElements);
processedBindingData.addCreationListener(exposedKeyFactory);
putBinding(
new ExposedBindingImpl<T>(
injector,
privateElements.getExposedSource(key),
key,
exposedKeyFactory,
privateElements));
new ExposedBindingImpl<T>(injector, source, key, exposedKeyFactory, privateElements));
}
}
17 changes: 12 additions & 5 deletions core/src/com/google/inject/internal/ExposedKeyFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@
*/
final class ExposedKeyFactory<T> implements InternalFactory<T>, CreationListener {
private final Key<T> key;
private final Object source;
private final PrivateElements privateElements;
private BindingImpl<T> delegate;
private InternalFactory<T> delegate;

ExposedKeyFactory(Key<T> key, PrivateElements privateElements) {
ExposedKeyFactory(Key<T> key, Object source, PrivateElements privateElements) {
this.key = key;
this.source = source;
this.privateElements = privateElements;
}

Expand All @@ -47,13 +49,18 @@ public void notify(Errors errors) {
return;
}

this.delegate = explicitBinding;
@SuppressWarnings("unchecked") // safe because InternalFactory<T> is covariant
InternalFactory<T> delegate = (InternalFactory<T>) explicitBinding.getInternalFactory();
this.delegate = delegate;
}

@Override
public T get(InternalContext context, Dependency<?> dependency, boolean linked)
throws InternalProvisionException {
// TODO(lukes): add a source to the thrown exception?
return delegate.getInternalFactory().get(context, dependency, linked);
try {
return delegate.get(context, dependency, linked);
} catch (InternalProvisionException ipe) {
throw ipe.addSource(source);
}
}
}
34 changes: 34 additions & 0 deletions core/test/com/google/inject/PrivateModuleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static com.google.inject.Asserts.assertContains;
import static com.google.inject.Asserts.getDeclaringSourcePart;
import static com.google.inject.name.Names.named;
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableSet;
import com.google.inject.internal.Annotations;
Expand Down Expand Up @@ -634,6 +635,39 @@ public void testParentBindingToPrivateJitBinding() {
}
}

public void testExposedBindingAdvertisesExposeSource() {
Injector injector =
Guice.createInjector(
new PrivateModule() {
@Override
protected void configure() {
binder().withSource("configure").expose(String.class);
}

@Provides
String provideIndirectlyExposed() {
throw new Error();
}

@Provides
@Exposed
Integer provideDirectlyExposed() {
throw new Error();
}
});
ProvisionException expected =
assertThrows(ProvisionException.class, () -> injector.getInstance(String.class));
assertContains(
expected.toString(), "provideIndirectlyExposed", "configure", "while locating String");
expected = assertThrows(ProvisionException.class, () -> injector.getInstance(Integer.class));
assertContains(
expected.toString(),
// We see the source of the exposed binding, and the provider as identical.
"provideDirectlyExposed",
"provideDirectlyExposed",
"while locating Integer");
}

private static class FailingModule extends AbstractModule {
@Override
protected void configure() {
Expand Down

0 comments on commit b673643

Please sign in to comment.