private boolean terminateWithSemicolon() throws Exception {
    final IDocument doc = editor.getCeylonSourceViewer().getDocument();
    final TextChange change = new DocumentChange("Terminate Statement", doc);
    change.setEdit(new MultiTextEdit());
    CeylonParseController parser = parse();
    CompilationUnit rootNode = parser.getRootNode();
    IRegion li = getLineInfo(doc);
    String lineText = doc.get(li.getOffset(), li.getLength());
    final List<CommonToken> tokens = parser.getTokens();
    // final int startOfCodeInLine = getCodeStart(li, lineText, tokens);
    final int endOfCodeInLine = getCodeEnd(li, lineText, tokens);
    if (!doc.get(endOfCodeInLine, 1).equals(";")) {
      new Processor() {
        @Override
        public void visit(Tree.Annotation that) {
          super.visit(that);
          terminateWithSemicolon(that);
        }

        @Override
        public void visit(Tree.StatementOrArgument that) {
          super.visit(that);
          if (that instanceof Tree.ExecutableStatement && !(that instanceof Tree.ControlStatement)
              || that instanceof Tree.AttributeDeclaration
              || that instanceof Tree.MethodDeclaration
              || that instanceof Tree.ClassDeclaration
              || that instanceof Tree.InterfaceDeclaration
              || that instanceof Tree.SpecifiedArgument) {
            terminateWithSemicolon(that);
          }
        }

        private void terminateWithSemicolon(Node that) {
          try {
            if (that.getStartIndex() <= endOfCodeInLine && that.getStopIndex() >= endOfCodeInLine) {
              Token et = that.getEndToken();
              if (et == null
                  || et.getType() != CeylonLexer.SEMICOLON
                  || that.getStopIndex() > endOfCodeInLine) {
                if (!change.getEdit().hasChildren()) {
                  change.addEdit(new InsertEdit(endOfCodeInLine + 1, ";"));
                }
              }
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }.visit(rootNode);
      if (change.getEdit().hasChildren()) {
        change.perform(new NullProgressMonitor());
        return true;
      }
    }
    return false;
  }
 @Override
 public boolean isEnabled() {
   IEditorPart editor = getCurrentEditor();
   if (super.isEnabled()
       && editor instanceof CeylonEditor
       && editor.getEditorInput() instanceof IFileEditorInput) {
     CeylonParseController cpc = ((CeylonEditor) editor).getParseController();
     return cpc == null || cpc.getRootNode() == null ? false : true;
     // !cpc.getRootNode().getImportList().getImports().isEmpty();
   }
   return false;
 }
 private Tree.Declaration getSelectionTarget(ITextSelection textSel) {
   CeylonEditor editor = (CeylonEditor) getCurrentEditor();
   CeylonParseController pc = editor.getParseController();
   if (pc == null) {
     return null;
   } else {
     Tree.CompilationUnit ast = pc.getRootNode();
     if (ast == null) {
       return null;
     } else {
       Object sourceNode = findNode(ast, textSel.getOffset());
       if (sourceNode == null) {
         return null;
       } else {
         return getReferencedNode(sourceNode, pc);
       }
     }
   }
 }
  private boolean terminateWithBrace() throws Exception {
    IDocument doc = editor.getCeylonSourceViewer().getDocument();
    final TextChange change = new DocumentChange("Terminate Statement", doc);
    change.setEdit(new MultiTextEdit());
    CeylonParseController parser = parse();
    CompilationUnit rootNode = parser.getRootNode();
    IRegion li = getLineInfo(doc);
    final String lineText = doc.get(li.getOffset(), li.getLength());
    final List<CommonToken> tokens = parser.getTokens();
    final int startOfCodeInLine = getCodeStart(li, lineText, tokens);
    final int endOfCodeInLine = getCodeEnd(li, lineText, tokens);
    new Processor() {
      @Override
      public void visit(Tree.Expression that) {
        super.visit(that);
        if (that.getStopIndex() <= endOfCodeInLine && that.getStartIndex() >= startOfCodeInLine) {
          Token et = that.getMainEndToken();
          Token st = that.getMainToken();
          if (st != null
              && st.getType() == CeylonLexer.LPAREN
              && (et == null || et.getType() != CeylonLexer.RPAREN)) {
            if (!change.getEdit().hasChildren()) {
              change.addEdit(new InsertEdit(that.getStopIndex() + 1, ")"));
            }
          }
        }
      }

      @Override
      public void visit(Tree.ParameterList that) {
        super.visit(that);
        terminate(that, CeylonLexer.RPAREN, ")");
      }

      public void visit(Tree.IndexExpression that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACKET, "]");
      }

      @Override
      public void visit(Tree.TypeParameterList that) {
        super.visit(that);
        terminate(that, CeylonLexer.LARGER_OP, ">");
      }

      @Override
      public void visit(Tree.TypeArgumentList that) {
        super.visit(that);
        terminate(that, CeylonLexer.LARGER_OP, ">");
      }

      @Override
      public void visit(Tree.PositionalArgumentList that) {
        super.visit(that);
        if (that.getToken().getType() == CeylonLexer.LPAREN) { // for infix function syntax
          terminate(that, CeylonLexer.RPAREN, ")");
        }
      }

      @Override
      public void visit(Tree.NamedArgumentList that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, " }");
      }

      @Override
      public void visit(Tree.SequenceEnumeration that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, " }");
      }

      @Override
      public void visit(Tree.IterableType that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, "}");
      }

      @Override
      public void visit(Tree.Tuple that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACKET, "]");
      }

      @Override
      public void visit(Tree.TupleType that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACKET, "]");
      }

      @Override
      public void visit(Tree.ConditionList that) {
        super.visit(that);
        initiate(that, CeylonLexer.LPAREN, "(");
        // does not really work right:
        terminate(that, CeylonLexer.RPAREN, ")");
      }

      @Override
      public void visit(Tree.ForIterator that) {
        super.visit(that);
        initiate(that, CeylonLexer.LPAREN, "(");
        // does not really work right:
        terminate(that, CeylonLexer.RPAREN, ")");
      }

      @Override
      public void visit(Tree.ImportMemberOrTypeList that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, " }");
      }

      @Override
      public void visit(Tree.ImportModule that) {
        super.visit(that);
        terminate(that, CeylonLexer.SEMICOLON, ";");
      }

      @Override
      public void visit(Tree.ImportModuleList that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, " }");
      }

      @Override
      public void visit(Tree.PackageDescriptor that) {
        super.visit(that);
        terminate(that, CeylonLexer.SEMICOLON, ";");
      }

      @Override
      public void visit(Tree.Body that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, " }");
      }

      @Override
      public void visit(Tree.StatementOrArgument that) {
        super.visit(that);
        if (
        /*that instanceof Tree.ExecutableStatement &&
        	!(that instanceof Tree.ControlStatement) ||
        that instanceof Tree.AttributeDeclaration ||
        that instanceof Tree.MethodDeclaration ||
        that instanceof Tree.ClassDeclaration ||
        that instanceof Tree.InterfaceDeclaration ||*/
        that instanceof Tree.SpecifiedArgument) {
          terminate(that, CeylonLexer.SEMICOLON, ";");
        }
      }

      private void initiate(Node that, int tokenType, String ch) {
        if (that.getStartIndex() >= startOfCodeInLine && that.getStartIndex() <= endOfCodeInLine) {
          Token et = that.getMainToken();
          if (et == null || et.getType() != tokenType || et.getText().startsWith("<missing ")) {
            if (!change.getEdit().hasChildren()) {
              change.addEdit(new InsertEdit(that.getStartIndex(), ch));
            }
          }
        }
      }

      private void terminate(Node that, int tokenType, String ch) {
        if (that.getStartIndex() >= startOfCodeInLine && that.getStartIndex() <= endOfCodeInLine) {
          Token et = that.getMainEndToken();
          if ((et == null || et.getType() != tokenType) || that.getStopIndex() > endOfCodeInLine) {
            if (!change.getEdit().hasChildren()) {
              change.addEdit(new InsertEdit(min(endOfCodeInLine, that.getStopIndex()) + 1, ch));
            }
          }
        }
      }
    }.visit(rootNode);
    if (change.getEdit().hasChildren()) {
      change.perform(new NullProgressMonitor());
      return true;
    }
    return false;
  }