@Override
 public void visit(Tree.AttributeDeclaration that) {
   if (that.getDeclarationModel() == declaration) {
     Tree.SpecifierOrInitializerExpression sie = that.getSpecifierOrInitializerExpression();
     if (sie != null) {
       super.visit(that);
       specify();
     } else {
       super.visit(that);
       if (declaration.isToplevel() && !isNativeHeader(declaration) && !isLate()) {
         if (isVariable()) {
           that.addError(
               "toplevel variable value must be initialized: '" + declaration.getName() + "'");
         } else {
           that.addError("toplevel value must be specified: '" + declaration.getName() + "'");
         }
       } else if (declaration.isClassOrInterfaceMember()
           && !isNativeHeader(declaration)
           && !declaration.isFormal()
           && that.getDeclarationModel().getInitializerParameter() == null
           && !that.getDeclarationModel().isLate()
           && declarationSection) {
         that.addError(
             "forward declaration may not occur in declaration section: '"
                 + declaration.getName()
                 + "'",
             1450);
       }
     }
   } else {
     super.visit(that);
   }
 }
 static List<TypedDeclaration> collectUninitializedMembers(Tree.Body body) {
   List<TypedDeclaration> uninitialized = new ArrayList<TypedDeclaration>();
   if (body != null) {
     List<Tree.Statement> statements = body.getStatements();
     for (Tree.Statement st : statements) {
       if (st instanceof Tree.AttributeDeclaration) {
         Tree.AttributeDeclaration ad = (Tree.AttributeDeclaration) st;
         if (ad.getSpecifierOrInitializerExpression() == null) {
           Value v = ad.getDeclarationModel();
           if (!v.isFormal()) {
             uninitialized.add(v);
           }
         }
       } else if (st instanceof Tree.MethodDeclaration) {
         Tree.MethodDeclaration md = (Tree.MethodDeclaration) st;
         if (md.getSpecifierExpression() == null) {
           Function m = md.getDeclarationModel();
           if (!m.isFormal()) {
             uninitialized.add(m);
           }
         }
       } else if (st instanceof Tree.SpecifierStatement) {
         Tree.SpecifierStatement ss = (Tree.SpecifierStatement) st;
         Tree.Term term = ss.getBaseMemberExpression();
         if (term instanceof Tree.BaseMemberExpression) {
           Tree.BaseMemberExpression bme = (Tree.BaseMemberExpression) term;
           uninitialized.remove(bme.getDeclaration());
         }
       }
     }
   }
   return uninitialized;
 }
 @Override
 public void visit(Tree.AttributeDeclaration that) {
   super.visit(that);
   if (hasOuterRefs(that.getDeclarationModel(), scope, statements)) {
     result = that;
   }
 }
 public ExtractFunctionRefactoring(ITextEditor editor) {
   super(editor);
   init((ITextSelection) editor.getSelectionProvider().getSelection());
   if (result != null) {
     newName = result.getDeclarationModel().getName();
   } else {
     newName = guessName();
   }
 }
 @Override
 public void visit(Tree.CompilationUnit that) {
   for (Tree.Declaration st : that.getDeclarations()) {
     if (st instanceof Tree.AttributeDeclaration) {
       Tree.AttributeDeclaration ad = (Tree.AttributeDeclaration) st;
       withinAttributeInitializer =
           ad.getDeclarationModel() == declaration
               && !(ad.getSpecifierOrInitializerExpression()
                   instanceof Tree.LazySpecifierExpression);
     } else {
       withinAttributeInitializer = false;
     }
     st.visit(this);
     withinAttributeInitializer = false;
   }
 }
 @Override
 public void visit(Tree.Body that) {
   if (hasParameter && that.getScope() == declaration.getContainer()) {
     hasParameter = false;
   }
   for (Tree.Statement st : that.getStatements()) {
     if (st instanceof Tree.AttributeDeclaration) {
       Tree.AttributeDeclaration ad = (Tree.AttributeDeclaration) st;
       withinAttributeInitializer =
           ad.getDeclarationModel() == declaration
               && !(ad.getSpecifierOrInitializerExpression()
                   instanceof Tree.LazySpecifierExpression);
     } else {
       withinAttributeInitializer = false;
     }
     st.visit(this);
     withinAttributeInitializer = false;
   }
 }
  private void extractStatementsInFile(TextChange tfc) throws CoreException {
    tfc.setEdit(new MultiTextEdit());
    IDocument doc = tfc.getCurrentDocument(null);

    Tree.Body body = (Tree.Body) node;

    Integer start = statements.get(0).getStartIndex();
    int length = statements.get(statements.size() - 1).getStopIndex() - start + 1;
    FindContainerVisitor fsv = new FindContainerVisitor(body);
    rootNode.visit(fsv);
    Tree.Declaration decNode = fsv.getDeclaration();
    /*if (decNode instanceof Tree.Declaration) {
        Tree.AnnotationList anns = ((Tree.Declaration) decNode).getAnnotationList();
        if (anns!=null && !anns.getAnnotations().isEmpty()) {
            decNode = anns.getAnnotations().get(0);
        }
    }*/
    Declaration dec = decNode.getDeclarationModel();
    FindLocalReferencesVisitor flrv = new FindLocalReferencesVisitor(dec);
    for (Statement s : statements) {
      s.visit(flrv);
    }
    List<TypeDeclaration> localTypes = new ArrayList<TypeDeclaration>();
    List<Tree.BaseMemberExpression> localRefs = new ArrayList<Tree.BaseMemberExpression>();
    for (Tree.BaseMemberExpression bme : flrv.getLocalReferences()) {
      if (result == null || !bme.getDeclaration().equals(result.getDeclarationModel())) {
        FindOuterReferencesVisitor v = new FindOuterReferencesVisitor(bme.getDeclaration());
        for (Statement s : body.getStatements()) {
          if (!statements.contains(s)) {
            s.visit(v);
          }
        }
        if (v.refs > 0) {
          addLocalType(dec, bme.getTypeModel(), localTypes, new ArrayList<ProducedType>());
          localRefs.add(bme);
        }
      }
    }

    String params = "";
    String args = "";
    Set<Declaration> done = new HashSet<Declaration>();
    boolean nonempty = false;
    for (Tree.BaseMemberExpression bme : localRefs) {
      if (done.add(bme.getDeclaration())) {
        params +=
            bme.getTypeModel().getProducedTypeName() + " " + bme.getIdentifier().getText() + ", ";
        args += bme.getIdentifier().getText() + ", ";
        nonempty = true;
      }
    }
    if (nonempty) {
      params = params.substring(0, params.length() - 2);
      args = args.substring(0, args.length() - 2);
    }

    String indent = "\n" + getIndent(decNode, doc);
    String extraIndent = indent + getDefaultIndent();

    String typeParams = "";
    String constraints = "";
    if (!localTypes.isEmpty()) {
      for (TypeDeclaration t : localTypes) {
        typeParams += t.getName() + ", ";
        if (!t.getSatisfiedTypes().isEmpty()) {
          constraints += extraIndent + getDefaultIndent() + "given " + t.getName() + " satisfies ";
          for (ProducedType pt : t.getSatisfiedTypes()) {
            constraints += pt.getProducedTypeName() + "&";
          }
          constraints = constraints.substring(0, constraints.length() - 1);
        }
      }
      typeParams = "<" + typeParams.substring(0, typeParams.length() - 2) + ">";
    }

    String content =
        result == null ? "void" : result.getDeclarationModel().getType().getProducedTypeName();
    content += " " + newName + typeParams + "(" + params + ")" + constraints + " {";
    for (Statement s : statements) {
      content += extraIndent + toString(s);
    }
    if (result != null) {
      content += extraIndent + "return " + result.getDeclarationModel().getName() + ";";
    }
    content += indent + "}" + indent + indent;

    String invocation = newName + "(" + args + ");";
    if (result != null) {
      String modifs;
      if (result.getDeclarationModel().isShared()) {
        modifs = "shared " + result.getDeclarationModel().getType().getProducedTypeName() + " ";
      } else {
        modifs = "value ";
      }
      invocation = modifs + result.getDeclarationModel().getName() + "=" + invocation;
    }

    tfc.addEdit(new InsertEdit(decNode.getStartIndex(), content));
    tfc.addEdit(new ReplaceEdit(start, length, invocation));
  }