Example #1
0
    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      JMethod target = x.getTarget();
      JDeclaredType type = target.getEnclosingType();

      if (type instanceof JClassType) {
        JClassType cType = (JClassType) type;

        if (target == enumNameMethod
            || target == enumToStringMethod
            || target == enumValueOfMethod) {
          warn(x);
        } else if (cType.isEnumOrSubclass() != null) {
          if ("valueOf".equals(target.getName())) {
            /*
             * Check for calls to the auto-generated
             * EnumSubType.valueOf(String). Note, the check of the signature for
             * the single String arg version is to avoid flagging user-defined
             * overloaded versions of the method, which are presumably ok.
             */
            List<JParameter> jParameters = target.getParams();
            if (jParameters.size() == 1 && jParameters.get(0).getType() == stringType) {
              warn(x);
            }
          }
        }
      }
    }
Example #2
0
 /** Traverse from all methods starting from a set of types. */
 private void traverseTypes(ControlFlowAnalyzer livenessAnalyzer, List<JClassType> types) {
   for (JClassType type : types) {
     livenessAnalyzer.traverseFromReferenceTo(type);
     for (JMethod method : type.getMethods()) {
       if (method instanceof JConstructor) {
         livenessAnalyzer.traverseFromInstantiationOf(type);
       }
       livenessAnalyzer.traverseFrom(method);
     }
   }
 }
Example #3
0
 private int countSuperTypes(JClassType type) {
   int count = 0;
   while ((type = type.getSuperClass()) != null) {
     ++count;
   }
   return count;
 }
Example #4
0
 /** Called to set this class's trivial initializer to point to a superclass. */
 void setClinitTarget(JDeclaredType newClinitTarget) {
   if (clinitTarget == newClinitTarget) {
     return;
   }
   if (newClinitTarget != null && getClass().desiredAssertionStatus()) {
     // Make sure this is a pure upgrade to a superclass or null.
     for (JClassType current = (JClassType) clinitTarget;
         current != newClinitTarget;
         current = current.getSuperClass()) {
       Preconditions.checkNotNull(
           current.getSuperClass(),
           "Null super class for: %s (currentTarget: %s; newTarget: %s) in %s",
           current,
           clinitTarget,
           newClinitTarget,
           this);
     }
   }
   clinitTarget = newClinitTarget;
 }
Example #5
0
  private JReferenceType generalizeClasses(JClassType thisClass, JClassType thatClass) {
    /*
     * see how far each type is from object; walk the one who's farther up
     * until they're even; then walk them up together until they meet (worst
     * case at Object)
     */
    int distance1 = countSuperTypes(thisClass);
    int distance2 = countSuperTypes(thatClass);
    for (; distance1 > distance2; --distance1) {
      thisClass = thisClass.getSuperClass();
    }

    for (; distance1 < distance2; --distance2) {
      thatClass = thatClass.getSuperClass();
    }

    while (thisClass != thatClass) {
      thisClass = thisClass.getSuperClass();
      thatClass = thatClass.getSuperClass();
    }

    return thisClass;
  }
Example #6
0
  /**
   * For each member with the given name, find the most derived members for each JSNI reference that
   * match it. For wildcard JSNI references, there will in general be more than one match. This
   * method does not ignore synthetic methods.
   */
  private static void findMostDerivedMembers(
      LinkedHashMap<String, LinkedHashMap<String, HasEnclosingType>> matchesBySig,
      JDeclaredType targetType,
      String memberName,
      boolean addConstructors) {
    /*
     * Analyze superclasses and interfaces first. More derived members will thus
     * be seen later.
     */
    if (targetType instanceof JClassType) {
      JClassType targetClass = (JClassType) targetType;
      if (targetClass.getSuperClass() != null) {
        findMostDerivedMembers(matchesBySig, targetClass.getSuperClass(), memberName, false);
      }
    }
    for (JDeclaredType intf : targetType.getImplements()) {
      findMostDerivedMembers(matchesBySig, intf, memberName, false);
    }

    // Get the methods on this class/interface.
    for (JMethod method : targetType.getMethods()) {
      if (method.getName().equals(memberName)) {
        if (addConstructors || !method.getName().equals(JsniRef.NEW)) {
          addMember(matchesBySig, method, getJsniSignature(method, false));
          addMember(matchesBySig, method, getJsniSignature(method, true));
        }
      }
    }

    // Get the fields on this class/interface.
    for (JField field : targetType.getFields()) {
      if (field.getName().equals(memberName)) {
        addMember(matchesBySig, field, field.getName());
      }
    }
  }
Example #7
0
 /**
  * Returns an instantiation expression for {@code type} using the default constructor, Returns
  * {@code null} if {@code type} does not have a default constructor.
  */
 public static JExpression createDefaultConstructorInstantiation(
     SourceInfo info, JClassType type) {
   /*
    * Find the appropriate (noArg) constructor. In our AST, constructors are
    * instance methods that should be qualified with a new expression.
    */
   JConstructor noArgCtor =
       (JConstructor)
           FluentIterable.from(type.getMethods())
               .firstMatch(
                   new Predicate<JMethod>() {
                     @Override
                     public boolean apply(JMethod method) {
                       return method instanceof JConstructor
                           && method.getOriginalParamTypes().size() == 0;
                     }
                   })
               .orNull();
   if (noArgCtor == null) {
     return null;
   }
   // Call it, using a new expression as a qualifier
   return new JNewInstance(info, noArgCtor);
 }
Example #8
0
 public ExternalSerializedForm(JClassType classType) {
   name = classType.getName();
 }
Example #9
0
 /** Resolve an external references during AST stitching. */
 public void resolve(JClassType jsoType) {
   assert jsoType.replaces(this.arrayType);
   this.arrayType = jsoType;
 }
Example #10
0
 public boolean isJavaLangString(JType type) {
   return type == typeString || type == typeString.getNonNull();
 }
Example #11
0
  /**
   * Return the least upper bound of two types. That is, the smallest type that is a supertype of
   * both types.
   */
  public JReferenceType generalizeTypes(JReferenceType type1, JReferenceType type2) {
    if (type1 == type2) {
      return type1;
    }

    if (type1 instanceof JNonNullType && type2 instanceof JNonNullType) {
      // Neither can be null.
      type1 = type1.getUnderlyingType();
      type2 = type2.getUnderlyingType();
      return generalizeTypes(type1, type2).getNonNull();
    } else if (type1 instanceof JNonNullType) {
      // type2 can be null, so the result can be null
      type1 = type1.getUnderlyingType();
    } else if (type2 instanceof JNonNullType) {
      // type1 can be null, so the result can be null
      type2 = type2.getUnderlyingType();
    }
    assert !(type1 instanceof JNonNullType);
    assert !(type2 instanceof JNonNullType);

    int classify1 = classifyType(type1);
    int classify2 = classifyType(type2);

    if (classify1 == IS_NULL) {
      return type2;
    }

    if (classify2 == IS_NULL) {
      return type1;
    }

    if (classify1 == classify2) {

      // same basic kind of type
      if (classify1 == IS_INTERFACE) {

        if (typeOracle.canTriviallyCast(type1, type2)) {
          return type2;
        }

        if (typeOracle.canTriviallyCast(type2, type1)) {
          return type1;
        }

        // unrelated
        return typeJavaLangObject;

      } else if (classify1 == IS_ARRAY) {

        JArrayType aType1 = (JArrayType) type1;
        JArrayType aType2 = (JArrayType) type2;
        int dims1 = aType1.getDims();
        int dims2 = aType2.getDims();

        int minDims = Math.min(dims1, dims2);
        /*
         * At a bare minimum, any two arrays generalize to an Object array with
         * one less dim than the lesser of the two; that is, int[][][][] and
         * String[][][] generalize to Object[][]. If minDims is 1, then they
         * just generalize to Object.
         */
        JReferenceType minimalGeneralType;
        if (minDims > 1) {
          minimalGeneralType = getTypeArray(typeJavaLangObject, minDims - 1);
        } else {
          minimalGeneralType = typeJavaLangObject;
        }

        if (dims1 == dims2) {

          // Try to generalize by leaf types
          JType leafType1 = aType1.getLeafType();
          JType leafType2 = aType2.getLeafType();

          if (!(leafType1 instanceof JReferenceType) || !(leafType2 instanceof JReferenceType)) {
            return minimalGeneralType;
          }

          /*
           * Both are reference types; the result is the generalization of the
           * leaf types combined with the number of dims; that is, Foo[] and
           * Bar[] generalize to X[] where X is the generalization of Foo and
           * Bar.
           */
          JReferenceType leafRefType1 = (JReferenceType) leafType1;
          JReferenceType leafRefType2 = (JReferenceType) leafType2;

          /**
           * Never generalize arrays to arrays of {@link JNonNullType} as null array initialization
           * is not accounted for in {@link TypeTightener}.
           */
          JReferenceType leafGeneralization =
              generalizeTypes(leafRefType1, leafRefType2).getUnderlyingType();
          return getTypeArray(leafGeneralization, dims1);

        } else {

          // Conflicting number of dims

          // int[][] and Object[] generalize to Object[]
          JArrayType lesser = dims1 < dims2 ? aType1 : aType2;
          if (lesser.getLeafType() == typeJavaLangObject) {
            return lesser;
          }

          // Totally unrelated
          return minimalGeneralType;
        }

      } else {

        assert (classify1 == IS_CLASS);
        JClassType class1 = (JClassType) type1;
        JClassType class2 = (JClassType) type2;

        /*
         * see how far each type is from object; walk the one who's farther up
         * until they're even; then walk them up together until they meet (worst
         * case at Object)
         */
        int distance1 = countSuperTypes(class1);
        int distance2 = countSuperTypes(class2);
        for (; distance1 > distance2; --distance1) {
          class1 = class1.getSuperClass();
        }

        for (; distance1 < distance2; --distance2) {
          class2 = class2.getSuperClass();
        }

        while (class1 != class2) {
          class1 = class1.getSuperClass();
          class2 = class2.getSuperClass();
        }

        return class1;
      }
    } else {

      // different kinds of types
      int lesser = Math.min(classify1, classify2);
      int greater = Math.max(classify1, classify2);

      JReferenceType tLesser = classify1 < classify2 ? type1 : type2;
      JReferenceType tGreater = classify1 > classify2 ? type1 : type2;

      if (lesser == IS_INTERFACE && greater == IS_CLASS) {

        // just see if the class implements the interface
        if (typeOracle.canTriviallyCast(tGreater, tLesser)) {
          return tLesser;
        }

        // unrelated
        return typeJavaLangObject;

      } else if (greater == IS_ARRAY
          && ((tLesser == typeJavaLangCloneable) || (tLesser == typeJavaIoSerializable))) {
        return tLesser;
      } else {

        // unrelated: the best commonality between an interface and array, or
        // between an array and a class is Object
        return typeJavaLangObject;
      }
    }
  }