Пример #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);
            }
          }
        }
      }
    }
Пример #2
0
 private static JMethod createEmptyMethodFromExample(
     JDeclaredType inType, JMethod exampleMethod, boolean isAbstract) {
   JMethod emptyMethod =
       new JMethod(
           exampleMethod.getSourceInfo(),
           exampleMethod.getName(),
           inType,
           exampleMethod.getType(),
           isAbstract,
           false,
           false,
           exampleMethod.getAccess());
   emptyMethod.addThrownExceptions(exampleMethod.getThrownExceptions());
   emptyMethod.setSynthetic();
   // Copy parameters.
   for (JParameter param : exampleMethod.getParams()) {
     emptyMethod.addParam(
         new JParameter(
             param.getSourceInfo(),
             param.getName(),
             param.getType(),
             param.isFinal(),
             param.isThis(),
             emptyMethod));
   }
   JMethodBody body = new JMethodBody(exampleMethod.getSourceInfo());
   emptyMethod.setBody(body);
   emptyMethod.freezeParamTypes();
   inType.addMethod(emptyMethod);
   return emptyMethod;
 }
Пример #3
0
    public EnumNameCallChecker(JProgram jprogram, TreeLogger logger) {
      this.logger = logger;
      this.enumNameMethod = jprogram.getIndexedMethod("Enum.name");
      this.enumToStringMethod = jprogram.getIndexedMethod("Enum.toString");
      this.classType = jprogram.getIndexedType("Class");
      this.enumType = jprogram.getIndexedType("Enum");
      this.stringType = jprogram.getIndexedType("String");

      /*
       * Find the correct version of enumValueOfMethod.
       *
       * Note: it doesn't work to check against a ref returned by
       * jprogram.getIndexedMethod("Enum.valueOf"), since there are 2 different
       * versions of Enum.valueOf in our jre emulation library, and the indexed
       * ref won't reliably flag the public instance, which is the one we want
       * here (i.e. Enum.valueOf(Class<T>,String)). The other version is
       * protected, but is called by the generated constructors for sub-classes
       * of Enum, and we don't want to warn for those cases.
       */
      JMethod foundMethod = null;
      List<JMethod> enumMethods = enumType.getMethods();
      for (JMethod enumMethod : enumMethods) {
        if ("valueOf".equals(enumMethod.getName())) {
          List<JParameter> jParameters = enumMethod.getParams();
          if (jParameters.size() == 2
              && jParameters.get(0).getType() == classType
              && jParameters.get(1).getType() == stringType) {
            foundMethod = enumMethod;
            break;
          }
        }
      }
      this.enumValueOfMethod = foundMethod;
    }
Пример #4
0
  /** Returns a description for a member suitable for reporting errors to the users. */
  public static String getReadableDescription(JMember member) {
    if (member instanceof JField) {
      return String.format(
          "%s %s.%s",
          getReadableDescription(member.getType()),
          getReadableDescription(member.getEnclosingType()),
          member.getName());
    }

    JMethod method = (JMethod) member;
    String printableDescription = "";
    if (!method.isConstructor()) {
      printableDescription += getReadableDescription(method.getType()) + " ";
    }
    printableDescription +=
        String.format(
            "%s.%s(%s)",
            getReadableDescription(method.getEnclosingType()),
            method.getName(),
            Joiner.on(", ")
                .join(
                    Iterables.transform(
                        method.getOriginalParamTypes(),
                        new Function<JType, String>() {
                          @Override
                          public String apply(JType type) {
                            return getReadableDescription(type);
                          }
                        })));
    return printableDescription;
  }
Пример #5
0
  public JExpression doRebind(String clsName, ReflectionGeneratorContext params)
      throws UnableToCompleteException {
    // generate
    params.getLogger().log(Type.INFO, "Binding magic class for " + clsName);
    // JType type = params.getClazz().getRefType();
    JDeclaredType type =
        params.getAst().searchForTypeBySource(params.getClazz().getRefType().getName());

    StandardGeneratorContext ctx = params.getGeneratorContext();
    Class<? extends Generator> generator = MagicClassGenerator.class;

    String result =
        ctx.runGenerator(params.getLogger(), generator, SourceUtil.toSourceName(type.getName()));
    ctx.finish(params.getLogger());

    params.getLogger().log(Type.INFO, "Generated Class Enhancer: " + result);
    JDeclaredType success = params.getAst().searchForTypeBySource(result);

    // Okay, we've generated the correct magic class subtype;
    // Now pull off its static accessor method to grab our generated class.

    for (JMethod method : success.getMethods()) {
      if (method.isStatic() && method.getName().equals("enhanceClass")) {
        JMethodCall call = new JMethodCall(method.getSourceInfo(), null, method);
        call.addArg(params.getClazz().makeStatement().getExpr());
        return call;
      }
    }
    params.getLogger().log(Type.ERROR, "Unable to load " + result + ".enhanceClass()");
    throw new UnableToCompleteException();
  }
Пример #6
0
  private static boolean isNewMethod(HasEnclosingType member) {
    if (member instanceof JMethod) {
      JMethod method = (JMethod) member;
      return method.getName().equals(JsniRef.NEW);
    }

    assert member instanceof JField;
    return false;
  }
Пример #7
0
  /**
   * Return the JSNI signature for a member. Leave off the return type for a method signature, so as
   * to match what a user would type in as a JsniRef.
   */
  private static String getJsniSignature(HasEnclosingType member, boolean wildcardParams) {
    if (member instanceof JField) {
      return ((JField) member).getName();
    }
    JMethod method = (JMethod) member;

    if (wildcardParams) {
      return method.getName() + "(" + JsniRef.WILDCARD_PARAM_LIST + ")";
    } else {
      return JProgram.getJsniSig(method, false);
    }
  }
Пример #8
0
 private static void setJsPropertyProperties(JMethod method) {
   String methodName = method.getName();
   if (startsWithCamelCase(methodName, "set")) {
     String jsName = Introspector.decapitalize(methodName.substring(3));
     method.setJsPropertyInfo(jsName, JsPropertyAccessorType.SETTER);
   } else if (startsWithCamelCase(methodName, "get")) {
     String jsName = Introspector.decapitalize(methodName.substring(3));
     method.setJsPropertyInfo(jsName, JsPropertyAccessorType.GETTER);
   } else if (startsWithCamelCase(methodName, "is")) {
     String jsName = Introspector.decapitalize(methodName.substring(2));
     method.setJsPropertyInfo(jsName, JsPropertyAccessorType.GETTER);
   } else {
     method.setJsPropertyInfo(INVALID_JSNAME, JsPropertyAccessorType.UNDEFINED);
   }
 }
Пример #9
0
 private static void setJsPropertyProperties(JMethod method) {
   String methodName = method.getName();
   if (startsWithCamelCase(methodName, "set")) {
     method.setJsPropertyType(JsPropertyType.SET);
     method.setJsMemberName(Introspector.decapitalize(methodName.substring(3)));
   } else if (startsWithCamelCase(methodName, "get")) {
     method.setJsPropertyType(JsPropertyType.GET);
     method.setJsMemberName(Introspector.decapitalize(methodName.substring(3)));
   } else if (startsWithCamelCase(methodName, "is")) {
     method.setJsPropertyType(JsPropertyType.GET);
     method.setJsMemberName(Introspector.decapitalize(methodName.substring(2)));
   } else {
     method.setJsPropertyType(JsPropertyType.UNDEFINED);
   }
 }
Пример #10
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());
      }
    }
  }
Пример #11
0
  /**
   * Java8 Method References such as String::equalsIgnoreCase should produce inner class names that
   * are a function of the samInterface (e.g. Runnable), the method being referred to, and the
   * qualifying disposition (this::foo vs Class::foo if foo is an instance method)
   */
  public static String classNameForMethodReference(
      JType cuType,
      JInterfaceType functionalInterface,
      JMethod referredMethod,
      boolean hasReceiver) {
    String prefix =
        classNamePrefixForMethodReference(
            cuType.getPackageName(),
            cuType.getName(),
            functionalInterface.getName(),
            referredMethod.getEnclosingType().getName(),
            referredMethod.getName(),
            hasReceiver);

    return StringInterner.get().intern(constructManglingSignature(referredMethod, prefix));
  }