// We generate the runtime debug method -memDebugStrongReferences.
 // This method will return an array of information about a strong reference,
 // including pointer to object and name.
 private void printStrongReferencesMethod(List<VariableDeclarationFragment> properties) {
   if (Options.memoryDebug()) {
     if (!Options.useReferenceCounting()) {
       println("- (NSArray *)memDebugStrongReferences {");
       println("  return nil;");
       println("}");
       return;
     }
     println("- (NSArray *)memDebugStrongReferences {");
     println("  NSMutableArray *result =");
     println("      [[[super memDebugStrongReferences] mutableCopy] autorelease];");
     for (VariableDeclarationFragment property : properties) {
       String propName = NameTable.getName(property.getName());
       String objCFieldName = NameTable.javaFieldToObjC(propName);
       if (isStrongReferenceProperty(property)) {
         println(
             String.format(
                 "  [result addObject:[JreMemDebugStrongReference "
                     + "strongReferenceWithObject:%s name:@\"%s\"]];",
                 objCFieldName, propName));
       }
     }
     println("  return result;");
     println("}\n");
   }
 }
  public void testCombinedJarHeaderMapping() throws IOException {
    File outputHeaderMappingFile = new File(tempDir, "mappings.j2objc");
    Options.setOutputHeaderMappingFile(outputHeaderMappingFile);
    Options.setOutputStyle(Options.OutputStyleOption.SOURCE);
    addSourceFile("package unit; public class Test { }", "unit/Test.java");
    addSourceFile(
        "package unit; public class AnotherTest extends Test { }", "unit/AnotherTest.java");
    addSourceFile(
        "package unit2;" + "import unit.Test;" + "public class AnotherTest extends Test { }",
        "unit2/AnotherTest.java");
    addSourceFile(
        "package unit2;"
            + "import unit.AnotherTest;"
            + "public class YetAnotherTest extends AnotherTest { }",
        "unit2/YetAnotherTest.java");

    translateCombinedFiles("unit/Foo", ".h", "unit/Test.java", "unit/AnotherTest.java");
    String header2 =
        translateCombinedFiles(
            "unit2/Foo", ".h", "unit2/AnotherTest.java", "unit2/YetAnotherTest.java");

    HeaderMap headerMap = Options.getHeaderMap();
    assertEquals("unit/Foo.h", headerMap.get("unit.Test"));
    assertEquals("unit/Foo.h", headerMap.get("unit.AnotherTest"));
    assertTranslation(header2, "#include \"unit/Foo.h\"");
    assertEquals("unit2/Foo.h", headerMap.get("unit2.AnotherTest"));
    assertEquals("unit2/Foo.h", headerMap.get("unit2.YetAnotherTest"));
  }
 private void printStaticInterface(
     AbstractTypeDeclaration node,
     String typeName,
     List<FieldDeclaration> fields,
     List<MethodDeclaration> methods) {
   List<IVariableBinding> staticFields =
       getStaticFieldsNeedingAccessors(fields, /* isInterface */ true);
   if (staticFields.isEmpty()) {
     if (!Options.stripReflection()) {
       printf("\n@interface %s : NSObject\n@end\n", typeName);
     } else {
       return;
     }
   }
   printf("\n@implementation %s\n\n", typeName);
   printStaticVars(fields, /* isInterface */ true);
   printStaticFieldAccessors(staticFields, methods);
   for (MethodDeclaration method : methods) {
     if (method.getBody() != null) {
       printNormalMethod(method);
     }
   }
   if (!Options.stripReflection()) {
     printMetadata(node);
   }
   println("@end");
 }
  public void testOutputHeaderFileMapping() throws IOException {
    Options.setHeaderMappingFiles(Lists.newArrayList("testMappings.j2objc"));
    Options.setOutputStyle(Options.OutputStyleOption.SOURCE);
    addSourceFile("package unit.test; public class Dummy {}", "unit/test/Dummy.java");
    addSourceFile(
        "package unit.test;"
            + "public class AnotherDummy extends Dummy { "
            + "    public AnotherDummy() {}"
            + "}",
        "unit/test/AnotherDummy.java");

    preprocessFiles("unit/test/Dummy.java", "unit/test/AnotherDummy.java");
    loadHeaderMappings();

    String translation =
        translateSourceFile(
            getTranslatedFile("unit/test/AnotherDummy.java"), "AnotherDummy", "AnotherDummy.h");
    assertTranslation(translation, "#include \"unit/test/Dummy.h\"");

    HeaderMap headerMap = Options.getHeaderMap();
    assertEquals(headerMap.get("unit.test.Dummy"), "unit/test/Dummy.h");
    assertEquals(headerMap.get("unit.test.AnotherDummy"), "unit/test/AnotherDummy.h");
    assertEquals(headerMap.get("unit.mapping.custom.Test"), "my/mapping/custom/Test.h");
    assertEquals(headerMap.get("unit.mapping.custom.AnotherTest"), "my/mapping/custom/Test.h");
  }
Пример #5
0
 public FileProcessor(JdtParser parser) {
   this.parser = Preconditions.checkNotNull(parser);
   if (Options.buildClosure()) {
     // Should be an error if the user specifies this with --build-closure
     assert !Options.shouldMapHeaders();
     closureQueue = new BuildClosureQueue();
   } else {
     closureQueue = null;
   }
 }
  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;
  }
 public void testFullyQualifiedDeprecatedTypeNameTranslation() throws IOException {
   Options.enableDeprecatedDeclarations();
   String translation =
       translateSourceFile(
           "public @java.lang.Deprecated class Example {}", "Example", "Example.h");
   assertTranslation(translation, "__attribute__((deprecated))\n@interface Example ");
 }
  @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");
  }
  @Override
  public void generate(TypeDeclaration node) {
    syncLineNumbers(node.getName()); // avoid doc-comment

    String typeName = NameTable.getFullName(node);
    List<FieldDeclaration> fields = Lists.newArrayList(node.getFields());
    List<MethodDeclaration> methods = Lists.newArrayList(node.getMethods());
    fieldHiders = HiddenFieldDetector.getFieldNameConflicts(node);
    if (node.isInterface()) {
      printStaticInterface(node, typeName, fields, methods);
    } else {
      printf("@implementation %s\n\n", typeName);
      printStaticReferencesMethod(fields);
      printStaticVars(fields, /* isInterface */ false);
      printStaticFieldAccessors(fields, methods, /* isInterface */ false);
      printMethods(node);
      if (!Options.stripReflection()) {
        printTypeAnnotationsMethod(node);
        printMethodAnnotationMethods(Lists.newArrayList(node.getMethods()));
        printFieldAnnotationMethods(Lists.newArrayList(node.getFields()));
        printMetadata(node);
      }

      println("@end");
    }
  }
 public void testDeprecatedInterfaceTranslation() throws IOException {
   Options.enableDeprecatedDeclarations();
   String translation =
       translateSourceFile(
           "package unit.test; public @Deprecated interface Example {}",
           "Example",
           "unit/test/Example.h");
   assertTranslation(translation, "__attribute__((deprecated))\n@protocol UnitTestExample");
 }
 public void testInterfaceWithDeprecatedMethodTranslation() throws IOException {
   Options.enableDeprecatedDeclarations();
   String translation =
       translateSourceFile(
           "package unit.test; public interface Example { @Deprecated Example getExample(); }",
           "Example",
           "unit/test/Example.h");
   assertTranslation(
       translation, "- (id<UnitTestExample>)getExample __attribute__((deprecated));");
 }
 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]");
     }
   }
 }
  public void testAddIgnoreDeprecationWarningsPragmaIfDeprecatedDeclarationsIsEnabled()
      throws IOException {
    Options.enableDeprecatedDeclarations();

    String sourceContent = "class Test {}";
    String translation = translateSourceFile(sourceContent, "FooBar", "FooBar.h");

    assertTranslation(translation, "#pragma clang diagnostic push");
    assertTranslation(translation, "#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"");
    assertTranslation(translation, "#pragma clang diagnostic pop");
  }
 public void testNoHeaderMapping() throws IOException {
   // Should be able to turn off header mappings by passing empty collection
   Options.setHeaderMappingFiles(Collections.<String>emptyList());
   addSourceFile("package unit.mapping; public class Test { }", "unit/mapping/Test.java");
   loadHeaderMappings();
   String translation =
       translateSourceFile(
           "import unit.mapping.Test; " + "public class MyTest extends Test { MyTest() {}}",
           "MyTest",
           "MyTest.h");
   assertTranslation(translation, "#include \"unit/mapping/Test.h\"");
 }
 public void testHeaderFileMapping() throws IOException {
   Options.setHeaderMappingFiles(Lists.newArrayList("testMappings.j2objc"));
   addSourceFile(
       "package unit.mapping.custom; public class Test { }", "unit/mapping/custom/Test.java");
   loadHeaderMappings();
   String translation =
       translateSourceFile(
           "import unit.mapping.custom.Test; " + "public class MyTest extends Test { MyTest() {}}",
           "MyTest",
           "MyTest.h");
   assertTranslation(translation, "#include \"my/mapping/custom/Test.h\"");
 }
Пример #16
0
 private Statement createReleaseStatement(IVariableBinding var) {
   if (Options.useARC()) {
     ITypeBinding voidType = typeEnv.resolveJavaType("void");
     FunctionInvocation invocation =
         new FunctionInvocation("JreRelease", voidType, voidType, null);
     invocation.getArguments().add(new SimpleName(var));
     return new ExpressionStatement(invocation);
   } else {
     return new ExpressionStatement(
         new MethodInvocation(typeEnv.getReleaseMethod(), new SimpleName(var)));
   }
 }
Пример #17
0
 /** Verify fields are released in a dealloc for reference counted code. */
 public void testFieldReleaseReferenceCounting() throws IOException {
   Options.setMemoryManagementOption(Options.MemoryManagementOption.REFERENCE_COUNTING);
   String translation =
       translateSourceFile("class Test { Object o; Runnable r; }", "Test", "Test.m");
   assertTranslatedLines(
       translation,
       "- (void)dealloc {",
       "RELEASE_(o_);",
       "RELEASE_(r_);",
       "[super dealloc];",
       "}");
 }
 @Override
 protected void printStaticFieldSetter(IVariableBinding var) {
   String fieldName = NameTable.getStaticVarQualifiedName(var);
   String paramName = NameTable.getName(var);
   String signature = staticFieldSetterSignature(var);
   if (Options.useReferenceCounting()) {
     printf(
         "%s {\n  JreOperatorRetainedAssign(&%s, nil, %s);\n}\n\n",
         signature, fieldName, paramName);
   } else {
     printf("%s {\n  %s = %s;\n}\n\n", signature, fieldName, paramName);
   }
 }
 // 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");
   }
 }
Пример #20
0
 /** Verify fields are not released for ARC code when a finalize() method is defined. */
 public void testFieldReleaseFinalizeARC() throws IOException {
   Options.setMemoryManagementOption(Options.MemoryManagementOption.ARC);
   String translation =
       translateSourceFile(
           "class Test { Object o; Runnable r;"
               + "public void finalize() throws Throwable { System.out.println(this); }}",
           "Test",
           "Test.m");
   assertTranslatedLines(
       translation,
       "- (void)dealloc {",
       "[((JavaIoPrintStream *) nil_chk(JreLoadStatic(JavaLangSystem, out_))) "
           + "printlnWithId:self];",
       "}");
 }
 @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 String enumConstructorDeclaration(
      MethodDeclaration m, List<Statement> statements, IMethodBinding binding) {
    assert !statements.isEmpty();

    // The InitializationNormalizer should have fixed this constructor so the
    // first statement is a constructor or super invocation.
    Statement s = statements.get(0);
    assert s instanceof ConstructorInvocation || s instanceof SuperConstructorInvocation;
    String invocation = generateStatement(statements.get(0), false);

    StringBuffer sb = new StringBuffer();
    boolean memDebug = Options.memoryDebug();
    if (statements.size() == 1) {
      sb.append("{\nreturn ");
      if (memDebug) {
        sb.append("JreMemDebugAdd(" + invocation + ")");
      } else {
        sb.append(invocation);
      }
      sb.append(";\n}");
    } else {
      sb.append("{\nif ((self = ");
      sb.append(invocation);
      sb.append(")) {\n");
      for (int i = 1; i < statements.size(); i++) {
        sb.append(generateStatement(statements.get(i), false));
      }
      if (memDebug) {
        sb.append("JreMemDebugAdd(self);\n");
      }
      sb.append("}\nreturn self;\n}");
    }

    if (invokedConstructors.contains(methodKey(binding))) {
      return super.constructorDeclaration(m, true)
          + " "
          + reindent(sb.toString())
          + "\n\n"
          + super.constructorDeclaration(m, false)
          + " {\n  return "
          + generateStatement(createInnerConstructorInvocation(m), false)
          + ";\n}\n\n";
    } else {
      return super.constructorDeclaration(m, false) + " " + reindent(sb.toString()) + "\n\n";
    }
  }
Пример #23
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);
    }
  }
 // Verify that inherited constructors are disallowed. Exception has four constructors,
 // so a subclass that only implements one should have the other three disallowed.
 public void testConstructorsDisallowed() throws IOException {
   Options.setDisallowInheritedConstructors(true);
   String translation =
       translateSourceFile(
           "class Test extends Exception { Test(String s) { super(s); } }", "Test", "Test.h");
   assertTranslation(translation, "- (instancetype)initWithNSString:(NSString *)s;");
   assertTranslation(translation, "- (instancetype)init NS_UNAVAILABLE;");
   assertTranslation(
       translation,
       "- (instancetype)initWithJavaLangThrowable:(JavaLangThrowable *)arg0 NS_UNAVAILABLE;");
   assertTranslatedLines(
       translation,
       "- (instancetype)initWithNSString:(NSString *)arg0",
       "withJavaLangThrowable:(JavaLangThrowable *)arg1 NS_UNAVAILABLE;");
   assertTranslatedLines(
       translation,
       "- (instancetype)initWithNSString:(NSString *)arg0",
       "withJavaLangThrowable:(JavaLangThrowable *)arg1",
       "withBoolean:(jboolean)arg2",
       "withBoolean:(jboolean)arg3 NS_UNAVAILABLE;");
 }
  public void testAcceptJsniDelimiters() throws IOException {
    String source =
        "class Example { "
            + "  native void test1() /*-[ ocni(); ]-*/; "
            + "  native void test2() /*-{ jsni(); }-*/; "
            + "}";

    // First test with defaults, JSNI should be accepted.
    String translation = translateSourceFile(source, "Example", "Example.m");
    assertTranslation(translation, "ocni();");
    assertTranslation(translation, "jsni();");

    // Now rebuild with option set.
    Options.setAcceptJsniDelimiters(false);
    translation = translateSourceFile(source, "Example", "Example.h");

    // Verify JSNI method is declared in a native methods category,
    // and not implemented.
    assertTranslation(translation, "@interface Example (NativeMethods)\n- (void)test2");
    translation = getTranslatedFile("Example.m");
    assertTranslation(translation, "ocni();");
    assertFalse(translation.contains("jsni();"));
  }
Пример #26
0
/**
 * Class for processing GenerationUnits in minimum increments of one GenerationUnit.
 *
 * @author Tom Ball, Keith Stanger, Mike Thvedt
 */
abstract class FileProcessor {

  private static final Logger logger = Logger.getLogger(FileProcessor.class.getName());

  private final JdtParser parser;
  protected final BuildClosureQueue closureQueue;
  private final NameTable.Factory nameTableFactory = NameTable.newFactory();

  private final int batchSize = Options.batchTranslateMaximum();
  private final Set<ProcessingContext> batchInputs =
      Sets.newLinkedHashSetWithExpectedSize(batchSize);

  private final boolean doBatching = batchSize > 0;

  public FileProcessor(JdtParser parser) {
    this.parser = Preconditions.checkNotNull(parser);
    if (Options.buildClosure()) {
      // Should be an error if the user specifies this with --build-closure
      assert !Options.shouldMapHeaders();
      closureQueue = new BuildClosureQueue();
    } else {
      closureQueue = null;
    }
  }

  public void processInputs(Iterable<ProcessingContext> inputs) {
    for (ProcessingContext input : inputs) {
      processInput(input);
    }
    processBatch();
  }

  public void processBuildClosureDependencies() {
    if (closureQueue != null) {
      while (true) {
        InputFile file = closureQueue.getNextFile();
        if (file == null) {
          processBatch();
          file = closureQueue.getNextFile();
        }
        if (file == null) {
          break;
        }
        processInput(ProcessingContext.fromFile(file));
      }
    }
  }

  private void processInput(ProcessingContext input) {
    InputFile file = input.getFile();

    if (isBatchable(file)) {
      batchInputs.add(input);
      if (batchInputs.size() == batchSize) {
        processBatch();
      }
      return;
    }

    logger.finest("parsing " + file);

    String source = null;
    CompilationUnit compilationUnit = null;
    try {
      source = FileUtil.readFile(file);
      compilationUnit = parser.parseWithBindings(file.getUnitName(), source);
    } catch (IOException e) {
      ErrorUtil.error(e.getMessage());
    }

    if (compilationUnit == null) {
      handleError(input);
      return;
    }

    processCompiledSource(input, source, compilationUnit);
  }

  protected boolean isBatchable(InputFile file) {
    return doBatching && file.getContainingPath().endsWith(".java");
  }

  private void processBatch() {
    if (batchInputs.isEmpty()) {
      return;
    }

    List<String> paths = Lists.newArrayListWithCapacity(batchInputs.size());
    final Map<String, ProcessingContext> inputMap =
        Maps.newHashMapWithExpectedSize(batchInputs.size());
    for (ProcessingContext input : batchInputs) {
      String path = input.getFile().getPath();
      paths.add(path);
      inputMap.put(path, input);
    }

    JdtParser.Handler handler =
        new JdtParser.Handler() {
          @Override
          public void handleParsedUnit(String path, CompilationUnit unit) {
            ProcessingContext input = inputMap.get(path);
            try {
              String source = FileUtil.readFile(input.getFile());
              processCompiledSource(input, source, unit);
              batchInputs.remove(input);
            } catch (IOException e) {
              ErrorUtil.error(e.getMessage());
            }
          }
        };
    logger.finest("Processing batch of size " + batchInputs.size());
    parser.parseFiles(paths, handler);

    // Any remaining files in batchFiles has some kind of error.
    for (ProcessingContext input : batchInputs) {
      handleError(input);
    }

    batchInputs.clear();
  }

  private void processCompiledSource(ProcessingContext input, String source, CompilationUnit unit) {
    InputFile file = input.getFile();
    if (closureQueue != null) {
      closureQueue.addProcessedName(FileUtil.getQualifiedMainTypeName(file, unit));
    }
    com.google.devtools.j2objc.ast.CompilationUnit convertedUnit =
        TreeConverter.convertCompilationUnit(
            unit,
            input.getOriginalSourcePath(),
            FileUtil.getMainTypeName(file),
            source,
            nameTableFactory);
    processConvertedTree(input, convertedUnit);
  }

  protected abstract void processConvertedTree(
      ProcessingContext input, com.google.devtools.j2objc.ast.CompilationUnit unit);

  protected abstract void handleError(ProcessingContext input);
}
Пример #27
0
 /** Verify fields are not released for ARC code, and a dealloc method is not created. */
 public void testFieldReleaseARC() throws IOException {
   Options.setMemoryManagementOption(Options.MemoryManagementOption.ARC);
   String translation =
       translateSourceFile("class Test { Object o; Runnable r; }", "Test", "Test.m");
   assertNotInTranslation(translation, "dealloc");
 }
 // Verify that the default constructor is disallowed if the class has a non-default
 // constructor.
 public void testDefaultConstructorDisallowed() throws IOException {
   Options.setDisallowInheritedConstructors(true);
   String translation = translateSourceFile("class Test { Test(int i) {} }", "Test", "Test.h");
   assertTranslation(translation, "- (instancetype)initWithInt:(jint)i;");
   assertTranslation(translation, "- (instancetype)init NS_UNAVAILABLE;");
 }
 public void testDeprecatedEnumType() throws IOException {
   Options.enableDeprecatedDeclarations();
   String translation =
       translateSourceFile("@Deprecated public enum Test { A, B }", "Test", "Test.h");
   assertTranslation(translation, "__attribute__((deprecated))\n@interface TestEnum");
 }
Пример #30
0
 @Override
 protected void tearDown() throws Exception {
   Options.resetFinalMethodsAsFunctions();
   super.tearDown();
 }