public void testInheritedOuterMethod() {
    resolveSource(
        "Test",
        "class Test { class A { void foo() {} } class B extends A { "
            + "class Inner { void test() { foo(); } } } }");

    TypeDeclaration aNode = (TypeDeclaration) nodesByType.get(ASTNode.TYPE_DECLARATION).get(1);
    TypeDeclaration bNode = (TypeDeclaration) nodesByType.get(ASTNode.TYPE_DECLARATION).get(2);
    TypeDeclaration innerNode = (TypeDeclaration) nodesByType.get(ASTNode.TYPE_DECLARATION).get(3);
    assertFalse(OuterReferenceResolver.needsOuterReference(aNode.resolveBinding()));
    assertFalse(OuterReferenceResolver.needsOuterReference(bNode.resolveBinding()));
    assertTrue(OuterReferenceResolver.needsOuterReference(innerNode.resolveBinding()));

    // B will need an outer reference to Test so it can initialize its
    // superclass A.
    List<IVariableBinding> bPath = OuterReferenceResolver.getPath(bNode);
    assertNotNull(bPath);
    assertEquals(1, bPath.size());
    assertEquals(OuterReferenceResolver.OUTER_PARAMETER, bPath.get(0));

    // foo() call will need to get to B's scope to call the inherited method.
    MethodInvocation fooCall = (MethodInvocation) nodesByType.get(ASTNode.METHOD_INVOCATION).get(0);
    List<IVariableBinding> fooPath = OuterReferenceResolver.getPath(fooCall);
    assertNotNull(fooPath);
    assertEquals(1, fooPath.size());
    assertEquals("B", fooPath.get(0).getType().getName());
  }
 private List<IVariableBinding> getCapturedVariables(ClassInstanceCreation node) {
   ITypeBinding newType = node.getTypeBinding().getTypeDeclaration();
   ITypeBinding owningType = TreeUtil.getOwningType(node).getTypeBinding().getTypeDeclaration();
   // Test for the recursive construction of a local class.
   if (owningType.isEqualTo(newType)) {
     return OuterReferenceResolver.getInnerFields(newType);
   }
   return OuterReferenceResolver.getCapturedVars(newType);
 }
  public void testOuterVarAccess() {
    resolveSource("Test", "class Test { int i; class Inner { void test() { i++; } } }");

    TypeDeclaration innerNode = (TypeDeclaration) nodesByType.get(ASTNode.TYPE_DECLARATION).get(1);
    assertTrue(OuterReferenceResolver.needsOuterReference(innerNode.resolveBinding()));

    PostfixExpression increment =
        (PostfixExpression) nodesByType.get(ASTNode.POSTFIX_EXPRESSION).get(0);
    List<IVariableBinding> path = OuterReferenceResolver.getPath(increment.getOperand());
    assertNotNull(path);
    assertEquals(2, path.size());
    assertEquals("Test", path.get(0).getType().getName());
  }
 @Override
 public boolean visit(MethodInvocation node) {
   List<IVariableBinding> path = OuterReferenceResolver.getPath(node);
   if (path != null) {
     node.setExpression(Name.newName(fixPath(path)));
   }
   return true;
 }
  public void testAnonymousClassInheritsLocalClassInStaticMethod() {
    resolveSource(
        "Test", "class Test { static void test() { class LocalClass {}; new LocalClass() {}; } }");

    AnonymousClassDeclaration decl =
        (AnonymousClassDeclaration) nodesByType.get(ASTNode.ANONYMOUS_CLASS_DECLARATION).get(0);
    ITypeBinding type = decl.resolveBinding();
    assertFalse(OuterReferenceResolver.needsOuterParam(type));
  }
 @Override
 public boolean visit(ThisExpression node) {
   List<IVariableBinding> path = OuterReferenceResolver.getPath(node);
   if (path != null) {
     node.replaceWith(Name.newName(fixPath(path)));
   } else {
     node.setQualifier(null);
   }
   return true;
 }
 @Override
 public void endVisit(SuperMethodInvocation node) {
   List<IVariableBinding> path = OuterReferenceResolver.getPath(node);
   if (path != null) {
     // We substitute the qualifying type name with the outer variable name.
     node.setQualifier(Name.newName(fixPath(path)));
   } else {
     node.setQualifier(null);
   }
 }
 @Override
 public boolean visit(SimpleName node) {
   List<IVariableBinding> path = OuterReferenceResolver.getPath(node);
   if (path != null) {
     if (path.size() == 1 && path.get(0).getConstantValue() != null) {
       IVariableBinding var = path.get(0);
       node.replaceWith(TreeUtil.newLiteral(var.getConstantValue()));
     } else {
       node.replaceWith(Name.newName(fixPath(path)));
     }
   }
   return true;
 }
  public void testCapturedLocalVariable() {
    resolveSource(
        "Test",
        "class Test { void test(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();
    assertFalse(OuterReferenceResolver.needsOuterReference(runnableBinding));
    List<IVariableBinding> capturedVars = OuterReferenceResolver.getCapturedVars(runnableBinding);
    List<IVariableBinding> innerFields = OuterReferenceResolver.getInnerFields(runnableBinding);
    assertEquals(1, capturedVars.size());
    assertEquals(1, innerFields.size());
    assertEquals("i", capturedVars.get(0).getName());
    assertEquals("val$i", innerFields.get(0).getName());

    InfixExpression addition = (InfixExpression) nodesByType.get(ASTNode.INFIX_EXPRESSION).get(0);
    List<IVariableBinding> iPath = OuterReferenceResolver.getPath(addition.getLeftOperand());
    assertNotNull(iPath);
    assertEquals(1, iPath.size());
    assertEquals("val$i", iPath.get(0).getName());
  }
  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)));
  }
示例#11
0
  private void addOuterArg(
      ClassInstanceCreation node, GeneratedMethodBinding binding, ITypeBinding declaringClass) {
    ITypeBinding type = node.getTypeBinding().getTypeDeclaration();
    if (!OuterReferenceResolver.needsOuterParam(type)) {
      return;
    }

    Expression outerExpr = node.getExpression();
    List<IVariableBinding> path = OuterReferenceResolver.getPath(node);
    Expression outerArg = null;

    if (outerExpr != null) {
      node.setExpression(null);
      outerArg = outerExpr;
    } else if (path != null) {
      outerArg = Name.newName(fixPath(path));
    } else {
      outerArg = new ThisExpression(declaringClass);
    }

    node.getArguments().add(0, outerArg);
    binding.addParameter(0, declaringClass);
  }
 @Override
 protected void tearDown() throws Exception {
   nodesByType.clear();
   OuterReferenceResolver.cleanup();
 }
 private void resolveSource(String name, String source) {
   CompilationUnit unit = compileType(name, source);
   OuterReferenceResolver.resolve(unit);
   findTypeDeclarations(unit);
 }