static TextChange createEditorChange(CeylonEditor editor, IDocument document) {
   if (editor.isDirty()) {
     return new DocumentChange("Move from Source File", document);
   } else {
     return new TextFileChange("Move from Source File", getFile(editor.getEditorInput()));
   }
 }
 @Override
 public Object execute(ExecutionEvent event) throws ExecutionException {
   CeylonEditor editor = (CeylonEditor) getCurrentEditor();
   Tree.CompilationUnit cu = editor.getParseController().getRootNode();
   if (cu != null) {
     String imports = imports(cu);
     if (imports != null) {
       TextFileChange tfc =
           new TextFileChange(
               "Clean Imports", ((IFileEditorInput) editor.getEditorInput()).getFile());
       tfc.setEdit(new MultiTextEdit());
       ImportList il = cu.getImportList();
       int start;
       int length;
       String extra;
       if (il == null || il.getImports().isEmpty()) {
         start = 0;
         length = 0;
         extra = "\n";
       } else {
         start = il.getStartIndex();
         length = il.getStopIndex() - il.getStartIndex() + 1;
         extra = "";
       }
       //                if (!imports.trim().isEmpty()) {
       tfc.addEdit(new ReplaceEdit(start, length, imports + extra));
       tfc.initializeValidationData(null);
       try {
         getWorkspace().run(new PerformChangeOperation(tfc), new NullProgressMonitor());
       } catch (CoreException ce) {
         throw new ExecutionException("Error cleaning imports", ce);
       }
       //                }
     }
   }
   return null;
 }
 public static void refineFormalMembers(CeylonEditor editor) throws ExecutionException {
   Tree.CompilationUnit cu = editor.getParseController().getRootNode();
   if (cu == null) return;
   Node node = getSelectedNode(editor);
   IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput());
   final TextChange change = new DocumentChange("Refine Formal Members", document);
   change.setEdit(new MultiTextEdit());
   // TODO: copy/pasted from CeylonQuickFixAssistant
   Tree.Body body;
   int offset;
   if (node instanceof Tree.ClassDefinition) {
     body = ((Tree.ClassDefinition) node).getClassBody();
     offset = -1;
   } else if (node instanceof Tree.InterfaceDefinition) {
     body = ((Tree.InterfaceDefinition) node).getInterfaceBody();
     offset = -1;
   } else if (node instanceof Tree.ObjectDefinition) {
     body = ((Tree.ObjectDefinition) node).getClassBody();
     offset = -1;
   } else if (node instanceof Tree.ClassBody || node instanceof Tree.InterfaceBody) {
     body = (Tree.Body) node;
     offset = editor.getSelection().getOffset();
   } else {
     // TODO run a visitor to find the containing body!
     return; // TODO popup error dialog
   }
   boolean isInterface = body instanceof Tree.InterfaceBody;
   // TODO: copy/pasted from ImplementFormalMembersProposal
   List<Statement> statements = body.getStatements();
   String indent;
   String bodyIndent = getIndent(body, document);
   if (statements.isEmpty()) {
     indent = "\n" + bodyIndent + getDefaultIndent();
     if (offset < 0) offset = body.getStartIndex() + 1;
   } else {
     Statement statement = statements.get(statements.size() - 1);
     indent = "\n" + getIndent(statement, document);
     if (offset < 0) offset = statement.getStopIndex() + 1;
   }
   StringBuilder result = new StringBuilder();
   Set<Declaration> already = new HashSet<Declaration>();
   for (DeclarationWithProximity dwp : getProposals(node, cu).values()) {
     Declaration d = dwp.getDeclaration();
     if (d.isFormal() && ((ClassOrInterface) node.getScope()).isInheritedFromSupertype(d)) {
       ProducedReference pr = getRefinedProducedReference(node, d);
       result
           .append(indent)
           .append(getRefinementTextFor(d, pr, isInterface, indent))
           .append(indent);
       importSignatureTypes(d, cu, already);
     }
   }
   try {
     if (document.getChar(offset) == '}' && result.length() > 0) {
       result.append("\n").append(bodyIndent);
     }
   } catch (BadLocationException e) {
     e.printStackTrace();
   }
   applyImports(change, already, cu);
   change.addEdit(new InsertEdit(offset, result.toString()));
   change.initializeValidationData(null);
   try {
     getWorkspace().run(new PerformChangeOperation(change), new NullProgressMonitor());
   } catch (CoreException ce) {
     throw new ExecutionException("Error cleaning imports", ce);
   }
 }
 public OutlinePopup(CeylonEditor editor, Shell shell, int shellStyle) {
   super(shell, shellStyle, PLUGIN_ID + ".editor.showOutline", editor);
   setTitleText("Quick Outline \u2014 " + editor.getEditorInput().getName());
 }