blob: f76c49c670b28d45d0a0620678c3c2e208f2348a [file] [log] [blame]
/*
* Copyright (C) 2018 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dagger.internal.codegen;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import dagger.internal.MissingBindingFactory;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
import dagger.producers.internal.MissingBindingProducer;
import java.util.Optional;
/**
* A {@link BindingExpression} that implements a method that encapsulates a binding that is not part
* of the binding graph when generating a final concrete implementation of a subcomponent. The
* implementation throws an exception. It is assumed that a binding may remain missing in a valid
* binding graph, because it's possible for there to be dependencies that are passively pruned when
* a non-leaf binding is re-defined (such as when {@code @Provides} bindings override
* {@code @Inject} bindings).
*
* <p>This method should never be invoked. If it is the exception indicates an issue within Dagger
* itself.
*/
final class PrunedConcreteMethodBindingExpression extends BindingExpression {
private static final CodeBlock METHOD_IMPLEMENTATION =
CodeBlock.of(
"throw new $T($S);",
UnsupportedOperationException.class,
"This binding is not part of the final binding graph. The key was requested by a binding "
+ "that was believed to possibly be part of the graph, but is no longer requested. "
+ "If this exception is thrown, it is the result of a Dagger bug.");
PrunedConcreteMethodBindingExpression() {}
@Override
CodeBlock getModifiableBindingMethodImplementation(
ModifiableBindingMethod modifiableBindingMethod,
ComponentImplementation component,
DaggerTypes types) {
Optional<FrameworkType> frameworkType = modifiableBindingMethod.request().frameworkType();
if (frameworkType.isPresent()) {
// If we make initializations replaceable, we can do away with these classes and this logic
// since the pruned framework instances will no longer be initialized
switch (frameworkType.get()) {
case PROVIDER:
return missingFrameworkInstance(MissingBindingFactory.class);
case PRODUCER_NODE:
return missingFrameworkInstance(MissingBindingProducer.class);
}
throw new AssertionError(frameworkType);
}
return METHOD_IMPLEMENTATION;
}
private static CodeBlock missingFrameworkInstance(Class<?> factoryClass) {
return CodeBlock.builder().addStatement("return $T.create()", factoryClass).build();
}
@Override
final Expression getDependencyExpression(ClassName requestingClass) {
throw new UnsupportedOperationException(
"Requesting a dependency expression for a pruned binding.");
}
}