// 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");
   }
 }
 private void printAnnotationValue(AST ast, Object value) {
   if (value == null) {
     print("nil");
   } else if (value instanceof IVariableBinding) {
     IVariableBinding var = (IVariableBinding) value;
     ITypeBinding declaringClass = var.getDeclaringClass();
     printf("[%s %s]", NameTable.getFullName(declaringClass), var.getName());
   } else if (value instanceof ITypeBinding) {
     ITypeBinding type = (ITypeBinding) value;
     printf("[[%s class] getClass]", NameTable.getFullName(type));
   } else if (value instanceof String) {
     StringLiteral node = ast.newStringLiteral();
     node.setLiteralValue((String) value);
     print(StatementGenerator.generateStringLiteral(node));
   } else if (value instanceof Number || value instanceof Character || value instanceof Boolean) {
     print(value.toString());
   } else if (value.getClass().isArray()) {
     print("[IOSObjectArray arrayWithObjects:(id[]) { ");
     Object[] array = (Object[]) value;
     for (int i = 0; i < array.length; i++) {
       if (i > 0) {
         print(", ");
       }
       printAnnotationValue(ast, array[i]);
     }
     printf(" } count:%d type:[[NSObject class] getClass]]", array.length);
   } else {
     assert false : "unknown annotation value type";
   }
 }
 @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);
 }
 private String methodKey(IMethodBinding method) {
   StringBuilder sb = new StringBuilder();
   if (method.isConstructor()) {
     sb.append(NameTable.getFullName(method.getDeclaringClass()));
   } else {
     sb.append(NameTable.getName(method));
   }
   sb.append(parameterKey(method));
   return sb.toString();
 }
 private static String getSuperFunctionSignature(IMethodBinding method) {
   StringBuilder signature =
       new StringBuilder(NameTable.getPrimitiveObjCType(method.getReturnType()));
   signature.append(" (*%s)(id, SEL");
   for (ITypeBinding paramType : method.getParameterTypes()) {
     signature.append(", ").append(NameTable.getPrimitiveObjCType(paramType));
   }
   signature.append(")");
   return signature.toString();
 }
 public void testCamelCaseQualifiedName() {
   String camelCaseName = NameTable.camelCaseQualifiedName("java.lang.Object");
   assertEquals("JavaLangObject", camelCaseName);
   camelCaseName = NameTable.camelCaseQualifiedName("java.util.logging.Level");
   assertEquals("JavaUtilLoggingLevel", camelCaseName);
   camelCaseName = NameTable.camelCaseQualifiedName("java");
   assertEquals("Java", camelCaseName);
   camelCaseName = NameTable.camelCaseQualifiedName("Level");
   assertEquals("Level", camelCaseName);
   camelCaseName = NameTable.camelCaseQualifiedName("");
   assertEquals("", camelCaseName);
 }
 @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);
   }
 }
 private String parameterKey(IMethodBinding method) {
   StringBuilder sb = new StringBuilder();
   ITypeBinding[] parameterTypes = method.getParameterTypes();
   for (int i = 0; i < parameterTypes.length; i++) {
     if (i == 0) {
       sb.append(NameTable.capitalize(NameTable.parameterKeyword(parameterTypes[i])));
     } else {
       sb.append(NameTable.parameterKeyword(parameterTypes[i]));
     }
     sb.append('_');
   }
   return sb.toString();
 }
  public void testMethodVarInSwitch() throws IOException {
    String source =
        "class Test { "
            + "  enum E { ONE, TWO };"
            + "  void foo(E e) { "
            + "    switch (e) {"
            + "      case ONE: {"
            + "        final Integer i = 1;"
            + "        Runnable r = new Runnable() { "
            + "          public void run() { int j = i + 1; } }; }}}}";

    // Verify method var in r1.run() isn't mistakenly made a field in r1.
    CompilationUnit unit = translateType("Test", source);
    List<TypeDeclaration> types = unit.types();
    TypeDeclaration r1 = types.get(2);
    assertEquals("Test_$1", NameTable.getFullName(r1));
    boolean found = false;
    for (FieldDeclaration field : r1.getFields()) {
      List<VariableDeclarationFragment> vars = field.fragments();
      for (VariableDeclaration var : vars) {
        if (var.getName().getIdentifier().equals("val$i")) {
          found = true;
        }
      }
    }
    assertTrue("required field not found", found);

    // Verify constructor takes both outer field and var.
    ObjectiveCImplementationGenerator.generate("Test.java", Language.OBJECTIVE_C, unit, source);
    String translation = getTranslatedFile("Test.m");
    assertTranslation(
        translation,
        "r = [[[Test_$1 alloc] " + "initWithTest:self withJavaLangInteger:i] autorelease]");
  }
  @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");
    }
  }
 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 printAnnotationProperties(List<AnnotationTypeMemberDeclaration> members) {
   int nPrinted = 0;
   for (AnnotationTypeMemberDeclaration member : members) {
     println(String.format("@synthesize %s;", NameTable.getName(member.getName())));
     nPrinted++;
   }
   if (nPrinted > 0) {
     newline();
   }
 }
 @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");
 }
Example #15
0
 private String getObjCMethodSignature(IMethodBinding method) {
   StringBuilder sb = new StringBuilder(method.getName());
   boolean first = true;
   for (ITypeBinding paramType : method.getParameterTypes()) {
     String keyword = nameTable.parameterKeyword(paramType);
     if (first) {
       first = false;
       keyword = NameTable.capitalize(keyword);
     }
     sb.append(keyword + ":");
   }
   return sb.toString();
 }
 // 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 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();
   }
 }
 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 generate(CompilationUnit unit) {
   println(J2ObjC.getFileHeader(getSourceFileName()));
   List<AbstractTypeDeclaration> typesToGenerate = collectTypes(unit);
   if (!typesToGenerate.isEmpty()) {
     findBlockComments(unit, typesToGenerate);
     findInvokedConstructors(unit);
     printStart(getSourceFileName());
     printImports(unit);
     pushIgnoreDeprecatedDeclarationsPragma();
     for (AbstractTypeDeclaration type : typesToGenerate) {
       generate(type);
     }
     popIgnoreDeprecatedDeclarationsPragma();
   } else {
     // Print a dummy C function so compiled object file is valid.
     List<AbstractTypeDeclaration> types = ASTUtil.getTypes(unit);
     if (!types.isEmpty()) {
       printf("void %s_unused() {}\n", NameTable.getFullName(types.get(0)));
     }
   }
   save(unit);
 }
 // 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");
   }
 }
Example #21
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);
}
 public void testCapitalize() {
   assertEquals("Test", NameTable.capitalize("test"));
   assertEquals("123", NameTable.capitalize("123"));
   assertEquals("", NameTable.capitalize(""));
 }
 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 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");
  }
 @Override
 protected void printStaticFieldReferenceGetter(IVariableBinding var) {
   printf(
       "%s {\n  return &%s;\n}\n\n",
       staticFieldReferenceGetterSignature(var), NameTable.getStaticVarQualifiedName(var));
 }