private void printTypeParameters(List<TypeParameter> args, Object arg) {
   if (args != null) {
     for (Iterator<TypeParameter> i = args.iterator(); i.hasNext(); ) {
       TypeParameter t = i.next();
       t.accept(this, arg);
       if (i.hasNext()) {}
     }
   }
 }
 public void visit(TypeParameter n, Object arg) {
   if (n.getTypeBound() != null) {
     for (Iterator<ClassOrInterfaceType> i = n.getTypeBound().iterator(); i.hasNext(); ) {
       ClassOrInterfaceType c = i.next();
       c.accept(this, arg);
       if (i.hasNext()) {}
     }
   }
 }
 /**
  * Determine if this is a decidable supertype, i.e. if it obeys the restriction that types with
  * contravariant type parameters may only appear in covariant positions.
  *
  * @return a list of type parameters which appear in illegal positions
  */
 public List<TypeDeclaration> checkDecidability() {
   List<TypeDeclaration> errors = new ArrayList<TypeDeclaration>();
   for (TypeParameter tp : getDeclaration().getTypeParameters()) {
     ProducedType pt = getTypeArguments().get(tp);
     if (pt != null) {
       pt.checkDecidability(tp.isCovariant(), tp.isContravariant(), errors);
     }
   }
   return errors;
 }
 private static List<TypeParameterRequirement> createTypeParameters(
     Iterable<TypeParameter> typeParameters, List<ImplementationDependency> dependencies) {
   Set<String> orderableRequired = new HashSet<>();
   Set<String> comparableRequired = new HashSet<>();
   for (ImplementationDependency dependency : dependencies) {
     if (dependency instanceof OperatorImplementationDependency) {
       OperatorType operator = ((OperatorImplementationDependency) dependency).getOperator();
       if (operator == CAST) {
         continue;
       }
       Set<String> argumentTypes =
           ((OperatorImplementationDependency) dependency)
               .getSignature()
               .getArgumentTypes()
               .stream()
               .map(TypeSignature::getBase)
               .collect(toImmutableSet());
       checkArgument(
           argumentTypes.size() == 1,
           "Operator dependency must only have arguments of a single type");
       String argumentType = Iterables.getOnlyElement(argumentTypes);
       if (COMPARABLE_TYPE_OPERATORS.contains(operator)) {
         comparableRequired.add(argumentType);
       }
       if (ORDERABLE_TYPE_OPERATORS.contains(operator)) {
         orderableRequired.add(argumentType);
       }
     }
   }
   ImmutableList.Builder<TypeParameterRequirement> typeParameterRequirements =
       ImmutableList.builder();
   for (TypeParameter typeParameter : typeParameters) {
     String name = typeParameter.value();
     if (orderableRequired.contains(name)) {
       typeParameterRequirements.add(orderableTypeParameter(name));
     } else if (comparableRequired.contains(name)) {
       typeParameterRequirements.add(comparableTypeParameter(name));
     } else {
       typeParameterRequirements.add(typeParameter(name));
     }
   }
   return typeParameterRequirements.build();
 }
 @Override
 public List<? extends Declaration> locallyDeclaredDeclarations() throws LookupException {
   if (_localDeclarationCache == null) {
     synchronized (this) {
       if (_localDeclarationCache == null) {
         List<Declaration> result = Lists.create();
         BlockFixer stub = new BlockFixer();
         stub.setUniParent(this);
         for (TypeParameter parameter : parameters()) {
           TypeParameter clone = clone(parameter);
           clone.setOrigin(parameter);
           result.add(clone);
           stub.add(clone);
         }
         _localDeclarationCache = ImmutableList.copyOf(result);
       }
     }
   }
   return _localDeclarationCache;
 }
 private void checkDecidability(
     boolean covariant, boolean contravariant, List<TypeDeclaration> errors) {
   if (getDeclaration() instanceof TypeParameter) {
     // nothing to do
   } else if (getDeclaration() instanceof UnionType) {
     for (ProducedType ct : getCaseTypes()) {
       ct.checkDecidability(covariant, contravariant, errors);
     }
   } else if (getDeclaration() instanceof IntersectionType) {
     for (ProducedType ct : getSatisfiedTypes()) {
       ct.checkDecidability(covariant, contravariant, errors);
     }
   } else {
     for (TypeParameter tp : getDeclaration().getTypeParameters()) {
       if (!covariant && tp.isContravariant()) {
         // a type with contravariant parameters appears at
         // a contravariant location in satisfies / extends
         errors.add(getDeclaration());
       }
       ProducedType pt = getTypeArguments().get(tp);
       if (pt != null) {
         if (tp.isCovariant()) {
           pt.checkDecidability(covariant, contravariant, errors);
         } else if (tp.isContravariant()) {
           if (covariant | contravariant) {
             pt.checkDecidability(!covariant, !contravariant, errors);
           } else {
             // else if we are in a nonvariant position, it stays nonvariant
             pt.checkDecidability(covariant, contravariant, errors);
           }
         } else {
           pt.checkDecidability(false, false, errors);
         }
       }
     }
   }
 }
 private void checkVariance(
     boolean covariant,
     boolean contravariant,
     Declaration declaration,
     List<TypeParameter> errors) {
   // TODO: fix this to allow reporting multiple errors!
   if (getDeclaration() instanceof TypeParameter) {
     TypeParameter tp = (TypeParameter) getDeclaration();
     boolean ok =
         tp.getDeclaration().equals(declaration)
             || ((covariant || !tp.isCovariant()) && (contravariant || !tp.isContravariant()));
     if (!ok) {
       // a covariant type parameter appears in a contravariant location, or
       // a contravariant type parameter appears in a covariant location.
       errors.add(tp);
     }
   } else if (getDeclaration() instanceof UnionType) {
     for (ProducedType ct : getCaseTypes()) {
       ct.checkVariance(covariant, contravariant, declaration, errors);
     }
   } else if (getDeclaration() instanceof IntersectionType) {
     for (ProducedType ct : getSatisfiedTypes()) {
       ct.checkVariance(covariant, contravariant, declaration, errors);
     }
   } else {
     for (TypeParameter tp : getDeclaration().getTypeParameters()) {
       ProducedType pt = getTypeArguments().get(tp);
       if (pt != null) {
         if (tp.isCovariant()) {
           pt.checkVariance(covariant, contravariant, declaration, errors);
         } else if (tp.isContravariant()) {
           if (covariant | contravariant) {
             pt.checkVariance(!covariant, !contravariant, declaration, errors);
           } else {
             // else if we are in a nonvariant position, it stays nonvariant
             pt.checkVariance(covariant, contravariant, declaration, errors);
           }
         } else {
           pt.checkVariance(false, false, declaration, errors);
         }
       }
     }
   }
 }
 private ProducedType getCommonSupertype(
     final List<ProducedType> caseTypes,
     TypeDeclaration dec,
     final TypeDeclaration selfTypeToIgnore) {
   // now try to construct a common produced
   // type that is a common supertype by taking
   // the type args and unioning them
   List<ProducedType> args = new ArrayList<ProducedType>();
   for (TypeParameter tp : dec.getTypeParameters()) {
     List<ProducedType> list2 = new ArrayList<ProducedType>();
     ProducedType result;
     if (tp.isContravariant()) {
       for (ProducedType pt : caseTypes) {
         ProducedType st = pt.getSupertype(dec, selfTypeToIgnore);
         if (st == null) {
           return null;
         }
         addToIntersection(list2, st.getTypeArguments().get(tp));
       }
       IntersectionType it = new IntersectionType(getDeclaration().getUnit());
       it.setSatisfiedTypes(list2);
       result = it.canonicalize().getType();
     } else {
       for (ProducedType pt : caseTypes) {
         ProducedType st = pt.getSupertype(dec, selfTypeToIgnore);
         if (st == null) {
           return null;
         }
         addToUnion(list2, st.getTypeArguments().get(tp));
       }
       UnionType ut = new UnionType(getDeclaration().getUnit());
       ut.setCaseTypes(list2);
       result = ut.getType();
     }
     args.add(result);
   }
   // check that the unioned type args
   // satisfy the type constraints
   for (int i = 0; i < args.size(); i++) {
     TypeParameter tp = dec.getTypeParameters().get(i);
     for (ProducedType ub : tp.getSatisfiedTypes()) {
       if (!args.get(i).isSubtypeOf(ub)) {
         return null;
       }
     }
   }
   // recurse to the qualifying type
   ProducedType outerType;
   if (dec.isMember()) {
     TypeDeclaration outer = (TypeDeclaration) dec.getContainer();
     List<ProducedType> list = new ArrayList<ProducedType>();
     for (ProducedType pt : caseTypes) {
       ProducedType st = pt.getQualifyingType().getSupertype(outer, null);
       list.add(st);
     }
     outerType = getCommonSupertype(list, outer, null);
   } else {
     outerType = null;
   }
   // make the resulting type
   ProducedType candidateResult = dec.getProducedType(outerType, args);
   // check the the resulting type is *really*
   // a subtype (take variance into account)
   for (ProducedType pt : caseTypes) {
     if (!pt.isSubtypeOf(candidateResult)) {
       return null;
     }
   }
   return candidateResult;
 }
 /** Is this type a subtype of the given type? Ignore a certain self type constraint. */
 public boolean isSubtypeOf(ProducedType type, TypeDeclaration selfTypeToIgnore) {
   if (getDeclaration() instanceof BottomType) {
     return true;
   } else if (type.getDeclaration() instanceof BottomType) {
     return false;
   } else if (getDeclaration() instanceof UnionType) {
     for (ProducedType ct : getInternalCaseTypes()) {
       if (ct == null || !ct.isSubtypeOf(type, selfTypeToIgnore)) {
         return false;
       }
     }
     return true;
   } else if (type.getDeclaration() instanceof UnionType) {
     for (ProducedType ct : type.getInternalCaseTypes()) {
       if (ct != null && isSubtypeOf(ct, selfTypeToIgnore)) {
         return true;
       }
     }
     return false;
   } else if (type.getDeclaration() instanceof IntersectionType) {
     for (ProducedType ct : type.getInternalSatisfiedTypes()) {
       if (ct != null && !isSubtypeOf(ct, selfTypeToIgnore)) {
         return false;
       }
     }
     return true;
   } else if (getDeclaration() instanceof IntersectionType) {
     for (ProducedType ct : getInternalSatisfiedTypes()) {
       if (ct == null || ct.isSubtypeOf(type, selfTypeToIgnore)) {
         return true;
       }
     }
     return false;
   } else {
     ProducedType st = getSupertype(type.getDeclaration(), selfTypeToIgnore);
     if (st == null) {
       return false;
     } else {
       ProducedType stqt = st.getQualifyingType();
       ProducedType tqt = type.getQualifyingType();
       if (stqt == null) {
         if (tqt != null) {
           // probably extraneous!
           return false;
         }
       } else {
         if (tqt == null) {
           // probably extraneous!
           return false;
         } else {
           // note that the qualifying type of the
           // given type may be an invariant subtype
           // of the type that declares the member
           // type, as long as it doesn't refine the
           // member type
           TypeDeclaration totd = (TypeDeclaration) type.getDeclaration().getContainer();
           ProducedType tqts = tqt.getSupertype(totd);
           if (!stqt.isSubtypeOf(tqts)) {
             return false;
           }
         }
       }
       for (TypeParameter p : type.getDeclaration().getTypeParameters()) {
         ProducedType arg = st.getTypeArguments().get(p);
         ProducedType otherArg = type.getTypeArguments().get(p);
         if (arg == null || otherArg == null) {
           /*throw new RuntimeException("Missing type argument for type parameter: " +
           p.getName() + " of " +
           type.getDeclaration().getName());*/
           return false;
         } else if (p.isCovariant()) {
           if (!arg.isSubtypeOf(otherArg)) {
             return false;
           }
         } else if (p.isContravariant()) {
           if (!otherArg.isSubtypeOf(arg)) {
             return false;
           }
         } else {
           if (!arg.isExactly(otherArg)) {
             return false;
           }
         }
       }
       return true;
     }
   }
 }
Exemple #10
0
 @Override
 public Void visitTypeParameter(TypeParameter node) {
   visit(node.getName());
   visit(" extends ", node.getBound());
   return null;
 }