Home | History | Annotate | Download | only in editors
      1 /*
      2 
      3  * Copyright (C) 2011 The Android Open Source Project
      4  *
      5  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.eclipse.org/org/documents/epl-v10.php
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package com.android.ide.eclipse.adt.internal.editors;
     19 
     20 import static com.android.SdkConstants.FD_RES;
     21 import static com.android.SdkConstants.FD_RES_ANIM;
     22 import static com.android.SdkConstants.FD_RES_ANIMATOR;
     23 import static com.android.SdkConstants.FD_RES_COLOR;
     24 import static com.android.SdkConstants.FD_RES_DRAWABLE;
     25 
     26 import com.android.ide.eclipse.adt.AdtPlugin;
     27 import com.android.ide.eclipse.adt.internal.editors.animator.AnimationContentAssist;
     28 import com.android.ide.eclipse.adt.internal.editors.color.ColorContentAssist;
     29 import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor;
     30 import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
     31 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
     32 import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableContentAssist;
     33 import com.android.ide.eclipse.adt.internal.editors.layout.LayoutContentAssist;
     34 import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
     35 import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.AdtProjectTest;
     36 import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestContentAssist;
     37 import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestEditor;
     38 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
     39 import com.android.ide.eclipse.adt.internal.editors.values.ValuesContentAssist;
     40 
     41 import org.eclipse.core.resources.IFile;
     42 import org.eclipse.jface.text.Document;
     43 import org.eclipse.jface.text.IDocument;
     44 import org.eclipse.jface.text.contentassist.ICompletionProposal;
     45 import org.eclipse.jface.text.source.ISourceViewer;
     46 import org.eclipse.swt.graphics.Point;
     47 import org.eclipse.ui.IEditorPart;
     48 import org.eclipse.ui.IWorkbenchPage;
     49 import org.eclipse.ui.PlatformUI;
     50 import org.eclipse.ui.ide.IDE;
     51 
     52 @SuppressWarnings("javadoc")
     53 public class AndroidContentAssistTest extends AdtProjectTest {
     54     private static final String CARET = "^"; //$NON-NLS-1$
     55 
     56     @Override
     57     protected boolean testCaseNeedsUniqueProject() {
     58         return true;
     59     }
     60 
     61     public void testStartsWith() {
     62         assertTrue(AndroidContentAssist.startsWith("", ""));
     63         assertTrue(AndroidContentAssist.startsWith("a", ""));
     64         assertTrue(AndroidContentAssist.startsWith("A", ""));
     65         assertTrue(AndroidContentAssist.startsWith("A", "a"));
     66         assertTrue(AndroidContentAssist.startsWith("A", "A"));
     67         assertTrue(AndroidContentAssist.startsWith("Ab", "a"));
     68         assertTrue(AndroidContentAssist.startsWith("ab", "A"));
     69         assertTrue(AndroidContentAssist.startsWith("ab", "AB"));
     70         assertFalse(AndroidContentAssist.startsWith("ab", "ABc"));
     71         assertFalse(AndroidContentAssist.startsWith("", "ABc"));
     72     }
     73 
     74     public void testNameStartsWith() {
     75         String fullWord = "android:marginTop";
     76         for (int i = 0; i < fullWord.length(); i++) {
     77             assertTrue(i + ":" + fullWord.substring(0, i),
     78                     AndroidContentAssist.nameStartsWith(
     79                     "android:layout_marginTop", fullWord.substring(0, i), "android:"));
     80         }
     81 
     82         fullWord = "android:layout_marginTop";
     83         for (int i = 0; i < fullWord.length(); i++) {
     84             assertTrue(i + ":" + fullWord.substring(0, i),
     85                     AndroidContentAssist.nameStartsWith("android:layout_marginTop", fullWord
     86                     .substring(0, i), "android:"));
     87         }
     88 
     89         fullWord = "layout_marginTop";
     90         for (int i = 0; i < fullWord.length(); i++) {
     91             assertTrue(i + ":" + fullWord.substring(0, i),
     92                     AndroidContentAssist.nameStartsWith("android:layout_marginTop", fullWord
     93                     .substring(0, i), "android:"));
     94         }
     95 
     96         fullWord = "marginTop";
     97         for (int i = 0; i < fullWord.length(); i++) {
     98             assertTrue(i + ":" + fullWord.substring(0, i),
     99                     AndroidContentAssist.nameStartsWith("android:layout_marginTop", fullWord
    100                     .substring(0, i), "android:"));
    101         }
    102 
    103         assertFalse(AndroidContentAssist.nameStartsWith("ab", "ABc", null));
    104         assertFalse(AndroidContentAssist.nameStartsWith("", "ABc", null));
    105     }
    106 
    107     public void testCompletion1() throws Exception {
    108         // Change attribute name completion
    109         checkLayoutCompletion("completion1.xml", "layout_w^idth=\"fill_parent\"");
    110     }
    111 
    112     public void testCompletion2() throws Exception {
    113         // Check attribute value completion for enum
    114         checkLayoutCompletion("completion1.xml", "layout_width=\"^fill_parent\"");
    115     }
    116 
    117     public void testCompletion3() throws Exception {
    118         // Check attribute value completion for enum with a prefix
    119         checkLayoutCompletion("completion1.xml", "layout_width=\"fi^ll_parent\"");
    120     }
    121 
    122     public void testCompletion4() throws Exception {
    123         // Check attribute value completion on units
    124         checkLayoutCompletion("completion1.xml", "marginBottom=\"50^\"");
    125     }
    126 
    127     public void testCompletion5() throws Exception {
    128         // Check attribute value completion on units with prefix
    129         checkLayoutCompletion("completion1.xml", "layout_marginLeft=\"50d^p\"");
    130     }
    131 
    132     public void testCompletion6() throws Exception {
    133         // Check resource sorting - "style" should bubble to the top for a style attribute
    134         checkLayoutCompletion("completion1.xml", "style=\"@android:^style/Widget.Button\"");
    135     }
    136 
    137     public void testCompletion7a() throws Exception {
    138         // Check flags (multiple values inside a single XML value, separated by | - where
    139         // the prefix is reset as soon as you pass each | )
    140         checkLayoutCompletion("completion1.xml", "android:gravity=\"l^eft|bottom\"");
    141     }
    142 
    143     public void testCompletion7b() throws Exception {
    144         checkLayoutCompletion("completion1.xml", "android:gravity=\"left|b^ottom\"");
    145     }
    146 
    147     public void testCompletion8() throws Exception {
    148         // Test completion right at the "=" sign; this will be taken to be the last
    149         // character of the attribute name (the caret is between the last char and before
    150         // the = characters), so it should match a single attribute
    151         checkLayoutCompletion("completion1.xml", "layout_width^=\"fill_parent\"");
    152     }
    153 
    154     public void testCompletion9() throws Exception {
    155         // Test completion right after the "=" sign; this will be taken to be the beginning
    156         // of the attribute value, but all values will also include a leading quote
    157         checkLayoutCompletion("completion1.xml", "layout_width=^\"fill_parent\"");
    158     }
    159 
    160     public void testCompletion10() throws Exception {
    161         // Test completion of element names
    162         checkLayoutCompletion("completion1.xml", "<T^extView");
    163     }
    164 
    165     public void testCompletion11() throws Exception {
    166         // Test completion of element names at the outside of the <. This should include
    167         // all the elements too (along with the leading <).
    168         checkLayoutCompletion("completion1.xml", "^<TextView");
    169     }
    170 
    171     public void testCompletion12() throws Exception {
    172         // Test completion of element names inside a nested XML; ensure that this will
    173         // correctly compute element names, not previous attribute
    174         checkLayoutCompletion("completion1.xml", "btn_default\">^</FrameLayout>");
    175     }
    176 
    177     public void testCompletion13a() throws Exception {
    178         checkLayoutCompletion("completion2.xml", "gravity=\"left|bottom|^cen");
    179     }
    180 
    181     public void testCompletion13b() throws Exception {
    182         checkLayoutCompletion("completion2.xml", "gravity=\"left|bottom|cen^");
    183     }
    184 
    185     public void testCompletion13c() throws Exception {
    186         checkLayoutCompletion("completion2.xml", "gravity=\"left|bottom^|cen");
    187     }
    188 
    189     public void testCompletion14() throws Exception {
    190         // Test completion of permissions
    191         checkManifestCompletion("manifest.xml", "android.permission.ACC^ESS_NETWORK_STATE");
    192     }
    193 
    194     public void testCompletion15() throws Exception {
    195         // Test completion of intents
    196         checkManifestCompletion("manifest.xml", "android.intent.category.L^AUNCHER");
    197     }
    198 
    199     public void testCompletion16() throws Exception {
    200         // Test completion of top level elements
    201         checkManifestCompletion("manifest.xml", "<^application android:i");
    202     }
    203 
    204     public void testCompletion17() throws Exception {
    205         // Test completion of attributes on the manifest element
    206         checkManifestCompletion("manifest.xml", "^android:versionCode=\"1\"");
    207     }
    208 
    209     public void testCompletion18() throws Exception {
    210         // Test completion of attributes on the manifest element
    211         checkManifestCompletion("manifest.xml",
    212                 "<activity android:^name=\".TestActivity\"");
    213     }
    214 
    215     public void testCompletion19() throws Exception {
    216         // Test special case where completing on a new element in an otherwise blank line
    217         // does not add in full completion (with closing tags)
    218         checkLayoutCompletion("broken3.xml", "<EditT^");
    219     }
    220 
    221     public void testCompletion20() throws Exception {
    222         checkLayoutCompletion("broken1.xml", "android:textColorHigh^");
    223     }
    224 
    225     public void testCompletion21() throws Exception {
    226         checkLayoutCompletion("broken2.xml", "style=^");
    227     }
    228 
    229     public void testCompletion22() throws Exception {
    230         // Test completion where the cursor is inside an element (e.g. the next
    231         // char is NOT a <) - should not complete with end tags
    232         checkLayoutCompletion("completion4.xml", "<Button^");
    233     }
    234 
    235     // Test completion in style files
    236 
    237     public void testCompletion23() throws Exception {
    238         checkResourceCompletion("completionvalues1.xml", "android:textS^ize");
    239     }
    240 
    241     public void testCompletion24() throws Exception {
    242         checkResourceCompletion("completionvalues1.xml", "17^sp");
    243     }
    244 
    245     public void testCompletion25() throws Exception {
    246         checkResourceCompletion("completionvalues1.xml", "textColor\">^@color/title_color</item>");
    247     }
    248 
    249     public void testCompletion26() throws Exception {
    250         checkResourceCompletion("completionvalues1.xml",
    251                 "<item name=\"android:shadowColor\">@an^</item>");
    252     }
    253 
    254     public void testCompletion27() throws Exception {
    255         checkResourceCompletion("completionvalues1.xml",
    256                 "<item name=\"android:gravity\">^  </item>");
    257     }
    258 
    259     public void testCompletion28() throws Exception {
    260         checkResourceCompletion("completionvalues1.xml",
    261                 "<item name=\"android:gravity\">  ^</item>");
    262     }
    263 
    264     public void testCompletion29() throws Exception {
    265         checkResourceCompletion("completionvalues1.xml", "<item name=\"gr^\">");
    266     }
    267 
    268     public void testCompletion30() throws Exception {
    269         checkResourceCompletion("completionvalues1.xml", "<item name=\"an^\">");
    270     }
    271 
    272     public void testCompletion31() throws Exception {
    273         checkResourceCompletion("completionvalues1.xml", "<item ^></item>");
    274     }
    275 
    276     public void testCompletion32() throws Exception {
    277         checkResourceCompletion("completionvalues1.xml", "<item name=\"^\"></item>");
    278     }
    279 
    280     public void testCompletion33() throws Exception {
    281         checkResourceCompletion("completionvalues1.xml",
    282                 "<item name=\"android:allowSingleTap\">^</item>");
    283     }
    284 
    285     public void testCompletion34() throws Exception {
    286         checkResourceCompletion("completionvalues1.xml",
    287                 "<item name=\"android:alwaysDrawnWithCache\">^  false  </item>");
    288     }
    289 
    290     public void testCompletion35() throws Exception {
    291         checkResourceCompletion("completionvalues1.xml",
    292                 "<item name=\"android:alwaysDrawnWithCache\">  ^false  </item>");
    293     }
    294 
    295     public void testCompletion36() throws Exception {
    296         checkResourceCompletion("completionvalues1.xml",
    297                 "<item name=\"android:alwaysDrawnWithCache\">  f^alse  </item>");
    298     }
    299 
    300     public void testCompletion37() throws Exception {
    301         checkResourceCompletion("completionvalues1.xml",
    302                 "<item name=\"android:orientation\">h^</item>");
    303     }
    304 
    305     public void testCompletion38() throws Exception {
    306         checkResourceCompletion("completionvalues1.xml",
    307                 "           c^");
    308     }
    309 
    310     public void testCompletion39() throws Exception {
    311         // If you are at the end of a closing quote (but with no space), completion should
    312         // include a separating space.
    313         checkLayoutCompletion("completion1.xml", "marginBottom=\"50\"^");
    314     }
    315 
    316     public void testCompletion40() throws Exception {
    317         // Same as test 39 but with single quote
    318         checkLayoutCompletion("completion5.xml",  "android:id='@+id/button2'^");
    319     }
    320 
    321     public void testCompletion41() throws Exception {
    322         // Test prefix matching on layout_ with namespace prefix
    323         checkLayoutCompletion("completion8.xml",  "android:mar^=\"50dp\"");
    324     }
    325 
    326     public void testCompletion42() throws Exception {
    327         // Test prefix matching on layout_ with namespace prefix
    328         checkLayoutCompletion("completion8.xml",  "android:w^i=\"100\"");
    329     }
    330 
    331     public void testCompletion43() throws Exception {
    332         // Test prefix matching on layout_ without namespace prefix
    333         checkLayoutCompletion("completion8.xml",  "mar^=\"60dp\"");
    334     }
    335 
    336     public void testCompletion44() throws Exception {
    337         // Test prefix matching on layout_ without namespace prefix
    338         checkLayoutCompletion("completion8.xml",  "android:layo^ut_width=\"fill_parent\"");
    339     }
    340 
    341     public void testCompletion45() throws Exception {
    342         // Test top level elements in colors
    343         checkColorCompletion("color1.xml",  "^<selector");
    344     }
    345 
    346     public void testCompletion46a() throws Exception {
    347         // Test children of selector: should offer item
    348         checkColorCompletion("color1.xml",  "^<item android");
    349     }
    350 
    351     public void testCompletion46b() throws Exception {
    352         // Test attribute matching in color files
    353         checkColorCompletion("color1.xml",  "<item ^android:state_focused=\"true\"/>");
    354     }
    355 
    356     public void testCompletion47() throws Exception {
    357         // Check root completion in drawables: should list all drawable root elements
    358         checkDrawableCompletion("drawable1.xml",  "^<layer-list");
    359     }
    360 
    361     public void testCompletion48() throws Exception {
    362         // Check attributes of the layer list
    363         checkDrawableCompletion("drawable1.xml",  "^xmlns:android");
    364     }
    365 
    366     public void testCompletion49() throws Exception {
    367         // Check attributes of the <item> element inside a <layer-list>
    368         checkDrawableCompletion("drawable1.xml",  "<item ^></item>");
    369     }
    370 
    371     public void testCompletion50() throws Exception {
    372         // Check elements nested inside the <item> in a layer list: can use any drawable again
    373         checkDrawableCompletion("drawable1.xml",  "<item >^</item>");
    374     }
    375 
    376     public void testCompletion51() throws Exception {
    377         // Check attributes of <shape> element
    378         checkDrawableCompletion("drawable2.xml",  "^android:innerRadiusRatio=\"2\"");
    379     }
    380 
    381     public void testCompletion52() throws Exception {
    382         // Check list of available elements inside a shape
    383         checkDrawableCompletion("drawable2.xml",  "^<gradient");
    384     }
    385 
    386     public void testCompletion53() throws Exception {
    387         // Check list of root anim elements
    388         checkAnimCompletion("anim1.xml",  "^<set xmlns");
    389     }
    390 
    391     public void testCompletion54() throws Exception {
    392         // Check that we can nest inside <set>'s
    393         checkAnimCompletion("anim1.xml",  "^<translate android:id=");
    394     }
    395 
    396     public void testCompletion55() throws Exception {
    397         // translate properties
    398         checkAnimCompletion("anim1.xml",  "android:^fromXDelta=");
    399     }
    400 
    401     public void testCompletion56() throws Exception {
    402         // alpha properties
    403         checkAnimCompletion("anim1.xml",  "android:^fromAlpha=");
    404     }
    405 
    406     public void testCompletion57() throws Exception {
    407         // Fractional properties
    408         checkAnimCompletion("anim1.xml",  "android:fromXDelta=\"100^%p\"");
    409     }
    410 
    411     public void testCompletion58() throws Exception {
    412         // Top level animator elements
    413         checkAnimatorCompletion("animator1.xml",  "^<set xmlns");
    414     }
    415 
    416     public void testCompletion59() throws Exception {
    417         // objectAnimator properties
    418         checkAnimatorCompletion("animator1.xml",  "android:^duration=\"2000\"");
    419     }
    420 
    421     public void testCompletion60() throws Exception {
    422         // propertyName completion
    423         checkAnimatorCompletion("animator1.xml",  "android:propertyName=\"scal^eX\"/>");
    424     }
    425 
    426     public void testCompletion61() throws Exception {
    427         // Interpolator completion
    428         checkAnimatorCompletion("animator1.xml",
    429                 "android:interpolator=\"^@android:anim/bounce_interpolator\"");
    430     }
    431 
    432     public void testCompletion62() throws Exception {
    433         // Test completing inside an element that contains .'s, such as a custom view tag
    434         checkLayoutCompletion("completion9.xml",  "android:layout_wi^dth=");
    435     }
    436 
    437     public void testCompletion63() throws Exception {
    438         // Test attribute completion inside a custom view tag
    439         // TODO: This works in a running IDE but not in a test context; figure out why.
    440         //checkLayoutCompletion("completion9.xml",  "android:drawable^Top");
    441     }
    442 
    443     public void testCompletion64() throws Exception {
    444         // Test element completion inside a custom view tag
    445         checkLayoutCompletion("completion9.xml",  "^<Button");
    446     }
    447 
    448     public void testCompletion65() throws Exception {
    449         // Test completion replacement when there is a selection
    450         // (see issue http://code.google.com/p/android/issues/detail?id=18607 )
    451         checkLayoutCompletion("completion10.xml", "\"[^wrap_content]\"");
    452     }
    453 
    454     public void testCompletion66() throws Exception {
    455         checkResourceCompletion("completionvalues1.xml", "17[^sp]");
    456     }
    457 
    458     public void testCompletion67() throws Exception {
    459         checkResourceCompletion("completionvalues1.xml", "17[^sp]");
    460     }
    461 
    462     public void testCompletion68() throws Exception {
    463         checkResourceCompletion("completionvalues1.xml", "[^false]");
    464     }
    465 
    466     public void testCompletion69() throws Exception {
    467         // Test minimum SDK completion
    468         checkManifestCompletion("manifest.xml", "<uses-sdk android:minSdkVersion=\"^11\" />");
    469     }
    470 
    471     public void testCompletion70() throws Exception {
    472         checkResourceCompletion("completionvalues2.xml",
    473                 "<item name=\"main_layout4\" type=\"layout\">^</item>");
    474     }
    475 
    476     public void testCompletion71() throws Exception {
    477         checkResourceCompletion("completionvalues2.xml",
    478                 "<item name=\"main_layout5\" type=\"string\">@string/^app_name</item>");
    479     }
    480 
    481     public void testCompletion72() throws Exception {
    482         // Test completion of theme attributes
    483         checkLayoutCompletion("completion11.xml", "?^android:attr/Textapp");
    484     }
    485 
    486     public void testCompletion73() throws Exception {
    487         checkLayoutCompletion("completion11.xml", "?android:attr/Textapp^");
    488     }
    489 
    490     public void testCompletion74() throws Exception {
    491         checkLayoutCompletion("completion11.xml", "?and^roid:attr/Textapp");
    492     }
    493 
    494     public void testCompletion75() throws Exception {
    495         // Test <include> attributes
    496         checkLayoutCompletion("completion12.xml", "<include ^/>");
    497     }
    498 
    499     public void testComplation76() throws Exception {
    500         // Test theme completion with implicit attr
    501         checkLayoutCompletion("navigation1.xml", "?android:a^ttr/alertDialogStyle");
    502     }
    503 
    504     public void testComplation77() throws Exception {
    505         // Test <fragment class="^" completion
    506         checkLayoutCompletion("fragmentlayout.xml", "android:name=\"^com");
    507     }
    508 
    509     public void testComplation78() throws Exception {
    510         // Test <fragment android:name="^" completion
    511         checkLayoutCompletion("fragmentlayout.xml", "class=\"^com");
    512     }
    513 
    514     public void testComplation79() throws Exception {
    515         // Test tools context completion
    516         checkLayoutCompletion("completion11.xml", "tools:context=\"^.MainActivity\"");
    517     }
    518 
    519     public void testComplation80() throws Exception {
    520         // Test manifest class completion
    521         checkManifestCompletion("manifest.xml", "<activity android:name=\"^.");
    522     }
    523 
    524     // TODO: Test <view completion!
    525 
    526     // ---- Test *applying* code completion ----
    527 
    528     // The following tests check -applying- a specific code completion
    529     // match - this verifies that the document is updated correctly, the
    530     // caret is moved appropriately, etc.
    531 
    532     public void testApplyCompletion1() throws Exception {
    533         // Change attribute name completion
    534         checkApplyLayoutCompletion("completion1.xml", "layout_w^idth=\"fill_parent\"",
    535                 "android:layout_weight");
    536     }
    537 
    538     public void testApplyCompletion2() throws Exception {
    539         // Check attribute value completion for enum
    540         checkApplyLayoutCompletion("completion1.xml", "layout_width=\"^fill_parent\"",
    541                 "match_parent");
    542     }
    543 
    544     public void testApplyCompletion3() throws Exception {
    545         // Check attribute value completion for enum with a prefix
    546         checkApplyLayoutCompletion("completion1.xml", "layout_width=\"fi^ll_parent\"",
    547                 "fill_parent");
    548     }
    549 
    550     public void testApplyCompletion4() throws Exception {
    551         // Check attribute value completion on units
    552         checkApplyLayoutCompletion("completion1.xml", "marginBottom=\"50^\"", "50mm");
    553     }
    554 
    555     public void testApplyCompletion5() throws Exception {
    556         // Check attribute value completion on units with prefix
    557         checkApplyLayoutCompletion("completion1.xml", "layout_marginLeft=\"50d^p\"", "50dp");
    558     }
    559 
    560     public void testApplyCompletion6() throws Exception {
    561         // Check resource sorting - "style" should bubble to the top for a style attribute
    562         checkApplyLayoutCompletion("completion1.xml", "style=\"@android:^style/Widget.Button\"",
    563                 "@android:drawable/");
    564     }
    565 
    566     public void testApplyCompletion7a() throws Exception {
    567         // Check flags (multiple values inside a single XML value, separated by | - where
    568         // the prefix is reset as soon as you pass each | )
    569         checkApplyLayoutCompletion("completion1.xml", "android:gravity=\"l^eft|bottom\"",
    570                 "left");
    571         // NOTE - this will replace all flag values with the newly selected value.
    572         // That may not be the best behavior - perhaps we should only replace one portion
    573         // of the value.
    574     }
    575 
    576     public void testApplyCompletion7b() throws Exception {
    577         checkApplyLayoutCompletion("completion1.xml", "android:gravity=\"left|b^ottom\"",
    578                 "bottom");
    579         // NOTE - this will replace all flag values with the newly selected value.
    580         // That may not be the best behavior - perhaps we should only replace one portion
    581         // of the value.
    582     }
    583 
    584     public void testApplyCompletion8() throws Exception {
    585         // Test completion right at the "=" sign; this will be taken to be the last
    586         // character of the attribute name (the caret is between the last char and before
    587         // the = characters), so it should match a single attribute
    588         checkApplyLayoutCompletion("completion1.xml", "layout_width^=\"fill_parent\"",
    589                 "android:layout_width");
    590     }
    591 
    592     public void testApplyCompletion9() throws Exception {
    593         // Test completion right after the "=" sign; this will be taken to be the beginning
    594         // of the attribute value, but all values will also include a leading quote
    595         checkApplyLayoutCompletion("completion1.xml", "layout_width=^\"fill_parent\"",
    596                 "\"wrap_content\"");
    597     }
    598 
    599     public void testApplyCompletion10() throws Exception {
    600         // Test completion of element names
    601         checkApplyLayoutCompletion("completion1.xml", "<T^extView", "TableLayout");
    602     }
    603 
    604     public void testApplyCompletion11a() throws Exception {
    605         // Test completion of element names at the outside of the <. This should include
    606         // all the elements too (along with the leading <).
    607         checkApplyLayoutCompletion("completion1.xml", "^<TextView", "<RadioGroup ></RadioGroup>");
    608     }
    609 
    610     public void testApplyCompletion11b() throws Exception {
    611         // Similar to testApplyCompletion11a, but replacing with an element that does not
    612         // have children (to test the closing tag insertion code)
    613         checkApplyLayoutCompletion("completion1.xml", "^<TextView", "<CheckBox />");
    614     }
    615 
    616     public void testApplyCompletion12() throws Exception {
    617         // Test completion of element names inside a nested XML; ensure that this will
    618         // correctly compute element names, not previous attribute
    619         checkApplyLayoutCompletion("completion1.xml", "btn_default\">^</FrameLayout>",
    620                 "<FrameLayout ></FrameLayout>");
    621     }
    622 
    623     public void testApplyCompletion13a() throws Exception {
    624         checkApplyLayoutCompletion("completion2.xml", "gravity=\"left|bottom|^cen",
    625                 "fill_vertical");
    626     }
    627 
    628     public void testApplyCompletion13b() throws Exception {
    629         checkApplyLayoutCompletion("completion2.xml", "gravity=\"left|bottom|cen^",
    630                 "center_horizontal");
    631     }
    632 
    633     public void testApplyCompletion13c() throws Exception {
    634         checkApplyLayoutCompletion("completion2.xml", "gravity=\"left|bottom^|cen",
    635                 "bottom|fill_horizontal");
    636     }
    637 
    638     public void testApplyCompletion14() throws Exception {
    639         // Test special case where completing on a new element in an otherwise blank line
    640         // does not add in full completion (with closing tags)
    641         checkApplyLayoutCompletion("broken3.xml", "<EditT^", "EditText />");
    642     }
    643 
    644     public void testApplyCompletion15() throws Exception {
    645         checkApplyLayoutCompletion("broken1.xml", "android:textColorHigh^",
    646                 "android:textColorHighlight");
    647     }
    648 
    649     public void testApplyCompletion16() throws Exception {
    650         checkApplyLayoutCompletion("broken2.xml", "style=^",
    651                 "\"@android:\"");
    652     }
    653 
    654     public void testApplyCompletion17() throws Exception {
    655         // Make sure that completion right before a / inside an element still
    656         // inserts the ="" part (e.g. handles it as "insertNew)
    657         checkApplyLayoutCompletion("completion3.xml", "<EditText ^/>",
    658                 "android:textColorHighlight");
    659     }
    660 
    661     public void testApplyCompletion18() throws Exception {
    662         // Make sure that completion right before a > inside an element still
    663         // inserts the ="" part (e.g. handles it as "insertNew)
    664         checkApplyLayoutCompletion("completion3.xml", "<Button ^></Button>",
    665                 "android:paddingRight");
    666     }
    667 
    668     public void testApplyCompletion19() throws Exception {
    669         // Test completion with single quotes (apostrophe)
    670         checkApplyLayoutCompletion("completion5.xml", "android:orientation='^'", "horizontal");
    671     }
    672 
    673     public void testApplyCompletion20() throws Exception {
    674         // Test completion with single quotes (apostrophe)
    675         checkApplyLayoutCompletion("completion5.xml", "android:layout_marginTop='50^dp'", "50pt");
    676     }
    677 
    678     public void testApplyCompletion21() throws Exception {
    679         // Test completion with single quotes (apostrophe)
    680         checkApplyLayoutCompletion("completion5.xml", "android:layout_width='^wrap_content'",
    681                 "match_parent");
    682         // Still broken - but not a common case
    683         //checkApplyLayoutCompletion("completion5.xml", "android:layout_width=^'wrap_content'",
    684         //     "\"match_parent\"");
    685     }
    686 
    687     public void testApplyCompletion22() throws Exception {
    688         // Test completion in an empty string
    689         checkApplyLayoutCompletion("completion6.xml", "android:orientation=\"^\"", "horizontal");
    690     }
    691 
    692     public void testApplyCompletion23() throws Exception {
    693         // Test completion in an empty string
    694         checkApplyLayoutCompletion("completion7.xml", "android:orientation=\"^", "horizontal");
    695     }
    696 
    697     // Test completion in style files
    698 
    699     public void testApplyCompletion24a() throws Exception {
    700         checkApplyResourceCompletion("completionvalues1.xml", "android:textS^ize",
    701                 "android:textSelectHandleLeft");
    702     }
    703 
    704     public void testApplyCompletion24b() throws Exception {
    705         checkApplyResourceCompletion("completionvalues1.xml", "17^sp", "17mm");
    706     }
    707 
    708     public void testApplyCompletion25() throws Exception {
    709         checkApplyResourceCompletion("completionvalues1.xml",
    710                 "textColor\">^@color/title_color</item>", "@android:");
    711     }
    712 
    713     public void testApplyCompletion26() throws Exception {
    714         checkApplyResourceCompletion("completionvalues1.xml",
    715                 "<item name=\"android:shadowColor\">@an^</item>", "@android:");
    716     }
    717 
    718     public void testApplyCompletion27() throws Exception {
    719         checkApplyResourceCompletion("completionvalues1.xml",
    720                 "<item name=\"android:gravity\">^  </item>", "center_vertical");
    721     }
    722 
    723     public void testApplyCompletion28() throws Exception {
    724         checkApplyResourceCompletion("completionvalues1.xml",
    725                 "<item name=\"android:gravity\">  ^</item>", "left");
    726     }
    727 
    728     public void testApplyCompletion29() throws Exception {
    729         checkApplyResourceCompletion("completionvalues1.xml", "<item name=\"gr^\">",
    730                 "android:gravity");
    731     }
    732 
    733     public void testApplyCompletion30() throws Exception {
    734         checkApplyResourceCompletion("completionvalues1.xml", "<item name=\"an^\">",
    735                 "android:animateOnClick");
    736     }
    737 
    738     public void testApplyCompletion31() throws Exception {
    739         checkApplyResourceCompletion("completionvalues1.xml", "<item ^></item>", "name");
    740     }
    741 
    742     public void testApplyCompletion32() throws Exception {
    743         checkApplyResourceCompletion("completionvalues1.xml", "<item name=\"^\"></item>",
    744                 "android:background");
    745     }
    746 
    747     public void testApplyCompletion33() throws Exception {
    748         checkApplyResourceCompletion("completionvalues1.xml",
    749                 "<item name=\"android:allowSingleTap\">^</item>", "true");
    750     }
    751 
    752     public void testApplyCompletion34() throws Exception {
    753         checkApplyResourceCompletion("completionvalues1.xml",
    754                 "<item name=\"android:alwaysDrawnWithCache\">^  false  </item>", "true");
    755     }
    756 
    757     public void testApplyCompletion35() throws Exception {
    758         checkApplyResourceCompletion("completionvalues1.xml",
    759                 "<item name=\"android:alwaysDrawnWithCache\">  ^false  </item>", "true");
    760     }
    761 
    762     public void testApplyCompletion36() throws Exception {
    763         checkApplyResourceCompletion("completionvalues1.xml",
    764                 "<item name=\"android:alwaysDrawnWithCache\">  f^alse  </item>", "false");
    765     }
    766 
    767     public void testApplyCompletion37() throws Exception {
    768         checkApplyResourceCompletion("completionvalues1.xml",
    769                 "<item name=\"android:orientation\">h^</item>", "horizontal");
    770     }
    771 
    772     public void testApplyCompletion38() throws Exception {
    773         checkApplyResourceCompletion("completionvalues1.xml",
    774                 "           c^", "center");
    775     }
    776 
    777     public void testApplyCompletion39() throws Exception {
    778         // If you are at the end of a closing quote (but with no space), completion should
    779         // include a separating space.
    780         checkApplyLayoutCompletion("completion1.xml", "marginBottom=\"50\"^", " android:maxEms");
    781     }
    782 
    783     public void testApplyCompletion40() throws Exception {
    784         // If you are at the end of a closing quote (but with no space), completion should
    785         // include a separating space.
    786         checkApplyLayoutCompletion("completion5.xml",  "android:id='@+id/button2'^",
    787                 " android:maxWidth");
    788     }
    789 
    790     public void testApplyCompletion41() throws Exception {
    791         // Test prefix matching on layout_ with namespace prefix
    792         checkApplyLayoutCompletion("completion8.xml",  "android:mar^=\"50dp\"",
    793                 "android:layout_marginRight");
    794     }
    795 
    796     public void testApplyCompletion42() throws Exception {
    797         // Test completion replacement when there is a selection
    798         // (see issue http://code.google.com/p/android/issues/detail?id=18607 )
    799         checkApplyLayoutCompletion("completion10.xml", "\"[^wrap_content]\"", "fill_parent");
    800     }
    801 
    802     public void testApplyCompletion43() throws Exception {
    803         // Same as testApplyCompletion42 but with a smaller selection range
    804         checkApplyLayoutCompletion("completion10.xml", "\"[^wrap_c]ontent\"", "fill_parent");
    805     }
    806 
    807     public void testApplyCompletion44() throws Exception {
    808         checkApplyResourceCompletion("completionvalues1.xml", "[^false]", "true");
    809     }
    810 
    811     public void testApplyCompletion45() throws Exception {
    812         checkApplyResourceCompletion("completionvalues2.xml",
    813                 "@string/^app_name", "@string/hello");
    814     }
    815 
    816     public void testApplyCompletion46() throws Exception {
    817         checkApplyLayoutCompletion("completion11.xml",
    818                 "?android:attr/Textapp^", "?android:attr/textAppearanceLargeInverse");
    819     }
    820 
    821     public void testApplyCompletion47() throws Exception {
    822         // Test applying <fragment android:name="^" completion
    823         checkApplyLayoutCompletion("fragmentlayout.xml", "class=\"^com",
    824                 "android.app.ListFragment");
    825     }
    826 
    827     // --- Code Completion test infrastructure ----
    828 
    829     private void checkLayoutCompletion(String name, String caretLocation) throws Exception {
    830         IFile file = getLayoutFile(getProject(), name);
    831         IDE.setDefaultEditor(file, CommonXmlEditor.ID);
    832         checkCompletion(name, file, caretLocation,
    833                 new LayoutContentAssist());
    834     }
    835 
    836     private void checkColorCompletion(String name, String caretLocation) throws Exception {
    837         IFile file = getTestDataFile(getProject(), name, FD_RES + "/" + FD_RES_COLOR + "/" + name);
    838         IDE.setDefaultEditor(file, CommonXmlEditor.ID);
    839         checkCompletion(name, file, caretLocation, new ColorContentAssist());
    840     }
    841 
    842     private void checkAnimCompletion(String name, String caretLocation) throws Exception {
    843         IFile file = getTestDataFile(getProject(), name, FD_RES + "/" + FD_RES_ANIM + "/" + name);
    844         IDE.setDefaultEditor(file, CommonXmlEditor.ID);
    845         checkCompletion(name, file, caretLocation, new AnimationContentAssist());
    846     }
    847 
    848     private void checkAnimatorCompletion(String name, String caretLocation) throws Exception {
    849         IFile file = getTestDataFile(getProject(), name, FD_RES + "/" + FD_RES_ANIMATOR + "/"
    850                 + name);
    851         IDE.setDefaultEditor(file, CommonXmlEditor.ID);
    852         checkCompletion(name, file, caretLocation, new AnimationContentAssist());
    853     }
    854 
    855     private void checkDrawableCompletion(String name, String caretLocation) throws Exception {
    856         IFile file = getTestDataFile(getProject(), name, FD_RES + "/" + FD_RES_DRAWABLE + "/"
    857                 + name);
    858         IDE.setDefaultEditor(file, CommonXmlEditor.ID);
    859         checkCompletion(name, file, caretLocation, new DrawableContentAssist());
    860     }
    861 
    862     private void checkManifestCompletion(String name, String caretLocation) throws Exception {
    863         // Manifest files must be named AndroidManifest.xml. Must overwrite to replace
    864         // the default manifest created in the test project.
    865         IFile file = getTestDataFile(getProject(), name, "AndroidManifest.xml", true);
    866         IDE.setDefaultEditor(file, ManifestEditor.ID);
    867 
    868         checkCompletion(name, file, caretLocation,
    869                 new ManifestContentAssist());
    870     }
    871 
    872     private void checkApplyLayoutCompletion(String name, String caretLocation,
    873             String match) throws Exception {
    874         checkApplyCompletion(name, getLayoutFile(getProject(), name), caretLocation,
    875                 new LayoutContentAssist(), match);
    876     }
    877 
    878     private void checkResourceCompletion(String name, String caretLocation) throws Exception {
    879         checkCompletion(name, getValueFile(getProject(), name), caretLocation,
    880                 new ValuesContentAssist());
    881     }
    882 
    883     private void checkApplyResourceCompletion(String name, String caretLocation,
    884             String match) throws Exception {
    885         checkApplyCompletion(name, getValueFile(getProject(), name), caretLocation,
    886                 new ValuesContentAssist(), match);
    887     }
    888 
    889     private ICompletionProposal[] complete(IFile file, String caretLocation,
    890             AndroidContentAssist assist) throws Exception {
    891 
    892         // Open file
    893         IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
    894         assertNotNull(page);
    895         IEditorPart editor = IDE.openEditor(page, file);
    896         assertTrue(editor instanceof AndroidXmlEditor);
    897         AndroidXmlEditor xmlEditor = (AndroidXmlEditor) editor;
    898 
    899         UiElementNode root = xmlEditor.getUiRootNode();
    900         ElementDescriptor descriptor = root.getDescriptor();
    901         if (descriptor instanceof ViewElementDescriptor) {
    902             ViewElementDescriptor vd = (ViewElementDescriptor) descriptor;
    903             AttributeDescriptor[] attributes = vd.getAttributes();
    904             assertTrue(Integer.toString(attributes.length), attributes.length > 0);
    905         }
    906 
    907         ISourceViewer viewer = xmlEditor.getStructuredSourceViewer();
    908 
    909         // Determine the offset, and possibly make text range selections as well
    910         int offset = updateCaret(viewer, caretLocation);
    911 
    912         // Run code completion
    913         ICompletionProposal[] proposals = assist.computeCompletionProposals(viewer, offset);
    914         if (proposals == null) {
    915             proposals = new ICompletionProposal[0];
    916         }
    917 
    918         editor.getEditorSite().getPage().closeAllEditors(false);
    919 
    920         return proposals;
    921     }
    922 
    923     private void checkApplyCompletion(String basename, IFile file, String caretLocation,
    924             AndroidContentAssist assist, String match) throws Exception {
    925         ICompletionProposal[] proposals = complete(file, caretLocation, assist);
    926         ICompletionProposal chosen = null;
    927         for (ICompletionProposal proposal : proposals) {
    928             if (proposal.getDisplayString().equals(match)) {
    929                 chosen = proposal;
    930                 break;
    931             }
    932         }
    933         assertNotNull(chosen);
    934         assert chosen != null; // Eclipse null pointer analysis doesn't believe the JUnit assertion
    935 
    936         String fileContent = AdtPlugin.readFile(file);
    937         IDocument document = new Document();
    938         document.set(fileContent);
    939 
    940         // Apply code completion
    941         chosen.apply(document);
    942 
    943         // Insert caret location as well
    944         Point location = chosen.getSelection(document);
    945         document.replace(location.x, 0, CARET);
    946 
    947         String actual = document.get();
    948 
    949         int offset = getCaretOffset(fileContent, caretLocation);
    950         String beforeWithCaret = fileContent.substring(0, offset) + CARET
    951                 + fileContent.substring(offset);
    952 
    953         String diff = getDiff(beforeWithCaret, actual);
    954         assertTrue(diff + " versus " + actual, diff.length() > 0 || beforeWithCaret.equals(actual));
    955 
    956         StringBuilder summary = new StringBuilder();
    957         summary.append("Code completion in " + basename + " for " + caretLocation + " selecting "
    958                 + match + ":\n");
    959         if (diff.length() == 0) {
    960             diff = "No changes";
    961         }
    962         summary.append(diff);
    963 
    964         // assertEqualsGolden(basename, actual);
    965         assertEqualsGolden(basename, summary.toString(), "diff");
    966     }
    967 
    968     private void checkCompletion(String basename, IFile file, String caretLocation,
    969             AndroidContentAssist assist) throws Exception {
    970         ICompletionProposal[] proposals = complete(file, caretLocation, assist);
    971         StringBuilder sb = new StringBuilder(1000);
    972         sb.append("Code completion in " + basename + " for " + caretLocation + ":\n");
    973         for (ICompletionProposal proposal : proposals) {
    974             // TODO: assertNotNull(proposal.getImage());
    975             int length = sb.length();
    976             sb.append(proposal.getDisplayString().trim());
    977             String help = proposal.getAdditionalProposalInfo();
    978             if (help != null && help.trim().length() > 0) {
    979                 sb.append(" : ");
    980                 sb.append(help.replace('\n', ' ').trim());
    981                 if (sb.length() > length + 300) {
    982                     sb.setLength(length + 300 - "...".length());
    983                     sb.append("...");
    984                 }
    985             }
    986             sb.append('\n');
    987         }
    988         assertEqualsGolden(basename, sb.toString(), "txt");
    989     }
    990 }
    991