@Override
 public boolean visit(MethodDeclaration node) {
   if (node.getBody() == null) {
     return VISIT_SUBTREE;
   }
   List<Statement> bodyStmts = statements(node.getBody());
   if (bodyStmts.size() == 1) {
     SuperMethodInvocation bodyMi = asExpression(bodyStmts.get(0), SuperMethodInvocation.class);
     if (bodyMi != null) {
       IMethodBinding bodyMethodBinding = bodyMi.resolveMethodBinding();
       IMethodBinding declMethodBinding = node.resolveBinding();
       if (declMethodBinding != null
           && bodyMethodBinding != null
           && declMethodBinding.overrides(bodyMethodBinding)
           && !hasSignificantAnnotations(declMethodBinding)
           && haveSameModifiers(bodyMethodBinding, declMethodBinding)) {
         if (Modifier.isProtected(declMethodBinding.getModifiers())
             && !declaredInSamePackage(bodyMethodBinding, declMethodBinding)) {
           // protected also means package visibility, so check if it is required
           if (!isMethodUsedInItsPackage(declMethodBinding, node)) {
             this.ctx.getRefactorings().remove(node);
             return DO_NOT_VISIT_SUBTREE;
           }
         } else {
           this.ctx.getRefactorings().remove(node);
           return DO_NOT_VISIT_SUBTREE;
         }
       }
     }
   }
   return VISIT_SUBTREE;
 }
 /*
  * @see ASTVisitor#visit(MethodDeclaration)
  */
 public boolean visit(MethodDeclaration node) {
   if (node.getJavadoc() != null) {
     node.getJavadoc().accept(this);
   }
   if (node.getAST().apiLevel() >= AST.JLS3) {
     printModifiers(node.modifiers());
     if (!node.typeParameters().isEmpty()) {
       this.fBuffer.append("<"); // $NON-NLS-1$
       for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) {
         TypeParameter t = (TypeParameter) it.next();
         t.accept(this);
         if (it.hasNext()) {
           this.fBuffer.append(", "); // $NON-NLS-1$
         }
       }
       this.fBuffer.append("> "); // $NON-NLS-1$
     }
   }
   if (!node.isConstructor()) {
     if (node.getReturnType2() != null) {
       node.getReturnType2().accept(this);
     } else {
       // methods really ought to have a return type
       this.fBuffer.append("void"); // $NON-NLS-1$
     }
     this.fBuffer.append(" "); // $NON-NLS-1$
   }
   node.getName().accept(this);
   this.fBuffer.append("("); // $NON-NLS-1$
   for (Iterator it = node.parameters().iterator(); it.hasNext(); ) {
     SingleVariableDeclaration v = (SingleVariableDeclaration) it.next();
     v.accept(this);
     if (it.hasNext()) {
       this.fBuffer.append(", "); // $NON-NLS-1$
     }
   }
   this.fBuffer.append(")"); // $NON-NLS-1$
   for (int i = 0; i < node.getExtraDimensions(); i++) {
     this.fBuffer.append("[]"); // $NON-NLS-1$
   }
   if (!node.thrownExceptions().isEmpty()) {
     this.fBuffer.append(" throws "); // $NON-NLS-1$
     for (Iterator it = node.thrownExceptions().iterator(); it.hasNext(); ) {
       Name n = (Name) it.next();
       n.accept(this);
       if (it.hasNext()) {
         this.fBuffer.append(", "); // $NON-NLS-1$
       }
     }
     this.fBuffer.append(" "); // $NON-NLS-1$
   }
   if (node.getBody() == null) {
     this.fBuffer.append(";"); // $NON-NLS-1$
   } else {
     node.getBody().accept(this);
   }
   return false;
 }
  private static boolean canAddFinal(IBinding binding, ASTNode declNode) {
    if (!(binding instanceof IVariableBinding)) return false;

    IVariableBinding varbinding = (IVariableBinding) binding;
    int modifiers = varbinding.getModifiers();
    if (Modifier.isFinal(modifiers)
        || Modifier.isVolatile(modifiers)
        || Modifier.isTransient(modifiers)) return false;

    ASTNode parent = ASTNodes.getParent(declNode, VariableDeclarationExpression.class);
    if (parent != null && ((VariableDeclarationExpression) parent).fragments().size() > 1)
      return false;

    if (varbinding.isField() && !Modifier.isPrivate(modifiers)) return false;

    if (varbinding.isParameter()) {
      ASTNode varDecl = declNode.getParent();
      if (varDecl instanceof MethodDeclaration) {
        MethodDeclaration declaration = (MethodDeclaration) varDecl;
        if (declaration.getBody() == null) return false;
      }
    }

    return true;
  }
  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;
  }
    private boolean callsWritingConstructor(
        MethodDeclaration methodDeclaration,
        HashSet writingConstructorBindings,
        Set visitedMethodDeclarations) {
      Block body = methodDeclaration.getBody();
      if (body == null) return false;

      List statements = body.statements();
      if (statements.size() == 0) return false;

      Statement statement = (Statement) statements.get(0);
      if (!(statement instanceof ConstructorInvocation)) return false;

      ConstructorInvocation invocation = (ConstructorInvocation) statement;
      IMethodBinding constructorBinding = invocation.resolveConstructorBinding();
      if (constructorBinding == null) return false;

      if (writingConstructorBindings.contains(constructorBinding)) {
        return true;
      } else {
        ASTNode declaration =
            ASTNodes.findDeclaration(constructorBinding, methodDeclaration.getParent());
        if (!(declaration instanceof MethodDeclaration)) return false;

        if (visitedMethodDeclarations.contains(declaration)) {
          return false;
        }
        visitedMethodDeclarations.add(methodDeclaration);
        return callsWritingConstructor(
            (MethodDeclaration) declaration, writingConstructorBindings, visitedMethodDeclarations);
      }
    }
  /**
   * Visits the method invocation to get number of assertion in this test method.
   *
   * @param md Visit method declaration in source code.
   * @return False because we don't look into child nodes.
   */
  public boolean visit(MethodDeclaration md) {
    if (md.getName() != null) {
      this.numOfMethods++;

      if (md.getName().getIdentifier().startsWith("test")) {
        this.numOfTestMethods++;
      } else if (isJUnit4Test(md)) {
        this.numOfTestMethods++;
      }

      // Check test method body to look for assertion statement.
      Block methodBody = md.getBody();
      if (methodBody != null && methodBody.statements() != null) {
        List stmts = methodBody.statements();
        this.numOfStatements += stmts.size();
        // Looks through all statements in this method body.
        for (Iterator i = stmts.iterator(); i.hasNext(); ) {
          Statement stmt = (Statement) i.next(); // NOPMD
          // MethodInvocation is one kind of expression statement.
          if (stmt instanceof ExpressionStatement) {
            ExpressionStatement estmt = (ExpressionStatement) stmt;
            checkAssertions(estmt);
          }
        }
      }
    }

    // No need to visit child nodes anymore.
    return false;
  }
 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");
 }
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.andmore.android.model.java.JavaClass#addComments()
   */
  @Override
  protected void addComments() throws AndroidException {
    ASTNode todoComment;

    ASTParser parser = ASTParser.newParser(AST.JLS3);
    parser.setSource(document.get().toCharArray());

    compUnit = (CompilationUnit) parser.createAST(null);
    ast = compUnit.getAST();
    rewrite = ASTRewrite.create(ast);

    todoComment =
        rewrite.createStringPlaceholder(
            CodeUtilsNLS.MODEL_Common_ToDoPutYourCodeHere, ASTNode.EMPTY_STATEMENT);

    TypeDeclaration receiverClass = (TypeDeclaration) compUnit.types().get(0);
    MethodDeclaration method;
    Block block;

    // Adds the Override annotation and ToDo comment to all overridden
    // methods
    for (int i = 0; i < receiverClass.bodyDeclarations().size(); i++) {
      method = (MethodDeclaration) receiverClass.bodyDeclarations().get(i);

      // Adds the Override annotation
      rewrite
          .getListRewrite(method, method.getModifiersProperty())
          .insertFirst(OVERRIDE_ANNOTATION, null);

      // Adds the ToDo comment
      block = method.getBody();
      rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY).insertFirst(todoComment, null);
    }

    try {
      // Writes the modifications
      TextEdit modifications = rewrite.rewriteAST(document, null);
      modifications.apply(document);
    } catch (IllegalArgumentException e) {
      String errMsg = NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className);

      AndmoreLogger.error(BroadcastReceiverClass.class, errMsg, e);
      throw new AndroidException(errMsg);
    } catch (MalformedTreeException e) {
      String errMsg = NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className);

      AndmoreLogger.error(BroadcastReceiverClass.class, errMsg, e);
      throw new AndroidException(errMsg);
    } catch (BadLocationException e) {
      String errMsg = NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className);

      AndmoreLogger.error(BroadcastReceiverClass.class, errMsg, e);
      throw new AndroidException(errMsg);
    }
  }
  @Test
  public void testIsThrowStatementInCatchClause() {
    TryStatement tryStatement;
    CatchClause catchStatement;

    // 測試 符合的例子 是否會抓出
    MethodDeclaration md = null;
    md = ASTNodeFinder.getMethodDeclarationNodeByName(compilationUnit, "false_throwAndPrint");
    tryStatement = (TryStatement) md.getBody().statements().get(0);
    catchStatement = (CatchClause) tryStatement.catchClauses().get(0);
    assertTrue(dummyHandlerVisitor.isThrowStatementInCatchClause(catchStatement));

    // 測試 不符合例子 是否會抓出
    md =
        ASTNodeFinder.getMethodDeclarationNodeByName(
            compilationUnit, "true_DummyHandlerTryNestedTry");
    tryStatement = (TryStatement) md.getBody().statements().get(1);
    catchStatement = (CatchClause) tryStatement.catchClauses().get(0);
    assertFalse(dummyHandlerVisitor.isThrowStatementInCatchClause(catchStatement));
  }
 @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");
 }
 @Override
 public boolean visit(MethodDeclaration node) {
   Block body = node.getBody();
   if (body == null) return false;
   Selection selection = getSelection();
   int nodeStart = body.getStartPosition();
   int nodeExclusiveEnd = nodeStart + body.getLength();
   // if selection node inside of the method body ignore method
   if (!(nodeStart < selection.getOffset() && selection.getExclusiveEnd() < nodeExclusiveEnd))
     return false;
   return super.visit(node);
 }
Beispiel #12
0
 @Override
 public boolean visit(final MethodDeclaration node) {
   @SuppressWarnings("rawtypes")
   final List l = node.getBody().statements();
   this.b_last = node.getBody(); // use method's body as virtual last
   if (l.size() == 0) {
     this.b_init = this.b_last;
     return false; // empty body
   }
   int i = 0; // we need to find the first actual SJ statement
   while ((i != l.size()) && (l.get(i) instanceof VariableDeclarationStatement)) {
     i++;
   }
   if (l.size() == i) {
     this.b_init = this.b_last;
     return false; // no SJ statements in body
   } else {
     this.b_init = (Statement) l.get(i); // first SJ statement
     // add edge from last statement in method body to virtual b_last
     addEdge(last(l), this.b_last);
   }
   return true;
 }
 @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";
   }
 }
  protected List getFeatureMethodSwitch(String type) {
    List cases = featureSwitchMap.get(type);
    if (cases == null) {
      MethodDeclaration method =
          newMethodDeclaration(
              "void",
              type,
              newSingleVariableDeclaration(FeatureDescriptor.class.getName(), "featureDesc"));
      SwitchStatement switchStm =
          newSwitchStatement(newMethodInvocation("featureDesc", "getOrdinal"));
      method.getBody().statements().add(switchStm);
      addBodyDeclaration(method);

      featureSwitchMap.put(type, cases = switchStm.statements());
    }
    return cases;
  }
  /** Verify that an anonymous class is moved to the compilation unit's types list. */
  public void testAnonymousClassExtracted() {
    List<TypeDeclaration> types =
        translateClassBody(
            "Object test() { return new java.util.Enumeration<Object>() { "
                + "public boolean hasMoreElements() { return false; } "
                + "public Object nextElement() { return null; } }; }");
    assertEquals(2, types.size());

    TypeDeclaration type = types.get(1);
    assertEquals("$1", type.getName().getIdentifier());

    type = types.get(0);
    assertEquals("Test", type.getName().getIdentifier());
    MethodDeclaration testMethod = (MethodDeclaration) type.bodyDeclarations().get(0);
    ReturnStatement stmt = (ReturnStatement) testMethod.getBody().statements().get(0);
    ClassInstanceCreation expr = (ClassInstanceCreation) stmt.getExpression();
    assertNull(expr.getAnonymousClassDeclaration());
  }
  protected List getEnumMethodSwitch(String type) {
    if (enumCases == null) {
      MethodDeclaration method =
          newMethodDeclaration(
              "void",
              "wEntity",
              newSingleVariableDeclaration(
                  newParameterizedType(EntityDescriptor.class.getName(), ast.newWildcardType()),
                  "entityDesc"),
              newSingleVariableDeclaration(EnumValue.class.getName(), "value"));
      SwitchStatement switchStm =
          newSwitchStatement(newMethodInvocation("entityDesc", "getOrdinal"));
      method.getBody().statements().add(switchStm);
      addBodyDeclaration(method);

      enumCases = switchStm.statements();
    }
    return enumCases;
  }
  protected List getMethodSwitch(String type) {
    List cases = switchMap.get(type);
    if (cases == null) {
      MethodDeclaration method =
          newMethodDeclaration(
              "void",
              type,
              newSingleVariableDeclaration(
                  newParameterizedType(EntityDescriptor.class.getName(), ast.newWildcardType()),
                  "entityDesc"));
      SwitchStatement switchStm =
          newSwitchStatement(newMethodInvocation("entityDesc", "getOrdinal"));
      method.getBody().statements().add(switchStm);
      addBodyDeclaration(method);

      switchMap.put(type, cases = switchStm.statements());
    }
    return cases;
  }
  @SuppressWarnings("unchecked")
  public void removeUnallowedAssignments() {
    CompilationUnit cu = catroidSource.getSourceAst();
    final List<AbstractTypeDeclaration> types = cu.types();
    assert types.size() > 0;

    for (AbstractTypeDeclaration abstractTypeDecl : types) {
      for (BodyDeclaration bodyDecl :
          new ArrayList<BodyDeclaration>(abstractTypeDecl.bodyDeclarations())) {
        if (bodyDecl.getNodeType() != ASTNode.METHOD_DECLARATION) {
          continue;
        }

        MethodDeclaration methodDeclaration = (MethodDeclaration) bodyDecl;
        Block body = methodDeclaration.getBody();
        if ((body == null) || (body.statements().size() == 0)) {
          continue;
        }
        methodDeclaration.accept(this);
      }
    }
  }
  /**
   * Regression test: verify that a class passed in the constructor of an anonymous class is
   * converted.
   */
  public void testAnonymousClassWithTypeArgParameter() {
    List<TypeDeclaration> types =
        translateClassBody(
            "public Test(Class c) {} static Test t = "
                + "new Test(Test.class) { @Override public int hashCode() { return 1; } };");
    assertEquals(2, types.size());

    TypeDeclaration type = types.get(0);
    List<BodyDeclaration> members = type.bodyDeclarations();
    for (BodyDeclaration member : members) {
      if (member instanceof MethodDeclaration) {
        MethodDeclaration m = (MethodDeclaration) member;
        if (m.getName().getIdentifier().equals("initialize")) {
          Block b = (Block) m.getBody().statements().get(0);
          ExpressionStatement expStmt = (ExpressionStatement) b.statements().get(0);
          Assignment assign = (Assignment) expStmt.getExpression();
          ClassInstanceCreation create = (ClassInstanceCreation) assign.getRightHandSide();
          assertTrue(create.arguments().get(0) instanceof TypeLiteral);
        }
      }
    }
  }
  /*
   * @see ASTVisitor#visit(MethodDeclaration)
   */
  @Override
  public boolean visit(MethodDeclaration node) {
    if (!isAffected(node)) {
      return false;
    }
    doVisitNode(node.getJavadoc());

    doVisitChildren(node.modifiers());
    doVisitChildren(node.typeParameters());

    if (!node.isConstructor()) {
      doVisitNode(node.getReturnType2());
    }
    // name not visited

    int apiLevel = node.getAST().apiLevel();
    if (apiLevel >= AST.JLS8) {
      doVisitNode(node.getReceiverType());
    }
    // receiverQualifier not visited:
    //   Enclosing class names cannot be shadowed by an import (qualification is always redundant).
    doVisitChildren(node.parameters());
    if (apiLevel >= AST.JLS8) {
      doVisitChildren(node.extraDimensions());
      doVisitChildren(node.thrownExceptionTypes());
    } else {
      Iterator<Name> iter = getThrownExceptions(node).iterator();
      while (iter.hasNext()) {
        typeRefFound(iter.next());
      }
    }
    if (!fSkipMethodBodies) {
      doVisitNode(node.getBody());
    }
    return false;
  }
 /*
  * @see ASTVisitor#visit(MethodDeclaration)
  */
 @Override
 public boolean visit(MethodDeclaration node) {
   if (node.getJavadoc() != null) {
     node.getJavadoc().accept(this);
   }
   if (node.getAST().apiLevel() >= JLS3) {
     printModifiers(node.modifiers());
     if (!node.typeParameters().isEmpty()) {
       this.fBuffer.append("<"); // $NON-NLS-1$
       for (Iterator<TypeParameter> it = node.typeParameters().iterator(); it.hasNext(); ) {
         TypeParameter t = it.next();
         t.accept(this);
         if (it.hasNext()) {
           this.fBuffer.append(", "); // $NON-NLS-1$
         }
       }
       this.fBuffer.append("> "); // $NON-NLS-1$
     }
   }
   if (!node.isConstructor()) {
     if (node.getReturnType2() != null) {
       node.getReturnType2().accept(this);
     } else {
       // methods really ought to have a return type
       this.fBuffer.append("void"); // $NON-NLS-1$
     }
     this.fBuffer.append(" "); // $NON-NLS-1$
   }
   node.getName().accept(this);
   this.fBuffer.append("("); // $NON-NLS-1$
   if (node.getAST().apiLevel() >= AST.JLS8) {
     Type receiverType = node.getReceiverType();
     if (receiverType != null) {
       receiverType.accept(this);
       this.fBuffer.append(' ');
       SimpleName qualifier = node.getReceiverQualifier();
       if (qualifier != null) {
         qualifier.accept(this);
         this.fBuffer.append('.');
       }
       this.fBuffer.append("this"); // $NON-NLS-1$
       if (node.parameters().size() > 0) {
         this.fBuffer.append(',');
       }
     }
   }
   for (Iterator<SingleVariableDeclaration> it = node.parameters().iterator(); it.hasNext(); ) {
     SingleVariableDeclaration v = it.next();
     v.accept(this);
     if (it.hasNext()) {
       this.fBuffer.append(", "); // $NON-NLS-1$
     }
   }
   this.fBuffer.append(")"); // $NON-NLS-1$
   if (node.getAST().apiLevel() >= AST.JLS8) {
     List<Dimension> dimensions = node.extraDimensions();
     for (Iterator<Dimension> it = dimensions.iterator(); it.hasNext(); ) {
       Dimension e = it.next();
       e.accept(this);
     }
   } else {
     for (int i = 0; i < node.getExtraDimensions(); i++) {
       this.fBuffer.append("[]"); // $NON-NLS-1$
     }
   }
   List<? extends ASTNode> thrownExceptions =
       node.getAST().apiLevel() >= AST.JLS8
           ? node.thrownExceptionTypes()
           : getThrownExceptions(node);
   if (!thrownExceptions.isEmpty()) {
     this.fBuffer.append(" throws "); // $NON-NLS-1$
     for (Iterator<? extends ASTNode> it = thrownExceptions.iterator(); it.hasNext(); ) {
       ASTNode n = it.next();
       n.accept(this);
       if (it.hasNext()) {
         this.fBuffer.append(", "); // $NON-NLS-1$
       }
     }
     this.fBuffer.append(" "); // $NON-NLS-1$
   }
   if (node.getBody() == null) {
     this.fBuffer.append(";"); // $NON-NLS-1$
   } else {
     node.getBody().accept(this);
   }
   return false;
 }
  public void testASTRewriteExample() throws Exception {
    // create a new project
    IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("Test");
    project.create(null);
    project.open(null);
    try {
      // set the Java nature and Java build path
      IProjectDescription description = project.getDescription();
      description.setNatureIds(new String[] {JavaCore.NATURE_ID});
      project.setDescription(description, null);

      IJavaProject javaProject = JavaCore.create(project);

      // build path is: project as source folder and JRE container
      IClasspathEntry[] cpentry =
          new IClasspathEntry[] {
            JavaCore.newSourceEntry(javaProject.getPath()),
            JavaRuntime.getDefaultJREContainerEntry()
          };
      javaProject.setRawClasspath(cpentry, javaProject.getPath(), null);
      Map<String, String> options = new HashMap<>();
      options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
      options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4");
      javaProject.setOptions(options);

      // create a test file
      IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(project);
      IPackageFragment pack1 = root.createPackageFragment("test1", false, null);
      StringBuffer buf = new StringBuffer();
      buf.append("package test1;\n");
      buf.append("public class E {\n");
      buf.append("    public void foo(int i) {\n");
      buf.append("        while (--i > 0) {\n");
      buf.append("            System.beep();\n");
      buf.append("        }\n");
      buf.append("    }\n");
      buf.append("}\n");
      ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null);

      // create an AST
      ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
      parser.setSource(cu);
      parser.setResolveBindings(false);
      CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
      AST ast = astRoot.getAST();

      // create the descriptive ast rewriter
      ASTRewrite rewrite = ASTRewrite.create(ast);

      // get the block node that contains the statements in the method body
      TypeDeclaration typeDecl = (TypeDeclaration) astRoot.types().get(0);
      MethodDeclaration methodDecl = typeDecl.getMethods()[0];
      Block block = methodDecl.getBody();

      // create new statements to insert
      MethodInvocation newInv1 = ast.newMethodInvocation();
      newInv1.setName(ast.newSimpleName("bar1"));
      Statement newStatement1 = ast.newExpressionStatement(newInv1);

      MethodInvocation newInv2 = ast.newMethodInvocation();
      newInv2.setName(ast.newSimpleName("bar2"));
      Statement newStatement2 = ast.newExpressionStatement(newInv2);

      // describe that the first node is inserted as first statement in block, the other one as last
      // statement
      // note: AST is not modified by this
      ListRewrite listRewrite = rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY);
      listRewrite.insertFirst(newStatement1, null);
      listRewrite.insertLast(newStatement2, null);

      // evaluate the text edits corresponding to the described changes. AST and CU still
      // unmodified.
      TextEdit res = rewrite.rewriteAST();

      // apply the text edits to the compilation unit
      Document document = new Document(cu.getSource());
      res.apply(document);
      cu.getBuffer().setContents(document.get());

      // test result
      String preview = cu.getSource();

      buf = new StringBuffer();
      buf.append("package test1;\n");
      buf.append("public class E {\n");
      buf.append("    public void foo(int i) {\n");
      buf.append("        bar1();\n");
      buf.append("        while (--i > 0) {\n");
      buf.append("            System.beep();\n");
      buf.append("        }\n");
      buf.append("        bar2();\n");
      buf.append("    }\n");
      buf.append("}\n");
      assertEquals(preview, buf.toString());
    } finally {
      project.delete(true, null);
    }
  }
  private Example makeExample(
      MethodDeclaration node,
      Set<? extends Expression> envolvedInvocations,
      List<ApiMethod> envolvedApiMethods) {

    //  Visitor responsável por realizar o slicing de programas
    SlicingStatementVisitor visitor =
        new SlicingStatementVisitor(node, new HashSet<ASTNode>(envolvedInvocations));
    node.accept(visitor);

    Collection<Statement> relatedStatements = visitor.getSlicedStatements();

    ASTNode newAST =
        ASTUtil.copyStatements(node.getBody(), relatedStatements, AST.newAST(AST.JLS3));
    if (!relatedStatements.isEmpty()) {
      LOGGER.error("Some statements were not included!");
    }

    if (newAST == null) {
      LOGGER.error("Slicing process failed for node ");
      // TODO Se AST retornada for nula é porque faltou incluir statement(s)
      return null;
    } else if (((Block) newAST).statements().isEmpty()) {
      LOGGER.error("Slicing process failed for node ");
      // TODO Se o Block retornado for vazio é porque faltou incluir statement(s)
      return null;
    }

    ASTUtil.removeEmptyBlocks((Block) newAST);

    // Adiciona declarações de variáveis que não foram encontradas no escopo do método
    // Para facilitar, tipos iguais são declarados no mesmo Statement
    Set<String> additionalDeclarationLines = new HashSet<String>();
    Map<ITypeBinding, List<IVariableBinding>> typesMap =
        new HashMap<ITypeBinding, List<IVariableBinding>>();
    for (IVariableBinding ivb : visitor.getUndiscoveredDeclarations()) {
      if (!typesMap.containsKey(ivb.getType())) {
        typesMap.put(ivb.getType(), new ArrayList<IVariableBinding>(2));
      }
      typesMap.get(ivb.getType()).add(ivb);
    }

    for (ITypeBinding typeBinding : typesMap.keySet()) {
      List<IVariableBinding> variableBindings = typesMap.get(typeBinding);

      Stack<VariableDeclarationFragment> fragments = new Stack<VariableDeclarationFragment>();
      for (IVariableBinding ivb : variableBindings) {
        VariableDeclarationFragment declarationFragment =
            newAST.getAST().newVariableDeclarationFragment();
        declarationFragment.setName(newAST.getAST().newSimpleName(ivb.getName()));
        fragments.add(declarationFragment);
      }

      VariableDeclarationStatement statement =
          newAST.getAST().newVariableDeclarationStatement(fragments.pop());
      while (!fragments.isEmpty()) {
        statement.fragments().add(fragments.pop());
      }

      statement.setType(this.getType(typeBinding, newAST.getAST()));

      additionalDeclarationLines.add(statement.toString());
      ((Block) newAST).statements().add(0, statement);
    }

    Example example = new Example();
    example.setAttachment(this.attachmentMap.get(node.getRoot()));
    example.setApiMethods(new HashSet<ApiElement>(envolvedApiMethods));
    example.setImports(visitor.getImports());

    for (Expression seed : envolvedInvocations) {
      example.getSeeds().add(seed.toString());
    }

    example.setSourceMethod(node.toString());
    example.setAddedAt(new Date(System.currentTimeMillis()));

    try {
      IMethodBinding nodeBinding = node.resolveBinding();
      if (!this.methodMap.containsKey(nodeBinding)) {
        ApiClass newApiClass = new ApiClass(nodeBinding.getDeclaringClass().getQualifiedName());
        methodDeclarationHandler(node, newApiClass);
      }
      example.setSourceMethodCall(this.methodMap.get(nodeBinding).getFullName());
    } catch (Exception e) {
      LOGGER.error(e);
      if (example.getSourceMethodCall() == null) {
        example.setSourceMethodCall("?");
      }
    }

    String codeExample = newAST.toString();
    for (String line : additionalDeclarationLines) {
      codeExample =
          codeExample.replace(
              line,
              line.replace("\n", "").concat("  ").concat("//initialized previously").concat("\n"));
    }

    // FIXME
    codeExample = codeExample.replaceAll("(\\{\n)(\\s+)(\\})", "$1 //do something \n$3");

    try {
      example.setCodeExample(codeExample);
      example.setFormattedCodeExample(ASTUtil.codeFormatter(codeExample));
    } catch (Exception e) {
      LOGGER.error(e);
      if (example.getFormattedCodeExample() == null) {
        example.setFormattedCodeExample(codeExample);
      }
    }

    // TODO Obter métricas do exemplo
    example
        .getMetrics()
        .put(ExampleMetric.LOC.name(), example.getFormattedCodeExample().split("\n").length - 1);
    example.getMetrics().put(ExampleMetric.ARGUMENTS.name(), visitor.getNumberOfArguments());
    example
        .getMetrics()
        .put(ExampleMetric.DECISION_STATEMENTS.name(), visitor.getNumberOfDecisionStatements());
    example.getMetrics().put(ExampleMetric.INVOCATIONS.name(), visitor.getNumberOfInvocations());
    example
        .getMetrics()
        .put(ExampleMetric.NULL_ARGUMENTS.name(), visitor.getNumberOfNullArguments());
    example
        .getMetrics()
        .put(ExampleMetric.PRIMITIVE_ARGUMENTS.name(), visitor.getNumberOfPrimitiveArguments());
    example
        .getMetrics()
        .put(ExampleMetric.FIELD_ARGUMENTS.name(), visitor.getNumberOfFieldArguments());
    example
        .getMetrics()
        .put(
            ExampleMetric.UNDISCOVERED_DECLARATIONS.name(),
            visitor.getNumberOfUndiscoveredDeclarations());
    example
        .getMetrics()
        .put(ExampleMetric.UNHANDLED_EXCEPTIONS.name(), visitor.getNumberOfUnhandledExceptions());

    return example;
  }
  private List<ClassObject> parseAST(CompilationUnit compilationUnit, IFile iFile) {
    List<ClassObject> classObjects = new ArrayList<ClassObject>();
    List<AbstractTypeDeclaration> topLevelTypeDeclarations = compilationUnit.types();
    for (AbstractTypeDeclaration abstractTypeDeclaration : topLevelTypeDeclarations) {
      if (abstractTypeDeclaration instanceof TypeDeclaration) {
        TypeDeclaration topLevelTypeDeclaration = (TypeDeclaration) abstractTypeDeclaration;
        List<TypeDeclaration> typeDeclarations = new ArrayList<TypeDeclaration>();
        typeDeclarations.add(topLevelTypeDeclaration);
        typeDeclarations.addAll(getRecursivelyInnerTypes(topLevelTypeDeclaration));
        for (TypeDeclaration typeDeclaration : typeDeclarations) {
          final ClassObject classObject = new ClassObject();
          classObject.setIFile(iFile);
          classObject.setName(typeDeclaration.resolveBinding().getQualifiedName());
          classObject.setTypeDeclaration(typeDeclaration);

          if (typeDeclaration.isInterface()) {
            classObject.setInterface(true);
          }

          int modifiers = typeDeclaration.getModifiers();
          if ((modifiers & Modifier.ABSTRACT) != 0) classObject.setAbstract(true);

          if ((modifiers & Modifier.PUBLIC) != 0) classObject.setAccess(Access.PUBLIC);
          else if ((modifiers & Modifier.PROTECTED) != 0) classObject.setAccess(Access.PROTECTED);
          else if ((modifiers & Modifier.PRIVATE) != 0) classObject.setAccess(Access.PRIVATE);
          else classObject.setAccess(Access.NONE);

          if ((modifiers & Modifier.STATIC) != 0) classObject.setStatic(true);

          Type superclassType = typeDeclaration.getSuperclassType();
          if (superclassType != null) {
            ITypeBinding binding = superclassType.resolveBinding();
            String qualifiedName = binding.getQualifiedName();
            TypeObject typeObject = TypeObject.extractTypeObject(qualifiedName);
            classObject.setSuperclass(typeObject);
          }

          List<Type> superInterfaceTypes = typeDeclaration.superInterfaceTypes();
          for (Type interfaceType : superInterfaceTypes) {
            ITypeBinding binding = interfaceType.resolveBinding();
            String qualifiedName = binding.getQualifiedName();
            TypeObject typeObject = TypeObject.extractTypeObject(qualifiedName);
            classObject.addInterface(typeObject);
          }

          FieldDeclaration[] fieldDeclarations = typeDeclaration.getFields();
          for (FieldDeclaration fieldDeclaration : fieldDeclarations) {
            Type fieldType = fieldDeclaration.getType();
            ITypeBinding binding = fieldType.resolveBinding();
            List<VariableDeclarationFragment> fragments = fieldDeclaration.fragments();
            for (VariableDeclarationFragment fragment : fragments) {
              String qualifiedName = binding.getQualifiedName();
              TypeObject typeObject = TypeObject.extractTypeObject(qualifiedName);
              typeObject.setArrayDimension(
                  typeObject.getArrayDimension() + fragment.getExtraDimensions());
              FieldObject fieldObject =
                  new FieldObject(typeObject, fragment.getName().getIdentifier());
              fieldObject.setClassName(classObject.getName());
              fieldObject.setVariableDeclarationFragment(fragment);

              int fieldModifiers = fieldDeclaration.getModifiers();
              if ((fieldModifiers & Modifier.PUBLIC) != 0) fieldObject.setAccess(Access.PUBLIC);
              else if ((fieldModifiers & Modifier.PROTECTED) != 0)
                fieldObject.setAccess(Access.PROTECTED);
              else if ((fieldModifiers & Modifier.PRIVATE) != 0)
                fieldObject.setAccess(Access.PRIVATE);
              else fieldObject.setAccess(Access.NONE);

              if ((fieldModifiers & Modifier.STATIC) != 0) fieldObject.setStatic(true);

              classObject.addField(fieldObject);
            }
          }

          MethodDeclaration[] methodDeclarations = typeDeclaration.getMethods();
          for (MethodDeclaration methodDeclaration : methodDeclarations) {
            String methodName = methodDeclaration.getName().getIdentifier();
            final ConstructorObject constructorObject = new ConstructorObject();
            constructorObject.setMethodDeclaration(methodDeclaration);
            constructorObject.setName(methodName);
            constructorObject.setClassName(classObject.getName());

            int methodModifiers = methodDeclaration.getModifiers();
            if ((methodModifiers & Modifier.PUBLIC) != 0)
              constructorObject.setAccess(Access.PUBLIC);
            else if ((methodModifiers & Modifier.PROTECTED) != 0)
              constructorObject.setAccess(Access.PROTECTED);
            else if ((methodModifiers & Modifier.PRIVATE) != 0)
              constructorObject.setAccess(Access.PRIVATE);
            else constructorObject.setAccess(Access.NONE);

            List<SingleVariableDeclaration> parameters = methodDeclaration.parameters();
            for (SingleVariableDeclaration parameter : parameters) {
              Type parameterType = parameter.getType();
              ITypeBinding binding = parameterType.resolveBinding();
              String qualifiedName = binding.getQualifiedName();
              TypeObject typeObject = TypeObject.extractTypeObject(qualifiedName);
              typeObject.setArrayDimension(
                  typeObject.getArrayDimension() + parameter.getExtraDimensions());
              if (parameter.isVarargs()) {
                typeObject.setArrayDimension(1);
              }
              ParameterObject parameterObject =
                  new ParameterObject(typeObject, parameter.getName().getIdentifier());
              parameterObject.setSingleVariableDeclaration(parameter);
              constructorObject.addParameter(parameterObject);
            }

            Block methodBody = methodDeclaration.getBody();
            if (methodBody != null) {
              MethodBodyObject methodBodyObject = new MethodBodyObject(methodBody);
              constructorObject.setMethodBody(methodBodyObject);
            }

            if (methodDeclaration.isConstructor()) {
              classObject.addConstructor(constructorObject);
            } else {
              MethodObject methodObject = new MethodObject(constructorObject);
              List<IExtendedModifier> extendedModifiers = methodDeclaration.modifiers();
              for (IExtendedModifier extendedModifier : extendedModifiers) {
                if (extendedModifier.isAnnotation()) {
                  Annotation annotation = (Annotation) extendedModifier;
                  if (annotation.getTypeName().getFullyQualifiedName().equals("Test")) {
                    methodObject.setTestAnnotation(true);
                    break;
                  }
                }
              }
              Type returnType = methodDeclaration.getReturnType2();
              ITypeBinding binding = returnType.resolveBinding();
              String qualifiedName = binding.getQualifiedName();
              TypeObject typeObject = TypeObject.extractTypeObject(qualifiedName);
              methodObject.setReturnType(typeObject);

              if ((methodModifiers & Modifier.ABSTRACT) != 0) methodObject.setAbstract(true);
              if ((methodModifiers & Modifier.STATIC) != 0) methodObject.setStatic(true);
              if ((methodModifiers & Modifier.SYNCHRONIZED) != 0)
                methodObject.setSynchronized(true);
              if ((methodModifiers & Modifier.NATIVE) != 0) methodObject.setNative(true);

              classObject.addMethod(methodObject);
              FieldInstructionObject fieldInstruction = methodObject.isGetter();
              if (fieldInstruction != null)
                systemObject.addGetter(methodObject.generateMethodInvocation(), fieldInstruction);
              fieldInstruction = methodObject.isSetter();
              if (fieldInstruction != null)
                systemObject.addSetter(methodObject.generateMethodInvocation(), fieldInstruction);
              fieldInstruction = methodObject.isCollectionAdder();
              if (fieldInstruction != null)
                systemObject.addCollectionAdder(
                    methodObject.generateMethodInvocation(), fieldInstruction);
              MethodInvocationObject methodInvocation = methodObject.isDelegate();
              if (methodInvocation != null)
                systemObject.addDelegate(methodObject.generateMethodInvocation(), methodInvocation);
            }
          }
          classObjects.add(classObject);
        }
      }
    }
    return classObjects;
  }
  /*(non-Javadoc)
   * @see org.eclipse.jdt.internal.ui.text.correction.ASTRewriteCorrectionProposal#getRewrite()
   */
  @Override
  protected ASTRewrite getRewrite() {
    AST ast = fMethodDecl.getAST();

    ITypeBinding returnBinding = getReturnTypeBinding();

    if (fExistingReturn != null) {
      ASTRewrite rewrite = ASTRewrite.create(ast);

      Expression expression =
          evaluateReturnExpressions(ast, returnBinding, fExistingReturn.getStartPosition());
      if (expression != null) {
        rewrite.set(fExistingReturn, ReturnStatement.EXPRESSION_PROPERTY, expression, null);

        addLinkedPosition(rewrite.track(expression), true, RETURN_EXPRESSION_KEY);
      }
      return rewrite;
    } else {
      ASTRewrite rewrite = ASTRewrite.create(ast);

      Block block = fMethodDecl.getBody();

      List<Statement> statements = block.statements();
      int nStatements = statements.size();
      ASTNode lastStatement = null;
      if (nStatements > 0) {
        lastStatement = statements.get(nStatements - 1);
      }

      if (returnBinding != null
          && lastStatement instanceof ExpressionStatement
          && lastStatement.getNodeType() != ASTNode.ASSIGNMENT) {
        Expression expression = ((ExpressionStatement) lastStatement).getExpression();
        ITypeBinding binding = expression.resolveTypeBinding();
        if (binding != null && binding.isAssignmentCompatible(returnBinding)) {
          Expression placeHolder = (Expression) rewrite.createMoveTarget(expression);

          ReturnStatement returnStatement = ast.newReturnStatement();
          returnStatement.setExpression(placeHolder);

          rewrite.replace(lastStatement, returnStatement, null);
          return rewrite;
        }
      }

      int offset;
      if (lastStatement == null) {
        offset = block.getStartPosition() + 1;
      } else {
        offset = lastStatement.getStartPosition() + lastStatement.getLength();
      }
      ReturnStatement returnStatement = ast.newReturnStatement();
      Expression expression = evaluateReturnExpressions(ast, returnBinding, offset);

      returnStatement.setExpression(expression);

      rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY).insertLast(returnStatement, null);

      addLinkedPosition(
          rewrite.track(returnStatement.getExpression()), true, RETURN_EXPRESSION_KEY);
      return rewrite;
    }
  }
  @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");
  }