org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Stephan Herrmann - Contribution for
 *                        bug 392384 - [1.8][compiler][null] Restore nullness info from type annotations in class files
 *                        Bug 416174 - [1.8][compiler][null] Bogus name clash error with null annotations
 *                        Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables
 *                        Bug 423504 - [1.8] Implement "18.5.3 Functional Interface Parameterization Inference"
 *                        Bug 425783 - An internal error occurred during: "Requesting Java AST from selection". java.lang.StackOverflowError
 *                        Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
 *                        Bug 441693 - [1.8][null] Bogus warning for type argument annotated with @NonNull
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;

import java.util.Set;

import org.eclipse.jdt.core.compiler.CharOperation;

/**
 * Denote a raw type, i.e. a generic type referenced without any type arguments.
 * e.g. X<T extends Exception> can be used a raw type 'X', in which case it
 *    will behave as X<Exception>
 */
public class RawTypeBinding extends ParameterizedTypeBinding {

    /**
     * Raw type arguments are erasure of respective parameter bounds. But we may not have resolved
     * these bounds yet if creating raw types while supertype hierarchies are being connected.
     * Therefore, use 'null' instead, and access these in a lazy way later on (when substituting).
     */
    public RawTypeBinding(ReferenceBinding type, ReferenceBinding enclosingType, LookupEnvironment environment) {
        super(type, null, enclosingType, environment);
        this.tagBits &= ~TagBits.HasMissingType;
        if ((type.tagBits & TagBits.HasMissingType) != 0) {
            if (type instanceof MissingTypeBinding) {
                this.tagBits |= TagBits.HasMissingType;
            } else if (type instanceof ParameterizedTypeBinding) {
                ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) type;
                if (parameterizedTypeBinding.genericType() instanceof MissingTypeBinding) {
                    this.tagBits |= TagBits.HasMissingType;
                }
            }
        }
        if (enclosingType != null && (enclosingType.tagBits & TagBits.HasMissingType) != 0) {
            if (enclosingType instanceof MissingTypeBinding) {
                this.tagBits |= TagBits.HasMissingType;
            } else if (enclosingType instanceof ParameterizedTypeBinding) {
                ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) enclosingType;
                if (parameterizedTypeBinding.genericType() instanceof MissingTypeBinding) {
                    this.tagBits |= TagBits.HasMissingType;
                }
            }
        }
        if (enclosingType == null || !this.hasEnclosingInstanceContext()
                || (enclosingType.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0) {
            this.modifiers &= ~ExtraCompilerModifiers.AccGenericSignature; // only need signature if enclosing needs one
        }
    }

    @Override
    public char[] computeUniqueKey(boolean isLeaf) {
        StringBuffer sig = new StringBuffer(10);
        if (isMemberType() && (enclosingType().isParameterizedType() || enclosingType().isRawType())) {
            if (!hasEnclosingInstanceContext()) {
                char[] typeSig = enclosingType().signature(); // don't consider generics from enclosing of static member
                sig.append(typeSig, 0, typeSig.length - 1); // copy all but trailing semicolon
                sig.append('$'); // for consistency with keys prior to https://bugs.eclipse.org/460491
            } else {
                char[] typeSig = enclosingType().computeUniqueKey(false/*not a leaf*/);
                sig.append(typeSig, 0, typeSig.length - 1); // copy all but trailing semicolon
                sig.append('.');
            }
            sig.append(sourceName());
            if (genericType().typeVariables() != Binding.NO_TYPE_VARIABLES) // don't show <> if raw only due to a generic enclosing
                sig.append('<').append('>');
            sig.append(';');
        } else {
            sig.append(genericType().computeUniqueKey(false/*not a leaf*/));
            sig.insert(sig.length() - 1, "<>"); //$NON-NLS-1$
        }

        int sigLength = sig.length();
        char[] uniqueKey = new char[sigLength];
        sig.getChars(0, sigLength, uniqueKey, 0);
        return uniqueKey;
    }

    @Override
    public TypeBinding clone(TypeBinding outerType) {
        return new RawTypeBinding(this.actualType(), (ReferenceBinding) outerType, this.environment);
    }

    @Override
    public TypeBinding withoutToplevelNullAnnotation() {
        if (!hasNullTypeAnnotations())
            return this;
        ReferenceBinding unannotatedGenericType = (ReferenceBinding) this.environment
                .getUnannotatedType(this.genericType());
        AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations);
        return this.environment.createRawType(unannotatedGenericType, this.enclosingType(), newAnnotations);
    }

    /**
     * @see org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding#createParameterizedMethod(org.eclipse.jdt.internal.compiler.lookup.MethodBinding)
     */
    @Override
    public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
        if (originalMethod.typeVariables == Binding.NO_TYPE_VARIABLES || originalMethod.isStatic()) {
            return super.createParameterizedMethod(originalMethod);
        }
        return this.environment.createParameterizedGenericMethod(originalMethod, this);
    }

    @Override
    public boolean isParameterizedType() {
        return false;
    }

    @Override
    public int kind() {
        return RAW_TYPE;
    }

    /**
     * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
     */
    @Override
    public String debugName() {
        if (this.hasTypeAnnotations())
            return annotatedDebugName();
        StringBuffer nameBuffer = new StringBuffer(10);
        nameBuffer.append(actualType().sourceName()).append("#RAW"); //$NON-NLS-1$
        return nameBuffer.toString();
    }

    @Override
    public String annotatedDebugName() {
        StringBuffer buffer = new StringBuffer(super.annotatedDebugName());
        buffer.append("#RAW"); //$NON-NLS-1$
        return buffer.toString();
    }

    /**
     * Ltype<param1 ... paramN>;
     * LY<TT;>;
     */
    @Override
    public char[] genericTypeSignature() {
        if (this.genericTypeSignature == null) {
            if ((this.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0) {
                this.genericTypeSignature = genericType().signature();
            } else {
                StringBuffer sig = new StringBuffer(10);
                if (isMemberType() && hasEnclosingInstanceContext()) {
                    ReferenceBinding enclosing = enclosingType();
                    char[] typeSig = enclosing.genericTypeSignature();
                    sig.append(typeSig, 0, typeSig.length - 1);// copy all but trailing semicolon
                    if ((enclosing.modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) {
                        sig.append('.');
                    } else {
                        sig.append('$');
                    }
                    sig.append(sourceName());
                } else {
                    char[] typeSig = genericType().signature();
                    sig.append(typeSig, 0, typeSig.length - 1);// copy all but trailing semicolon
                }
                sig.append(';');
                int sigLength = sig.length();
                this.genericTypeSignature = new char[sigLength];
                sig.getChars(0, sigLength, this.genericTypeSignature, 0);
            }
        }
        return this.genericTypeSignature;
    }

    @Override
    public boolean isEquivalentTo(TypeBinding otherType) {
        if (equalsEquals(this, otherType) || equalsEquals(erasure(), otherType))
            return true;
        if (otherType == null)
            return false;
        switch (otherType.kind()) {

        case Binding.WILDCARD_TYPE:
        case Binding.INTERSECTION_TYPE:
            return ((WildcardBinding) otherType).boundCheck(this);

        case Binding.GENERIC_TYPE:
        case Binding.PARAMETERIZED_TYPE:
        case Binding.RAW_TYPE:
            return TypeBinding.equalsEquals(erasure(), otherType.erasure());
        }
        return false;
    }

    @Override
    public boolean isProvablyDistinct(TypeBinding otherType) {
        if (TypeBinding.equalsEquals(this, otherType) || TypeBinding.equalsEquals(erasure(), otherType)) // https://bugs.eclipse.org/bugs/show_bug.cgi?id=329588
            return false;
        if (otherType == null)
            return true;
        switch (otherType.kind()) {

        case Binding.GENERIC_TYPE:
        case Binding.PARAMETERIZED_TYPE:
        case Binding.RAW_TYPE:
            return TypeBinding.notEquals(erasure(), otherType.erasure());
        }
        return true;
    }

    @Override
    public boolean isSubtypeOf(TypeBinding right, boolean simulatingBugJDK8026527) {
        if (simulatingBugJDK8026527) {
            right = this.environment.convertToRawType(right.erasure(), false);
        }
        return super.isSubtypeOf(right, simulatingBugJDK8026527);
    }

    @Override
    public boolean isProperType(boolean admitCapture18) {
        TypeBinding actualType = actualType();
        return actualType != null && actualType.isProperType(admitCapture18);
    }

    @Override
    protected void initializeArguments() {
        TypeVariableBinding[] typeVariables = genericType().typeVariables();
        int length = typeVariables.length;
        TypeBinding[] typeArguments = new TypeBinding[length];
        for (int i = 0; i < length; i++) {
            // perform raw conversion on variable upper bound - could cause infinite regression if arguments were initialized lazily
            typeArguments[i] = this.environment.convertToRawType(typeVariables[i].erasure(),
                    false /*do not force conversion of enclosing types*/);
        }
        this.arguments = typeArguments;
    }

    @Override
    public ParameterizedTypeBinding capture(Scope scope, int start, int end) {
        return this;
    }

    @Override
    public TypeBinding uncapture(Scope scope) {
        return this;
    }

    @Override
    TypeBinding substituteInferenceVariable(InferenceVariable var, TypeBinding substituteType) {
        // NEVER substitute the type arguments of a raw type
        return this;
    }

    @Override
    public MethodBinding getSingleAbstractMethod(Scope scope, boolean replaceWildcards) {
        int index = replaceWildcards ? 0 : 1;
        if (this.singleAbstractMethod != null) {
            if (this.singleAbstractMethod[index] != null)
                return this.singleAbstractMethod[index];
        } else {
            this.singleAbstractMethod = new MethodBinding[2];
        }
        final ReferenceBinding genericType = genericType();
        MethodBinding theAbstractMethod = genericType.getSingleAbstractMethod(scope, replaceWildcards);
        if (theAbstractMethod == null || !theAbstractMethod.isValidBinding())
            return this.singleAbstractMethod[index] = theAbstractMethod;

        ReferenceBinding declaringType = (ReferenceBinding) scope.environment().convertToRawType(genericType, true);
        declaringType = (ReferenceBinding) declaringType
                .findSuperTypeOriginatingFrom(theAbstractMethod.declaringClass);
        MethodBinding[] choices = declaringType.getMethods(theAbstractMethod.selector);
        for (int i = 0, length = choices.length; i < length; i++) {
            MethodBinding method = choices[i];
            if (!method.isAbstract() || method.redeclaresPublicObjectMethod(scope))
                continue; // (re)skip statics, defaults, public object methods ...
            this.singleAbstractMethod[index] = method;
            break;
        }
        return this.singleAbstractMethod[index];
    }

    @Override
    public boolean mentionsAny(TypeBinding[] parameters, int idx) {
        return false;
    }

    /**
     * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
     */
    @Override
    public char[] readableName(boolean showGenerics) /*java.lang.Object,  p.X<T> */ {
        char[] readableName;
        if (isMemberType()) {
            readableName = CharOperation.concat(
                    enclosingType().readableName(showGenerics && hasEnclosingInstanceContext()), this.sourceName,
                    '.');
        } else {
            readableName = CharOperation.concatWith(actualType().compoundName, '.');
        }
        return readableName;
    }

    /**
     * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
     */
    @Override
    public char[] shortReadableName(boolean showGenerics) /*Object*/ {
        char[] shortReadableName;
        if (isMemberType()) {
            shortReadableName = CharOperation.concat(
                    enclosingType().shortReadableName(showGenerics && hasEnclosingInstanceContext()),
                    this.sourceName, '.');
        } else {
            shortReadableName = actualType().sourceName;
        }
        return shortReadableName;
    }

    @Override
    void collectInferenceVariables(Set<InferenceVariable> variables) {
        // nothing to collect for a raw type.
    }

    @Override
    public ReferenceBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) {
        return this;
    }

    @Override
    public ReferenceBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) {
        return this;
    }

    @Override
    public ReferenceBinding enclosingType() {
        // ParameterizedTypeBinding earlier always had a resolved enclosed type, but now it does on-demand resolving.
        // Behaviour for RawTypeBinding should be unchanged. 
        return this.enclosingType;
    }
}