Package org.eclipse.jdt.internal.compiler.ast

Source Code of org.eclipse.jdt.internal.compiler.ast.IntersectionCastTypeReference

/*******************************************************************************
* Copyright (c) 2011, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*     Stephan Herrmann - Contribution for
*              Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*        Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
*                          Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.IntersectionCastTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;

@SuppressWarnings({"rawtypes"})
public class IntersectionCastTypeReference extends TypeReference {
  public TypeReference[] typeReferences;

  public IntersectionCastTypeReference(TypeReference[] typeReferences) {
    this.typeReferences = typeReferences;
    this.sourceStart = typeReferences[0].sourceStart;
    int length = typeReferences.length;
    this.sourceEnd = typeReferences[length - 1].sourceEnd;
    for (int i = 0, max = typeReferences.length; i < max; i++) {
      if ((typeReferences[i].bits & ASTNode.HasTypeAnnotations) != 0) {
        this.bits |= ASTNode.HasTypeAnnotations;
        break;
      }
    }
  }

  public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
    throw new UnsupportedOperationException(); // no syntax for this.
  }

  /* (non-Javadoc)
   * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getLastToken()
   */
  public char[] getLastToken() {
    return null;
  }

  /**
   * @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
   */
  protected TypeBinding getTypeBinding(Scope scope) {
    return null; // not supported here - combined with resolveType(...)
  }

  public TypeReference[] getTypeReferences() {
    return this.typeReferences;
  }
 
  /* (non-Javadoc)
   * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
   */
  public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {

    int length = this.typeReferences.length;
    ReferenceBinding[] intersectingTypes = new ReferenceBinding[length];
    boolean hasError = false;
   
    int typeCount = 0;
    nextType:
    for (int i = 0; i < length; i++) {
      final TypeReference typeReference = this.typeReferences[i];
      TypeBinding type = typeReference.resolveType(scope, checkBounds, location);
      if (type == null || ((type.tagBits & TagBits.HasMissingType) != 0)) {
        hasError = true;
        continue;
      }
      if (i == 0) {
        if (type.isBaseType()) { // rejected in grammar for i > 0
          scope.problemReporter().onlyReferenceTypesInIntersectionCast(typeReference);
          hasError = true;
          continue;
        }
        if (type.isArrayType()) { // javac rejects the pedantic cast: (X[] & Serializable & Cloneable) new X[0], what is good for the goose ...
          scope.problemReporter().illegalArrayTypeInIntersectionCast(typeReference);
          hasError = true;
          continue;
        }
      } else if (!type.isInterface()) {
        scope.problemReporter().boundMustBeAnInterface(typeReference, type);
        hasError = true;
        continue;
      }
      for (int j = 0; j < typeCount; j++) {
        final ReferenceBinding priorType = intersectingTypes[j];
        if (TypeBinding.equalsEquals(priorType, type)) {
          scope.problemReporter().duplicateBoundInIntersectionCast(typeReference);
          hasError = true;
          continue;
        }
        if (!priorType.isInterface())
          continue;
        if (TypeBinding.equalsEquals(type.findSuperTypeOriginatingFrom(priorType), priorType)) {
          intersectingTypes[j] = (ReferenceBinding) type;
          continue nextType;
        }
        if (TypeBinding.equalsEquals(priorType.findSuperTypeOriginatingFrom(type), type))
          continue nextType;
      }
      intersectingTypes[typeCount++] = (ReferenceBinding) type;
    }

    if (hasError) {
      return null;
    }
    if (typeCount != length) {
      if (typeCount == 1) {
        return this.resolvedType = intersectingTypes[0];
      }
      System.arraycopy(intersectingTypes, 0, intersectingTypes = new ReferenceBinding[typeCount], 0, typeCount);
    }
    IntersectionCastTypeBinding intersectionType = (IntersectionCastTypeBinding) scope.environment().createIntersectionCastType(intersectingTypes);
    // check for parameterized interface collisions (when different parameterizations occur)
    ReferenceBinding itsSuperclass = null;
    ReferenceBinding[] interfaces = intersectingTypes;
    ReferenceBinding firstType = intersectingTypes[0];
    if (firstType.isClass()) {
      itsSuperclass = firstType.superclass();
      System.arraycopy(intersectingTypes, 1, interfaces = new ReferenceBinding[typeCount - 1], 0, typeCount - 1);
    }
   
    Map invocations = new HashMap(2);
    nextInterface: for (int i = 0, interfaceCount = interfaces.length; i < interfaceCount; i++) {
      ReferenceBinding one = interfaces[i];
      if (one == null) continue nextInterface;
      if (itsSuperclass != null && scope.hasErasedCandidatesCollisions(itsSuperclass, one, invocations, intersectionType, this))
        continue nextInterface;
      nextOtherInterface: for (int j = 0; j < i; j++) {
        ReferenceBinding two = interfaces[j];
        if (two == null) continue nextOtherInterface;
        if (scope.hasErasedCandidatesCollisions(one, two, invocations, intersectionType, this))
          continue nextInterface;
      }
    }
    if ((intersectionType.tagBits & TagBits.HierarchyHasProblems) != 0)
      return null;

    return (this.resolvedType = intersectionType);
  }

  /* (non-Javadoc)
   * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeName()
   */
  public char[][] getTypeName() {
    // we need to keep a return value that is a char[][]
    return this.typeReferences[0].getTypeName();
  }

  /* (non-Javadoc)
   * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public void traverse(ASTVisitor visitor, BlockScope scope) {
    if (visitor.visit(this, scope)) {
      int length = this.typeReferences == null ? 0 : this.typeReferences.length;
      for (int i = 0; i < length; i++) {
        this.typeReferences[i].traverse(visitor, scope);
      }
    }
    visitor.endVisit(this, scope);
  }

  /* (non-Javadoc)
   * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
   */
  public void traverse(ASTVisitor visitor, ClassScope scope) {
    throw new UnsupportedOperationException("Unexpected traversal request: IntersectionTypeReference in class scope"); //$NON-NLS-1$
  }

  /* (non-Javadoc)
   * @see org.eclipse.jdt.internal.compiler.ast.Expression#printExpression(int, java.lang.StringBuffer)
   */
  public StringBuffer printExpression(int indent, StringBuffer output) {
    int length = this.typeReferences == null ? 0 : this.typeReferences.length;
    printIndent(indent, output);
    for (int i = 0; i < length; i++) {
      this.typeReferences[i].printExpression(0, output);
      if (i != length - 1) {
        output.append(" & "); //$NON-NLS-1$
      }
    }
    return output;
  }
}
TOP

Related Classes of org.eclipse.jdt.internal.compiler.ast.IntersectionCastTypeReference

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.