/** * Returns {@code true} if injecting an instance of {@code binding} from {@code callingPackage} * requires the use of an injection method. */ static boolean requiresInjectionMethod( ProvisionBinding binding, ImmutableList<Expression> arguments, CompilerOptions compilerOptions, String callingPackage, DaggerTypes types) { ExecutableElement method = MoreElements.asExecutable(binding.bindingElement().get()); return !binding.injectionSites().isEmpty() || binding.shouldCheckForNull(compilerOptions) || !isElementAccessibleFrom(method, callingPackage) || !areParametersAssignable(method, arguments, types) // This check should be removable once we drop support for -source 7 || method.getParameters().stream() .map(VariableElement::asType) .anyMatch(type -> !isRawTypeAccessible(type, callingPackage)); }
/** * The module constructor being proxied. A proxy is generated if it is not publicly accessible and * has no arguments. If an implicit reference to the enclosing class exists, or the module is * abstract, no proxy method can be generated. */ // TODO(ronshapiro): make this an @Injectable class that injects DaggerElements static Optional<ExecutableElement> nonPublicNullaryConstructor( TypeElement moduleElement, DaggerElements elements) { ModuleKind.checkIsModule(moduleElement); if (moduleElement.getModifiers().contains(ABSTRACT) || (moduleElement.getNestingKind().isNested() && !moduleElement.getModifiers().contains(STATIC))) { return Optional.empty(); } return constructorsIn(elements.getAllMembers(moduleElement)).stream() .filter(constructor -> !Accessibility.isElementPubliclyAccessible(constructor)) .filter(constructor -> !constructor.getModifiers().contains(PRIVATE)) .filter(constructor -> constructor.getParameters().isEmpty()) .findAny(); }
/** * Returns the accessible type for {@code type}. If the raw type is not accessible, returns {@link * Object}. */ private static TypeName accessibleType(TypeMirror type) { return isRawTypePubliclyAccessible(type) ? TypeName.get(type) : TypeName.OBJECT; }
/** * Returns an accessible type in {@code requestingClass}'s package based on {@code type}: * * <ul> * <li>If {@code type} is accessible from the package, returns it. * <li>If not, but {@code type}'s raw type is accessible from the package, returns the raw type. * <li>Otherwise returns {@link Object}. * </ul> */ protected TypeMirror accessibleType(TypeMirror type, ClassName requestingClass) { return accessibleType( type, t -> Accessibility.isTypeAccessibleFrom(t, requestingClass.packageName()), t -> Accessibility.isRawTypeAccessible(t, requestingClass.packageName())); }
/** Returns {@code true} if {@code type} is accessible from the generated component. */ boolean isTypeAccessible(TypeMirror type) { return isTypeAccessibleFrom(type, name.packageName()); }
&& !isRawTypePubliclyAccessible(requestedType) && isRawTypeAccessible(requestedType, requestingClass.packageName())) { return dependencyExpression.castTo(types.erasure(requestedType)); && !isTypeAccessibleFrom(dependencyType, requestingClass.packageName()) && isRawTypeAccessible(dependencyType, requestingClass.packageName())) { return dependencyExpression.castTo(types.erasure(dependencyType));
/** Returns true if the given element can be referenced from other code in its own package. */ static boolean isElementAccessibleFromOwnPackage(Element element) { return isElementAccessibleFrom( element, MoreElements.getPackage(element).getQualifiedName().toString()); }
private void checkInjectIntoPrivateClass(Element element, Builder<TypeElement> builder) { if (!Accessibility.isElementAccessibleFromOwnPackage( DaggerElements.closestEnclosingTypeElement(element))) { builder.addItem( "Dagger does not support injection into private classes", privateMemberDiagnosticKind(), element); } }
static boolean isMapKeyAccessibleFrom(AnnotationMirror annotation, String accessingPackage) { return new MapKeyAccessibility(type -> isTypeAccessibleFrom(type, accessingPackage)) .visitAnnotation(annotation, null); }
private static CodeBlock injectionMethodArgument( DependencyRequest dependency, CodeBlock argument, ClassName generatedTypeName) { TypeMirror keyType = dependency.key().type(); CodeBlock.Builder codeBlock = CodeBlock.builder(); if (!isRawTypeAccessible(keyType, generatedTypeName.packageName()) && isTypeAccessibleFrom(keyType, generatedTypeName.packageName())) { if (!dependency.kind().equals(RequestKind.INSTANCE)) { TypeName usageTypeName = accessibleType(dependency); codeBlock.add("($T) ($T)", usageTypeName, rawTypeName(usageTypeName)); } else if (dependency.requestElement().get().asType().getKind().equals(TypeKind.TYPEVAR)) { codeBlock.add("($T)", keyType); } } return codeBlock.add(argument).build(); }
/** * Returns a code block that creates a new module instance, either by invoking the nullary * constructor if it's accessible from {@code requestingClass} or else by invoking the * constructor's generated proxy method. */ static CodeBlock newModuleInstance( TypeElement moduleElement, ClassName requestingClass, DaggerElements elements) { ModuleKind.checkIsModule(moduleElement); String packageName = requestingClass.packageName(); return nonPublicNullaryConstructor(moduleElement, elements) .filter(constructor -> !isElementAccessibleFrom(constructor, packageName)) .map( constructor -> CodeBlock.of("$T.newInstance()", constructorProxyTypeName(moduleElement))) .orElse(CodeBlock.of("new $T()", moduleElement)); } }
private TypeName constructorTypeName(ClassName requestingClass) { DeclaredType type = MoreTypes.asDeclared(provisionBinding.key().type()); TypeName typeName = TypeName.get(type); if (type.getTypeArguments() .stream() .allMatch(t -> isTypeAccessibleFrom(t, requestingClass.packageName()))) { return typeName; } return rawTypeName(typeName); }
/** * Returns the accessible type for {@code type}. If the raw type is not accessible, returns {@link * Object}. */ // TODO(ronshapiro): Can we use DaggerTypes.publiclyAccessibleType in place of this method? private static TypeMirror accessibleType(TypeMirror type, DaggerElements elements) { return isRawTypePubliclyAccessible(type) ? type : elements.getTypeElement(Object.class).asType(); }
@Override CodeBlock getExpressionFor(ClassName usingClass) { boolean accessible = true; for (TypeMirror typeParameter : typeParameters) { accessible &= isTypeAccessibleFrom(typeParameter, usingClass.packageName()); } if (accessible) { return CodeBlock.of( "$T.<$L>$L", owningClass(), typeParameters.stream().map(CodeBlocks::type).collect(toParametersCodeBlock()), methodCodeBlock); } else { return CodeBlock.of("(($T) $T.$L)", rawReturnType, owningClass(), methodCodeBlock); } } }
private static CodeBlock instanceWithPotentialCast(CodeBlock instance, TypeMirror instanceType) { return isRawTypePubliclyAccessible(instanceType) ? instance : CodeBlock.of("(($T) $L)", instanceType, instance); }
private boolean instanceRequiresCast(Expression delegateExpression, ClassName requestingClass) { // delegateExpression.type() could be Object if expression is satisfied with a raw // Provider's get() method. return !bindsTypeChecker.isAssignable( delegateExpression.type(), binding.contributedType(), binding.contributionType()) && isTypeAccessibleFrom(binding.contributedType(), requestingClass.packageName()); }
/** * Adds {@code parameter} as a parameter of this method, using a publicly accessible version of * the parameter's type. Returns a {@link CodeBlock} of the usage of this parameter within the * injection method's {@link #methodBody()}. */ CodeBlock copyParameter(VariableElement parameter) { TypeMirror elementType = parameter.asType(); boolean useObject = !isRawTypePubliclyAccessible(elementType); TypeMirror publicType = useObject ? objectType() : elementType; ParameterSpec parameterSpec = addParameter(parameter.getSimpleName().toString(), publicType); return useObject ? CodeBlock.of("($T) $N", elementType, parameterSpec) : CodeBlock.of("$N", parameterSpec); }
private CodeBlock maybeTypeParameter(ClassName requestingClass) { TypeMirror elementType = SetType.from(binding.key()).elementType(); return isTypeAccessibleFrom(elementType, requestingClass.packageName()) ? CodeBlock.of("<$T>", elementType) : CodeBlock.of(""); }
&& isTypeAccessibleFrom(injectSiteType, generatedTypeName.packageName()) ? CodeBlock.of("($T) $L", injectSiteType, instanceCodeBlock) : instanceCodeBlock;
TypeMirror keyType = binding.key().type(); TypeMirror membersInjectedType = isTypeAccessibleFrom(keyType, componentImplementation.name().packageName()) ? keyType : elements.getTypeElement(Object.class).asType();