@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");
  }
 private Statement createInnerConstructorInvocation(MethodDeclaration m) {
   ConstructorInvocation invocation = m.getAST().newConstructorInvocation();
   Types.addBinding(invocation, Types.getBinding(m));
   for (SingleVariableDeclaration param : ASTUtil.getParameters(m)) {
     SimpleName paramName = param.getName();
     IVariableBinding paramBinding = Types.getVariableBinding(paramName);
     SimpleName argName = m.getAST().newSimpleName(paramName.getIdentifier());
     Types.addBinding(argName, paramBinding);
     ASTUtil.getArguments(invocation).add(argName);
   }
   return invocation;
 }
  private String generateMethodBody(MethodDeclaration m) {
    String methodBody;
    if (Modifier.isNative(m.getModifiers())) {
      if (hasNativeCode(m, true)) {
        methodBody = extractNativeMethodBody(m);
      } else if (Options.generateNativeStubs()) {
        return generateNativeStub(m);
      } else {
        return null;
      }
    } else if (Modifier.isAbstract(m.getModifiers())) {
      // Generate a body which throws a NSInvalidArgumentException.
      String body =
          "{\n // can't call an abstract method\n " + "[self doesNotRecognizeSelector:_cmd];\n ";
      if (!Types.isVoidType(m.getReturnType2())) {
        body += "return 0;\n"; // Never executes, but avoids a gcc warning.
      }
      return body + "}";
    } else {
      // generate a normal method body
      methodBody = generateStatement(m.getBody(), false);
    }

    boolean isStatic = (m.getModifiers() & Modifier.STATIC) != 0;
    boolean isSynchronized = (m.getModifiers() & Modifier.SYNCHRONIZED) != 0;
    if (isStatic && isSynchronized) {
      methodBody = "{\n@synchronized([self class]) {\n" + methodBody + "}\n}\n";
    } else if (isSynchronized) {
      methodBody = "{\n@synchronized(self) {\n" + methodBody + "}\n}\n";
    }

    return methodBody;
  }
Example #4
0
  public IOSMethod(String s, IMethodBinding binding, ITypeBinding returnType, AST ast) {
    if (s.endsWith(";")) {
      s = s.substring(0, s.length() - 1);
    }
    int i = s.indexOf(' ');
    String className = s.substring(0, i);
    IOSTypeBinding clazz = Types.resolveIOSType(className);
    if (clazz == null) {
      clazz = new IOSTypeBinding(className, false);
    }
    declaringClass = clazz.getName();
    s = s.substring(i + 1);

    parameters = Lists.newArrayList();
    i = s.indexOf(':');
    if (i > 0) { // if there are parameters
      name = s.substring(0, i);
      String[] argDefs = splitParameterString(s);
      for (i = 0; i < argDefs.length; i++) {
        IOSParameter param = new IOSParameter(argDefs[i], i, ast);
        parameters.add(param);
        if (param.isVarArgs()) {
          varArgs = true;
          break;
        }
      }
    } else {
      name = s;
    }
    this.binding = new IOSMethodBinding(name, binding, clazz, returnType, varArgs);
  }
 @Override
 protected void printStaticConstructorDeclaration(MethodDeclaration m) {
   String className = NameTable.getFullName(Types.getMethodBinding(m).getDeclaringClass());
   StringBuffer sb = new StringBuffer();
   sb.append("{\nif (self == [" + className + " class]) {\n");
   for (Statement statement : ASTUtil.getStatements(m.getBody())) {
     sb.append(generateStatement(statement, false));
   }
   sb.append("}\n}");
   print("+ (void)initialize " + reindent(sb.toString()) + "\n\n");
 }
 private void printMethodAnnotationMethods(List<MethodDeclaration> methods) {
   for (MethodDeclaration method : methods) {
     List<Annotation> runtimeAnnotations =
         ASTUtil.getRuntimeAnnotations(ASTUtil.getModifiers(method));
     if (runtimeAnnotations.size() > 0) {
       printf(
           "+ (IOSObjectArray *)__annotations_%s {\n", methodKey(Types.getMethodBinding(method)));
       printAnnotationCreate(runtimeAnnotations);
     }
     printParameterAnnotationMethods(method);
   }
 }
 // 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);
   }
 }
  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");
    }
  }
 @Override
 protected String constructorDeclaration(MethodDeclaration m) {
   String methodBody;
   IMethodBinding binding = Types.getMethodBinding(m);
   boolean memDebug = Options.memoryDebug();
   List<Statement> statements = ASTUtil.getStatements(m.getBody());
   if (binding.getDeclaringClass().isEnum()) {
     return enumConstructorDeclaration(m, statements, binding);
   }
   StringBuffer sb = new StringBuffer("{\n");
   int constructorIdx = findConstructorInvocation(statements);
   int idx = 0;
   while (idx < constructorIdx) {
     sb.append(generateStatement(statements.get(idx++), false));
   }
   String superCall =
       idx == constructorIdx ? generateStatement(statements.get(idx++), false) : "[super init]";
   if (idx >= statements.size()) {
     sb.append("return ");
     if (memDebug) {
       sb.append("JreMemDebugAdd(");
     }
     sb.append(superCall).append(memDebug ? ");\n}" : ";\n}");
   } else {
     sb.append("if (self = ").append(superCall).append(") {\n");
     while (idx < statements.size()) {
       sb.append(generateStatement(statements.get(idx++), false));
     }
     if (memDebug) {
       sb.append("JreMemDebugAdd(self);\n");
     }
     sb.append("}\nreturn self;\n}");
   }
   methodBody = sb.toString();
   if (invokedConstructors.contains(methodKey(binding))) {
     return super.constructorDeclaration(m, true)
         + " "
         + reindent(methodBody)
         + "\n\n"
         + super.constructorDeclaration(m, false)
         + " {\n  return "
         + generateStatement(createInnerConstructorInvocation(m), false)
         + ";\n}\n\n";
   } else {
     return super.constructorDeclaration(m, false) + " " + reindent(methodBody) + "\n\n";
   }
 }
  private void printParameterAnnotationMethods(MethodDeclaration method) {
    List<SingleVariableDeclaration> params = ASTUtil.getParameters(method);

    // Quick test to see if there are any parameter annotations.
    boolean hasAnnotations = false;
    for (SingleVariableDeclaration param : params) {
      List<Annotation> runtimeAnnotations =
          ASTUtil.getRuntimeAnnotations(ASTUtil.getModifiers(param));
      if (runtimeAnnotations.size() > 0) {
        hasAnnotations = true;
        break;
      }
    }

    if (hasAnnotations) {
      // Print array of arrays, with an element in the outer array for each parameter.
      printf(
          "+ (IOSObjectArray *)__annotations_%s_params {\n",
          methodKey(Types.getMethodBinding(method)));
      print("  return [IOSObjectArray arrayWithObjects:(id[]) { ");
      for (int i = 0; i < params.size(); i++) {
        if (i > 0) {
          print(", ");
        }
        SingleVariableDeclaration param = params.get(i);
        List<Annotation> runtimeAnnotations =
            ASTUtil.getRuntimeAnnotations(ASTUtil.getModifiers(param));
        if (runtimeAnnotations.size() > 0) {
          print("[IOSObjectArray arrayWithObjects:(id[]) { ");
          printAnnotations(runtimeAnnotations);
          printf(
              " } count:%d type:[IOSClass classWithProtocol:"
                  + "@protocol(JavaLangAnnotationAnnotation)]]",
              runtimeAnnotations.size());
        } else {
          print(
              "[IOSObjectArray arrayWithLength:0 "
                  + "type:[IOSClass classWithProtocol:@protocol(JavaLangAnnotationAnnotation)]]");
        }
      }
      printf(
          " } count:%d type:[IOSClass classWithProtocol:"
              + "@protocol(JavaLangAnnotationAnnotation)]];\n}\n",
          params.size());
    }
  }
  private void printMethods(TypeDeclaration node) {
    printMethodsAndOcni(node, Arrays.asList(node.getMethods()), blockComments.get(node));

    // If node implements CharSequence, add forwarding method from the
    // sequenceDescription method to description (toString()).  See
    // JavaToIOSMethodTranslator.loadCharSequenceMethods() for details.
    ITypeBinding binding = Types.getTypeBinding(node);
    for (ITypeBinding interfaze : binding.getInterfaces()) {
      if (interfaze.getQualifiedName().equals("java.lang.CharSequence")) {
        println("- (NSString *)description {\n  return [self sequenceDescription];\n}\n");
      }
    }

    List<VariableDeclarationFragment> properties = getProperties(node.getFields());
    if (properties.size() > 0) {
      printStrongReferencesMethod(properties);
    }
  }
 private void printAnnotationAccessors(List<AnnotationTypeMemberDeclaration> members) {
   int nPrinted = 0;
   for (AnnotationTypeMemberDeclaration member : members) {
     Expression deflt = member.getDefault();
     if (deflt != null) {
       ITypeBinding type = Types.getTypeBinding(member.getType());
       String typeString = NameTable.getSpecificObjCType(type);
       String propertyName = NameTable.getName(member.getName());
       printf("+ (%s)%sDefault {\n", typeString, propertyName);
       printf("  return %s;\n", generateExpression(deflt));
       println("}\n");
       nPrinted++;
     }
   }
   if (nPrinted > 0) {
     newline();
   }
 }
 private void printAnnotations(List<Annotation> runtimeAnnotations) {
   boolean first = true;
   for (Annotation annotation : runtimeAnnotations) {
     if (first) {
       first = false;
     } else {
       print(", ");
     }
     if (Options.useReferenceCounting()) {
       print('[');
     }
     printf("[[%s alloc] init", NameTable.getFullName(Types.getTypeBinding(annotation)));
     printAnnotationParameters(annotation);
     print(']');
     if (Options.useReferenceCounting()) {
       print(" autorelease]");
     }
   }
 }
Example #14
0
  /** Verifies that abstract methods to implement an interface are added to an abstract class. */
  public void testAbstractMethodsAdded() {
    String source =
        "import java.util.Iterator; public abstract class Test implements Iterator<Test> { "
            + "public boolean hasNext() { return true; } }";
    CompilationUnit unit = translateType("Test", source);
    List<AbstractTypeDeclaration> types = unit.getTypes();
    assertEquals(1, types.size());
    assertTrue(types.get(0) instanceof TypeDeclaration);
    TypeDeclaration testType = (TypeDeclaration) types.get(0);
    List<MethodDeclaration> methods = TreeUtil.getMethodDeclarationsList(testType);
    assertEquals(4, methods.size());

    // verify added methods are abstract, and that existing method wasn't changed
    for (MethodDeclaration m : methods) {
      int modifiers = m.getModifiers();
      String name = m.getName().getIdentifier();
      if (name.equals("hasNext")) {
        assertFalse(Modifier.isAbstract(modifiers));
      } else if (name.equals(NameTable.FINALIZE_METHOD)
          || name.equals(NameTable.DEALLOC_METHOD)
          || name.equals(NameTable.INIT_NAME)) {
        // it's ok.
      } else {
        // it's an added method
        assertTrue(Modifier.isAbstract(modifiers));
        assertEquals(0, m.getParameters().size());
        if (name.equals("next")) {
          assertEquals(testType.getTypeBinding(), m.getReturnType().getTypeBinding());
        } else if (name.equals("remove")) {
          ITypeBinding voidType = Types.resolveJavaType("void");
          assertEquals(voidType, m.getReturnType().getTypeBinding());
        } else {
          fail("unknown method added: " + name);
        }
      }
    }
  }
 // We generate the runtime debug method +memDebugStaticReferences.
 // This method will return an array of NSNumber containing pointers (casted into unsigned long)
 // to the objects referenced by a class variable with a strong reference.
 // It will be useful for debug purpose.
 //
 // Arrays returned by -memDebugStaticReferences and -memDebugStaticReferencesNames (see below)
 // must be the same size.
 //
 // In case of a Java enum, valuesVarNameis the name of the array of enum values.
 private void printStaticReferencesMethod(List<FieldDeclaration> fields, String valuesVarName) {
   if (Options.memoryDebug()) {
     if (!Options.useReferenceCounting()) {
       println("+ (NSArray *)memDebugStaticReferences {");
       println("  return nil;");
       println("}");
       return;
     }
     println("+ (NSArray *)memDebugStaticReferences {");
     println("  NSMutableArray *result = [NSMutableArray array];");
     for (FieldDeclaration f : fields) {
       if (Modifier.isStatic(f.getModifiers())) {
         for (VariableDeclarationFragment var : ASTUtil.getFragments(f)) {
           IVariableBinding binding = Types.getVariableBinding(var);
           // All non-primitive static variables are strong references.
           if (!binding.getType().isPrimitive()) {
             String name = NameTable.getStaticVarQualifiedName(binding);
             println(
                 String.format(
                     "  [result addObject:[JreMemDebugStrongReference "
                         + "strongReferenceWithObject:%s name:@\"%s\"]];",
                     name, name));
           }
         }
       }
     }
     if (valuesVarName != null) {
       println(
           String.format(
               "  [result addObject:[JreMemDebugStrongReference "
                   + "strongReferenceWithObject:%s name:@\"enumValues\"]];",
               valuesVarName));
     }
     println("  return result;");
     println("}\n");
   }
 }
 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();
   }
 }
Example #17
0
 public NullLiteral() {
   super(Types.resolveJavaType("java.lang.Object"));
 }
 // 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);
 }
  @Override
  protected void generate(EnumDeclaration node) {
    List<EnumConstantDeclaration> constants = ASTUtil.getEnumConstants(node);
    List<MethodDeclaration> methods = Lists.newArrayList();
    List<FieldDeclaration> fields = Lists.newArrayList();
    MethodDeclaration initializeMethod = null;
    for (BodyDeclaration decl : ASTUtil.getBodyDeclarations(node)) {
      if (decl instanceof FieldDeclaration) {
        fields.add((FieldDeclaration) decl);
      } else if (decl instanceof MethodDeclaration) {
        MethodDeclaration md = (MethodDeclaration) decl;
        if (md.getName().getIdentifier().equals("initialize")) {
          initializeMethod = md;
        } else {
          methods.add(md);
        }
      }
    }
    syncLineNumbers(node.getName()); // avoid doc-comment

    String typeName = NameTable.getFullName(node);
    newline();
    for (EnumConstantDeclaration constant : constants) {
      IVariableBinding var = Types.getVariableBinding(constant.getName());
      printf("static %s *%s;\n", typeName, NameTable.getStaticVarQualifiedName(var));
    }
    printf("IOSObjectArray *%s_values;\n", typeName);
    newline();

    printf("@implementation %s\n\n", typeName);
    printStaticVars(fields, /* isInterface */ false);
    printStaticReferencesMethod(fields, typeName + "_values");

    for (EnumConstantDeclaration constant : constants) {
      String name = NameTable.getName(constant.getName());
      printf("+ (%s *)%s {\n", typeName, name);
      printf("  return %s_%s;\n", typeName, name);
      println("}");
    }
    newline();

    // Enum constants needs to implement NSCopying.  Being singletons, they
    // can just return self, as long the retain count is incremented.
    String selfString = Options.useReferenceCounting() ? "[self retain]" : "self";
    printf("- (id)copyWithZone:(NSZone *)zone {\n  return %s;\n}\n\n", selfString);

    printStaticFieldAccessors(fields, methods, /* isInterface */ false);
    printMethodsAndOcni(node, methods, blockComments.get(node));

    printf("+ (void)initialize {\n  if (self == [%s class]) {\n", typeName);
    for (int i = 0; i < constants.size(); i++) {
      EnumConstantDeclaration constant = constants.get(i);
      List<Expression> args = ASTUtil.getArguments(constant);
      String name = NameTable.getName(constant.getName());
      String constantTypeName =
          NameTable.getFullName(Types.getMethodBinding(constant).getDeclaringClass());
      printf("    %s_%s = [[%s alloc] init", typeName, name, constantTypeName);

      if (args.isEmpty()) {
        print("With");
      } else {
        print(
            StatementGenerator.generateArguments(
                Types.getMethodBinding(constant),
                args,
                fieldHiders,
                getBuilder().getSourcePosition()));
        print(" with");
      }
      printf("NSString:@\"%s\" withInt:%d];\n", name, i);
    }
    printf("    %s_values = [[IOSObjectArray alloc] initWithObjects:(id[]){ ", typeName);
    for (EnumConstantDeclaration constant : constants) {
      printf("%s_%s, ", typeName, NameTable.getName(constant.getName()));
    }
    printf(
        "nil } count:%d type:[IOSClass classWithClass:[%s class]]];\n", constants.size(), typeName);
    if (initializeMethod != null) {
      for (Statement s : ASTUtil.getStatements(initializeMethod.getBody())) {
        printf(
            "    %s",
            StatementGenerator.generate(s, fieldHiders, false, getBuilder().getSourcePosition()));
      }
    }
    println("  }\n}\n");

    // Print generated values and valueOf methods.
    println("+ (IOSObjectArray *)values {");
    printf("  return [IOSObjectArray arrayWithArray:%s_values];\n", typeName);
    println("}\n");
    printf("+ (%s *)valueOfWithNSString:(NSString *)name {\n", typeName);
    printf("  for (int i = 0; i < [%s_values count]; i++) {\n", typeName);
    printf("    %s *e = %s_values->buffer_[i];\n", typeName, typeName);
    printf("    if ([name isEqual:[e name]]) {\n");
    printf("      return e;\n");
    printf("    }\n");
    printf("  }\n");
    if (Options.useReferenceCounting()) {
      printf(
          "  @throw [[[JavaLangIllegalArgumentException alloc] initWithNSString:name]"
              + " autorelease];\n");
    } else {
      printf("  @throw [[JavaLangIllegalArgumentException alloc] initWithNSString:name];\n");
    }
    printf("  return nil;\n");
    println("}\n");

    if (!Options.stripReflection()) {
      printTypeAnnotationsMethod(node);
      printMetadata(node);
    }
    println("@end");
  }
 private String generateNativeStub(MethodDeclaration m) {
   IMethodBinding binding = Types.getMethodBinding(m);
   String methodName = NameTable.getName(binding);
   return String.format("{\n  @throw \"%s method not implemented\";\n}", methodName);
 }
 @Override
 protected String getParameterName(SingleVariableDeclaration param) {
   String name = super.getParameterName(param);
   IVariableBinding binding = Types.getVariableBinding(param);
   return binding != null && fieldHiders.contains(binding) ? name + "Arg" : name;
 }