package com.redhat.ceylon.eclipse.code.editor; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.DocumentCommand; import org.eclipse.jface.text.IDocument; import org.eclipse.swt.graphics.Point; class AutoEditTest extends CeylonAutoEditStrategy { AutoEditTest() { super(); } public static void main(String[] args) { AutoEditTest instance = new AutoEditTest(); Document doc = new Document("class Test()\n\t\textends Super(){\n\nvoid method(){\n\nfor (x in xs){}\n\n}\n\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "class Test()\n\t\textends Super(){\n\t\n\tvoid method(){\n\t\t\n\t\tfor (x in xs){}\n\t\t\n\t}\n\t\n}"); doc = new Document("class Test()\n\t\textends Super(){\n\nvoid method(){}\n\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "class Test()\n\t\textends Super(){\n\t\n\tvoid method(){}\n\t\n}"); doc = new Document("class Test()\n\t\textends Super(){\n\n\t\tvoid method(){}\n\t\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "class Test()\n\t\textends Super(){\n\t\n\tvoid method(){}\n\t\n}"); doc = new Document("class Test()\n\t\textends Super(){\nvoid method(){}\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "class Test()\n\t\textends Super(){\n\tvoid method(){}\n}"); doc = new Document("class Test()\n\t\textends Super(){\nvoid method(){\nfor (x in xs){}\n}\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "class Test()\n\t\textends Super(){\n\tvoid method(){\n\t\tfor (x in xs){}\n\t}\n}"); doc = new Document("class Test()\n\t\textends Super(){\n\t\tvoid method(){}\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "class Test()\n\t\textends Super(){\n\tvoid method(){}\n}"); doc = new Document("class Test()\nextends Super(){\n\nvoid method(){}\n\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "class Test()\n\t\textends Super(){\n\t\n\tvoid method(){}\n\t\n}"); doc = new Document("class Test() extends Super(){\n\nvoid method(){}\n\t\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "class Test() extends Super(){\n\t\n\tvoid method(){}\n\t\n}"); doc = new Document("class Test()\n\t\textends Super()\n{\n\nvoid method(){}\n\t\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "class Test()\n\t\textends Super()\n{\n\t\n\tvoid method(){}\n\t\n}"); doc = new Document("\tclass Test()\n\t\textends Super(){\n\nvoid method(){\n}\n\t\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "class Test()\n\t\textends Super(){\n\t\n\tvoid method(){\n\t}\n\t\n}"); doc = new Document("void x(){\n\tclass Test()\n\t\textends Super(){\n\nvoid method(){\n}\n\t\n}"); instance.doCorrectIndentation(doc); assertResult(doc, "void x(){\n\tclass Test()\n\t\t\textends Super(){\n\t\t\n\t\tvoid method(){\n\t\t}\n\t\t\n\t}"); doc = new Document("void x(){\n\tclass Test()\n\t\textends Super(){\nvoid method(){\n}\n}\n"); instance.doCorrectIndentation(doc); assertResult(doc, "void x(){\n\tclass Test()\n\t\t\textends Super(){\n\t\tvoid method(){\n\t\t}\n\t}\n"); doc = new Document("void x(){\n\tclass Test()\n\t\textends Super(){//foo\nvoid method(){//bar\n}//baz\n}\n"); instance.doCorrectIndentation(doc); assertResult(doc, "void x(){\n\tclass Test()\n\t\t\textends Super(){//foo\n\t\tvoid method(){//bar\n\t\t}//baz\n\t}\n"); doc = new Document("doc (\"Hello\n\t World\n\t !\")\nvoid hello(){}"); instance.doCorrectIndentation(doc); // assertResult(doc, "doc (\"Hello\n\t World\n\t !\")\nvoid hello(){}"); assertResult(doc, "doc (\"Hello\n World\n !\")\nvoid hello(){}"); doc = new Document("\"Hello\n World\n !\"\nvoid hello(){}"); instance.doCorrectIndentation(doc); assertResult(doc, "\"Hello\n World\n !\"\nvoid hello(){}"); doc = new Document("\"\"\"Hello\n World\n !\"\"\"\nvoid hello(){}"); instance.doCorrectIndentation(doc); assertResult(doc, "\"\"\"Hello\n World\n !\"\"\"\nvoid hello(){}"); doc = new Document("void x(){\n\t\"\"\"Hello\n\t World\n\t !\"\"\"\n\tvoid hello(){}"); instance.doCorrectIndentation(doc); assertResult(doc, "void x(){\n\t\"\"\"Hello\n\t World\n\t !\"\"\"\n\tvoid hello(){}"); //Note: this test fails, but that is more of a conceptual // problem with how the whole concept of correct // indentation works! doc = new Document("\t\"\"\"Hello\n\t World\n\t !\"\"\"\n\tvoid hello(){}"); instance.doCorrectIndentation(doc); assertResult(doc, "\"\"\"Hello\n World\n !\"\"\"\nvoid hello(){}"); doc = new Document("String x()\n=>\"hello\";"); instance.doCorrectIndentation(doc); assertResult(doc, "String x()\n\t\t=>\"hello\";"); doc = new Document("String x()\n\t=>\"hello\";"); instance.doCorrectIndentation(doc); assertResult(doc, "String x()\n\t\t=>\"hello\";"); doc = new Document("String x()\n\t\t=>\"hello\";"); instance.doCorrectIndentation(doc); assertResult(doc, "String x()\n\t\t=>\"hello\";"); doc = new Document("void x(){\n\tString x()\n\t\t\t=>\"hello\";"); instance.doCorrectIndentation(doc); assertResult(doc, "void x(){\n\tString x()\n\t\t\t=>\"hello\";"); doc = new Document("\tString x()\n\t\t\t=>\"hello\";"); instance.doCorrectIndentation(doc); assertResult(doc, "String x()\n\t\t=>\"hello\";"); doc = new Document("class X()\nextends Y()"); instance.doCorrectIndentation(doc); assertResult(doc, "class X()\n\t\textends Y()"); doc = new Document("class X()\n\textends Y()"); instance.doCorrectIndentation(doc); assertResult(doc, "class X()\n\t\textends Y()"); doc = new Document("class X()\n\t\textends Y()"); instance.doCorrectIndentation(doc); assertResult(doc, "class X()\n\t\textends Y()"); doc = new Document("void x(){\n\tclass X()\n\t\t\textends Y()"); instance.doCorrectIndentation(doc); assertResult(doc, "void x(){\n\tclass X()\n\t\t\textends Y()"); doc = new Document("class X()\nextends Y()\nsatisfies Z"); instance.doCorrectIndentation(doc); assertResult(doc, "class X()\n\t\textends Y()\n\t\tsatisfies Z"); doc = new Document("class X()\n\textends Y()\n\tsatisfies Z"); instance.doCorrectIndentation(doc); assertResult(doc, "class X()\n\t\textends Y()\n\t\tsatisfies Z"); doc = new Document("class X()\n\t\textends Y()\n\t\tsatisfies Z"); instance.doCorrectIndentation(doc); assertResult(doc, "class X()\n\t\textends Y()\n\t\tsatisfies Z"); doc = new Document("void x(){\n\tclass X()\n\t\t\textends Y()\n\t\t\tsatisfies Z"); instance.doCorrectIndentation(doc); assertResult(doc, "void x(){\n\tclass X()\n\t\t\textends Y()\n\t\t\tsatisfies Z"); doc = new Document("\tclass X()\n\t\t\textends Y()\n\t\t\tsatisfies Z"); instance.doCorrectIndentation(doc); assertResult(doc, "class X()\n\t\textends Y()\n\t\tsatisfies Z"); doc = new Document("void x(){\n\t//comment\n"); instance.doCorrectIndentation(doc); assertResult(doc, "void x(){\n\t//comment\n"); doc = new Document("void x(){\n//comment\n"); instance.doCorrectIndentation(doc); assertResult(doc, "void x(){\n\t//comment\n"); doc = new Document("void x(){\n\t\t//comment\n"); instance.doCorrectIndentation(doc); assertResult(doc, "void x(){\n\t//comment\n"); doc = new Document("\t//comment\n"); instance.doCorrectIndentation(doc); assertResult(doc, "//comment\n"); doc = new Document("\t\t//comment\n"); instance.doCorrectIndentation(doc); assertResult(doc, "//comment\n"); doc = new Document("\t/*\n\tcomment\n\t*/\n"); instance.doCorrectIndentation(doc); assertResult(doc, "/*\n comment\n */\n"); doc = new Document("\t\t/*\n\tcomment\n\t*/\n"); instance.doCorrectIndentation(doc); assertResult(doc, "/*\n comment\n */\n"); doc = new Document("/*\nhello\n world\n*/\n"); instance.doCorrectIndentation(doc); assertResult(doc, "/*\n hello\n world\n */\n"); doc = new Document("x=1;"); instance.doNewline(doc); assertResult(doc, "x=1;\n"); doc = new Document("x=1; "); instance.doNewline(doc); assertResult(doc, "x=1; \n"); doc = new Document("void x(){\n\tx=1;"); instance.doNewline(doc); assertResult(doc, "void x(){\n\tx=1;\n\t"); doc = new Document("void x(){\n\tx=1; //foo"); instance.doNewline(doc); assertResult(doc, "void x(){\n\tx=1; //foo\n\t"); doc = new Document("void x(){\nvoid y(){\n\t\tx=1; //foo"); instance.doNewline(doc); assertResult(doc, "void x(){\nvoid y(){\n\t\tx=1; //foo\n\t\t"); doc = new Document("\tx=1; //foo"); instance.doNewline(doc); assertResult(doc, "\tx=1; //foo\n\t"); doc = new Document("\t\tx=1; //foo"); instance.doNewline(doc); assertResult(doc, "\t\tx=1; //foo\n\t\t"); doc = new Document("Integer x {"); instance.doNewline(doc); assertResult(doc, "Integer x {\n\t\n}"); doc = new Document("Integer x { "); instance.doNewline(doc); assertResult(doc, "Integer x { \n\t\n}"); doc = new Document("\tInteger x {"); instance.doNewline(doc); assertResult(doc, "\tInteger x {\n\t\t\n\t}"); doc = new Document("\tInteger x { //foo"); instance.doNewline(doc); assertResult(doc, "\tInteger x { //foo\n\t\t\n\t}"); doc = new Document("\t\tInteger x { //foo"); instance.doNewline(doc); assertResult(doc, "\t\tInteger x { //foo\n\t\t\t\n\t\t}"); doc = new Document("//hello"); instance.doNewline(doc); assertResult(doc, "//hello\n"); doc = new Document("//hello "); instance.doNewline(doc); assertResult(doc, "//hello \n"); doc = new Document("\t//hello"); instance.doNewline(doc); assertResult(doc, "\t//hello\n\t"); doc = new Document("\t//hello "); instance.doNewline(doc); assertResult(doc, "\t//hello \n\t"); doc = new Document("\t\t//hello"); instance.doNewline(doc); assertResult(doc, "\t\t//hello\n\t\t"); doc = new Document("//hello\n"); instance.doNewline(doc); assertResult(doc, "//hello\n\n"); doc = new Document("\t//hello\n"); instance.doNewline(doc); assertResult(doc, "\t//hello\n\n\t"); doc = new Document("\t//hello\n\t"); instance.doNewline(doc); assertResult(doc, "\t//hello\n\t\n\t"); doc = new Document("//hello \n "); instance.doNewline(doc); assertResult(doc, "//hello \n \n"); doc = new Document("//hello \n\t"); instance.doNewline(doc); assertResult(doc, "//hello \n\t\n"); doc = new Document("\t//hello \n\t"); instance.doNewline(doc); assertResult(doc, "\t//hello \n\t\n\t"); doc = new Document("\t//hello\n\t"); instance.doNewline(doc); assertResult(doc, "\t//hello\n\t\n\t"); doc = new Document("\t//hello \n\t"); instance.doNewline(doc); assertResult(doc, "\t//hello \n\t\n\t"); doc = new Document("/*hello"); instance.doNewline(doc); assertResult(doc, "/*hello\n \n */"); doc = new Document("\t/*hello"); instance.doNewline(doc); assertResult(doc, "\t/*hello\n\t \n\t */"); doc = new Document("\t/*\n\thello"); instance.doNewline(doc); assertResult(doc, "\t/*\n\thello\n\t "); doc = new Document("void x() {}"); instance.doNewline(doc); assertResult(doc, "void x() {}\n"); doc = new Document("void x() {} "); instance.doNewline(doc); assertResult(doc, "void x() {} \n"); doc = new Document("\tvoid x() {}"); instance.doNewline(doc); assertResult(doc, "\tvoid x() {}\n\t"); doc = new Document("\tvoid x() {} //foo"); instance.doNewline(doc); assertResult(doc, "\tvoid x() {} //foo\n\t"); doc = new Document("x=1;\n"); instance.doNewline(doc); assertResult(doc, "x=1;\n\n"); doc = new Document("x=1; \n "); instance.doNewline(doc); assertResult(doc, "x=1; \n \n "); //do we really want the space at the end here? doc = new Document("\tx=1;\n\t"); instance.doNewline(doc); assertResult(doc, "\tx=1;\n\t\n\t"); doc = new Document("\tx=1; //foo\n\t"); instance.doNewline(doc); assertResult(doc, "\tx=1; //foo\n\t\n\t"); doc = new Document("\t\tx=1; //foo\n\t\t"); instance.doNewline(doc); assertResult(doc, "\t\tx=1; //foo\n\t\t\n\t\t"); doc = new Document("Integer x {\n\t"); instance.doNewline(doc); assertResult(doc, "Integer x {\n\t\n\t"); doc = new Document("Integer x { \n\t"); instance.doNewline(doc); assertResult(doc, "Integer x { \n\t\n\t"); doc = new Document("\tInteger x {\n\t\t"); instance.doNewline(doc); assertResult(doc, "\tInteger x {\n\t\t\n\t\t"); doc = new Document("\tInteger x { //foo\n\t\t"); instance.doNewline(doc); assertResult(doc, "\tInteger x { //foo\n\t\t\n\t\t"); doc = new Document("\t\tInteger x { //foo\n\t\t\t"); instance.doNewline(doc); assertResult(doc, "\t\tInteger x { //foo\n\t\t\t\n\t\t\t"); doc = new Document("void x() {}\n"); instance.doNewline(doc); assertResult(doc, "void x() {}\n\n"); doc = new Document("void x() {} \n "); instance.doNewline(doc); assertResult(doc, "void x() {} \n \n "); //do we really want the space doc = new Document("\tvoid x() {}\n\t"); instance.doNewline(doc); assertResult(doc, "\tvoid x() {}\n\t\n\t"); doc = new Document("\tvoid x() {} //foo\n\t"); instance.doNewline(doc); assertResult(doc, "\tvoid x() {} //foo\n\t\n\t"); doc = new Document("String greeting = \"hello"); instance.doNewline(doc); assertResult(doc, "String greeting = \"hello\n "); doc = new Document("\tString greeting = \"hello"); instance.doNewline(doc); assertResult(doc, "\tString greeting = \"hello\n\t "); doc = new Document("String greeting = \"hello\n world"); instance.doNewline(doc); assertResult(doc, "String greeting = \"hello\n world\n "); doc = new Document("\tString greeting = \"hello\n\t world"); instance.doNewline(doc); assertResult(doc, "\tString greeting = \"hello\n\t world\n\t "); doc = new Document("String greeting = \"\"\"hello"); instance.doNewline(doc); assertResult(doc, "String greeting = \"\"\"hello\n "); doc = new Document("\tString greeting = \"\"\"hello"); instance.doNewline(doc); assertResult(doc, "\tString greeting = \"\"\"hello\n\t "); doc = new Document("String greeting = \"\"\"hello\n world"); instance.doNewline(doc); assertResult(doc, "String greeting = \"\"\"hello\n world\n "); doc = new Document("\tString greeting = \"\"\"hello\n\t world"); instance.doNewline(doc); assertResult(doc, "\tString greeting = \"\"\"hello\n\t world\n\t "); doc = new Document("String x()\n=>\"hello\" +"); instance.doNewline(doc); assertResult(doc, "String x()\n=>\"hello\" +\n\t\t"); //What should this one really do? Not well-defined doc = new Document("String x()\n\t=>\"hello\" +"); instance.doNewline(doc); assertResult(doc, "String x()\n\t=>\"hello\" +\n\t\t"); doc = new Document("String x()\n\t\t=>\"hello\" +"); instance.doNewline(doc); assertResult(doc, "String x()\n\t\t=>\"hello\" +\n\t\t"); doc = new Document("\tString x()\n\t\t\t=>\"hello\" +"); instance.doNewline(doc); assertResult(doc, "\tString x()\n\t\t\t=>\"hello\" +\n\t\t\t"); doc = new Document("String x()\n=>\"hello\";"); instance.doNewline(doc); assertResult(doc, "String x()\n=>\"hello\";\n"); doc = new Document("String x()\n\t=>\"hello\";"); instance.doNewline(doc); assertResult(doc, "String x()\n\t=>\"hello\";\n"); doc = new Document("String x()\n\t\t=>\"hello\";"); instance.doNewline(doc); assertResult(doc, "String x()\n\t\t=>\"hello\";\n"); doc = new Document("\tString x()\n\t\t\t=>\"hello\";"); instance.doNewline(doc); assertResult(doc, "\tString x()\n\t\t\t=>\"hello\";\n\t"); doc = new Document("void x() {\n\t"); instance.doClosingBrace(doc); assertResult(doc, "void x() {\n}"); doc = new Document("\tvoid x() {\n\t\t"); instance.doClosingBrace(doc); assertResult(doc, "\tvoid x() {\n\t}"); doc = new Document("void x() {\n\tprint(\"hello\");\n\t"); instance.doClosingBrace(doc); assertResult(doc, "void x() {\n\tprint(\"hello\");\n}"); doc = new Document("void x() {\n\tprint(\"hello\");\n\t//bye\n\t"); instance.doClosingBrace(doc); assertResult(doc, "void x() {\n\tprint(\"hello\");\n\t//bye\n}"); } static int count=0; private static void assertResult(Document doc, String expected) { count++; String actual = doc.get(); if (!actual.equals(expected)) { System.out.println("assertion failed: " + count); System.out.println(actual); System.out.println("expected:"); System.out.println(expected); } } private void doNewline(IDocument doc) { try { DocumentCommand cmd= new DocumentCommand() { }; cmd.offset= doc.getLength(); cmd.length= 0; cmd.text= Character.toString('\n'); cmd.doit= true; cmd.shiftsCaret= true; customizeDocumentCommand(doc, cmd); doc.replace(cmd.offset, cmd.length, cmd.text); } catch (BadLocationException e) { System.err.println("Correct Indentation command failed " + e.getMessage()); } } private void doClosingBrace(IDocument doc) { try { DocumentCommand cmd= new DocumentCommand() { }; cmd.offset= doc.getLength(); cmd.length= 0; cmd.text= Character.toString('}'); cmd.doit= true; cmd.shiftsCaret= true; customizeDocumentCommand(doc, cmd); doc.replace(cmd.offset, cmd.length, cmd.text); } catch (BadLocationException e) { System.err.println("Correct Indentation command failed " + e.getMessage()); } } void doCorrectIndentation(IDocument doc) { Point p = new Point(0, doc.getLength()); try { final int selStart= p.x; final int selLen= p.y; final int selEnd= selStart + selLen; final int startLine= doc.getLineOfOffset(selStart); int endLine= doc.getLineOfOffset(selEnd); // If the selection extends just to the beginning of the next line, don't indent that one too if (selLen > 0 && lookingAtLineEnd(doc, selEnd)) { endLine--; } // Indent each line using the AutoEditStrategy for(int line= startLine; line <= endLine; line++) { int lineStartOffset= doc.getLineOffset(line); // Replace the existing indentation with the desired indentation. // Use the language-specific AutoEditStrategy, which requires a DocumentCommand. DocumentCommand cmd= new DocumentCommand() { }; cmd.offset= lineStartOffset; cmd.length= 0; cmd.text= Character.toString('\t'); cmd.doit= true; cmd.shiftsCaret= false; // boolean saveMode= fAutoEditStrategy.setFixMode(true); customizeDocumentCommand(doc, cmd); // fAutoEditStrategy.setFixMode(saveMode); doc.replace(cmd.offset, cmd.length, cmd.text); } } catch (BadLocationException e) { System.err.println("Correct Indentation command failed " + e.getMessage()); } } boolean lookingAtLineEnd(IDocument doc, int pos) { String[] legalLineTerms= doc.getLegalLineDelimiters(); try { for(String lineTerm: legalLineTerms) { int len= lineTerm.length(); if (pos > len && doc.get(pos - len, len).equals(lineTerm)) { return true; } } } catch (BadLocationException e) { //System.err.println("Error examining document for line termination", e); } return false; } }