Home | History | Annotate | Download | only in editors
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.ide.eclipse.adt.internal.editors;
     17 
     18 import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.AdtProjectTest;
     19 
     20 import org.eclipse.core.resources.IFile;
     21 import org.eclipse.jface.text.DocumentCommand;
     22 import org.eclipse.jface.text.IDocument;
     23 import org.eclipse.jface.text.source.ISourceViewer;
     24 import org.eclipse.swt.graphics.Point;
     25 import org.eclipse.ui.IEditorPart;
     26 import org.eclipse.ui.IWorkbenchPage;
     27 import org.eclipse.ui.PlatformUI;
     28 import org.eclipse.ui.ide.IDE;
     29 
     30 @SuppressWarnings("javadoc")
     31 public class AndroidXmlAutoEditStrategyTest extends AdtProjectTest {
     32 
     33     public void checkInsertNewline(String before, String after) throws Exception {
     34         AndroidXmlAutoEditStrategy s = new AndroidXmlAutoEditStrategy();
     35 
     36         // All tests just operate on the "edithandling" document; the contents are
     37         // ignored and replaced with the before-document passed in
     38         IFile file = getLayoutFile(getProject(), "edithandling.xml");
     39 
     40         IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
     41         assertNotNull(page);
     42         IEditorPart editor = IDE.openEditor(page, file);
     43         assertTrue(editor instanceof AndroidXmlEditor);
     44         AndroidXmlEditor layoutEditor = (AndroidXmlEditor) editor;
     45         ISourceViewer viewer = layoutEditor.getStructuredSourceViewer();
     46 
     47         String newDocumentContent = stripCaret(before);
     48         IDocument document = viewer.getDocument();
     49         document.replace(0, document.getLength(), newDocumentContent);
     50 
     51         // Determine the offset, and possibly make text range selections as well
     52         int offset = updateCaret(viewer, before);
     53 
     54         DocumentCommand c = new TestDocumentCommand();
     55         c.doit = true;
     56         c.offset = offset;
     57         c.caretOffset = -1;
     58         c.length = 0;
     59         c.text = "\n";
     60 
     61         s.customizeDocumentCommand(document, c);
     62 
     63         if (c.doit) {
     64             if (c.length == 0 && c.text == null) {
     65                 return;
     66             }
     67 
     68             document.replace(c.offset, c.length, c.text);
     69 
     70             int caretOffset = c.offset + c.text.length();
     71 
     72             // The shiftsCaret flag doesn't behave the way it's documented to
     73             //if (c.shiftsCaret && c.caretOffset != -1) {
     74             if (c.caretOffset != -1) {
     75                 caretOffset = c.caretOffset;
     76             }
     77             viewer.setSelectedRange(caretOffset, 0);
     78         }
     79 
     80         String text = document.get();
     81         Point selectedRange = viewer.getSelectedRange();
     82         assert selectedRange.y == 0;
     83         String textWithCaret = text;
     84         if (selectedRange.x >= 0) {
     85             textWithCaret = text.substring(0, selectedRange.x) + "^" +
     86                 text.substring(selectedRange.x);
     87         }
     88 
     89         assertEquals(after, textWithCaret);
     90     }
     91 
     92     private static String stripCaret(String s) {
     93         int index = s.indexOf('^');
     94         assertTrue(index != -1);
     95         return s.substring(0, index) + s.substring(index + 1);
     96     }
     97 
     98     public void testCornerCase1() throws Exception {
     99         checkInsertNewline("^", "\n^");
    100     }
    101 
    102     public void testCornerCase2() throws Exception {
    103         checkInsertNewline(
    104                 "\n^",
    105 
    106                 "\n\n^");
    107     }
    108 
    109     public void testCornerCase3() throws Exception {
    110         checkInsertNewline(
    111                 "    ^",
    112 
    113                 "    \n" +
    114                 "    ^");
    115     }
    116 
    117     public void testSimpleIndentation1() throws Exception {
    118         checkInsertNewline(
    119                 "   ^ ",
    120 
    121                 "   \n" +
    122                 "   ^ ");
    123     }
    124 
    125     public void testSimpleIndentation2() throws Exception {
    126         checkInsertNewline(
    127                 "\n" +
    128                 "   foo^\n",
    129 
    130                 "\n" +
    131                 "   foo\n" +
    132                 "   ^\n");
    133     }
    134 
    135     public void testSimpleIndentation3() throws Exception {
    136         checkInsertNewline(
    137                 "\n" +
    138                 "    <newtag>^\n",
    139 
    140                 "\n" +
    141                 "    <newtag>\n" +
    142                 "        ^\n");
    143     }
    144 
    145     public void testSimpleIndentation4() throws Exception {
    146         checkInsertNewline(
    147                 "\n" +
    148                 "    <newtag/>^\n",
    149 
    150                 "\n" +
    151                 "    <newtag/>\n" +
    152                 "    ^\n");
    153     }
    154 
    155     public void testSimpleIndentation5() throws Exception {
    156         checkInsertNewline(
    157                 "\n" +
    158                 "    <newtag^\n",
    159                 "\n" +
    160                 "    <newtag\n" +
    161                 "        ^\n");
    162     }
    163 
    164     public void testSplitAttribute() throws Exception {
    165         checkInsertNewline(
    166                 "\n" +
    167                 "    <newtag ^attribute='value'/>\n",
    168 
    169                 "\n" +
    170                 "    <newtag \n" +
    171                 "        ^attribute='value'/>\n");
    172     }
    173 
    174     public void testIndentationInComments1() throws Exception {
    175         // Make sure that inside a comment we ignore tags etc
    176         checkInsertNewline(
    177                 "<!--\n   foo^\n--->\n",
    178 
    179                 "<!--\n   foo\n   ^\n--->\n");
    180     }
    181 
    182     public void testIndentationInComments2() throws Exception {
    183         // Make sure that inside a comment we ignore tags etc
    184         checkInsertNewline(
    185                 "\n" +
    186                 "<!--\n" +
    187                 "<foo><^\n" +
    188                 "-->\n",
    189 
    190                 "\n" +
    191                 "<!--\n" +
    192                 "<foo><\n" +
    193                 "^\n" +
    194                 "-->\n");
    195     }
    196 
    197     public void testSurroundCaret() throws Exception {
    198         checkInsertNewline(
    199                 "\n" +
    200                 "    <item>^</item>\n",
    201 
    202                 "\n" +
    203                 "    <item>\n" +
    204                 "        ^\n" +
    205                 "    </item>\n");
    206     }
    207 
    208     public void testSurroundCaret2() throws Exception {
    209         // This test combines both surround with and continuing earlier lines (where
    210         // it searches for a matching tag)
    211         checkInsertNewline(
    212                 "\n" +
    213                 "    <foo\n" +
    214                 "        name='value'>^</foo>\n",
    215 
    216                 "\n" +
    217                 "    <foo\n" +
    218                 "        name='value'>\n" +
    219                 "        ^\n" +
    220                 "    </foo>\n");
    221     }
    222 
    223     public void testContinueEarlierLine1() throws Exception {
    224         // Here we need to indent to the exact location of an earlier line
    225         checkInsertNewline(
    226                 "\n" +
    227                 "    <foo\n" +
    228                 "        name='value'/>^\n",
    229 
    230                 "\n" +
    231                 "    <foo\n" +
    232                 "        name='value'/>\n" +
    233                 "    ^\n");
    234     }
    235 
    236     public void testContinueEarlierLine2() throws Exception {
    237         checkInsertNewline(
    238                 "\n" +
    239                 "    <foo\n" +
    240                 "        name='value'></foo>^\n",
    241 
    242                 "\n" +
    243                 "    <foo\n" +
    244                 "        name='value'></foo>\n" +
    245                 "    ^\n");
    246         // Note that
    247         //    <foo
    248         //           >
    249         //    </foo>
    250         // does not require special handling, this only happens with the closing tag is sharing
    251         // a line.
    252     }
    253 
    254     public void testContinueEarlierLine3() throws Exception {
    255         // Make sure the code to look up the corresponding opening tag works properly
    256         checkInsertNewline(
    257                 "\n" +
    258                 "    <foo\n" +
    259                 "        name='value'><bar></bar><baz/></foo>^\n",
    260 
    261                 "\n" +
    262                 "    <foo\n" +
    263                 "        name='value'><bar></bar><baz/></foo>\n" +
    264                 "    ^\n");
    265     }
    266 
    267     public void testContinueEarlierLine4() throws Exception {
    268         checkInsertNewline(
    269                 "    <Button\n" +
    270                 "        android:id=\"@+id/button1\"\n" +
    271                 "        android:layout_width=\"wrap_content\"\n" +
    272                 "        android:layout_height=\"wrap_content\"\n" +
    273                 "        android:text=\"Button\" >^\n" +
    274                 "    </Button>\n",
    275 
    276                 "    <Button\n" +
    277                 "        android:id=\"@+id/button1\"\n" +
    278                 "        android:layout_width=\"wrap_content\"\n" +
    279                 "        android:layout_height=\"wrap_content\"\n" +
    280                 "        android:text=\"Button\" >\n" +
    281                 "        ^\n" +
    282                 "    </Button>\n");
    283     }
    284 
    285     public void testIndent() throws Exception {
    286         checkInsertNewline(
    287                 "    <Button\n" +
    288                 "        attr=\"value\"></Button>^\n",
    289 
    290                 "    <Button\n" +
    291                 "        attr=\"value\"></Button>\n" +
    292                 "    ^\n" +
    293                 "");
    294     }
    295 
    296     public void testLineBeginning1() throws Exception {
    297         // Test that if you insert on a blank line, we just add a newline and indent
    298         checkInsertNewline(
    299                 "<foo>\n" +
    300                 "^\n" +
    301                 "</foo>",
    302 
    303                 "<foo>\n" +
    304                 "\n" +
    305                 "    ^\n" +
    306                 "</foo>");
    307     }
    308 
    309     public void testLineBeginning2() throws Exception {
    310         // Test that if you insert with the caret on the beginning of a line that has
    311         // content, we insert an indent correctly
    312         checkInsertNewline(
    313                 "<foo>\n" +
    314                 "^    <bar/>\n" +
    315                 "</foo>",
    316 
    317                 "<foo>\n" +
    318                 "\n" +
    319                 "    ^<bar/>\n" +
    320                 "</foo>");
    321     }
    322 
    323     public void testLineBeginning3() throws Exception {
    324         checkInsertNewline(
    325                 "<foo>\n" +
    326                 "    <bar>\n" +
    327                 "^\n" +
    328                 "        <baz/>\n" +
    329                 "    </bar>\n" +
    330                 "</foo>",
    331 
    332                 "<foo>\n" +
    333                 "    <bar>\n" +
    334                 "\n" +
    335                 "        ^\n" +
    336                 "        <baz/>\n" +
    337                 "    </bar>\n" +
    338                 "</foo>");
    339 
    340     }
    341 
    342     public void testLineBeginning4() throws Exception {
    343         // Test that if you insert with the caret on the beginning of a line that has
    344         // content, we insert an indent correctly
    345         checkInsertNewline(
    346                 "<foo>\n" +
    347                 "    <bar>\n" +
    348                 "\n" +
    349                 "^        <baz/>\n" +
    350                 "    </bar>\n" +
    351                 "</foo>",
    352 
    353                 "<foo>\n" +
    354                 "    <bar>\n" +
    355                 "\n" +
    356                 "\n" +
    357                 "        ^<baz/>\n" +
    358                 "    </bar>\n" +
    359                 "</foo>");
    360     }
    361 
    362     public void testLineBeginning5() throws Exception {
    363         // Test that if you insert with the caret on the beginning of a line that has
    364         // content, we insert an indent correctly
    365         checkInsertNewline(
    366                 "<foo>\n" +
    367                 "    <bar>\n" +
    368                 "\n" +
    369                 "    ^    <baz/>\n" +
    370                 "    </bar>\n" +
    371                 "</foo>",
    372 
    373                 "<foo>\n" +
    374                 "    <bar>\n" +
    375                 "\n" +
    376                 "    \n" +
    377                 "        ^<baz/>\n" +
    378                 "    </bar>\n" +
    379                 "</foo>");
    380     }
    381 
    382     public void testLineBeginning6() throws Exception {
    383 
    384         checkInsertNewline(
    385                 "    <foo>\n" +
    386                 "        <bar>\n" +
    387                 "            \n" +
    388                 "        \n" +
    389                 "^        </bar>\n" +
    390                 "    </foo>\n",
    391 
    392                 "    <foo>\n" +
    393                 "        <bar>\n" +
    394                 "            \n" +
    395                 "        \n" +
    396                 "\n" +
    397                 "        ^</bar>\n" +
    398                 "    </foo>\n");
    399     }
    400 
    401     public void testBlankContinuation() throws Exception {
    402 
    403         checkInsertNewline(
    404                 "    <foo>\n" +
    405                 "        <bar>\n" +
    406                 "            ^\n" +
    407                 "        </bar>\n" +
    408                 "    </foo>\n" +
    409                 "",
    410 
    411                 "    <foo>\n" +
    412                 "        <bar>\n" +
    413                 "            \n" +
    414                 "            ^\n" +
    415                 "        </bar>\n" +
    416                 "    </foo>\n" +
    417                 "");
    418     }
    419 
    420     public void testIssue22332a() throws Exception {
    421         checkInsertNewline(
    422                 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    423                 "<resources>\n" +
    424                 "\n" +
    425                 "    <string name=\"hello\">Hello World, MainActivity!</string>^\n" +
    426                 "\n" +
    427                 "</resources>",
    428 
    429                 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    430                 "<resources>\n" +
    431                 "\n" +
    432                 "    <string name=\"hello\">Hello World, MainActivity!</string>\n" +
    433                 "    ^\n" +
    434                 "\n" +
    435                 "</resources>");
    436     }
    437 
    438     public void testIssue22332b() throws Exception {
    439         checkInsertNewline(
    440                 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    441                         "<resources>\n" +
    442                         "\n" +
    443                         "    <string name=\"hello\">Hello World, MainActivity!</string>\n" +
    444                         "    ^\n" +
    445                         "\n" +
    446                         "</resources>",
    447 
    448                 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    449                         "<resources>\n" +
    450                         "\n" +
    451                         "    <string name=\"hello\">Hello World, MainActivity!</string>\n" +
    452                         "    \n" +
    453                         "    ^\n" +
    454                         "\n" +
    455                         "</resources>");
    456     }
    457 
    458     /**
    459      * To test
    460      *    When you press / after < I should reindent the current line. For example,
    461      *    if you have
    462      *        <foo>
    463      *            <bar>
    464      *            </ the moment you've typed this we should dedent it back out
    465      *    When you press newline we need to reindent
    466      */
    467 
    468     /** Subclassed for test usage since constructor is protected */
    469     private class TestDocumentCommand extends DocumentCommand {
    470         public TestDocumentCommand() {
    471         }
    472     }
    473 }
    474