public boolean canUseDiamond(String[] parameterTypes, char[] fullyQualifiedTypeName) {
   TypeBinding guessedType = null;
   char[][] cn = CharOperation.splitOn('.', fullyQualifiedTypeName);
   Scope scope = this.assistScope;
   if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_7) return false;
   // If no LHS or return type expected, then we can safely use diamond
   char[][] expectedTypekeys = this.completionContext.getExpectedTypesKeys();
   if (expectedTypekeys == null || expectedTypekeys.length == 0) return true;
   // Next, find out whether any of the constructor parameters are the same as one of the
   // class type variables. If yes, diamond cannot be used.
   TypeReference ref;
   if (cn.length == 1) {
     ref = new SingleTypeReference(cn[0], 0);
   } else {
     ref = new QualifiedTypeReference(cn, new long[cn.length]);
   }
   // {ObjectTeams: protect call into the compiler
   try (Config config =
       Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true)) {
     // orig:
     switch (scope.kind) {
       case Scope.METHOD_SCOPE:
       case Scope.BLOCK_SCOPE:
         guessedType = ref.resolveType((BlockScope) scope);
         break;
       case Scope.CLASS_SCOPE:
         guessedType = ref.resolveType((ClassScope) scope);
         break;
     }
     // :giro
   }
   // SH}
   if (guessedType != null && guessedType.isValidBinding()) {
     // the erasure must be used because guessedType can be a RawTypeBinding
     guessedType = guessedType.erasure();
     TypeVariableBinding[] typeVars = guessedType.typeVariables();
     for (int i = 0; i < parameterTypes.length; i++) {
       for (int j = 0; j < typeVars.length; j++) {
         if (CharOperation.equals(parameterTypes[i].toCharArray(), typeVars[j].sourceName))
           return false;
       }
     }
     return true;
   }
   return false;
 }
예제 #2
0
  /**
   * Resolve and bind arguments, return type.
   *
   * @param scope used for resolving. Newly bound arguments are entered here.
   * @param isBaseSide TODO
   */
  public void resolveTypes(CallinCalloutScope scope, boolean isBaseSide) {
    if (this.typeParameters != null) {
      for (int i = 0, length = this.typeParameters.length; i < length; i++) {
        if (isBaseSide)
          scope.problemReporter().illegalMappingRHSTypeParameter(this.typeParameters[i]);
        else this.typeParameters[i].resolve(scope);
      }
      if (!isBaseSide) scope.connectTypeVariables(this.typeParameters, true);
    }
    TypeBinding[] types = Binding.NO_PARAMETERS;
    if (this.arguments != null) {
      types = new TypeBinding[this.arguments.length];
      for (int i = 0; i < this.arguments.length; i++) {
        TypeReference type = this.arguments[i].type;
        if (isBaseSide) type.setBaseclassDecapsulation(DecapsulationState.ALLOWED);
        types[i] = type.resolveType(scope);
        if (types[i] != null) {
          type.resolvedType =
              types[i] =
                  RoleTypeCreator.maybeWrapUnqualifiedRoleType(scope, types[i], this.arguments[i]);
        } else {
          // ensure we have a type set!
          types[i] = type.resolvedType; // a ProblemBinding !?
          if (types[i] == null)
            types[i] =
                new ProblemReferenceBinding(type.getTypeName(), null, ProblemReasons.NotFound);
        }

        // record in scope, needed for role types anchored to an argument
        // (all arguments must be bound in order!)
        this.arguments[i].bind(scope, types[i], false);
      }
    }
    if (this.hasSignature) this.argNeedsTranslation = new boolean[types.length];
    if (this.returnType != null) {
      if (isBaseSide) this.returnType.setBaseclassDecapsulation(DecapsulationState.ALLOWED);
      this.returnType.resolve(scope);
      if (this.returnType.resolvedType != null)
        this.returnType.resolvedType =
            RoleTypeCreator.maybeWrapUnqualifiedRoleType(
                scope, this.returnType.resolvedType, this.returnType);
    }
    this.parameters = types;
  }
  public TypeBinding resolveType(BlockScope scope) {

    // Build an array type reference using the current dimensions
    // The parser does not check for the fact that dimension may be null
    // only at the -end- like new int [4][][]. The parser allows new int[][4][]
    // so this must be checked here......(this comes from a reduction to LL1 grammar)

    TypeBinding referenceType = type.resolveType(scope, true /* check bounds*/);

    // will check for null after dimensions are checked
    constant = Constant.NotAConstant;
    if (referenceType == VoidBinding) {
      scope.problemReporter().cannotAllocateVoidArray(this);
      referenceType = null;
    }

    // check the validity of the dimension syntax (and test for all null dimensions)
    int explicitDimIndex = -1;
    loop:
    for (int i = dimensions.length; --i >= 0; ) {
      if (dimensions[i] != null) {
        if (explicitDimIndex < 0) explicitDimIndex = i;
      } else if (explicitDimIndex > 0) {
        // should not have an empty dimension before an non-empty one
        scope.problemReporter().incorrectLocationForNonEmptyDimension(this, explicitDimIndex);
        break loop;
      }
    }

    // explicitDimIndex < 0 says if all dimensions are nulled
    // when an initializer is given, no dimension must be specified
    if (initializer == null) {
      if (explicitDimIndex < 0) {
        scope.problemReporter().mustDefineDimensionsOrInitializer(this);
      }
      // allow new List<?>[5] - only check for generic array when no initializer, since also checked
      // inside initializer resolution
      if (referenceType != null && !referenceType.isReifiable()) {
        scope.problemReporter().illegalGenericArray(referenceType, this);
      }
    } else if (explicitDimIndex >= 0) {
      scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
    }

    // dimensions resolution
    for (int i = 0; i <= explicitDimIndex; i++) {
      if (dimensions[i] != null) {
        TypeBinding dimensionType = dimensions[i].resolveTypeExpecting(scope, IntBinding);
        if (dimensionType != null) {
          dimensions[i].computeConversion(scope, IntBinding, dimensionType);
        }
      }
    }

    // building the array binding
    if (referenceType != null) {
      if (dimensions.length > 255) {
        scope.problemReporter().tooManyDimensions(this);
      }
      this.resolvedType = scope.createArrayType(referenceType, dimensions.length);

      // check the initializer
      if (initializer != null) {
        if ((initializer.resolveTypeExpecting(scope, this.resolvedType)) != null)
          initializer.binding = (ArrayBinding) this.resolvedType;
      }
    }
    return this.resolvedType;
  }
  private TypeBinding internalResolveLeafType(
      Scope scope, ReferenceBinding enclosingType, boolean checkBounds) {
    ReferenceBinding currentType;
    if (enclosingType == null) {
      this.resolvedType = scope.getType(this.token);
      if (this.resolvedType.isValidBinding()) {
        currentType = (ReferenceBinding) this.resolvedType;
      } else {
        reportInvalidType(scope);
        switch (this.resolvedType.problemId()) {
          case ProblemReasons.NotFound:
          case ProblemReasons.NotVisible:
          case ProblemReasons.InheritedNameHidesEnclosingName:
            TypeBinding type = this.resolvedType.closestMatch();
            if (type instanceof ReferenceBinding) {
              currentType = (ReferenceBinding) type;
              break;
            }
            // $FALL-THROUGH$ - unable to complete type binding, but still resolve type arguments
          default:
            boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
            int argLength = this.typeArguments.length;
            for (int i = 0; i < argLength; i++) {
              TypeReference typeArgument = this.typeArguments[i];
              if (isClassScope) {
                typeArgument.resolveType((ClassScope) scope);
              } else {
                typeArgument.resolveType((BlockScope) scope, checkBounds);
              }
            }
            return null;
        }
        // be resilient, still attempt resolving arguments
      }
      enclosingType = currentType.enclosingType(); // if member type
      if (enclosingType != null) {
        enclosingType =
            currentType.isStatic()
                ? (ReferenceBinding)
                    scope
                        .environment()
                        .convertToRawType(
                            enclosingType, false /*do not force conversion of enclosing types*/)
                : scope.environment().convertToParameterizedType(enclosingType);
        currentType =
            scope
                .environment()
                .createParameterizedType(
                    (ReferenceBinding) currentType.erasure(), null /* no arg */, enclosingType);
      }
    } else { // resolving member type (relatively to enclosingType)
      this.resolvedType = currentType = scope.getMemberType(this.token, enclosingType);
      if (!this.resolvedType.isValidBinding()) {
        scope.problemReporter().invalidEnclosingType(this, currentType, enclosingType);
        return null;
      }
      if (isTypeUseDeprecated(currentType, scope))
        scope.problemReporter().deprecatedType(currentType, this);
      ReferenceBinding currentEnclosing = currentType.enclosingType();
      if (currentEnclosing != null && currentEnclosing.erasure() != enclosingType.erasure()) {
        enclosingType =
            currentEnclosing; // inherited member type, leave it associated with its enclosing
                              // rather than subtype
      }
    }

    // check generic and arity
    boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
    TypeReference keep = null;
    if (isClassScope) {
      keep = ((ClassScope) scope).superTypeReference;
      ((ClassScope) scope).superTypeReference = null;
    }
    int argLength = this.typeArguments.length;
    TypeBinding[] argTypes = new TypeBinding[argLength];
    boolean argHasError = false;
    ReferenceBinding currentOriginal = (ReferenceBinding) currentType.original();
    for (int i = 0; i < argLength; i++) {
      TypeReference typeArgument = this.typeArguments[i];
      TypeBinding argType =
          isClassScope
              ? typeArgument.resolveTypeArgument((ClassScope) scope, currentOriginal, i)
              : typeArgument.resolveTypeArgument((BlockScope) scope, currentOriginal, i);
      this.bits |= (typeArgument.bits & ASTNode.HasTypeAnnotations);
      if (argType == null) {
        argHasError = true;
      } else {
        if (typeArgument.annotations != null)
          argTypes[i] =
              captureTypeAnnotations(scope, enclosingType, argType, typeArgument.annotations[0]);
        else argTypes[i] = argType;
      }
    }
    if (argHasError) {
      return null;
    }
    if (isClassScope) {
      ((ClassScope) scope).superTypeReference = keep;
      if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) return null;
    }

    final boolean isDiamond = (this.bits & ASTNode.IsDiamond) != 0;
    TypeVariableBinding[] typeVariables = currentOriginal.typeVariables();
    if (typeVariables == Binding.NO_TYPE_VARIABLES) { // non generic invoked with arguments
      boolean isCompliant15 =
          scope.compilerOptions().originalSourceLevel >= ClassFileConstants.JDK1_5;
      if ((currentOriginal.tagBits & TagBits.HasMissingType) == 0) {
        if (isCompliant15) { // below 1.5, already reported as syntax error
          this.resolvedType = currentType;
          scope
              .problemReporter()
              .nonGenericTypeCannotBeParameterized(0, this, currentType, argTypes);
          return null;
        }
      }
      // resilience do not rebuild a parameterized type unless compliance is allowing it
      if (!isCompliant15) {
        if (!this.resolvedType.isValidBinding()) return currentType;
        return this.resolvedType = currentType;
      }
      // if missing generic type, and compliance >= 1.5, then will rebuild a parameterized binding
    } else if (argLength != typeVariables.length) {
      if (!isDiamond) { // check arity, IsDiamond never set for 1.6-
        scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes);
        return null;
      }
    } else if (!currentType.isStatic()) {
      ReferenceBinding actualEnclosing = currentType.enclosingType();
      if (actualEnclosing != null && actualEnclosing.isRawType()) {
        scope
            .problemReporter()
            .rawMemberTypeCannotBeParameterized(
                this,
                scope.environment().createRawType(currentOriginal, actualEnclosing),
                argTypes);
        return null;
      }
    }

    ParameterizedTypeBinding parameterizedType =
        scope.environment().createParameterizedType(currentOriginal, argTypes, enclosingType);
    // check argument type compatibility for non <> cases - <> case needs no bounds check, we will
    // scream foul if needed during inference.
    if (!isDiamond) {
      if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method
                       // resolution
      parameterizedType.boundCheck(scope, this.typeArguments);
      else scope.deferBoundCheck(this);
    }
    if (isTypeUseDeprecated(parameterizedType, scope))
      reportDeprecatedType(parameterizedType, scope);

    if (!this.resolvedType.isValidBinding()) {
      return parameterizedType;
    }
    return this.resolvedType = parameterizedType;
  }
  public TypeBinding resolveType(BlockScope scope) {
    // added for code assist...cannot occur with 'normal' code
    if (this.anonymousType == null && this.enclosingInstance == null) {
      return super.resolveType(scope);
    }

    // Propagate the type checking to the arguments, and checks if the constructor is defined.
    // ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')'
    // ClassBodyopt
    // ClassInstanceCreationExpression ::= Name '.' 'new' SimpleName '(' ArgumentListopt ')'
    // ClassBodyopt

    this.constant = Constant.NotAConstant;
    TypeBinding enclosingInstanceType = null;
    ReferenceBinding enclosingInstanceReference = null;
    TypeBinding receiverType = null;
    boolean hasError = false;
    boolean enclosingInstanceContainsCast = false;
    boolean argsContainCast = false;

    if (this.enclosingInstance != null) {
      if (this.enclosingInstance instanceof CastExpression) {
        this.enclosingInstance.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
        enclosingInstanceContainsCast = true;
      }
      if ((enclosingInstanceType = this.enclosingInstance.resolveType(scope)) == null) {
        hasError = true;
      } else if (enclosingInstanceType.isBaseType() || enclosingInstanceType.isArrayType()) {
        scope
            .problemReporter()
            .illegalPrimitiveOrArrayTypeForEnclosingInstance(
                enclosingInstanceType, this.enclosingInstance);
        hasError = true;
      } else if (this.type instanceof QualifiedTypeReference) {
        scope
            .problemReporter()
            .illegalUsageOfQualifiedTypeReference((QualifiedTypeReference) this.type);
        hasError = true;
      } else if (!(enclosingInstanceReference = (ReferenceBinding) enclosingInstanceType)
          .canBeSeenBy(scope)) {
        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=317212
        enclosingInstanceType =
            new ProblemReferenceBinding(
                enclosingInstanceReference.compoundName,
                enclosingInstanceReference,
                ProblemReasons.NotVisible);
        scope.problemReporter().invalidType(this.enclosingInstance, enclosingInstanceType);
        hasError = true;
      } else {
        receiverType =
            ((SingleTypeReference) this.type)
                .resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstanceType);
        if (receiverType != null && enclosingInstanceContainsCast) {
          CastExpression.checkNeedForEnclosingInstanceCast(
              scope, this.enclosingInstance, enclosingInstanceType, receiverType);
        }
      }
    } else {
      if (this.type == null) {
        // initialization of an enum constant
        receiverType = scope.enclosingSourceType();
      } else {
        receiverType = this.type.resolveType(scope, true /* check bounds*/);
        checkParameterizedAllocation:
        {
          if (receiverType == null || !receiverType.isValidBinding())
            break checkParameterizedAllocation;
          if (this.type
              instanceof
              ParameterizedQualifiedTypeReference) { // disallow new X<String>.Y<Integer>()
            ReferenceBinding currentType = (ReferenceBinding) receiverType;
            do {
              // isStatic() is answering true for toplevel types
              if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0)
                break checkParameterizedAllocation;
              if (currentType.isRawType()) break checkParameterizedAllocation;
            } while ((currentType = currentType.enclosingType()) != null);
            ParameterizedQualifiedTypeReference qRef =
                (ParameterizedQualifiedTypeReference) this.type;
            for (int i = qRef.typeArguments.length - 2; i >= 0; i--) {
              if (qRef.typeArguments[i] != null) {
                scope
                    .problemReporter()
                    .illegalQualifiedParameterizedTypeAllocation(this.type, receiverType);
                break;
              }
            }
          }
        }
      }
    }
    if (receiverType == null || !receiverType.isValidBinding()) {
      hasError = true;
    }

    // resolve type arguments (for generic constructor call)
    final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0;
    if (this.typeArguments != null) {
      int length = this.typeArguments.length;
      boolean argHasError = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5;
      this.genericTypeArguments = new TypeBinding[length];
      for (int i = 0; i < length; i++) {
        TypeReference typeReference = this.typeArguments[i];
        if ((this.genericTypeArguments[i] =
                typeReference.resolveType(scope, true /* check bounds*/))
            == null) {
          argHasError = true;
        }
        if (argHasError && typeReference instanceof Wildcard) {
          scope.problemReporter().illegalUsageOfWildcard(typeReference);
        }
      }
      if (isDiamond) {
        scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments);
        return null;
      }
      if (argHasError) {
        if (this.arguments != null) { // still attempt to resolve arguments
          for (int i = 0, max = this.arguments.length; i < max; i++) {
            this.arguments[i].resolveType(scope);
          }
        }
        return null;
      }
    }

    // will check for null after args are resolved
    TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
    if (this.arguments != null) {
      int length = this.arguments.length;
      argumentTypes = new TypeBinding[length];
      for (int i = 0; i < length; i++) {
        Expression argument = this.arguments[i];
        if (argument instanceof CastExpression) {
          argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
          argsContainCast = true;
        }
        if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
          hasError = true;
        }
      }
    }

    // limit of fault-tolerance
    if (hasError) {
      /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359, if arguments have errors, completely bail out in the <> case.
        No meaningful type resolution is possible since inference of the elided types is fully tied to argument types. Do
        not return the partially resolved type.
      */
      if (isDiamond) {
        return null; // not the partially cooked this.resolvedType
      }
      if (receiverType instanceof ReferenceBinding) {
        ReferenceBinding referenceReceiver = (ReferenceBinding) receiverType;
        if (receiverType.isValidBinding()) {
          // record a best guess, for clients who need hint about possible contructor match
          int length = this.arguments == null ? 0 : this.arguments.length;
          TypeBinding[] pseudoArgs = new TypeBinding[length];
          for (int i = length; --i >= 0; ) {
            pseudoArgs[i] =
                argumentTypes[i] == null
                    ? TypeBinding.NULL
                    : argumentTypes[i]; // replace args with errors with null type
          }
          this.binding = scope.findMethod(referenceReceiver, TypeConstants.INIT, pseudoArgs, this);
          if (this.binding != null && !this.binding.isValidBinding()) {
            MethodBinding closestMatch = ((ProblemMethodBinding) this.binding).closestMatch;
            // record the closest match, for clients who may still need hint about possible method
            // match
            if (closestMatch != null) {
              if (closestMatch.original().typeVariables
                  != Binding.NO_TYPE_VARIABLES) { // generic method
                // shouldn't return generic method outside its context, rather convert it to raw
                // method (175409)
                closestMatch =
                    scope
                        .environment()
                        .createParameterizedGenericMethod(
                            closestMatch.original(), (RawTypeBinding) null);
              }
              this.binding = closestMatch;
              MethodBinding closestMatchOriginal = closestMatch.original();
              if (closestMatchOriginal.isOrEnclosedByPrivateType()
                  && !scope.isDefinedInMethod(closestMatchOriginal)) {
                // ignore cases where method is used from within inside itself (e.g. direct
                // recursions)
                closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
              }
            }
          }
        }
        if (this.anonymousType != null) {
          // insert anonymous type in scope (see
          // https://bugs.eclipse.org/bugs/show_bug.cgi?id=210070)
          scope.addAnonymousType(this.anonymousType, referenceReceiver);
          this.anonymousType.resolve(scope);
          return this.resolvedType = this.anonymousType.binding;
        }
      }
      return this.resolvedType = receiverType;
    }
    if (this.anonymousType == null) {
      // qualified allocation with no anonymous type
      if (!receiverType.canBeInstantiated()) {
        scope.problemReporter().cannotInstantiate(this.type, receiverType);
        return this.resolvedType = receiverType;
      }
      if (isDiamond) {
        TypeBinding[] inferredTypes =
            inferElidedTypes(
                ((ParameterizedTypeBinding) receiverType).genericType(),
                receiverType.enclosingType(),
                argumentTypes,
                scope);
        if (inferredTypes == null) {
          scope.problemReporter().cannotInferElidedTypes(this);
          return this.resolvedType = null;
        }
        receiverType =
            this.type.resolvedType =
                scope
                    .environment()
                    .createParameterizedType(
                        ((ParameterizedTypeBinding) receiverType).genericType(),
                        inferredTypes,
                        ((ParameterizedTypeBinding) receiverType).enclosingType());
      }
      ReferenceBinding allocationType = (ReferenceBinding) receiverType;
      if ((this.binding = scope.getConstructor(allocationType, argumentTypes, this))
          .isValidBinding()) {
        if (isMethodUseDeprecated(this.binding, scope, true)) {
          scope.problemReporter().deprecatedMethod(this.binding, this);
        }
        if (checkInvocationArguments(
            scope,
            null,
            allocationType,
            this.binding,
            this.arguments,
            argumentTypes,
            argsContainCast,
            this)) {
          this.bits |= ASTNode.Unchecked;
        }
        if (this.typeArguments != null
            && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
          scope
              .problemReporter()
              .unnecessaryTypeArgumentsForMethodInvocation(
                  this.binding, this.genericTypeArguments, this.typeArguments);
        }
      } else {
        if (this.binding.declaringClass == null) {
          this.binding.declaringClass = allocationType;
        }
        if (this.type != null && !this.type.resolvedType.isValidBinding()) {
          // problem already got signaled on type reference, do not report secondary problem
          return null;
        }
        scope.problemReporter().invalidConstructor(this, this.binding);
        return this.resolvedType = receiverType;
      }
      if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
        scope.problemReporter().missingTypeInConstructor(this, this.binding);
      }
      if (!isDiamond && receiverType.isParameterizedTypeWithActualArguments()) {
        checkTypeArgumentRedundancy(
            (ParameterizedTypeBinding) receiverType,
            receiverType.enclosingType(),
            argumentTypes,
            scope);
      }
      // The enclosing instance must be compatible with the innermost enclosing type
      ReferenceBinding expectedType = this.binding.declaringClass.enclosingType();
      if (expectedType
          != enclosingInstanceType) // must call before computeConversion() and typeMismatchError()
      scope.compilationUnitScope().recordTypeConversion(expectedType, enclosingInstanceType);
      if (enclosingInstanceType.isCompatibleWith(expectedType)
          || scope.isBoxingCompatibleWith(enclosingInstanceType, expectedType)) {
        this.enclosingInstance.computeConversion(scope, expectedType, enclosingInstanceType);
        return this.resolvedType = receiverType;
      }
      scope
          .problemReporter()
          .typeMismatchError(enclosingInstanceType, expectedType, this.enclosingInstance, null);
      return this.resolvedType = receiverType;
    } else {
      if (isDiamond) {
        scope.problemReporter().diamondNotWithAnoymousClasses(this.type);
        return null;
      }
    }
    ReferenceBinding superType = (ReferenceBinding) receiverType;
    if (superType.isTypeVariable()) {
      superType =
          new ProblemReferenceBinding(
              new char[][] {superType.sourceName()},
              superType,
              ProblemReasons.IllegalSuperTypeVariable);
      scope.problemReporter().invalidType(this, superType);
      return null;
    } else if (this.type != null && superType.isEnum()) { // tolerate enum constant body
      scope.problemReporter().cannotInstantiate(this.type, superType);
      return this.resolvedType = superType;
    }
    // anonymous type scenario
    // an anonymous class inherits from java.lang.Object when declared "after" an interface
    ReferenceBinding anonymousSuperclass =
        superType.isInterface() ? scope.getJavaLangObject() : superType;
    // insert anonymous type in scope
    scope.addAnonymousType(this.anonymousType, superType);
    this.anonymousType.resolve(scope);

    // find anonymous super constructor
    this.resolvedType = this.anonymousType.binding; // 1.2 change
    if ((this.resolvedType.tagBits & TagBits.HierarchyHasProblems) != 0) {
      return null; // stop secondary errors
    }
    MethodBinding inheritedBinding = scope.getConstructor(anonymousSuperclass, argumentTypes, this);
    if (!inheritedBinding.isValidBinding()) {
      if (inheritedBinding.declaringClass == null) {
        inheritedBinding.declaringClass = anonymousSuperclass;
      }
      if (this.type != null && !this.type.resolvedType.isValidBinding()) {
        // problem already got signaled on type reference, do not report secondary problem
        return null;
      }
      scope.problemReporter().invalidConstructor(this, inheritedBinding);
      return this.resolvedType;
    }
    if ((inheritedBinding.tagBits & TagBits.HasMissingType) != 0) {
      scope.problemReporter().missingTypeInConstructor(this, inheritedBinding);
    }
    if (this.enclosingInstance != null) {
      ReferenceBinding targetEnclosing = inheritedBinding.declaringClass.enclosingType();
      if (targetEnclosing == null) {
        scope
            .problemReporter()
            .unnecessaryEnclosingInstanceSpecification(this.enclosingInstance, superType);
        return this.resolvedType;
      } else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing)
          && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) {
        scope
            .problemReporter()
            .typeMismatchError(
                enclosingInstanceType, targetEnclosing, this.enclosingInstance, null);
        return this.resolvedType;
      }
      this.enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType);
    }
    if (this.arguments != null) {
      if (checkInvocationArguments(
          scope,
          null,
          anonymousSuperclass,
          inheritedBinding,
          this.arguments,
          argumentTypes,
          argsContainCast,
          this)) {
        this.bits |= ASTNode.Unchecked;
      }
    }
    if (this.typeArguments != null
        && inheritedBinding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
      scope
          .problemReporter()
          .unnecessaryTypeArgumentsForMethodInvocation(
              inheritedBinding, this.genericTypeArguments, this.typeArguments);
    }
    // Update the anonymous inner class : superclass, interface
    this.binding =
        this.anonymousType.createDefaultConstructorWithBinding(
            inheritedBinding,
            (this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null);
    return this.resolvedType;
  }
  public TypeBinding resolveType(BlockScope scope) {
    // Propagate the type checking to the arguments, and check if the constructor is defined.
    this.constant = Constant.NotAConstant;
    if (this.type == null) {
      // initialization of an enum constant
      this.resolvedType = scope.enclosingReceiverType();
    } else {
      this.resolvedType = this.type.resolveType(scope, true /* check bounds*/);
      checkParameterizedAllocation:
      {
        if (this.type
            instanceof ParameterizedQualifiedTypeReference) { // disallow new X<String>.Y<Integer>()
          ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
          if (currentType == null) return currentType;
          do {
            // isStatic() is answering true for toplevel types
            if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0)
              break checkParameterizedAllocation;
            if (currentType.isRawType()) break checkParameterizedAllocation;
          } while ((currentType = currentType.enclosingType()) != null);
          ParameterizedQualifiedTypeReference qRef =
              (ParameterizedQualifiedTypeReference) this.type;
          for (int i = qRef.typeArguments.length - 2; i >= 0; i--) {
            if (qRef.typeArguments[i] != null) {
              scope
                  .problemReporter()
                  .illegalQualifiedParameterizedTypeAllocation(this.type, this.resolvedType);
              break;
            }
          }
        }
      }
    }
    // will check for null after args are resolved

    final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0;
    // resolve type arguments (for generic constructor call)
    if (this.typeArguments != null) {
      int length = this.typeArguments.length;
      boolean argHasError = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5;
      this.genericTypeArguments = new TypeBinding[length];
      for (int i = 0; i < length; i++) {
        TypeReference typeReference = this.typeArguments[i];
        if ((this.genericTypeArguments[i] =
                typeReference.resolveType(scope, true /* check bounds*/))
            == null) {
          argHasError = true;
        }
        if (argHasError && typeReference instanceof Wildcard) {
          scope.problemReporter().illegalUsageOfWildcard(typeReference);
        }
      }
      if (isDiamond) {
        scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments);
        return null;
      }
      if (argHasError) {
        if (this.arguments != null) { // still attempt to resolve arguments
          for (int i = 0, max = this.arguments.length; i < max; i++) {
            this.arguments[i].resolveType(scope);
          }
        }
        return null;
      }
    }

    // buffering the arguments' types
    boolean argsContainCast = false;
    TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
    if (this.arguments != null) {
      boolean argHasError = false;
      int length = this.arguments.length;
      argumentTypes = new TypeBinding[length];
      for (int i = 0; i < length; i++) {
        Expression argument = this.arguments[i];
        if (argument instanceof CastExpression) {
          argument.bits |= DisableUnnecessaryCastCheck; // will check later on
          argsContainCast = true;
        }
        if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
          argHasError = true;
        }
      }
      if (argHasError) {
        /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359, if arguments have errors, completely bail out in the <> case.
          No meaningful type resolution is possible since inference of the elided types is fully tied to argument types. Do
          not return the partially resolved type.
        */
        if (isDiamond) {
          return null; // not the partially cooked this.resolvedType
        }
        if (this.resolvedType instanceof ReferenceBinding) {
          // record a best guess, for clients who need hint about possible constructor match
          TypeBinding[] pseudoArgs = new TypeBinding[length];
          for (int i = length; --i >= 0; ) {
            pseudoArgs[i] =
                argumentTypes[i] == null
                    ? TypeBinding.NULL
                    : argumentTypes[i]; // replace args with errors with null type
          }
          this.binding =
              scope.findMethod(
                  (ReferenceBinding) this.resolvedType, TypeConstants.INIT, pseudoArgs, this);
          if (this.binding != null && !this.binding.isValidBinding()) {
            MethodBinding closestMatch = ((ProblemMethodBinding) this.binding).closestMatch;
            // record the closest match, for clients who may still need hint about possible method
            // match
            if (closestMatch != null) {
              if (closestMatch.original().typeVariables
                  != Binding.NO_TYPE_VARIABLES) { // generic method
                // shouldn't return generic method outside its context, rather convert it to raw
                // method (175409)
                closestMatch =
                    scope
                        .environment()
                        .createParameterizedGenericMethod(
                            closestMatch.original(), (RawTypeBinding) null);
              }
              this.binding = closestMatch;
              MethodBinding closestMatchOriginal = closestMatch.original();
              if (closestMatchOriginal.isOrEnclosedByPrivateType()
                  && !scope.isDefinedInMethod(closestMatchOriginal)) {
                // ignore cases where method is used from within inside itself (e.g. direct
                // recursions)
                closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
              }
            }
          }
        }
        return this.resolvedType;
      }
    }
    if (this.resolvedType == null || !this.resolvedType.isValidBinding()) {
      return null;
    }

    // null type denotes fake allocation for enum constant inits
    if (this.type != null && !this.resolvedType.canBeInstantiated()) {
      scope.problemReporter().cannotInstantiate(this.type, this.resolvedType);
      return this.resolvedType;
    }
    if (isDiamond) {
      TypeBinding[] inferredTypes =
          inferElidedTypes(
              ((ParameterizedTypeBinding) this.resolvedType).genericType(),
              null,
              argumentTypes,
              scope);
      if (inferredTypes == null) {
        scope.problemReporter().cannotInferElidedTypes(this);
        return this.resolvedType = null;
      }
      this.resolvedType =
          this.type.resolvedType =
              scope
                  .environment()
                  .createParameterizedType(
                      ((ParameterizedTypeBinding) this.resolvedType).genericType(),
                      inferredTypes,
                      ((ParameterizedTypeBinding) this.resolvedType).enclosingType());
    }
    ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
    if (!(this.binding = scope.getConstructor(allocationType, argumentTypes, this))
        .isValidBinding()) {
      if (this.binding.declaringClass == null) {
        this.binding.declaringClass = allocationType;
      }
      if (this.type != null && !this.type.resolvedType.isValidBinding()) {
        return null;
      }
      scope.problemReporter().invalidConstructor(this, this.binding);
      return this.resolvedType;
    }
    if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
      scope.problemReporter().missingTypeInConstructor(this, this.binding);
    }
    if (isMethodUseDeprecated(this.binding, scope, true))
      scope.problemReporter().deprecatedMethod(this.binding, this);
    if (checkInvocationArguments(
        scope,
        null,
        allocationType,
        this.binding,
        this.arguments,
        argumentTypes,
        argsContainCast,
        this)) {
      this.bits |= ASTNode.Unchecked;
    }
    if (this.typeArguments != null
        && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
      scope
          .problemReporter()
          .unnecessaryTypeArgumentsForMethodInvocation(
              this.binding, this.genericTypeArguments, this.typeArguments);
    }
    if (!isDiamond && this.resolvedType.isParameterizedTypeWithActualArguments()) {
      checkTypeArgumentRedundancy(
          (ParameterizedTypeBinding) this.resolvedType, null, argumentTypes, scope);
    }
    final CompilerOptions compilerOptions = scope.compilerOptions();
    if (compilerOptions.isAnnotationBasedNullAnalysisEnabled
        && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
      new ImplicitNullAnnotationVerifier(
              scope.environment(), compilerOptions.inheritNullAnnotations)
          .checkImplicitNullAnnotations(this.binding, null /*srcMethod*/, false, scope);
    }
    return allocationType;
  }
예제 #7
0
 private boolean containsLong(final TypeReference type, ClassScope scope) {
   return type != null && JsniReferenceResolver.this.containsLong(type.resolveType(scope));
 }
예제 #8
0
  public TypeBinding resolveType(BlockScope scope) {
    // Answer the signature return type
    // Base type promotion

    this.constant = Constant.NotAConstant;
    boolean receiverCast = false, argsContainCast = false;
    if (this.receiver instanceof CastExpression) {
      this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
      receiverCast = true;
    }
    this.actualReceiverType = this.receiver.resolveType(scope);
    boolean receiverIsType =
        this.receiver instanceof NameReference
            && (((NameReference) this.receiver).bits & Binding.TYPE) != 0;
    if (receiverCast && this.actualReceiverType != null) {
      // due to change of declaring class with receiver type, only identity cast should be notified
      if (((CastExpression) this.receiver).expression.resolvedType == this.actualReceiverType) {
        scope.problemReporter().unnecessaryCast((CastExpression) this.receiver);
      }
    }
    // resolve type arguments (for generic constructor call)
    if (this.typeArguments != null) {
      int length = this.typeArguments.length;
      boolean argHasError =
          scope.compilerOptions().sourceLevel
              < ClassFileConstants.JDK1_5; // typeChecks all arguments
      this.genericTypeArguments = new TypeBinding[length];
      for (int i = 0; i < length; i++) {
        TypeReference typeReference = this.typeArguments[i];
        if ((this.genericTypeArguments[i] =
                typeReference.resolveType(scope, true /* check bounds*/))
            == null) {
          argHasError = true;
        }
        if (argHasError && typeReference instanceof Wildcard) {
          scope.problemReporter().illegalUsageOfWildcard(typeReference);
        }
      }
      if (argHasError) {
        if (this.arguments != null) { // still attempt to resolve arguments
          for (int i = 0, max = this.arguments.length; i < max; i++) {
            this.arguments[i].resolveType(scope);
          }
        }
        return null;
      }
    }
    // will check for null after args are resolved
    TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
    if (this.arguments != null) {
      boolean argHasError = false; // typeChecks all arguments
      int length = this.arguments.length;
      argumentTypes = new TypeBinding[length];
      for (int i = 0; i < length; i++) {
        Expression argument = this.arguments[i];
        if (argument instanceof CastExpression) {
          argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
          argsContainCast = true;
        }
        if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
          argHasError = true;
        }
      }
      if (argHasError) {
        if (this.actualReceiverType instanceof ReferenceBinding) {
          //  record a best guess, for clients who need hint about possible method match
          TypeBinding[] pseudoArgs = new TypeBinding[length];
          for (int i = length; --i >= 0; )
            pseudoArgs[i] =
                argumentTypes[i] == null
                    ? TypeBinding.NULL
                    : argumentTypes[i]; // replace args with errors with null type
          this.binding =
              this.receiver.isImplicitThis()
                  ? scope.getImplicitMethod(this.selector, pseudoArgs, this)
                  : scope.findMethod(
                      (ReferenceBinding) this.actualReceiverType, this.selector, pseudoArgs, this);
          if (this.binding != null && !this.binding.isValidBinding()) {
            MethodBinding closestMatch = ((ProblemMethodBinding) this.binding).closestMatch;
            // record the closest match, for clients who may still need hint about possible method
            // match
            if (closestMatch != null) {
              if (closestMatch.original().typeVariables
                  != Binding.NO_TYPE_VARIABLES) { // generic method
                // shouldn't return generic method outside its context, rather convert it to raw
                // method (175409)
                closestMatch =
                    scope
                        .environment()
                        .createParameterizedGenericMethod(
                            closestMatch.original(), (RawTypeBinding) null);
              }
              this.binding = closestMatch;
              MethodBinding closestMatchOriginal = closestMatch.original();
              if (closestMatchOriginal.isOrEnclosedByPrivateType()
                  && !scope.isDefinedInMethod(closestMatchOriginal)) {
                // ignore cases where method is used from within inside itself (e.g. direct
                // recursions)
                closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
              }
            }
          }
        }
        return null;
      }
    }
    if (this.actualReceiverType == null) {
      return null;
    }
    // base type cannot receive any message
    if (this.actualReceiverType.isBaseType()) {
      scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
      return null;
    }
    this.binding =
        this.receiver.isImplicitThis()
            ? scope.getImplicitMethod(this.selector, argumentTypes, this)
            : scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this);
    if (!this.binding.isValidBinding()) {
      if (this.binding.declaringClass == null) {
        if (this.actualReceiverType instanceof ReferenceBinding) {
          this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
        } else {
          scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
          return null;
        }
      }
      // https://bugs.eclipse.org/bugs/show_bug.cgi?id=245007 avoid secondary errors in case of
      // missing super type for anonymous classes ...
      ReferenceBinding declaringClass = this.binding.declaringClass;
      boolean avoidSecondary =
          declaringClass != null
              && declaringClass.isAnonymousType()
              && declaringClass.superclass() instanceof MissingTypeBinding;
      if (!avoidSecondary) scope.problemReporter().invalidMethod(this, this.binding);
      MethodBinding closestMatch = ((ProblemMethodBinding) this.binding).closestMatch;
      switch (this.binding.problemId()) {
        case ProblemReasons.Ambiguous:
          break; // no resilience on ambiguous
        case ProblemReasons.NotVisible:
        case ProblemReasons.NonStaticReferenceInConstructorInvocation:
        case ProblemReasons.NonStaticReferenceInStaticContext:
        case ProblemReasons.ReceiverTypeNotVisible:
        case ProblemReasons.ParameterBoundMismatch:
          // only steal returnType in cases listed above
          if (closestMatch != null) this.resolvedType = closestMatch.returnType;
          break;
      }
      // record the closest match, for clients who may still need hint about possible method match
      if (closestMatch != null) {
        this.binding = closestMatch;
        MethodBinding closestMatchOriginal = closestMatch.original();
        if (closestMatchOriginal.isOrEnclosedByPrivateType()
            && !scope.isDefinedInMethod(closestMatchOriginal)) {
          // ignore cases where method is used from within inside itself (e.g. direct recursions)
          closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
        }
      }
      return (this.resolvedType != null
              && (this.resolvedType.tagBits & TagBits.HasMissingType) == 0)
          ? this.resolvedType
          : null;
    }
    final CompilerOptions compilerOptions = scope.compilerOptions();
    if (compilerOptions.complianceLevel <= ClassFileConstants.JDK1_6
        && this.binding.isPolymorphic()) {
      scope.problemReporter().polymorphicMethodNotBelow17(this);
      return null;
    }

    if (((this.bits & ASTNode.InsideExpressionStatement) != 0) && this.binding.isPolymorphic()) {
      // we only set the return type to be void if this method invocation is used inside an
      // expression statement
      this.binding =
          scope
              .environment()
              .updatePolymorphicMethodReturnType(
                  (PolymorphicMethodBinding) this.binding, TypeBinding.VOID);
    }
    if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
      scope.problemReporter().missingTypeInMethod(this, this.binding);
    }
    if (!this.binding.isStatic()) {
      // the "receiver" must not be a type
      if (receiverIsType) {
        scope.problemReporter().mustUseAStaticMethod(this, this.binding);
        if (this.actualReceiverType.isRawType()
            && (this.receiver.bits & ASTNode.IgnoreRawTypeCheck) == 0
            && compilerOptions.getSeverity(CompilerOptions.RawTypeReference)
                != ProblemSeverities.Ignore) {
          scope.problemReporter().rawTypeReference(this.receiver, this.actualReceiverType);
        }
      } else {
        // handle indirect inheritance thru variable secondary bound
        // receiver may receive generic cast, as part of implicit conversion
        TypeBinding oldReceiverType = this.actualReceiverType;
        this.actualReceiverType =
            this.actualReceiverType.getErasureCompatibleType(this.binding.declaringClass);
        this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType);
        if (this.actualReceiverType != oldReceiverType
            && this.receiver.postConversionType(scope)
                != this
                    .actualReceiverType) { // record need for explicit cast at codegen since
                                           // receiver could not handle it
          this.bits |= NeedReceiverGenericCast;
        }
      }
    } else {
      // static message invoked through receiver? legal but unoptimal (optional warning).
      if (!(this.receiver.isImplicitThis() || this.receiver.isSuper() || receiverIsType)) {
        scope.problemReporter().nonStaticAccessToStaticMethod(this, this.binding);
      }
      if (!this.receiver.isImplicitThis()
          && this.binding.declaringClass != this.actualReceiverType) {
        scope.problemReporter().indirectAccessToStaticMethod(this, this.binding);
      }
    }
    if (checkInvocationArguments(
        scope,
        this.receiver,
        this.actualReceiverType,
        this.binding,
        this.arguments,
        argumentTypes,
        argsContainCast,
        this)) {
      this.bits |= ASTNode.Unchecked;
    }

    // -------message send that are known to fail at compile time-----------
    if (this.binding.isAbstract()) {
      if (this.receiver.isSuper()) {
        scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, this.binding);
      }
      // abstract private methods cannot occur nor abstract static............
    }
    if (isMethodUseDeprecated(this.binding, scope, true))
      scope.problemReporter().deprecatedMethod(this.binding, this);

    // from 1.5 source level on, array#clone() returns the array type (but binding still shows
    // Object)
    if (this.binding == scope.environment().arrayClone
        && compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5) {
      this.resolvedType = this.actualReceiverType;
    } else {
      TypeBinding returnType;
      if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) {
        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643, align with javac on JLS 15.12.2.6
        returnType = this.binding.returnType;
        if (returnType != null) {
          returnType = scope.environment().convertToRawType(returnType.erasure(), true);
        }
      } else {
        returnType = this.binding.returnType;
        if (returnType != null) {
          returnType = returnType.capture(scope, this.sourceEnd);
        }
      }
      this.resolvedType = returnType;
    }
    if (this.receiver.isSuper()
        && compilerOptions.getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation)
            != ProblemSeverities.Ignore) {
      final ReferenceContext referenceContext = scope.methodScope().referenceContext;
      if (referenceContext instanceof AbstractMethodDeclaration) {
        final AbstractMethodDeclaration abstractMethodDeclaration =
            (AbstractMethodDeclaration) referenceContext;
        MethodBinding enclosingMethodBinding = abstractMethodDeclaration.binding;
        if (enclosingMethodBinding.isOverriding()
            && CharOperation.equals(this.binding.selector, enclosingMethodBinding.selector)
            && this.binding.areParametersEqual(enclosingMethodBinding)) {
          abstractMethodDeclaration.bits |= ASTNode.OverridingMethodWithSupercall;
        }
      }
    }
    if (this.typeArguments != null
        && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
      scope
          .problemReporter()
          .unnecessaryTypeArgumentsForMethodInvocation(
              this.binding, this.genericTypeArguments, this.typeArguments);
    }
    return (this.resolvedType.tagBits & TagBits.HasMissingType) == 0 ? this.resolvedType : null;
  }