All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dagger.internal.codegen.langmodel.Accessibility Maven / Gradle / Ivy

There is a newer version: 2.52
Show newest version
/*
 * Copyright (C) 2015 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.langmodel;

import static androidx.room.compiler.processing.XElementKt.isField;
import static androidx.room.compiler.processing.XElementKt.isTypeElement;
import static androidx.room.compiler.processing.XTypeKt.isArray;
import static dagger.internal.codegen.xprocessing.XElements.asTypeElement;
import static dagger.internal.codegen.xprocessing.XElements.isExecutable;
import static dagger.internal.codegen.xprocessing.XElements.isPackage;
import static dagger.internal.codegen.xprocessing.XElements.isPrivate;
import static dagger.internal.codegen.xprocessing.XElements.isPublic;
import static dagger.internal.codegen.xprocessing.XTypeElements.isNested;
import static dagger.internal.codegen.xprocessing.XTypes.asArray;
import static dagger.internal.codegen.xprocessing.XTypes.getEnclosingType;
import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
import static dagger.internal.codegen.xprocessing.XTypes.isNoType;
import static dagger.internal.codegen.xprocessing.XTypes.isNullType;
import static dagger.internal.codegen.xprocessing.XTypes.isPrimitive;
import static dagger.internal.codegen.xprocessing.XTypes.isTypeVariable;
import static dagger.internal.codegen.xprocessing.XTypes.isWildcard;

import androidx.room.compiler.processing.XElement;
import androidx.room.compiler.processing.XProcessingEnv;
import androidx.room.compiler.processing.XType;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.TypeName;
import java.util.Optional;

/**
 * Utility methods for determining whether a {@link XType} or an {@link XElement} is accessible
 * given the rules outlined in section 6.6 of the
 * Java Language Specification.
 *
 * 

This class only provides an approximation for accessibility. It does not always yield the same * result as the compiler, but will always err on the side of declaring something inaccessible. This * ensures that using this class will never result in generating code that will not compile. */ public final class Accessibility { /** Returns true if the given type can be referenced from any package. */ public static boolean isTypePubliclyAccessible(XType type) { return isTypeAccessibleFrom(type, Optional.empty()); } /** Returns true if the given type can be referenced from code in the given package. */ public static boolean isTypeAccessibleFrom(XType type, String packageName) { return isTypeAccessibleFrom(type, Optional.of(packageName)); } private static boolean isTypeAccessibleFrom(XType type, Optional packageName) { if (isNoType(type) || isPrimitive(type) || isNullType(type) || isTypeVariable(type)) { return true; } else if (isArray(type)) { return isTypeAccessibleFrom(asArray(type).getComponentType(), packageName); } else if (isDeclared(type)) { XType enclosingType = getEnclosingType(type); if (enclosingType != null && !isTypeAccessibleFrom(enclosingType, packageName)) { return false; } if (!isElementAccessibleFrom(type.getTypeElement(), packageName)) { return false; } return type.getTypeArguments().stream() .allMatch(typeArgument -> isTypeAccessibleFrom(typeArgument, packageName)); } else if (isWildcard(type)) { return type.extendsBound() == null || isTypeAccessibleFrom(type.extendsBound(), packageName); } throw new AssertionError(String.format("%s should not be checked for accessibility", type)); } /** Returns true if the given element can be referenced from any package. */ public static boolean isElementPubliclyAccessible(XElement element) { return isElementAccessibleFrom(element, Optional.empty()); } /** Returns true if the given element can be referenced from other code in its own package. */ public static boolean isElementAccessibleFromOwnPackage(XElement element) { return isElementAccessibleFrom( element, Optional.of(element.getClosestMemberContainer().getClassName().packageName())); } /** Returns true if the given element can be referenced from code in the given package. */ // TODO(gak): account for protected // TODO(bcorso): account for kotlin srcs (package-private doesn't exist, internal does exist). public static boolean isElementAccessibleFrom(XElement element, String packageName) { return isElementAccessibleFrom(element, Optional.of(packageName)); } private static boolean isElementAccessibleFrom(XElement element, Optional packageName) { if (isPackage(element)) { return true; } else if (isTypeElement(element)) { return isNested(asTypeElement(element)) ? accessibleMember(element, packageName) : accessibleModifiers(element, packageName); } else if (isExecutable(element) || isField(element)) { return accessibleMember(element, packageName); } throw new AssertionError(); } private static boolean accessibleMember(XElement element, Optional packageName) { return isElementAccessibleFrom(element.getEnclosingElement(), packageName) && accessibleModifiers(element, packageName); } private static boolean accessibleModifiers(XElement element, Optional packageName) { if (isPublic(element)) { return true; } else if (isPrivate(element)) { return false; } return packageName.isPresent() && element .getClosestMemberContainer() .getClassName() .packageName() .contentEquals(packageName.get()); } /** Returns true if the raw type of {@code type} is accessible from the given package. */ public static boolean isRawTypeAccessible(XType type, String requestingPackage) { return isDeclared(type) ? isElementAccessibleFrom(type.getTypeElement(), requestingPackage) : isTypeAccessibleFrom(type, requestingPackage); } /** Returns true if the raw type of {@code type} is accessible from any package. */ public static boolean isRawTypePubliclyAccessible(XType type) { return isDeclared(type) ? isElementPubliclyAccessible(type.getTypeElement()) : isTypePubliclyAccessible(type); } /** * Returns an accessible type in {@code requestingClass}'s package based on {@code type}: * *

    *
  • If {@code type} is accessible from the package, returns it. *
  • If not, but {@code type}'s raw type is accessible from the package, returns the raw type. *
  • Otherwise returns {@link Object}. *
*/ public static TypeName accessibleTypeName( XType type, ClassName requestingClass, XProcessingEnv processingEnv) { if (isTypeAccessibleFrom(type, requestingClass.packageName())) { return type.getTypeName(); } else if (isDeclared(type) && isRawTypeAccessible(type, requestingClass.packageName())) { return type.getRawType().getTypeName(); } else { return TypeName.OBJECT; } } private Accessibility() {} }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy