Beispiel #1
0
 /** Determines if a type can access fields and methods from an outer class. */
 public static boolean hasOuterContext(ITypeBinding type) {
   if (type.getDeclaringClass() == null) {
     return false;
   }
   // Local types can't be declared static, but if the declaring method is
   // static then the local type is effectively static.
   IMethodBinding declaringMethod = type.getTypeDeclaration().getDeclaringMethod();
   if (declaringMethod != null) {
     return !BindingUtil.isStatic(declaringMethod);
   }
   return !BindingUtil.isStatic(type);
 }
Beispiel #2
0
 /** Locate method which matches either Java or Objective C getter name patterns. */
 public static IMethodBinding findGetterMethod(
     String propertyName, ITypeBinding propertyType, ITypeBinding declaringClass) {
   // Try Objective-C getter naming convention.
   IMethodBinding getter = BindingUtil.findDeclaredMethod(declaringClass, propertyName);
   if (getter == null) {
     // Try Java getter naming conventions.
     String prefix = BindingUtil.isBoolean(propertyType) ? "is" : "get";
     getter =
         BindingUtil.findDeclaredMethod(
             declaringClass, prefix + NameTable.capitalize(propertyName));
   }
   return getter;
 }
  @Override
  protected void generate(AnnotationTypeDeclaration node) {
    syncLineNumbers(node.getName()); // avoid doc-comment

    String typeName = NameTable.getFullName(node);
    printf("@implementation %s\n", typeName);
    if (BindingUtil.isRuntimeAnnotation(Types.getTypeBinding(node))) {
      List<AnnotationTypeMemberDeclaration> members = Lists.newArrayList();
      for (BodyDeclaration decl : ASTUtil.getBodyDeclarations(node)) {
        if (decl instanceof AnnotationTypeMemberDeclaration) {
          members.add((AnnotationTypeMemberDeclaration) decl);
        }
      }
      printAnnotationProperties(members);
      if (!members.isEmpty()) {
        printAnnotationConstructor(Types.getTypeBinding(node));
      }
      printAnnotationAccessors(members);
    }
    List<FieldDeclaration> fields = ASTUtil.getFieldDeclarations(node);
    List<IVariableBinding> fieldsNeedingAccessors =
        getStaticFieldsNeedingAccessors(fields, /* isInterface */ true);
    printStaticVars(fields, /* isInterface */ true);
    printStaticFieldAccessors(fieldsNeedingAccessors, Collections.<MethodDeclaration>emptyList());
    println("- (IOSClass *)annotationType {");
    printf("  return [IOSClass classWithProtocol:@protocol(%s)];\n", typeName);
    println("}\n");
    if (!Options.stripReflection()) {
      printTypeAnnotationsMethod(node);
      printMetadata(node);
    }
    println("@end\n");
  }
Beispiel #4
0
  /**
   * Adds a cast check to compareTo methods. This helps Comparable types behave well in sorted
   * collections which rely on Java's runtime type checking.
   */
  @Override
  public void endVisit(MethodDeclaration node) {
    IMethodBinding binding = node.getMethodBinding();
    if (!binding.getName().equals("compareTo") || node.getBody() == null) {
      return;
    }
    ITypeBinding comparableType =
        BindingUtil.findInterface(binding.getDeclaringClass(), "java.lang.Comparable");
    if (comparableType == null) {
      return;
    }
    ITypeBinding[] typeArguments = comparableType.getTypeArguments();
    ITypeBinding[] parameterTypes = binding.getParameterTypes();
    if (typeArguments.length != 1
        || parameterTypes.length != 1
        || !typeArguments[0].isEqualTo(parameterTypes[0])) {
      return;
    }

    IVariableBinding param = node.getParameters().get(0).getVariableBinding();

    FunctionInvocation castCheck = createCastCheck(typeArguments[0], new SimpleName(param));
    if (castCheck != null) {
      node.getBody().getStatements().add(0, new ExpressionStatement(castCheck));
    }
  }
Beispiel #5
0
 private void initializeCommonJavaTypes() {
   ITypeBinding charSequence = BindingUtil.findInterface(javaStringType, "java.lang.CharSequence");
   javaBindingMap.put("java.lang.CharSequence", charSequence);
   iosBindingMap.put("JavaLangCharSequence", charSequence);
   javaBindingMap.put("java.lang.Number", javaNumberType);
   javaBindingMap.put("java.lang.Throwable", javaThrowableType);
 }
Beispiel #6
0
 private List<Statement> getFieldAdjustments(TypeDeclaration node) {
   List<Statement> adjustments = Lists.newArrayList();
   for (VariableDeclarationFragment decl : TreeUtil.getAllFields(node)) {
     IVariableBinding var = decl.getVariableBinding();
     if (BindingUtil.isStatic(var) || var.getType().isPrimitive()) {
       continue;
     }
     boolean isWeak = BindingUtil.isWeakReference(var);
     boolean isVolatile = BindingUtil.isVolatile(var);
     if (isWeak && !isVolatile) {
       adjustments.add(createReleaseStatement(var));
     } else if (!isWeak && isVolatile) {
       adjustments.add(createVolatileRetainStatement(var));
     }
   }
   return adjustments;
 }
 @Override
 protected void printStaticFieldGetter(IVariableBinding var) {
   String name =
       BindingUtil.isPrimitiveConstant(var)
           ? NameTable.getPrimitiveConstantName(var)
           : NameTable.getStaticVarQualifiedName(var);
   printf("%s {\n  return %s;\n}\n\n", staticFieldGetterSignature(var), name);
 }
Beispiel #8
0
 @Override
 public void endVisit(MethodInvocation node) {
   IMethodBinding binding = node.getMethodBinding();
   Expression receiver = node.getExpression();
   if (receiver != null && !BindingUtil.isStatic(binding)) {
     maybeAddCast(receiver, null, true);
   }
   maybeCastArguments(node.getArguments(), binding);
   if (returnValueNeedsIntCast(node)) {
     addCast(node);
   }
 }
  public void testCapturedWeakLocalVariable() {
    resolveSource(
        "Test",
        "import com.google.j2objc.annotations.Weak;"
            + "class Test { void test(@Weak final int i) { Runnable r = new Runnable() { "
            + "public void run() { int i2 = i + 1; } }; } }");

    AnonymousClassDeclaration runnableNode =
        (AnonymousClassDeclaration) nodesByType.get(ASTNode.ANONYMOUS_CLASS_DECLARATION).get(0);
    ITypeBinding runnableBinding = runnableNode.resolveBinding();
    List<IVariableBinding> innerFields = OuterReferenceResolver.getInnerFields(runnableBinding);
    assertEquals(1, innerFields.size());
    assertTrue(BindingUtil.isWeakReference(innerFields.get(0)));
  }
 // Prints an annotation's values as a constructor argument list. If
 // the annotation type declares default values, then for any value that
 // isn't specified in the annotation will use the default.
 private void printAnnotationParameters(Annotation annotation) {
   IAnnotationBinding binding = Types.getAnnotationBinding(annotation);
   IMemberValuePairBinding[] valueBindings = BindingUtil.getSortedMemberValuePairs(binding);
   for (int i = 0; i < valueBindings.length; i++) {
     if (i > 0) {
       print(' ');
     }
     IMemberValuePairBinding valueBinding = valueBindings[i];
     print(i == 0 ? "With" : "with");
     printf("%s:", NameTable.capitalize(valueBinding.getName()));
     Object value = valueBinding.getValue();
     printAnnotationValue(annotation.getAST(), value);
   }
 }
Beispiel #11
0
 /**
  * Returns true if the specified binding is of an annotation that has a runtime retention policy.
  */
 public static boolean isRuntimeAnnotation(ITypeBinding binding) {
   if (binding != null && binding.isAnnotation()) {
     for (IAnnotationBinding ann : binding.getAnnotations()) {
       if (ann.getName().equals("Retention")) {
         IVariableBinding retentionBinding =
             (IVariableBinding) ann.getDeclaredMemberValuePairs()[0].getValue();
         return retentionBinding.getName().equals(RetentionPolicy.RUNTIME.name());
       }
     }
     if (binding.isNested()) {
       return BindingUtil.isRuntimeAnnotation(binding.getDeclaringClass());
     }
   }
   return false;
 }
  private void printMethodsAndOcni(
      AbstractTypeDeclaration typeNode,
      Iterable<MethodDeclaration> methods,
      Iterable<Comment> comments) {
    Set<String> methodsPrinted = Sets.newHashSet();
    Iterator<MethodDeclaration> methodsIter = methods.iterator();
    Iterator<Comment> commentsIter = comments.iterator();
    MethodDeclaration nextMethod = methodsIter.hasNext() ? methodsIter.next() : null;
    Comment nextComment = commentsIter.hasNext() ? commentsIter.next() : null;
    int minPos = 0;
    while (nextMethod != null || nextComment != null) {
      int methodStartPos = nextMethod != null ? nextMethod.getStartPosition() : Integer.MAX_VALUE;
      if (methodStartPos < 0) {
        methodStartPos = minPos;
      }
      int commentStartPos =
          nextComment != null ? nextComment.getStartPosition() : Integer.MAX_VALUE;
      if (methodStartPos < commentStartPos) {
        assert nextMethod != null;
        printMethod(nextMethod);
        minPos = methodStartPos + nextMethod.getLength();
        nextMethod = methodsIter.hasNext() ? methodsIter.next() : null;
      } else {
        assert nextComment != null;
        if (commentStartPos > minPos) {
          String nativeCode = extractNativeCode(commentStartPos, nextComment.getLength());
          if (nativeCode != null) {
            nativeCode = reindent(nativeCode.trim());
            findMethodSignatures(nativeCode, methodsPrinted);
            print(nativeCode + "\n\n");
          }
        }
        nextComment = commentsIter.hasNext() ? commentsIter.next() : null;
      }
    }

    // If the type implements Iterable and there's no existing implementation
    // for NSFastEnumeration's protocol method, then add the default
    // implementation.
    if (BindingUtil.findInterface(Types.getTypeBinding(typeNode), "java.lang.Iterable") != null
        && !methodsPrinted.contains("countByEnumeratingWithState:objects:count:")) {
      print(
          "- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state "
              + "objects:(__unsafe_unretained id *)stackbuf count:(NSUInteger)len {\n"
              + "  return JreDefaultFastEnumeration(self, state, stackbuf, len);\n}\n\n");
    }
  }
Beispiel #13
0
  @Override
  public void endVisit(CastExpression node) {
    ITypeBinding type = node.getType().getTypeBinding();
    Expression expr = node.getExpression();
    ITypeBinding exprType = expr.getTypeBinding();

    // TODO(kirbs): Implement correct conversion of Java 8 intersection types to Objective-C.
    if (node.getType().isIntersectionType() && !Options.isJava8Translator()) {
      // Technically we can't currently get here, but as we add support and change flags in the
      // future this should alert us to implement intersection types.
      assert false : "not implemented yet";
    }

    if (BindingUtil.isFloatingPoint(exprType)) {
      assert type.isPrimitive(); // Java wouldn't allow a cast from primitive to non-primitive.
      switch (type.getBinaryName().charAt(0)) {
        case 'J':
          node.replaceWith(rewriteFloatToIntegralCast(type, expr, "JreFpToLong", type));
          return;
        case 'C':
          node.replaceWith(rewriteFloatToIntegralCast(type, expr, "JreFpToChar", type));
          return;
        case 'B':
        case 'S':
        case 'I':
          node.replaceWith(
              rewriteFloatToIntegralCast(type, expr, "JreFpToInt", typeEnv.resolveJavaType("int")));
          return;
      }
      // else fall-through.
    }

    // Lean on Java's type-checking.
    if (!type.isPrimitive() && exprType.isAssignmentCompatible(type.getErasure())) {
      node.replaceWith(TreeUtil.remove(expr));
      return;
    }

    FunctionInvocation castCheck = createCastCheck(type, expr);
    if (castCheck != null) {
      node.setExpression(castCheck);
    }
  }
 private void printStaticVars(List<FieldDeclaration> fields, boolean isInterface) {
   boolean hadStaticVar = false;
   for (FieldDeclaration f : fields) {
     if (Modifier.isStatic(f.getModifiers()) || isInterface) {
       for (VariableDeclarationFragment var : ASTUtil.getFragments(f)) {
         IVariableBinding binding = Types.getVariableBinding(var);
         if (!BindingUtil.isPrimitiveConstant(binding)) {
           String name = NameTable.getStaticVarQualifiedName(binding);
           String objcType = NameTable.getObjCType(binding.getType());
           Expression initializer = var.getInitializer();
           if (initializer != null) {
             printf("static %s %s = %s;\n", objcType, name, generateExpression(initializer));
           } else {
             printf("static %s %s;\n", objcType, name);
           }
           hadStaticVar = true;
         }
       }
     }
   }
   if (hadStaticVar) {
     newline();
   }
 }
Beispiel #15
0
 public boolean apply(Annotation annotation) {
   return BindingUtil.isRuntimeAnnotation(annotation.getAnnotationBinding());
 }
Beispiel #16
0
 /** Locate method which matches the Java/Objective C setter name pattern. */
 public static IMethodBinding findSetterMethod(String propertyName, ITypeBinding declaringClass) {
   return BindingUtil.findDeclaredMethod(
       declaringClass, "set" + NameTable.capitalize(propertyName));
 }
 // Returns whether the property is a strong reference.
 private boolean isStrongReferenceProperty(VariableDeclarationFragment property) {
   IVariableBinding varBinding = Types.getVariableBinding(property);
   ITypeBinding type = Types.getTypeBinding(property);
   return !type.isPrimitive() && !BindingUtil.isWeakReference(varBinding);
 }