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